Compare commits

..

88 Commits

Author SHA1 Message Date
Damien George
ff8d0e071c docs: Bump version to 1.3.6.
This needs to be done before actually tagging the new version.
2014-11-04 19:04:12 +00:00
Damien George
0e3722137f docs: Update front page to display date of last update. 2014-11-04 18:51:29 +00:00
Damien George
8e701604d5 docs: Add links from quickref to pyb classes. 2014-11-04 18:25:20 +00:00
Damien George
bc0bc764fc docs: Add debounce tutorial; order Pin methods; add pull resistor info. 2014-11-04 18:07:06 +00:00
Damien George
183ac71dc8 docs: Add pdf size info to datasheet links. 2014-11-03 22:21:25 +00:00
Damien George
1e3fde0a10 docs: Add skin imgs; change external links to micropython.org/resources. 2014-11-03 22:14:23 +00:00
Damien George
72165c01f0 docs: Adjust table spacing in topindex page. 2014-11-03 20:48:43 +00:00
Damien George
ff319dffad py: Explicitly set uninitialised struct member to false.
Uninitialised struct members get a default value of 0/false, so this is
not strictly needed.  But it actually decreases code size because when
all members are initialised the compiler doesn't need to insert a call
to memset to clear everything.  In other words, setting 1 extra member
to 0 uses less code than calling memset.

ROM savings in bytes: 32-bit unix: 100; bare-arm: 44; stmhal: 52.
2014-11-03 16:18:51 +00:00
Damien George
0344fa1ddf py: Fix builtin callable so it checks user-defined instances correctly.
Addresses issue #953.
2014-11-03 16:09:39 +00:00
Damien George
2cd79fa924 Merge branch 'szinya-master' 2014-11-03 10:22:59 +00:00
Márton Szinovszki
bfd11a35db docs: Fix typo in Fading LEDs 2014-11-03 09:42:38 +01:00
Damien George
f6e825b42e docs: Disable logo and add spacing to top index. 2014-11-02 23:45:29 +00:00
Damien George
6e6dfdc56b docs: Make custom index page; add more docs. 2014-11-02 23:37:02 +00:00
Paul Sokolovsky
1060baa2c2 unix: Provide "fast" target to build interpreter for benchmarking.
This build is primarily intended for benchmarking, and may have random
features enabled/disabled to get high scores in synthetic benchmarks.
The intent is to show/prove that MicroPython codebase can compete with
CPython, when configured appropriately. But the main MicroPython aim
still remains to optimize for memory usage (which inevitibly leads to
performance degradation in some areas on some workloads).
2014-11-02 18:17:43 +02:00
Damien George
38bd762121 stmhal: Improve pyb.freq to allow 8 and 16MHz (not usable with USB).
Also restrict higher frequencies to have a VCO_OUT frequency below
432MHz, as specified in the datasheet.

Docs improved to list allowed frequencies, and explain about USB
stability.
2014-11-02 15:10:15 +00:00
Paul Sokolovsky
039887a0ac py: Fix bug with right-shifting small ints by large amounts.
Undefined behavior in C, needs explicit check.
2014-11-02 02:41:30 +02:00
Damien George
a58713a899 docs: Cleanup and update some docs. 2014-10-31 22:21:37 +00:00
Damien George
c7da7838ba tests: Add heapalloc.py.exp, since CPython can't generate it. 2014-10-31 22:09:40 +00:00
Damien George
109c1de015 py: Make gc.enable/disable just control auto-GC; alloc is still allowed.
gc.enable/disable are now the same as CPython: they just control whether
automatic garbage collection is enabled or not.  If disabled, you can
still allocate heap memory, and initiate a manual collection.
2014-10-31 21:30:46 +00:00
Damien George
4029f51842 stmhal: Fix UART so bits counts number of data bits, not incl parity.
Addresses issue #950.
2014-10-31 20:28:10 +00:00
Damien George
1559a97810 py: Add builtin round function.
Addresses issue #934.
2014-10-31 11:28:50 +00:00
Damien George
fa73c9cb25 docs: Add 2 images for tutorials. 2014-10-31 01:43:37 +00:00
Damien George
88d3054ac0 docs: Import documentation from source-code inline comments.
The inline docs (prefixed with /// in .c files) have been converted to
RST format and put in the docs subdirectory.
2014-10-31 01:37:19 +00:00
Damien George
7c4445afe1 tools: Make gendoc.py able to output RST format. 2014-10-31 01:36:11 +00:00
Damien George
1a8573ed0e stmhal: Update some inlined docs for network and CAN. 2014-10-31 01:12:54 +00:00
Damien George
47f349e7de docs: Fix links to images and other parts of the docs. 2014-10-31 00:58:23 +00:00
Shuning Bian
c92ef361c7 docs: Add tutorial for fading LED using PWM, with fritzing image 2014-10-31 00:49:17 +00:00
Damien George
4ef67d30f1 stmhal: Implement support for RTS/CTS hardware flow control in UART.
This is experimental support.  API is subject to changes.  RTS/CTS
available on UART(2) and UART(3) only.  Use as:

    uart = pyb.UART(2, 9600, flow=pyb.UART.RTS | pyb.UART.CTS)
2014-10-31 00:40:57 +00:00
Damien George
9a41b32b3f stmhal: Add ioctl to USB_VCP object, so it works with select.
This patch also enables non-blocking streams on stmhal port.

One can now make a USB-UART pass-through function:

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))
2014-10-31 00:12:02 +00:00
Damien George
efc49c5591 stmhal: Improve CAN print function. 2014-10-30 23:16:05 +00:00
Henrik Sölver
6a15ac80dc tests: Added and adapted CAN tests for extended messages 2014-10-30 23:16:01 +00:00
Henrik Sölver
504636815e stmhal: Added support for extended CAN frames. 2014-10-30 23:16:01 +00:00
stijn
0e557facb9 mpz: Fix 64bit msvc build
msvc does not treat 1L a 64bit integer hence all occurences of shifting it left or right
result in undefined behaviour since the maximum allowed shift count for 32bit ints is 31.
Forcing the correct type explicitely, stored in MPZ_LONG_1, solves this.
2014-10-30 23:00:24 +00:00
Paul Sokolovsky
e62a0fe367 objstr: Allow to convert any buffer proto object to str.
Original motivation is to support converting bytearrays, but easier to just
support buffer protocol at all.
2014-10-31 00:03:53 +02:00
Paul Sokolovsky
31619cc589 py: mp_obj_str_get_str(): Work with bytes too.
It should be fair to say that almost in all cases where some API call
expects string, it should be also possible to pass byte string. For example,
it should be open/delete/rename file with name as bytestring. Note that
similar change was done quite a long ago to mp_obj_str_get_data().
2014-10-31 00:00:39 +02:00
Damien George
11aa91615e stmhal: Fix ptr arith in CC3000 code; enable network build in travis. 2014-10-30 15:28:15 +00:00
Paul Sokolovsky
8bb71f0b06 moductypes: Make .sizeof() work with bytearrays. 2014-10-30 03:50:37 +02:00
Paul Sokolovsky
66d08eb4fe moductypes: Add test for accessing UINT8 array. 2014-10-30 03:50:37 +02:00
Paul Sokolovsky
6d287a6a02 moductypes: When dereferencing a field which is array of uint8, use bytearray.
Because bytearrays are much friendlier to work with, e.g. they can be printed
easily.
2014-10-30 03:50:34 +02:00
Paul Sokolovsky
2559e13957 moductypes: Make sure we can apply .sizeof() to all aggregate types.
Before, sizeof() could be applied to a structure field only if that field
was itself a structure. Now it can be applied to PTR and ARRAY fields too.
It's not possible to apply it to scalar fields though, because as soon as
scalar field (int or float) is dereferenced, its value is converted into
Python int/float value, and all original type info is lost. Moreover, we
allow sizeof of type definitions too, and there int is used to represent
(scalar) types. So, we have ambiguity what int may be - either dereferenced
scalar structure field, or encoded scalar type. So, rather throw an error
if user tries to apply sizeof() to int.
2014-10-30 03:50:23 +02:00
Paul Sokolovsky
b1422de12f py: Allow to override port config file and thus have >1 configs per port.
Use it like:

make CFLAGS_EXTRA='-DMP_CONFIGFILE="<mpconfigport_my.h>"'
2014-10-29 23:37:45 +00:00
stijn
49c47da804 Fix errors after enabling -Wpointer-arith 2014-10-29 15:42:38 +00:00
stijn
4e54c876a7 Add -Wpointer-arith flag to prevent problems with pointer arithmetic on void* 2014-10-29 10:29:09 +01:00
Damien George
ccedf000ed docs: Increase size of pyboard pinout. 2014-10-26 22:58:18 +00:00
Paul Sokolovsky
429e3f077e unix: Make -v dump memory info at exit.
Also, move bytecode dumps to -v -v, because they're too verbose for just -v.
2014-10-26 22:36:56 +00:00
Damien George
8768f8ad4b docs: Add quick reference page, with pinout and short example code. 2014-10-26 22:11:34 +00:00
Damien George
e4e52f5370 stmhal: Allow DAC object to be initialised from a pin.
Eg: dac = DAC(Pin.board.X5)
2014-10-26 21:46:06 +00:00
Paul Sokolovsky
e503512f83 unix: Implement -m option (execute module from stdlib).
Support for packages as argument not implemented, but otherwise error and
exit handling should be correct. This for example will allow to do:

pip-micropython install micropython-test.pystone
micropython -m test.pystone
2014-10-26 15:54:19 +00:00
Damien George
bc1488a05f stmhal: Improve REPL control codes; improve pyboard.py script.
Improvements are:

2 ctrl-C's are now needed to truly kill running script on pyboard, so
make CDC interface allow multiple ctrl-C's through at once (ie sending
b'\x03\x03' to pyboard now counts as 2 ctrl-C's).

ctrl-C in friendly-repl can now stop multi-line input.

In raw-repl mode, use ctrl-D to indicate end of running script, and also
end of any error message.  Thus, output of raw-repl is always at least 2
ctrl-D's and it's much easier to parse.

pyboard.py is now a bit faster, handles exceptions from pyboard better
(prints them and exits with exit code 1), prints out the pyboard output
while the script is running (instead of waiting till the end), and
allows to follow the output of a previous script when run with no
arguments.
2014-10-26 15:39:22 +00:00
Damien George
b2f19b8d34 tests: Get builtin_compile to skin properly on pyboard. 2014-10-26 15:38:28 +00:00
Damien George
480a7ce58f stmhal: Change SPI phase spec to 0,1 to match standard conventions.
Was 1 or 2, now 0 or 1 (respectively).  0 means sample MISO on first
edge, 1 means sample on second edge.

Addresses issue #936.
2014-10-26 13:54:31 +00:00
Damien George
de3c806965 py: Fix memoryview referencing so it retains ptr to original buffer.
This way, if original parent object is GC'd, the memoryview still points
to the underlying buffer data so that buffer is not GC'd.
2014-10-26 13:20:50 +00:00
Damien George
c76af32575 unix/windows: Disable sigaction on windows port. 2014-10-26 00:42:41 +01:00
Damien George
b0b0012fd8 py: Fix VM dispatch following a pending exception check. 2014-10-26 00:33:23 +01:00
Sebastian Plamauer
91bd4e8a23 changed file paths to new names 2014-10-25 23:59:33 +01:00
Damien George
124df6f8d0 py: Add mp_pending_exception global variable, for VM soft interrupt.
This allows to implement KeyboardInterrupt on unix, and a much safer
ctrl-C in stmhal port.  First ctrl-C is a soft one, with hope that VM
will notice it; second ctrl-C is a hard one that kills anything (for
both unix and stmhal).

One needs to check for a pending exception in the VM only for jump
opcodes.  Others can't produce an infinite loop (infinite recursion is
caught by stack check).
2014-10-25 23:37:57 +01:00
Damien George
d7353fe6fe stmhal: Change USB PID when in CDC+HID mode.
This gets CDC+HID working on Windows, since it needs a different PID for
a different USB configuration.

Thanks to tmbinc and dhylands.
2014-10-25 22:55:07 +01:00
Damien George
627852019b tests: Add test for compile builtin. 2014-10-25 22:07:25 +01:00
Damien George
c9fc620723 py: Implement compile builtin, enabled only on unix port.
This should be pretty compliant with CPython, except perhaps for some
corner cases to do with globals/locals context.

Addresses issue #879.
2014-10-25 22:07:25 +01:00
Paul Sokolovsky
e5a3759ff5 py: Factor out mp_obj_is_package() function. 2014-10-25 22:31:33 +03:00
Paul Sokolovsky
8becca7c82 py: mp_builtin___import__(): Add const to arg type. 2014-10-25 22:31:26 +03:00
Damien George
8456cc017b py: Compress load-int, load-fast, store-fast, unop, binop bytecodes.
There is a lot potential in compress bytecodes and make more use of the
coding space.  This patch introduces "multi" bytecodes which have their
argument included in the bytecode (by addition).

UNARY_OP and BINARY_OP now no longer take a 1 byte argument for the
opcode.  Rather, the opcode is included in the first byte itself.

LOAD_FAST_[0,1,2] and STORE_FAST_[0,1,2] are removed in favour of their
multi versions, which can take an argument between 0 and 15 inclusive.
The majority of LOAD_FAST/STORE_FAST codes fit in this range and so this
saves a byte for each of these.

LOAD_CONST_SMALL_INT_MULTI is used to load small ints between -16 and 47
inclusive.  Such ints are quite common and now only need 1 byte to
store, and now have much faster decoding.

In all this patch saves about 2% RAM for typically bytecode (1.8% on
64-bit test, 2.5% on pyboard test).  It also reduces the binary size
(because bytecodes are simplified) and doesn't harm performance.
2014-10-25 20:23:13 +01:00
Damien George
1084b0f9c2 py: Store bytecode arg names in bytecode (were in own array).
This saves a lot of RAM for 2 reasons:

1. For functions that don't have default values, var args or var kw
args (which is a large number of functions in the general case), the
mp_obj_fun_bc_t type now fits in 1 GC block (previously needed 2 because
of the extra pointer to point to the arg_names array).  So this saves 16
bytes per function (32 bytes on 64-bit machines).

2. Combining separate memory regions generally saves RAM because the
unused bytes at the end of the GC block are saved for 1 of the blocks
(since that block doesn't exist on its own anymore).  So generally this
saves 8 bytes per function.

Tested by importing lots of modules:

- 64-bit Linux gave about an 8% RAM saving for 86k of used RAM.
- pyboard gave about a 6% RAM saving for 31k of used RAM.
2014-10-25 20:23:13 +01:00
Paul Sokolovsky
fcff4663dd unix: Allow -X heapsize= option take numbers with K & M suffixes.
For kilobytes and megabytes respectively.
2014-10-25 17:00:55 +01:00
Damien George
8204db6831 stmhal: Change fresh boot.py and main.py to use \r\n newlines.
This is so it's compatible with Windows.
2014-10-25 01:14:39 +01:00
Damien George
21dfd207ca stmhal: Fill in USB class/subclass/proto for CDC+HID device.
Also change HID device from keyboard to mouse (should have been mouse
all along).
2014-10-25 01:14:39 +01:00
Felix Domke
a64d5d67b5 USB CDC ACM: populate bFunction{Class,SubClass,Protocol} in the interface association descriptor 2014-10-25 01:14:39 +01:00
Damien George
0b13f3e026 py: Improve memory usage debugging; better GC AT dumping.
In unix port, mem_info(1) now prints pretty GC alloc table.
2014-10-24 23:12:25 +01:00
Damien George
564963a170 py: Fix debug-printing of bytecode line numbers.
Also move the raw bytecode printing code from emitglue to mp_bytecode_print.
2014-10-24 14:42:50 +00:00
Damien George
d00d8ac95c py: Use mp_uint_t where appropriate in stream functions. 2014-10-24 11:26:12 +00:00
Damien George
e294bee45b stmhal: Use stream's readinto. 2014-10-24 11:19:01 +00:00
Damien George
e5b1b7348a stmhal: Fix pin af definition: TIM2_CH1_ETR -> TIM2_CH1/TIM2_ETR. 2014-10-23 22:07:24 +01:00
Paul Sokolovsky
e2f8d98525 stream: Add optional 2nd "length" arg to .readinto() - extension to CPython.
While extension to file.readinto() definition of CPython, the additional arg
is similar to what in CPython available in socket.recv_into().
2014-10-23 21:43:59 +03:00
Damien George
185cb0d943 stmhal: Use OSError with POSIX error code for HAL errors.
Addresses issue #921.
2014-10-23 14:25:32 +01:00
Damien George
e7bb0443cd py: Properly free string parse-node; add assertion to gc_free. 2014-10-23 14:13:05 +01:00
Damien George
dd4f4530ab py: Add builtin memoryview object (mostly using array code). 2014-10-23 13:34:35 +01:00
Damien George
3aa09f5784 py: Use MP_OBJ_NULL instead of NULL in a few places. 2014-10-23 12:06:53 +01:00
Damien George
37378f8a9d py: Clean up edge cases of malloc/realloc/free. 2014-10-23 12:02:00 +01:00
Damien George
f5d69794a8 extmod: Add uheapq module. 2014-10-22 23:20:15 +01:00
Damien George
e72be1b999 py: Fix smallint modulo with negative arguments.
Addresses issue #927.
2014-10-22 23:05:50 +01:00
Damien George
5fc42a6c97 tools, pydfu: Some fixes to support Python 3. 2014-10-22 20:27:43 +01:00
Dave Hylands
842210f53a Add pydfu.py to the micropython tree. Use dfu_util bgy default
You can do:

make USE_PYDFU=1 deploy

to use pydfu.py
2014-10-22 20:18:38 +01:00
Damien George
e7a478204a py: Remove unused and unneeded SystemError exception.
It's purpose is for internal errors that are not catastrophic (ie not as
bad as RuntimeError).  Since we don't use it, we don't need it.
2014-10-22 19:42:55 +01:00
Damien George
efa04eafd3 stmhal: Add MMA_INT/PB2 to available pins on PYBV10.
This allows you to register ExtInt on the MMA interrupt pin.
2014-10-22 19:31:27 +01:00
Dave Hylands
d46a822262 Fixed TIM2_CH1 definition.
TIM2_CH1_ETR is really bundling 2 functions to the same pin:
TIM2_CH1 (where its used as a channel)
TIM2_ETR (where iss used as an external trigger).

I fixed most of these a while back, but it looks like I missed this one.
2014-10-22 19:16:51 +01:00
Damien George
3be6984b8f stmhal: Don't return SystemExit value from parse_compile_execute.
There is no need, since we don't (currently) use the value.
2014-10-22 19:14:20 +01:00
Dave Hylands
8d62bbd46a Add pyb.hard_reset, and make sys.exit() or raise SystemExit do a soft reset. 2014-10-22 19:14:20 +01:00
Damien George
3e42570538 stmhal: Change cc3k.recv to only make 1 call to underlying recv().
Also make cc3k.send and cc3k.recv independent functions (not wrapped by
stream write/read).  Also make wiznet5k.recv more memory efficient.

This might address issue #920.
2014-10-22 01:10:53 +01:00
168 changed files with 5951 additions and 1112 deletions

View File

@@ -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-

View File

@@ -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)

View File

@@ -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
View 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
View 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)

View File

@@ -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
View 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
View 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
View 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
View 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
View 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
View 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
View 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.

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

View 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.

View 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
View 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
View 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``.

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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 %}

View File

@@ -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

View 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()

View 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.

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

View File

@@ -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

View File

@@ -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>`_.

View 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))

View 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

View File

@@ -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
-----

View File

@@ -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``

View File

@@ -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.

View File

@@ -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():

View File

@@ -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
View 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
View 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
View File

@@ -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]);

View File

@@ -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
View File

@@ -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)

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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);

View File

@@ -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:

View File

@@ -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
View File

@@ -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;
}

View File

@@ -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 {

View File

@@ -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

View File

@@ -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 },
};

View File

@@ -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 */

View File

@@ -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.

View File

@@ -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)

View File

@@ -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) {

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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)

View File

@@ -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);

View File

@@ -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

View File

@@ -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;

View File

@@ -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:

View File

@@ -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));

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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))

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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) {

View File

@@ -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)

View File

@@ -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");
}

View File

@@ -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;
}

View File

@@ -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);

Some files were not shown because too many files have changed in this diff Show More