initial v1.19.1 merge; not compiled yet
This commit is contained in:
commit
0d4bc8c163
@ -1,3 +1,15 @@
|
||||
#all: Reformat remaining C code that doesn't have a space after a comma.
|
||||
5b700b0af90591d6b1a2c087bb8de6b7f1bfdd2d
|
||||
|
||||
# ports: Reformat more C and Python source code.
|
||||
5c32111fa0e31e451b0f1666bdf926be2fdfd82c
|
||||
|
||||
# all: Update Python formatting to latest Black version 22.1.0.
|
||||
ab2923dfa1174dc177f0a90cb00a7e4ff87958d2
|
||||
|
||||
# all: Update Python formatting to latest Black version 21.12b0.
|
||||
3770fab33449a5dadf8eb06edfae0767e75320a6
|
||||
|
||||
# tools/gen-cpydiff.py: Fix formatting of doc strings for new Black.
|
||||
0f78c36c5aa458a954eed39a46942209107a553e
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
:mod:`array` -- arrays of numeric data
|
||||
=======================================
|
||||
======================================
|
||||
|
||||
.. module:: array
|
||||
:synopsis: efficient arrays of numeric data
|
||||
|
||||
|see_cpython_module| :mod:`cpython:array`.
|
||||
|see_cpython_module| :mod:`python:array`.
|
||||
|
||||
Supported format codes: ``b``, ``B``, ``h``, ``H``, ``i``, ``I``, ``l``,
|
||||
``L``, ``q``, ``Q``, ``f``, ``d`` (the latter 2 depending on the
|
||||
|
@ -1,10 +1,10 @@
|
||||
:mod:`binascii` -- binary/ASCII conversions
|
||||
============================================
|
||||
===========================================
|
||||
|
||||
.. module:: binascii
|
||||
:synopsis: binary/ASCII conversions
|
||||
|
||||
|see_cpython_module| :mod:`cpython:binascii`.
|
||||
|see_cpython_module| :mod:`python:binascii`.
|
||||
|
||||
This module implements conversions between binary data and various
|
||||
encodings of it in ASCII form (in both directions).
|
||||
@ -31,11 +31,11 @@ Functions
|
||||
Conforms to `RFC 2045 s.6.8 <https://tools.ietf.org/html/rfc2045#section-6.8>`_.
|
||||
Returns a bytes object.
|
||||
|
||||
.. function:: b2a_base64(data)
|
||||
.. function:: b2a_base64(data, *, newline=True)
|
||||
|
||||
Encode binary data in base64 format, as in `RFC 3548
|
||||
<https://tools.ietf.org/html/rfc3548.html>`_. Returns the encoded data
|
||||
followed by a newline character, as a bytes object.
|
||||
followed by a newline character if ``newline``is true, as a bytes object.
|
||||
|
||||
.. function:: crc32(data, value=0, /)
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
:synopsis: simple BTree database
|
||||
|
||||
The ``btree`` module implements a simple key-value database using external
|
||||
storage (disk files, or in general case, a random-access ``stream``). Keys are
|
||||
storage (disk files, or in general case, a random-access `stream`). Keys are
|
||||
stored sorted in the database, and besides efficient retrieval by a key
|
||||
value, a database also supports efficient ordered range scans (retrieval
|
||||
of values with the keys in a given range). On the application interface
|
||||
@ -80,7 +80,7 @@ Functions
|
||||
|
||||
.. function:: open(stream, *, flags=0, pagesize=0, cachesize=0, minkeypage=0)
|
||||
|
||||
Open a database from a random-access ``stream`` (like an open file). All
|
||||
Open a database from a random-access `stream` (like an open file). All
|
||||
other parameters are optional and keyword-only, and allow to tweak advanced
|
||||
parameters of the database operation (most users will not need them):
|
||||
|
||||
|
@ -33,7 +33,7 @@ Functions and types
|
||||
|
||||
.. class:: bytes()
|
||||
|
||||
|see_cpython| `bytes`.
|
||||
|see_cpython| `python:bytes`.
|
||||
|
||||
.. function:: callable()
|
||||
|
||||
@ -68,7 +68,7 @@ Functions and types
|
||||
|
||||
.. class:: frozenset()
|
||||
|
||||
`frozenset()` is not enabled on non-Express CircuitPython boards.
|
||||
`frozenset()` is not enabled on the smallest CircuitPython boards for space reasons.
|
||||
|
||||
.. function:: getattr()
|
||||
|
||||
@ -88,12 +88,12 @@ Functions and types
|
||||
|
||||
.. classmethod:: from_bytes(bytes, byteorder)
|
||||
|
||||
In CircuitPython, ``byteorder`` parameter must be positional (this is
|
||||
In CircuitPython, the ``byteorder`` parameter must be positional (this is
|
||||
compatible with CPython).
|
||||
|
||||
.. method:: to_bytes(size, byteorder)
|
||||
|
||||
In CircuitPython, ``byteorder`` parameter must be positional (this is
|
||||
In CircuitPython, the ``byteorder`` parameter must be positional (this is
|
||||
compatible with CPython).
|
||||
|
||||
.. function:: isinstance()
|
||||
@ -138,7 +138,7 @@ Functions and types
|
||||
|
||||
.. function:: reversed()
|
||||
|
||||
`reversed()` is not enabled on non-Express CircuitPython boards.
|
||||
`reversed()` is not enabled on the smallest CircuitPython boards for space reasons.
|
||||
|
||||
.. function:: round()
|
||||
|
||||
@ -224,10 +224,14 @@ Exceptions
|
||||
|
||||
.. exception:: SystemExit
|
||||
|
||||
|see_cpython| `python:SystemExit`.
|
||||
|
||||
.. exception:: TimeoutError
|
||||
|
||||
.. exception:: TypeError
|
||||
|
||||
|see_cpython| `python:TypeError`.
|
||||
|
||||
.. exception:: UnicodeError
|
||||
|
||||
.. exception:: ValueError
|
||||
|
@ -1,12 +1,12 @@
|
||||
:mod:`collections` -- collection and container types
|
||||
=====================================================
|
||||
====================================================
|
||||
|
||||
.. include:: ../templates/unsupported_in_circuitpython.inc
|
||||
**Limitations:** Not implemented on the smallest CircuitPython boards for space reasons.
|
||||
|
||||
.. module:: collections
|
||||
:synopsis: collection and container types
|
||||
|
||||
|see_cpython_module| :mod:`cpython:collections`.
|
||||
|see_cpython_module| :mod:`python:collections`.
|
||||
|
||||
This module implements advanced collection and container types to
|
||||
hold/accumulate various objects.
|
||||
@ -14,7 +14,7 @@ hold/accumulate various objects.
|
||||
Classes
|
||||
-------
|
||||
|
||||
.. function:: deque(iterable, maxlen[, flags])
|
||||
.. class:: deque(iterable, maxlen[, flags])
|
||||
|
||||
Deques (double-ended queues) are a list-like container that support O(1)
|
||||
appends and pops from either side of the deque. New deques are created
|
||||
@ -59,7 +59,7 @@ Classes
|
||||
print(t1.name)
|
||||
assert t2.name == t2[1]
|
||||
|
||||
.. function:: OrderedDict(...)
|
||||
.. class:: OrderedDict(...)
|
||||
|
||||
``dict`` type subclass which remembers and preserves the order of keys
|
||||
added. When ordered dict is iterated over, keys/items are returned in
|
||||
|
@ -4,10 +4,10 @@
|
||||
.. module:: errno
|
||||
:synopsis: system error codes
|
||||
|
||||
|see_cpython_module| :mod:`cpython:errno`.
|
||||
|see_cpython_module| :mod:`python:errno`.
|
||||
|
||||
This module provides access to symbolic error codes for `OSError` exception.
|
||||
A particular inventory of codes depends on :term:`MicroPython port`.
|
||||
The codes available may vary per CircuitPython build.
|
||||
|
||||
Constants
|
||||
---------
|
||||
@ -15,14 +15,13 @@ Constants
|
||||
.. data:: EEXIST, EAGAIN, etc.
|
||||
|
||||
Error codes, based on ANSI C/POSIX standard. All error codes start with
|
||||
"E". As mentioned above, inventory of the codes depends on
|
||||
:term:`MicroPython port`. Errors are usually accessible as ``exc.args[0]``
|
||||
"E". Errors are usually accessible as ``exc.errno``
|
||||
where ``exc`` is an instance of `OSError`. Usage example::
|
||||
|
||||
try:
|
||||
os.mkdir("my_dir")
|
||||
except OSError as exc:
|
||||
if exc.args[0] == errno.EEXIST:
|
||||
if exc.errno == errno.EEXIST:
|
||||
print("Directory already exists")
|
||||
|
||||
.. data:: errorcode
|
||||
|
@ -1,12 +1,10 @@
|
||||
:mod:`gc` -- control the garbage collector
|
||||
==========================================
|
||||
|
||||
.. include:: ../templates/unsupported_in_circuitpython.inc
|
||||
|
||||
.. module:: gc
|
||||
:synopsis: control the garbage collector
|
||||
|
||||
|see_cpython_module| :mod:`cpython:gc`.
|
||||
|see_cpython_module| :mod:`python:gc`.
|
||||
|
||||
Functions
|
||||
---------
|
||||
@ -63,6 +61,6 @@ Functions
|
||||
.. admonition:: Difference to CPython
|
||||
:class: attention
|
||||
|
||||
This function is a a MicroPython extension. CPython has a similar
|
||||
This function is a MicroPython extension. CPython has a similar
|
||||
function - ``set_threshold()``, but due to different GC
|
||||
implementations, its signature and semantics are different.
|
||||
|
@ -6,7 +6,7 @@
|
||||
.. module:: heapq
|
||||
:synopsis: heap queue algorithm
|
||||
|
||||
|see_cpython_module| :mod:`cpython:heapq`.
|
||||
|see_cpython_module| :mod:`python:heapq`.
|
||||
|
||||
This module implements the
|
||||
`min heap queue algorithm <https://en.wikipedia.org/wiki/Heap_%28data_structure%29>`_.
|
||||
|
@ -15,7 +15,7 @@ CircuitPython's long-term goal is that code written in CircuitPython
|
||||
using Python standard libraries will be runnable on CPython without changes.
|
||||
|
||||
These libraries are not enabled on CircuitPython builds with
|
||||
limited flash memory, usually on non-Express builds:
|
||||
limited flash memory:
|
||||
``binascii``, ``errno``, ``json``, ``re``.
|
||||
|
||||
These libraries are not currently enabled in any CircuitPython build, but may be in the future:
|
||||
@ -42,21 +42,6 @@ Omitted functions in the ``string`` library
|
||||
-------------------------------------------
|
||||
|
||||
A few string operations are not enabled on small builds
|
||||
(usually non-Express), due to limited flash memory:
|
||||
due to limited flash memory:
|
||||
``string.center()``, ``string.partition()``, ``string.splitlines()``,
|
||||
``string.reversed()``.
|
||||
|
||||
|
||||
CircuitPython/MicroPython-specific libraries
|
||||
--------------------------------------------
|
||||
|
||||
Functionality specific to the CircuitPython/MicroPython implementation is available in
|
||||
the following libraries. These libraries may change significantly or be removed in future
|
||||
versions of CircuitPython.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
btree.rst
|
||||
framebuf.rst
|
||||
micropython.rst
|
||||
|
@ -1,10 +1,10 @@
|
||||
:mod:`io` -- input/output streams
|
||||
==================================
|
||||
=================================
|
||||
|
||||
.. module:: io
|
||||
:synopsis: input/output streams
|
||||
|
||||
|see_cpython_module| :mod:`cpython:io`.
|
||||
|see_cpython_module| :mod:`python:io`.
|
||||
|
||||
This module contains additional types of ``stream`` (file-like) objects
|
||||
and helper functions.
|
||||
@ -112,3 +112,20 @@ Classes
|
||||
.. method:: getvalue()
|
||||
|
||||
Get the current contents of the underlying buffer which holds data.
|
||||
|
||||
.. class:: StringIO(alloc_size)
|
||||
:noindex:
|
||||
.. class:: BytesIO(alloc_size)
|
||||
:noindex:
|
||||
|
||||
Create an empty `StringIO`/`BytesIO` object, preallocated to hold up
|
||||
to *alloc_size* number of bytes. That means that writing that amount
|
||||
of bytes won't lead to reallocation of the buffer, and thus won't hit
|
||||
out-of-memory situation or lead to memory fragmentation. These constructors
|
||||
are a MicroPython extension and are recommended for usage only in special
|
||||
cases and in system-level libraries, not for end-user applications.
|
||||
|
||||
.. admonition:: Difference to CPython
|
||||
:class: attention
|
||||
|
||||
These constructors are a MicroPython extension.
|
||||
|
@ -1,10 +1,10 @@
|
||||
:mod:`json` -- JSON encoding and decoding
|
||||
==========================================
|
||||
=========================================
|
||||
|
||||
.. module:: json
|
||||
:synopsis: JSON encoding and decoding
|
||||
|
||||
|see_cpython_module| :mod:`cpython:json`.
|
||||
|see_cpython_module| :mod:`python:json`.
|
||||
|
||||
This modules allows to convert between Python objects and the JSON
|
||||
data format.
|
||||
@ -12,14 +12,20 @@ data format.
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: dump(obj, stream)
|
||||
.. function:: dump(obj, stream, separators=None)
|
||||
|
||||
Serialise ``obj`` to a JSON string, writing it to the given *stream*.
|
||||
|
||||
.. function:: dumps(obj)
|
||||
If specified, separators should be an ``(item_separator, key_separator)``
|
||||
tuple. The default is ``(', ', ': ')``. To get the most compact JSON
|
||||
representation, you should specify ``(',', ':')`` to eliminate whitespace.
|
||||
|
||||
.. function:: dumps(obj, separators=None)
|
||||
|
||||
Return ``obj`` represented as a JSON string.
|
||||
|
||||
The arguments have the same meaning as in `dump`.
|
||||
|
||||
.. function:: load(stream)
|
||||
|
||||
Parse the given ``stream``, interpreting it as a JSON string and
|
||||
|
@ -1,7 +1,5 @@
|
||||
:mod:`micropython` -- access and control MicroPython internals
|
||||
==============================================================
|
||||
|
||||
.. include:: ../templates/unsupported_in_circuitpython.inc
|
||||
:mod:`micropython` -- MicroPython extensions and internals
|
||||
==========================================================
|
||||
|
||||
.. module:: micropython
|
||||
:synopsis: access and control MicroPython internals
|
||||
@ -11,7 +9,7 @@ Functions
|
||||
|
||||
.. function:: const(expr)
|
||||
|
||||
Used to declare that the expression is a constant so that the compile can
|
||||
Used to declare that the expression is a constant so that the compiler can
|
||||
optimise it. The use of this function should be as follows::
|
||||
|
||||
from micropython import const
|
||||
@ -28,111 +26,3 @@ Functions
|
||||
provided as part of the :mod:`micropython` module mainly so that scripts can be
|
||||
written which run under both CPython and MicroPython, by following the above
|
||||
pattern.
|
||||
|
||||
.. function:: opt_level([level])
|
||||
|
||||
If *level* is given then this function sets the optimisation level for subsequent
|
||||
compilation of scripts, and returns ``None``. Otherwise it returns the current
|
||||
optimisation level.
|
||||
|
||||
The optimisation level controls the following compilation features:
|
||||
|
||||
- Assertions: at level 0 assertion statements are enabled and compiled into the
|
||||
bytecode; at levels 1 and higher assertions are not compiled.
|
||||
- Built-in ``__debug__`` variable: at level 0 this variable expands to ``True``;
|
||||
at levels 1 and higher it expands to ``False``.
|
||||
- Source-code line numbers: at levels 0, 1 and 2 source-code line number are
|
||||
stored along with the bytecode so that exceptions can report the line number
|
||||
they occurred at; at levels 3 and higher line numbers are not stored.
|
||||
|
||||
The default optimisation level is usually level 0.
|
||||
|
||||
.. function:: mem_info([verbose])
|
||||
|
||||
Print information about currently used memory. If the *verbose* argument
|
||||
is given then extra information is printed.
|
||||
|
||||
The information that is printed is implementation dependent, but currently
|
||||
includes the amount of stack and heap used. In verbose mode it prints out
|
||||
the entire heap indicating which blocks are used and which are free.
|
||||
|
||||
.. function:: qstr_info([verbose])
|
||||
|
||||
Print information about currently interned strings. If the *verbose*
|
||||
argument is given then extra information is printed.
|
||||
|
||||
The information that is printed is implementation dependent, but currently
|
||||
includes the number of interned strings and the amount of RAM they use. In
|
||||
verbose mode it prints out the names of all RAM-interned strings.
|
||||
|
||||
.. function:: stack_use()
|
||||
|
||||
Return an integer representing the current amount of stack that is being
|
||||
used. The absolute value of this is not particularly useful, rather it
|
||||
should be used to compute differences in stack usage at different points.
|
||||
|
||||
.. function:: heap_lock()
|
||||
.. function:: heap_unlock()
|
||||
.. function:: heap_locked()
|
||||
|
||||
Lock or unlock the heap. When locked no memory allocation can occur and a
|
||||
``MemoryError`` will be raised if any heap allocation is attempted.
|
||||
`heap_locked()` returns a true value if the heap is currently locked.
|
||||
|
||||
These functions can be nested, ie `heap_lock()` can be called multiple times
|
||||
in a row and the lock-depth will increase, and then `heap_unlock()` must be
|
||||
called the same number of times to make the heap available again.
|
||||
|
||||
Both `heap_unlock()` and `heap_locked()` return the current lock depth
|
||||
(after unlocking for the former) as a non-negative integer, with 0 meaning
|
||||
the heap is not locked.
|
||||
|
||||
If the REPL becomes active with the heap locked then it will be forcefully
|
||||
unlocked.
|
||||
|
||||
Note: `heap_locked()` is not enabled on most ports by default,
|
||||
requires ``MICROPY_PY_MICROPYTHON_HEAP_LOCKED``.
|
||||
|
||||
.. function:: kbd_intr(chr)
|
||||
|
||||
Set the character that will raise a `KeyboardInterrupt` exception. By
|
||||
default this is set to 3 during script execution, corresponding to Ctrl-C.
|
||||
Passing -1 to this function will disable capture of Ctrl-C, and passing 3
|
||||
will restore it.
|
||||
|
||||
This function can be used to prevent the capturing of Ctrl-C on the
|
||||
incoming stream of characters that is usually used for the REPL, in case
|
||||
that stream is used for other purposes.
|
||||
|
||||
.. function:: schedule(func, arg)
|
||||
|
||||
Schedule the function *func* to be executed "very soon". The function
|
||||
is passed the value *arg* as its single argument. "Very soon" means that
|
||||
the MicroPython runtime will do its best to execute the function at the
|
||||
earliest possible time, given that it is also trying to be efficient, and
|
||||
that the following conditions hold:
|
||||
|
||||
- A scheduled function will never preempt another scheduled function.
|
||||
- Scheduled functions are always executed "between opcodes" which means
|
||||
that all fundamental Python operations (such as appending to a list)
|
||||
are guaranteed to be atomic.
|
||||
- A given port may define "critical regions" within which scheduled
|
||||
functions will never be executed. Functions may be scheduled within
|
||||
a critical region but they will not be executed until that region
|
||||
is exited. An example of a critical region is a preempting interrupt
|
||||
handler (an IRQ).
|
||||
|
||||
A use for this function is to schedule a callback from a preempting IRQ.
|
||||
Such an IRQ puts restrictions on the code that runs in the IRQ (for example
|
||||
the heap may be locked) and scheduling a function to call later will lift
|
||||
those restrictions.
|
||||
|
||||
Note: If `schedule()` is called from a preempting IRQ, when memory
|
||||
allocation is not allowed and the callback to be passed to `schedule()` is
|
||||
a bound method, passing this directly will fail. This is because creating a
|
||||
reference to a bound method causes memory allocation. A solution is to
|
||||
create a reference to the method in the class constructor and to pass that
|
||||
reference to `schedule()`.
|
||||
|
||||
There is a finite queue to hold the scheduled functions and `schedule()`
|
||||
will raise a `RuntimeError` if the queue is full.
|
||||
|
@ -1,10 +1,10 @@
|
||||
:mod:`re` -- simple regular expressions
|
||||
========================================
|
||||
=======================================
|
||||
|
||||
.. module:: re
|
||||
:synopsis: regular expressions
|
||||
|
||||
|see_cpython_module| :mod:`cpython:re`.
|
||||
|see_cpython_module| :mod:`python:re`.
|
||||
|
||||
This module implements regular expression operations. Regular expression
|
||||
syntax supported is a subset of CPython ``re`` module (and actually is
|
||||
|
@ -1,8 +1,6 @@
|
||||
:mod:`select` -- wait for events on a set of streams
|
||||
====================================================
|
||||
|
||||
.. include:: ../templates/unsupported_in_circuitpython.inc
|
||||
|
||||
.. module:: select
|
||||
:synopsis: wait for events on a set of streams
|
||||
|
||||
@ -86,7 +84,7 @@ Methods
|
||||
.. method:: poll.ipoll(timeout=-1, flags=0, /)
|
||||
|
||||
Like :meth:`poll.poll`, but instead returns an iterator which yields a
|
||||
``callee-owned tuples``. This function provides efficient, allocation-free
|
||||
"callee-owned tuple". This function provides an efficient, allocation-free
|
||||
way to poll on streams.
|
||||
|
||||
If *flags* is 1, one-shot behaviour for events is employed: streams for
|
||||
|
@ -1,12 +1,10 @@
|
||||
:mod:`sys` -- system specific functions
|
||||
========================================
|
||||
|
||||
.. include:: ../templates/unsupported_in_circuitpython.inc
|
||||
=======================================
|
||||
|
||||
.. module:: sys
|
||||
:synopsis: system specific functions
|
||||
|
||||
|see_cpython_module| :mod:`cpython:sys`.
|
||||
|see_cpython_module| :mod:`python:sys`.
|
||||
|
||||
Functions
|
||||
---------
|
||||
@ -35,6 +33,7 @@ Constants
|
||||
|
||||
* *name* - string "circuitpython"
|
||||
* *version* - tuple (major, minor, micro), e.g. (1, 7, 0)
|
||||
* *_mpy* - supported mpy file-format version (optional attribute)
|
||||
|
||||
This object is the recommended way to distinguish CircuitPython from other
|
||||
Python implementations (note that it still may not exist in the very
|
||||
@ -97,6 +96,12 @@ Constants
|
||||
If you need to check whether your program runs on CircuitPython (vs other
|
||||
Python implementation), use `sys.implementation` instead.
|
||||
|
||||
.. data:: ps1
|
||||
ps2
|
||||
|
||||
Mutable attributes holding strings, which are used for the REPL prompt. The defaults
|
||||
give the standard Python prompt of ``>>>`` and ``...``.
|
||||
|
||||
.. data:: stderr
|
||||
|
||||
Standard error ``stream``.
|
||||
@ -109,6 +114,14 @@ Constants
|
||||
|
||||
Standard output ``stream``.
|
||||
|
||||
.. data:: tracebacklimit
|
||||
|
||||
A mutable attribute holding an integer value which is the maximum number of traceback
|
||||
entries to store in an exception. Set to 0 to disable adding tracebacks. Defaults
|
||||
to 1000.
|
||||
|
||||
Note: this is not available on all ports.
|
||||
|
||||
.. data:: version
|
||||
|
||||
Python language version that this implementation conforms to, as a string.
|
||||
|
@ -159,7 +159,7 @@ Glossary
|
||||
typically accessible on a host PC via USB.
|
||||
|
||||
stream
|
||||
Also known as a "file-like object". An Python object which provides
|
||||
Also known as a "file-like object". A Python object which provides
|
||||
sequential read-write access to the underlying data. A stream object
|
||||
implements a corresponding interface, which consists of methods like
|
||||
``read()``, ``write()``, ``readinto()``, ``seek()``, ``flush()``,
|
||||
|
199
docs/reference/mpyfiles.rst
Normal file
199
docs/reference/mpyfiles.rst
Normal file
@ -0,0 +1,199 @@
|
||||
.. _mpy_files:
|
||||
|
||||
MicroPython .mpy files
|
||||
======================
|
||||
|
||||
MicroPython defines the concept of an .mpy file which is a binary container
|
||||
file format that holds precompiled code, and which can be imported like a
|
||||
normal .py module. The file ``foo.mpy`` can be imported via ``import foo``,
|
||||
as long as ``foo.mpy`` can be found in the usual way by the import machinery.
|
||||
Usually, each directory listed in ``sys.path`` is searched in order. When
|
||||
searching a particular directory ``foo.py`` is looked for first and if that
|
||||
is not found then ``foo.mpy`` is looked for, then the search continues in the
|
||||
next directory if neither is found. As such, ``foo.py`` will take precedence
|
||||
over ``foo.mpy``.
|
||||
|
||||
These .mpy files can contain bytecode which is usually generated from Python
|
||||
source files (.py files) via the ``mpy-cross`` program. For some architectures
|
||||
an .mpy file can also contain native machine code, which can be generated in
|
||||
a variety of ways, most notably from C source code.
|
||||
|
||||
Versioning and compatibility of .mpy files
|
||||
------------------------------------------
|
||||
|
||||
A given .mpy file may or may not be compatible with a given MicroPython system.
|
||||
Compatibility is based on the following:
|
||||
|
||||
* Version of the .mpy file: the version of the file must match the version
|
||||
supported by the system loading it.
|
||||
|
||||
* Sub-version of the .mpy file: if the .mpy file contains native machine code
|
||||
then the sub-version of the file must match the version support by the
|
||||
system loading it. Otherwise, if there is no native machine code in the .mpy
|
||||
file, then the sub-version is ignored when loading.
|
||||
|
||||
* Small integer bits: the .mpy file will require a minimum number of bits in
|
||||
a small integer and the system loading it must support at least this many
|
||||
bits.
|
||||
|
||||
* Native architecture: if the .mpy file contains native machine code then
|
||||
it will specify the architecture of that machine code and the system
|
||||
loading it must support execution of that architecture's code.
|
||||
|
||||
If a MicroPython system supports importing .mpy files then the
|
||||
``sys.implementation._mpy`` field will exist and return an integer which
|
||||
encodes the version (lower 8 bits), features and native architecture.
|
||||
|
||||
Trying to import an .mpy file that fails one of the first four tests will
|
||||
raise ``ValueError('incompatible .mpy file')``. Trying to import an .mpy
|
||||
file that fails the native architecture test (if it contains native machine
|
||||
code) will raise ``ValueError('incompatible .mpy arch')``.
|
||||
|
||||
If importing an .mpy file fails then try the following:
|
||||
|
||||
* Determine the .mpy version and flags supported by your MicroPython system
|
||||
by executing::
|
||||
|
||||
import sys
|
||||
sys_mpy = sys.implementation._mpy
|
||||
arch = [None, 'x86', 'x64',
|
||||
'armv6', 'armv6m', 'armv7m', 'armv7em', 'armv7emsp', 'armv7emdp',
|
||||
'xtensa', 'xtensawin'][sys_mpy >> 10]
|
||||
print('mpy version:', sys_mpy & 0xff)
|
||||
print('mpy flags:', end='')
|
||||
if arch:
|
||||
print(' -march=' + arch, end='')
|
||||
print()
|
||||
|
||||
* Check the validity of the .mpy file by inspecting the first two bytes of
|
||||
the file. The first byte should be an uppercase 'M' and the second byte
|
||||
will be the version number, which should match the system version from above.
|
||||
If it doesn't match then rebuild the .mpy file.
|
||||
|
||||
* Check if the system .mpy version matches the version emitted by ``mpy-cross``
|
||||
that was used to build the .mpy file, found by ``mpy-cross --version``.
|
||||
If it doesn't match then recompile ``mpy-cross`` from the Git repository
|
||||
checked out at the tag (or hash) reported by ``mpy-cross --version``.
|
||||
|
||||
* Make sure you are using the correct ``mpy-cross`` flags, found by the code
|
||||
above, or by inspecting the ``MPY_CROSS_FLAGS`` Makefile variable for the
|
||||
port that you are using.
|
||||
|
||||
The following table shows the correspondence between MicroPython release
|
||||
and .mpy version.
|
||||
|
||||
=================== ============
|
||||
MicroPython release .mpy version
|
||||
=================== ============
|
||||
v1.19 and up 6
|
||||
v1.12 - v1.18 5
|
||||
v1.11 4
|
||||
v1.9.3 - v1.10 3
|
||||
v1.9 - v1.9.2 2
|
||||
v1.5.1 - v1.8.7 0
|
||||
=================== ============
|
||||
|
||||
For completeness, the next table shows the Git commit of the main
|
||||
MicroPython repository at which the .mpy version was changed.
|
||||
|
||||
=================== ========================================
|
||||
.mpy version change Git commit
|
||||
=================== ========================================
|
||||
5 to 6 f2040bfc7ee033e48acef9f289790f3b4e6b74e5
|
||||
4 to 5 5716c5cf65e9b2cb46c2906f40302401bdd27517
|
||||
3 to 4 9a5f92ea72754c01cc03e5efcdfe94021120531e
|
||||
2 to 3 ff93fd4f50321c6190e1659b19e64fef3045a484
|
||||
1 to 2 dd11af209d226b7d18d5148b239662e30ed60bad
|
||||
0 to 1 6a11048af1d01c78bdacddadd1b72dc7ba7c6478
|
||||
initial version 0 d8c834c95d506db979ec871417de90b7951edc30
|
||||
=================== ========================================
|
||||
|
||||
Binary encoding of .mpy files
|
||||
-----------------------------
|
||||
|
||||
MicroPython .mpy files are a binary container format with code objects (bytecode
|
||||
and native machine code) stored internally in a nested hierarchy. The code for
|
||||
the outer module is stored first, and then its children follow. Each child may
|
||||
have further children, for example in the case of a class having methods, or a
|
||||
function defining a lambda or comprehension. To keep files small while still
|
||||
providing a large range of possible values it uses the concept of a
|
||||
variably-encoded-unsigned-integer (vuint) in many places. Similar to utf-8
|
||||
encoding, this encoding stores 7 bits per byte with the 8th bit (MSB) set
|
||||
if one or more bytes follow. The bits of the unsigned integer are stored
|
||||
in the vuint in LSB form.
|
||||
|
||||
The top-level of an .mpy file consists of three parts:
|
||||
|
||||
* The header.
|
||||
|
||||
* The global qstr and constant tables.
|
||||
|
||||
* The raw-code for the outer scope of the module.
|
||||
This outer scope is executed when the .mpy file is imported.
|
||||
|
||||
You can inspect the contents of a .mpy file by using ``mpy-tool.py``, for
|
||||
example (run from the root of the main MicroPython repository)::
|
||||
|
||||
$ ./tools/mpy-tool.py -xd myfile.mpy
|
||||
|
||||
The header
|
||||
~~~~~~~~~~
|
||||
|
||||
The .mpy header is:
|
||||
|
||||
====== ================================
|
||||
size field
|
||||
====== ================================
|
||||
byte value 0x4d (ASCII 'M')
|
||||
byte .mpy version number
|
||||
byte feature flags
|
||||
byte number of bits in a small int
|
||||
====== ================================
|
||||
|
||||
The global qstr and constant tables
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
An .mpy file contains a single qstr table, and a single constant object table.
|
||||
These are global to the .mpy file, they are referenced by all nested raw-code
|
||||
objects. The qstr table maps internal qstr number (internal to the .mpy file)
|
||||
to the resolved qstr number of the runtime that the .mpy file is imported into.
|
||||
This links the .mpy file with the rest of the system that it executes within.
|
||||
The constant object table is populated with references to all constant objects
|
||||
that the .mpy file needs.
|
||||
|
||||
====== ================================
|
||||
size field
|
||||
====== ================================
|
||||
vuint number of qstrs
|
||||
vuint number of constant objects
|
||||
... qstr data
|
||||
... encoded constant objects
|
||||
====== ================================
|
||||
|
||||
Raw code elements
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
A raw-code element contains code, either bytecode or native machine code. Its
|
||||
contents are:
|
||||
|
||||
====== ================================
|
||||
size field
|
||||
====== ================================
|
||||
vuint type, size and whether there are sub-raw-code elements
|
||||
... code (bytecode or machine code)
|
||||
vuint number of sub-raw-code elements (only if non-zero)
|
||||
... sub-raw-code elements
|
||||
====== ================================
|
||||
|
||||
The first vuint in a raw-code element encodes the type of code stored in this
|
||||
element (the two least-significant bits), whether this raw-code has any
|
||||
children (the third least-significant bit), and the length of the code that
|
||||
follows (the amount of RAM to allocate for it).
|
||||
|
||||
Following the vuint comes the code itself. Unless the code type is viper code
|
||||
with relocations, this code is constant data and does not need to be modified.
|
||||
|
||||
If this raw-code has any children (as indicated by a bit in the first vuint),
|
||||
following the code comes a vuint counting the number of sub-raw-code elements.
|
||||
|
||||
Finally any sub-raw-code elements are stored, recursively.
|
@ -94,6 +94,10 @@ MDNS is used to resolve [`circuitpython.local`](http://circuitpython.local) to a
|
||||
hostname of the form `cpy-XXXXXX.local`. The `XXXXXX` is based on network MAC address. The device
|
||||
also provides the MDNS service with service type `_circuitpython` and protocol `_tcp`.
|
||||
|
||||
Since port 80 (or the port assigned to `CIRCUITPY_WEB_API_PORT`) is used for web workflow, the `mdns`
|
||||
[module](https://docs.circuitpython.org/en/latest/shared-bindings/mdns/index.html#mdns.Server.advertise_service)
|
||||
can't advertise an additional service on that port.
|
||||
|
||||
### HTTP
|
||||
The web server is HTTP 1.1 and may use chunked responses so that it doesn't need to precompute
|
||||
content length.
|
||||
|
1
examples/natmod/.gitignore
vendored
1
examples/natmod/.gitignore
vendored
@ -1 +0,0 @@
|
||||
*.mpy
|
@ -1,37 +0,0 @@
|
||||
# Location of top-level MicroPython directory
|
||||
MPY_DIR = ../../..
|
||||
|
||||
# Name of module (different to built-in btree so it can coexist)
|
||||
MOD = btree_$(ARCH)
|
||||
|
||||
# Source files (.c or .py)
|
||||
SRC = btree_c.c btree_py.py
|
||||
|
||||
# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin)
|
||||
ARCH = x64
|
||||
|
||||
BTREE_DIR = $(MPY_DIR)/lib/berkeley-db-1.xx
|
||||
BTREE_DEFS = -D__DBINTERFACE_PRIVATE=1 -Dmpool_error="(void)" -Dabort=abort_ "-Dvirt_fd_t=void*" $(BTREE_DEFS_EXTRA)
|
||||
CFLAGS += -I$(BTREE_DIR)/PORT/include
|
||||
CFLAGS += -Wno-old-style-definition -Wno-sign-compare -Wno-unused-parameter $(BTREE_DEFS)
|
||||
|
||||
SRC += $(addprefix $(realpath $(BTREE_DIR))/,\
|
||||
btree/bt_close.c \
|
||||
btree/bt_conv.c \
|
||||
btree/bt_delete.c \
|
||||
btree/bt_get.c \
|
||||
btree/bt_open.c \
|
||||
btree/bt_overflow.c \
|
||||
btree/bt_page.c \
|
||||
btree/bt_put.c \
|
||||
btree/bt_search.c \
|
||||
btree/bt_seq.c \
|
||||
btree/bt_split.c \
|
||||
btree/bt_utils.c \
|
||||
mpool/mpool.c \
|
||||
)
|
||||
|
||||
include $(MPY_DIR)/py/dynruntime.mk
|
||||
|
||||
# btree needs gnu99 defined
|
||||
CFLAGS += -std=gnu99
|
@ -1,148 +0,0 @@
|
||||
#define MICROPY_PY_BTREE (1)
|
||||
|
||||
#include "py/dynruntime.h"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#if !defined(__linux__)
|
||||
void *memcpy(void *dst, const void *src, size_t n) {
|
||||
return mp_fun_table.memmove_(dst, src, n);
|
||||
}
|
||||
void *memset(void *s, int c, size_t n) {
|
||||
return mp_fun_table.memset_(s, c, n);
|
||||
}
|
||||
#endif
|
||||
|
||||
void *memmove(void *dest, const void *src, size_t n) {
|
||||
return mp_fun_table.memmove_(dest, src, n);
|
||||
}
|
||||
|
||||
void *malloc(size_t n) {
|
||||
void *ptr = m_malloc(n, false);
|
||||
return ptr;
|
||||
}
|
||||
void *realloc(void *ptr, size_t n) {
|
||||
mp_printf(&mp_plat_print, "UNDEF %d\n", __LINE__);
|
||||
return NULL;
|
||||
}
|
||||
void *calloc(size_t n, size_t m) {
|
||||
void *ptr = m_malloc(n * m, false);
|
||||
// memory already cleared by conservative GC
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void free(void *ptr) {
|
||||
m_free(ptr);
|
||||
}
|
||||
|
||||
void abort_(void) {
|
||||
nlr_raise(mp_obj_new_exception(mp_load_global(MP_QSTR_RuntimeError)));
|
||||
}
|
||||
|
||||
int native_errno;
|
||||
#if defined(__linux__)
|
||||
int *__errno_location (void)
|
||||
#else
|
||||
int *__errno (void)
|
||||
#endif
|
||||
{
|
||||
return &native_errno;
|
||||
}
|
||||
|
||||
ssize_t mp_stream_posix_write(void *stream, const void *buf, size_t len) {
|
||||
mp_obj_base_t* o = stream;
|
||||
const mp_stream_p_t *stream_p = o->type->ext[0].protocol;
|
||||
mp_uint_t out_sz = stream_p->write(MP_OBJ_FROM_PTR(stream), buf, len, &native_errno);
|
||||
if (out_sz == MP_STREAM_ERROR) {
|
||||
return -1;
|
||||
} else {
|
||||
return out_sz;
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t mp_stream_posix_read(void *stream, void *buf, size_t len) {
|
||||
mp_obj_base_t* o = stream;
|
||||
const mp_stream_p_t *stream_p = o->type->ext[0].protocol;
|
||||
mp_uint_t out_sz = stream_p->read(MP_OBJ_FROM_PTR(stream), buf, len, &native_errno);
|
||||
if (out_sz == MP_STREAM_ERROR) {
|
||||
return -1;
|
||||
} else {
|
||||
return out_sz;
|
||||
}
|
||||
}
|
||||
|
||||
off_t mp_stream_posix_lseek(void *stream, off_t offset, int whence) {
|
||||
const mp_obj_base_t* o = stream;
|
||||
const mp_stream_p_t *stream_p = o->type->ext[0].protocol;
|
||||
struct mp_stream_seek_t seek_s;
|
||||
seek_s.offset = offset;
|
||||
seek_s.whence = whence;
|
||||
mp_uint_t res = stream_p->ioctl(MP_OBJ_FROM_PTR(stream), MP_STREAM_SEEK, (mp_uint_t)(uintptr_t)&seek_s, &native_errno);
|
||||
if (res == MP_STREAM_ERROR) {
|
||||
return -1;
|
||||
}
|
||||
return seek_s.offset;
|
||||
}
|
||||
|
||||
int mp_stream_posix_fsync(void *stream) {
|
||||
mp_obj_base_t* o = stream;
|
||||
const mp_stream_p_t *stream_p = o->type->ext[0].protocol;
|
||||
mp_uint_t res = stream_p->ioctl(MP_OBJ_FROM_PTR(stream), MP_STREAM_FLUSH, 0, &native_errno);
|
||||
if (res == MP_STREAM_ERROR) {
|
||||
return -1;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
mp_obj_full_type_t btree_type;
|
||||
|
||||
#include "extmod/modbtree.c"
|
||||
|
||||
mp_map_elem_t btree_locals_dict_table[8];
|
||||
STATIC MP_DEFINE_CONST_DICT(btree_locals_dict, btree_locals_dict_table);
|
||||
|
||||
STATIC mp_obj_t btree_open(size_t n_args, const mp_obj_t *args) {
|
||||
// Make sure we got a stream object
|
||||
mp_get_stream_raise(args[0], MP_STREAM_OP_READ | MP_STREAM_OP_WRITE | MP_STREAM_OP_IOCTL);
|
||||
|
||||
BTREEINFO openinfo = {0};
|
||||
openinfo.flags = mp_obj_get_int(args[1]);
|
||||
openinfo.cachesize = mp_obj_get_int(args[2]);
|
||||
openinfo.psize = mp_obj_get_int(args[3]);
|
||||
openinfo.minkeypage = mp_obj_get_int(args[4]);
|
||||
DB *db = __bt_open(MP_OBJ_TO_PTR(args[0]), &btree_stream_fvtable, &openinfo, 0);
|
||||
if (db == NULL) {
|
||||
mp_raise_OSError(native_errno);
|
||||
}
|
||||
|
||||
return MP_OBJ_FROM_PTR(btree_new(db, args[0]));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(btree_open_obj, 5, 5, btree_open);
|
||||
|
||||
mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
|
||||
MP_DYNRUNTIME_INIT_ENTRY
|
||||
|
||||
btree_type.base.type = (void*)&mp_fun_table.type_type;
|
||||
btree_type.flags = MP_TYPE_FLAG_EXTENDED;
|
||||
btree_type.name = MP_QSTR_btree;
|
||||
btree_type.print = btree_print;
|
||||
btree_type.ext[0].getiter = btree_getiter;
|
||||
btree_type.ext[0].iternext = btree_iternext;
|
||||
btree_type.ext[0].binary_op = btree_binary_op;
|
||||
btree_type.ext[0].subscr = btree_subscr;
|
||||
btree_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_close), MP_OBJ_FROM_PTR(&btree_close_obj) };
|
||||
btree_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_flush), MP_OBJ_FROM_PTR(&btree_flush_obj) };
|
||||
btree_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_get), MP_OBJ_FROM_PTR(&btree_get_obj) };
|
||||
btree_locals_dict_table[3] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_put), MP_OBJ_FROM_PTR(&btree_put_obj) };
|
||||
btree_locals_dict_table[4] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_seq), MP_OBJ_FROM_PTR(&btree_seq_obj) };
|
||||
btree_locals_dict_table[5] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_keys), MP_OBJ_FROM_PTR(&btree_keys_obj) };
|
||||
btree_locals_dict_table[6] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_values), MP_OBJ_FROM_PTR(&btree_values_obj) };
|
||||
btree_locals_dict_table[7] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_items), MP_OBJ_FROM_PTR(&btree_items_obj) };
|
||||
btree_type.locals_dict = (void*)&btree_locals_dict;
|
||||
|
||||
mp_store_global(MP_QSTR__open, MP_OBJ_FROM_PTR(&btree_open_obj));
|
||||
mp_store_global(MP_QSTR_INCL, MP_OBJ_NEW_SMALL_INT(FLAG_END_KEY_INCL));
|
||||
mp_store_global(MP_QSTR_DESC, MP_OBJ_NEW_SMALL_INT(FLAG_DESC));
|
||||
|
||||
MP_DYNRUNTIME_INIT_EXIT
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
# Implemented in Python to support keyword arguments
|
||||
def open(stream, *, flags=0, cachesize=0, pagesize=0, minkeypage=0):
|
||||
return _open(stream, flags, cachesize, pagesize, minkeypage)
|
@ -1,14 +0,0 @@
|
||||
# Location of top-level MicroPython directory
|
||||
MPY_DIR = ../../..
|
||||
|
||||
# Name of module
|
||||
MOD = features0
|
||||
|
||||
# Source files (.c or .py)
|
||||
SRC = features0.c
|
||||
|
||||
# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin)
|
||||
ARCH = x64
|
||||
|
||||
# Include to get the rules for compiling and linking the module
|
||||
include $(MPY_DIR)/py/dynruntime.mk
|
@ -1,40 +0,0 @@
|
||||
/* This example demonstrates the following features in a native module:
|
||||
- defining a simple function exposed to Python
|
||||
- defining a local, helper C function
|
||||
- getting and creating integer objects
|
||||
*/
|
||||
|
||||
// Include the header file to get access to the MicroPython API
|
||||
#include "py/dynruntime.h"
|
||||
|
||||
// Helper function to compute factorial
|
||||
STATIC mp_int_t factorial_helper(mp_int_t x) {
|
||||
if (x == 0) {
|
||||
return 1;
|
||||
}
|
||||
return x * factorial_helper(x - 1);
|
||||
}
|
||||
|
||||
// This is the function which will be called from Python, as factorial(x)
|
||||
STATIC mp_obj_t factorial(mp_obj_t x_obj) {
|
||||
// Extract the integer from the MicroPython input object
|
||||
mp_int_t x = mp_obj_get_int(x_obj);
|
||||
// Calculate the factorial
|
||||
mp_int_t result = factorial_helper(x);
|
||||
// Convert the result to a MicroPython integer object and return it
|
||||
return mp_obj_new_int(result);
|
||||
}
|
||||
// Define a Python reference to the function above
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(factorial_obj, factorial);
|
||||
|
||||
// This is the entry point and is called when the module is imported
|
||||
mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
|
||||
// This must be first, it sets up the globals dict and other things
|
||||
MP_DYNRUNTIME_INIT_ENTRY
|
||||
|
||||
// Make the function available in the module's namespace
|
||||
mp_store_global(MP_QSTR_factorial, MP_OBJ_FROM_PTR(&factorial_obj));
|
||||
|
||||
// This must be last, it restores the globals dict
|
||||
MP_DYNRUNTIME_INIT_EXIT
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
# Location of top-level MicroPython directory
|
||||
MPY_DIR = ../../..
|
||||
|
||||
# Name of module
|
||||
MOD = features1
|
||||
|
||||
# Source files (.c or .py)
|
||||
SRC = features1.c
|
||||
|
||||
# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin)
|
||||
ARCH = x64
|
||||
|
||||
# Include to get the rules for compiling and linking the module
|
||||
include $(MPY_DIR)/py/dynruntime.mk
|
@ -1,106 +0,0 @@
|
||||
/* This example demonstrates the following features in a native module:
|
||||
- defining simple functions exposed to Python
|
||||
- defining local, helper C functions
|
||||
- defining constant integers and strings exposed to Python
|
||||
- getting and creating integer objects
|
||||
- creating Python lists
|
||||
- raising exceptions
|
||||
- allocating memory
|
||||
- BSS and constant data (rodata)
|
||||
- relocated pointers in rodata
|
||||
*/
|
||||
|
||||
// Include the header file to get access to the MicroPython API
|
||||
#include "py/dynruntime.h"
|
||||
|
||||
// BSS (zero) data
|
||||
uint16_t data16[4];
|
||||
|
||||
// Constant data (rodata)
|
||||
const uint8_t table8[] = { 0, 1, 1, 2, 3, 5, 8, 13 };
|
||||
const uint16_t table16[] = { 0x1000, 0x2000 };
|
||||
|
||||
// Constant data pointing to BSS/constant data
|
||||
uint16_t *const table_ptr16a[] = { &data16[0], &data16[1], &data16[2], &data16[3] };
|
||||
const uint16_t *const table_ptr16b[] = { &table16[0], &table16[1] };
|
||||
|
||||
// A simple function that adds its 2 arguments (must be integers)
|
||||
STATIC mp_obj_t add(mp_obj_t x_in, mp_obj_t y_in) {
|
||||
mp_int_t x = mp_obj_get_int(x_in);
|
||||
mp_int_t y = mp_obj_get_int(y_in);
|
||||
return mp_obj_new_int(x + y);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(add_obj, add);
|
||||
|
||||
// A local helper function (not exposed to Python)
|
||||
STATIC mp_int_t fibonacci_helper(mp_int_t x) {
|
||||
if (x < MP_ARRAY_SIZE(table8)) {
|
||||
return table8[x];
|
||||
} else {
|
||||
return fibonacci_helper(x - 1) + fibonacci_helper(x - 2);
|
||||
}
|
||||
}
|
||||
|
||||
// A function which computes Fibonacci numbers
|
||||
STATIC mp_obj_t fibonacci(mp_obj_t x_in) {
|
||||
mp_int_t x = mp_obj_get_int(x_in);
|
||||
if (x < 0) {
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("can't compute negative Fibonacci number"));
|
||||
}
|
||||
return mp_obj_new_int(fibonacci_helper(x));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(fibonacci_obj, fibonacci);
|
||||
|
||||
// A function that accesses the BSS data
|
||||
STATIC mp_obj_t access(size_t n_args, const mp_obj_t *args) {
|
||||
if (n_args == 0) {
|
||||
// Create a list holding all items from data16
|
||||
mp_obj_list_t *lst = MP_OBJ_TO_PTR(mp_obj_new_list(MP_ARRAY_SIZE(data16), NULL));
|
||||
for (int i = 0; i < MP_ARRAY_SIZE(data16); ++i) {
|
||||
lst->items[i] = mp_obj_new_int(data16[i]);
|
||||
}
|
||||
return MP_OBJ_FROM_PTR(lst);
|
||||
} else if (n_args == 1) {
|
||||
// Get one item from data16
|
||||
mp_int_t idx = mp_obj_get_int(args[0]) & 3;
|
||||
return mp_obj_new_int(data16[idx]);
|
||||
} else {
|
||||
// Set one item in data16 (via table_ptr16a)
|
||||
mp_int_t idx = mp_obj_get_int(args[0]) & 3;
|
||||
*table_ptr16a[idx] = mp_obj_get_int(args[1]);
|
||||
return mp_const_none;
|
||||
}
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(access_obj, 0, 2, access);
|
||||
|
||||
// A function that allocates memory and creates a bytearray
|
||||
STATIC mp_obj_t make_array(void) {
|
||||
uint16_t *ptr = m_new(uint16_t, MP_ARRAY_SIZE(table_ptr16b));
|
||||
for (int i = 0; i < MP_ARRAY_SIZE(table_ptr16b); ++i) {
|
||||
ptr[i] = *table_ptr16b[i];
|
||||
}
|
||||
return mp_obj_new_bytearray_by_ref(sizeof(uint16_t) * MP_ARRAY_SIZE(table_ptr16b), ptr);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(make_array_obj, make_array);
|
||||
|
||||
// This is the entry point and is called when the module is imported
|
||||
mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
|
||||
// This must be first, it sets up the globals dict and other things
|
||||
MP_DYNRUNTIME_INIT_ENTRY
|
||||
|
||||
// Messages can be printed as usually
|
||||
mp_printf(&mp_plat_print, "initialising module self=%p\n", self);
|
||||
|
||||
// Make the functions available in the module's namespace
|
||||
mp_store_global(MP_QSTR_add, MP_OBJ_FROM_PTR(&add_obj));
|
||||
mp_store_global(MP_QSTR_fibonacci, MP_OBJ_FROM_PTR(&fibonacci_obj));
|
||||
mp_store_global(MP_QSTR_access, MP_OBJ_FROM_PTR(&access_obj));
|
||||
mp_store_global(MP_QSTR_make_array, MP_OBJ_FROM_PTR(&make_array_obj));
|
||||
|
||||
// Add some constants to the module's namespace
|
||||
mp_store_global(MP_QSTR_VAL, MP_OBJ_NEW_SMALL_INT(42));
|
||||
mp_store_global(MP_QSTR_MSG, MP_OBJ_NEW_QSTR(MP_QSTR_HELLO_MICROPYTHON));
|
||||
|
||||
// This must be last, it restores the globals dict
|
||||
MP_DYNRUNTIME_INIT_EXIT
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
# Location of top-level MicroPython directory
|
||||
MPY_DIR = ../../..
|
||||
|
||||
# Name of module
|
||||
MOD = features2
|
||||
|
||||
# Source files (.c or .py)
|
||||
SRC = main.c prod.c test.py
|
||||
|
||||
# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin)
|
||||
ARCH = x64
|
||||
|
||||
# Include to get the rules for compiling and linking the module
|
||||
include $(MPY_DIR)/py/dynruntime.mk
|
@ -1,83 +0,0 @@
|
||||
/* This example demonstrates the following features in a native module:
|
||||
- using floats
|
||||
- defining additional code in Python (see test.py)
|
||||
- have extra C code in a separate file (see prod.c)
|
||||
*/
|
||||
|
||||
// Include the header file to get access to the MicroPython API
|
||||
#include "py/dynruntime.h"
|
||||
|
||||
// Include the header for auxiliary C code for this module
|
||||
#include "prod.h"
|
||||
|
||||
// Automatically detect if this module should include double-precision code.
|
||||
// If double precision is supported by the target architecture then it can
|
||||
// be used in native module regardless of what float setting the target
|
||||
// MicroPython runtime uses (being none, float or double).
|
||||
#if defined(__i386__) || defined(__x86_64__) || (defined(__ARM_FP) && (__ARM_FP & 8))
|
||||
#define USE_DOUBLE 1
|
||||
#else
|
||||
#define USE_DOUBLE 0
|
||||
#endif
|
||||
|
||||
// A function that uses the default float type configured for the current target
|
||||
// This default can be overridden by specifying MICROPY_FLOAT_IMPL at the make level
|
||||
STATIC mp_obj_t add(mp_obj_t x, mp_obj_t y) {
|
||||
return mp_obj_new_float(mp_obj_get_float(x) + mp_obj_get_float(y));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(add_obj, add);
|
||||
|
||||
// A function that explicitly uses single precision floats
|
||||
STATIC mp_obj_t add_f(mp_obj_t x, mp_obj_t y) {
|
||||
return mp_obj_new_float_from_f(mp_obj_get_float_to_f(x) + mp_obj_get_float_to_f(y));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(add_f_obj, add_f);
|
||||
|
||||
#if USE_DOUBLE
|
||||
// A function that explicitly uses double precision floats
|
||||
STATIC mp_obj_t add_d(mp_obj_t x, mp_obj_t y) {
|
||||
return mp_obj_new_float_from_d(mp_obj_get_float_to_d(x) + mp_obj_get_float_to_d(y));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(add_d_obj, add_d);
|
||||
#endif
|
||||
|
||||
// A function that computes the product of floats in an array.
|
||||
// This function uses the most general C argument interface, which is more difficult
|
||||
// to use but has access to the globals dict of the module via self->globals.
|
||||
STATIC mp_obj_t productf(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
|
||||
// Check number of arguments is valid
|
||||
mp_arg_check_num(n_args, n_kw, 1, 1, false);
|
||||
|
||||
// Extract buffer pointer and verify typecode
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_RW);
|
||||
if (bufinfo.typecode != 'f') {
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("expecting float array"));
|
||||
}
|
||||
|
||||
// Compute product, store result back in first element of array
|
||||
float *ptr = bufinfo.buf;
|
||||
float prod = prod_array(bufinfo.len / sizeof(*ptr), ptr);
|
||||
ptr[0] = prod;
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
// This is the entry point and is called when the module is imported
|
||||
mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
|
||||
// This must be first, it sets up the globals dict and other things
|
||||
MP_DYNRUNTIME_INIT_ENTRY
|
||||
|
||||
// Make the functions available in the module's namespace
|
||||
mp_store_global(MP_QSTR_add, MP_OBJ_FROM_PTR(&add_obj));
|
||||
mp_store_global(MP_QSTR_add_f, MP_OBJ_FROM_PTR(&add_f_obj));
|
||||
#if USE_DOUBLE
|
||||
mp_store_global(MP_QSTR_add_d, MP_OBJ_FROM_PTR(&add_d_obj));
|
||||
#endif
|
||||
|
||||
// The productf function uses the most general C argument interface
|
||||
mp_store_global(MP_QSTR_productf, MP_DYNRUNTIME_MAKE_FUNCTION(productf));
|
||||
|
||||
// This must be last, it restores the globals dict
|
||||
MP_DYNRUNTIME_INIT_EXIT
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
#include "prod.h"
|
||||
|
||||
float prod_array(int n, float *ar) {
|
||||
float ans = 1;
|
||||
for (int i = 0; i < n; ++i) {
|
||||
ans *= ar[i];
|
||||
}
|
||||
return ans;
|
||||
}
|
@ -1 +0,0 @@
|
||||
float prod_array(int n, float *ar);
|
@ -1,29 +0,0 @@
|
||||
# This Python code will be merged with the C code in main.c
|
||||
|
||||
import array
|
||||
|
||||
|
||||
def isclose(a, b):
|
||||
return abs(a - b) < 1e-3
|
||||
|
||||
|
||||
def test():
|
||||
tests = [
|
||||
isclose(add(0.1, 0.2), 0.3),
|
||||
isclose(add_f(0.1, 0.2), 0.3),
|
||||
]
|
||||
|
||||
ar = array.array("f", [1, 2, 3.5])
|
||||
productf(ar)
|
||||
tests.append(isclose(ar[0], 7))
|
||||
|
||||
if "add_d" in globals():
|
||||
tests.append(isclose(add_d(0.1, 0.2), 0.3))
|
||||
|
||||
print(tests)
|
||||
|
||||
if not all(tests):
|
||||
raise SystemExit(1)
|
||||
|
||||
|
||||
test()
|
@ -1,13 +0,0 @@
|
||||
# Location of top-level MicroPython directory
|
||||
MPY_DIR = ../../..
|
||||
|
||||
# Name of module (different to built-in framebuf so it can coexist)
|
||||
MOD = framebuf_$(ARCH)
|
||||
|
||||
# Source files (.c or .py)
|
||||
SRC = framebuf.c
|
||||
|
||||
# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin)
|
||||
ARCH = x64
|
||||
|
||||
include $(MPY_DIR)/py/dynruntime.mk
|
@ -1,50 +0,0 @@
|
||||
#define MICROPY_PY_FRAMEBUF (1)
|
||||
|
||||
#include "py/dynruntime.h"
|
||||
|
||||
#if !defined(__linux__)
|
||||
void *memset(void *s, int c, size_t n) {
|
||||
return mp_fun_table.memset_(s, c, n);
|
||||
}
|
||||
#endif
|
||||
|
||||
mp_obj_full_type_t mp_type_framebuf;
|
||||
|
||||
#include "extmod/modframebuf.c"
|
||||
|
||||
mp_map_elem_t framebuf_locals_dict_table[10];
|
||||
STATIC MP_DEFINE_CONST_DICT(framebuf_locals_dict, framebuf_locals_dict_table);
|
||||
|
||||
mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
|
||||
MP_DYNRUNTIME_INIT_ENTRY
|
||||
|
||||
mp_type_framebuf.base.type = (void*)&mp_type_type;
|
||||
mp_type_framebuf.flags = MP_TYPE_FLAG_EXTENDED;
|
||||
mp_type_framebuf.name = MP_QSTR_FrameBuffer;
|
||||
mp_type_framebuf.make_new = framebuf_make_new;
|
||||
mp_type_framebuf.ext[0].buffer_p.get_buffer = framebuf_get_buffer;
|
||||
framebuf_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_fill), MP_OBJ_FROM_PTR(&framebuf_fill_obj) };
|
||||
framebuf_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_fill_rect), MP_OBJ_FROM_PTR(&framebuf_fill_rect_obj) };
|
||||
framebuf_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_pixel), MP_OBJ_FROM_PTR(&framebuf_pixel_obj) };
|
||||
framebuf_locals_dict_table[3] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_hline), MP_OBJ_FROM_PTR(&framebuf_hline_obj) };
|
||||
framebuf_locals_dict_table[4] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_vline), MP_OBJ_FROM_PTR(&framebuf_vline_obj) };
|
||||
framebuf_locals_dict_table[5] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_rect), MP_OBJ_FROM_PTR(&framebuf_rect_obj) };
|
||||
framebuf_locals_dict_table[6] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_line), MP_OBJ_FROM_PTR(&framebuf_line_obj) };
|
||||
framebuf_locals_dict_table[7] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_blit), MP_OBJ_FROM_PTR(&framebuf_blit_obj) };
|
||||
framebuf_locals_dict_table[8] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_scroll), MP_OBJ_FROM_PTR(&framebuf_scroll_obj) };
|
||||
framebuf_locals_dict_table[9] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_text), MP_OBJ_FROM_PTR(&framebuf_text_obj) };
|
||||
mp_type_framebuf.locals_dict = (void*)&framebuf_locals_dict;
|
||||
|
||||
mp_store_global(MP_QSTR_FrameBuffer, MP_OBJ_FROM_PTR(&mp_type_framebuf));
|
||||
mp_store_global(MP_QSTR_FrameBuffer1, MP_OBJ_FROM_PTR(&legacy_framebuffer1_obj));
|
||||
mp_store_global(MP_QSTR_MVLSB, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_MVLSB));
|
||||
mp_store_global(MP_QSTR_MONO_VLSB, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_MVLSB));
|
||||
mp_store_global(MP_QSTR_RGB565, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_RGB565));
|
||||
mp_store_global(MP_QSTR_GS2_HMSB, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_GS2_HMSB));
|
||||
mp_store_global(MP_QSTR_GS4_HMSB, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_GS4_HMSB));
|
||||
mp_store_global(MP_QSTR_GS8, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_GS8));
|
||||
mp_store_global(MP_QSTR_MONO_HLSB, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_MHLSB));
|
||||
mp_store_global(MP_QSTR_MONO_HMSB, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_MHMSB));
|
||||
|
||||
MP_DYNRUNTIME_INIT_EXIT
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
# Location of top-level MicroPython directory
|
||||
MPY_DIR = ../../..
|
||||
|
||||
# Name of module (different to built-in uheapq so it can coexist)
|
||||
MOD = uheapq_$(ARCH)
|
||||
|
||||
# Source files (.c or .py)
|
||||
SRC = uheapq.c
|
||||
|
||||
# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin)
|
||||
ARCH = x64
|
||||
|
||||
include $(MPY_DIR)/py/dynruntime.mk
|
@ -1,16 +0,0 @@
|
||||
#define MICROPY_PY_UHEAPQ (1)
|
||||
|
||||
#include "py/dynruntime.h"
|
||||
|
||||
#include "extmod/moduheapq.c"
|
||||
|
||||
mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
|
||||
MP_DYNRUNTIME_INIT_ENTRY
|
||||
|
||||
mp_store_global(MP_QSTR___name__, MP_OBJ_NEW_QSTR(MP_QSTR_uheapq));
|
||||
mp_store_global(MP_QSTR_heappush, MP_OBJ_FROM_PTR(&mod_uheapq_heappush_obj));
|
||||
mp_store_global(MP_QSTR_heappop, MP_OBJ_FROM_PTR(&mod_uheapq_heappop_obj));
|
||||
mp_store_global(MP_QSTR_heapify, MP_OBJ_FROM_PTR(&mod_uheapq_heapify_obj));
|
||||
|
||||
MP_DYNRUNTIME_INIT_EXIT
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
# Location of top-level MicroPython directory
|
||||
MPY_DIR = ../../..
|
||||
|
||||
# Name of module (different to built-in urandom so it can coexist)
|
||||
MOD = urandom_$(ARCH)
|
||||
|
||||
# Source files (.c or .py)
|
||||
SRC = urandom.c
|
||||
|
||||
# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin)
|
||||
ARCH = x64
|
||||
|
||||
include $(MPY_DIR)/py/dynruntime.mk
|
@ -1,33 +0,0 @@
|
||||
#define MICROPY_PY_URANDOM (1)
|
||||
#define MICROPY_PY_URANDOM_EXTRA_FUNCS (1)
|
||||
|
||||
#include "py/dynruntime.h"
|
||||
|
||||
// Dynamic native modules don't support a data section so these must go in the BSS
|
||||
uint32_t yasmarang_pad, yasmarang_n, yasmarang_d;
|
||||
uint8_t yasmarang_dat;
|
||||
|
||||
#include "extmod/modurandom.c"
|
||||
|
||||
mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
|
||||
MP_DYNRUNTIME_INIT_ENTRY
|
||||
|
||||
yasmarang_pad = 0xeda4baba;
|
||||
yasmarang_n = 69;
|
||||
yasmarang_d = 233;
|
||||
|
||||
mp_store_global(MP_QSTR___name__, MP_OBJ_NEW_QSTR(MP_QSTR_urandom));
|
||||
mp_store_global(MP_QSTR_getrandbits, MP_OBJ_FROM_PTR(&mod_urandom_getrandbits_obj));
|
||||
mp_store_global(MP_QSTR_seed, MP_OBJ_FROM_PTR(&mod_urandom_seed_obj));
|
||||
#if MICROPY_PY_URANDOM_EXTRA_FUNCS
|
||||
mp_store_global(MP_QSTR_randrange, MP_OBJ_FROM_PTR(&mod_urandom_randrange_obj));
|
||||
mp_store_global(MP_QSTR_randint, MP_OBJ_FROM_PTR(&mod_urandom_randint_obj));
|
||||
mp_store_global(MP_QSTR_choice, MP_OBJ_FROM_PTR(&mod_urandom_choice_obj));
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
mp_store_global(MP_QSTR_random, MP_OBJ_FROM_PTR(&mod_urandom_random_obj));
|
||||
mp_store_global(MP_QSTR_uniform, MP_OBJ_FROM_PTR(&mod_urandom_uniform_obj));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
MP_DYNRUNTIME_INIT_EXIT
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
# Location of top-level MicroPython directory
|
||||
MPY_DIR = ../../..
|
||||
|
||||
# Name of module (different to built-in ure so it can coexist)
|
||||
MOD = ure_$(ARCH)
|
||||
|
||||
# Source files (.c or .py)
|
||||
SRC = ure.c
|
||||
|
||||
# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin)
|
||||
ARCH = x64
|
||||
|
||||
include $(MPY_DIR)/py/dynruntime.mk
|
@ -1,78 +0,0 @@
|
||||
#define MICROPY_STACK_CHECK (1)
|
||||
#define MICROPY_PY_URE (1)
|
||||
#define MICROPY_PY_URE_MATCH_GROUPS (1)
|
||||
#define MICROPY_PY_URE_MATCH_SPAN_START_END (1)
|
||||
#define MICROPY_PY_URE_SUB (0) // requires vstr interface
|
||||
|
||||
#include <alloca.h>
|
||||
#include "py/dynruntime.h"
|
||||
|
||||
#define STACK_LIMIT (2048)
|
||||
|
||||
const char *stack_top;
|
||||
|
||||
void mp_stack_check(void) {
|
||||
// Assumes descending stack on target
|
||||
volatile char dummy;
|
||||
if (stack_top - &dummy >= STACK_LIMIT) {
|
||||
mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("maximum recursion depth exceeded"));
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(__linux__)
|
||||
void *memcpy(void *dst, const void *src, size_t n) {
|
||||
return mp_fun_table.memmove_(dst, src, n);
|
||||
}
|
||||
void *memset(void *s, int c, size_t n) {
|
||||
return mp_fun_table.memset_(s, c, n);
|
||||
}
|
||||
#endif
|
||||
|
||||
void *memmove(void *dest, const void *src, size_t n) {
|
||||
return mp_fun_table.memmove_(dest, src, n);
|
||||
}
|
||||
|
||||
mp_obj_type_t match_type;
|
||||
mp_obj_type_t re_type;
|
||||
|
||||
#include "extmod/modure.c"
|
||||
|
||||
mp_map_elem_t match_locals_dict_table[5];
|
||||
STATIC MP_DEFINE_CONST_DICT(match_locals_dict, match_locals_dict_table);
|
||||
|
||||
mp_map_elem_t re_locals_dict_table[3];
|
||||
STATIC MP_DEFINE_CONST_DICT(re_locals_dict, re_locals_dict_table);
|
||||
|
||||
mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
|
||||
MP_DYNRUNTIME_INIT_ENTRY
|
||||
|
||||
char dummy;
|
||||
stack_top = &dummy;
|
||||
|
||||
// Because MP_QSTR_start/end/split are static, xtensa and xtensawin will make a small data section
|
||||
// to copy in this key/value pair if they are specified as a struct, so assign them separately.
|
||||
|
||||
match_type.base.type = (void*)&mp_fun_table.type_type;
|
||||
match_type.name = MP_QSTR_match;
|
||||
match_type.print = match_print;
|
||||
match_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_group), MP_OBJ_FROM_PTR(&match_group_obj) };
|
||||
match_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_groups), MP_OBJ_FROM_PTR(&match_groups_obj) };
|
||||
match_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_span), MP_OBJ_FROM_PTR(&match_span_obj) };
|
||||
match_locals_dict_table[3] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_start), MP_OBJ_FROM_PTR(&match_start_obj) };
|
||||
match_locals_dict_table[4] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_end), MP_OBJ_FROM_PTR(&match_end_obj) };
|
||||
match_type.locals_dict = (void*)&match_locals_dict;
|
||||
|
||||
re_type.base.type = (void*)&mp_fun_table.type_type;
|
||||
re_type.name = MP_QSTR_ure;
|
||||
re_type.print = re_print;
|
||||
re_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_match), MP_OBJ_FROM_PTR(&re_match_obj) };
|
||||
re_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_search), MP_OBJ_FROM_PTR(&re_search_obj) };
|
||||
re_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_split), MP_OBJ_FROM_PTR(&re_split_obj) };
|
||||
re_type.locals_dict = (void*)&re_locals_dict;
|
||||
|
||||
mp_store_global(MP_QSTR_compile, MP_OBJ_FROM_PTR(&mod_re_compile_obj));
|
||||
mp_store_global(MP_QSTR_match, MP_OBJ_FROM_PTR(&re_match_obj));
|
||||
mp_store_global(MP_QSTR_search, MP_OBJ_FROM_PTR(&re_search_obj));
|
||||
|
||||
MP_DYNRUNTIME_INIT_EXIT
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
# Location of top-level MicroPython directory
|
||||
MPY_DIR = ../../..
|
||||
|
||||
# Name of module (different to built-in uzlib so it can coexist)
|
||||
MOD = uzlib_$(ARCH)
|
||||
|
||||
# Source files (.c or .py)
|
||||
SRC = uzlib.c
|
||||
|
||||
# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin)
|
||||
ARCH = x64
|
||||
|
||||
include $(MPY_DIR)/py/dynruntime.mk
|
@ -1,40 +0,0 @@
|
||||
#define MICROPY_PY_UZLIB (1)
|
||||
|
||||
#include "py/dynruntime.h"
|
||||
|
||||
#if !defined(__linux__)
|
||||
void *memset(void *s, int c, size_t n) {
|
||||
return mp_fun_table.memset_(s, c, n);
|
||||
}
|
||||
#endif
|
||||
|
||||
mp_obj_full_type_t decompio_type;
|
||||
mp_stream_p_t decompio_stream_p;
|
||||
|
||||
#include "extmod/moduzlib.c"
|
||||
|
||||
mp_map_elem_t decompio_locals_dict_table[3];
|
||||
STATIC MP_DEFINE_CONST_DICT(decompio_locals_dict, decompio_locals_dict_table);
|
||||
|
||||
mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
|
||||
MP_DYNRUNTIME_INIT_ENTRY
|
||||
|
||||
decompio_stream_p.name = MP_QSTR_protocol_stream;
|
||||
decompio_stream_p.read = decompio_read;
|
||||
|
||||
decompio_type.base.type = mp_fun_table.type_type;
|
||||
decompio_type.flags = MP_TYPE_FLAG_EXTENDED;
|
||||
decompio_type.name = MP_QSTR_DecompIO;
|
||||
decompio_type.make_new = decompio_make_new;
|
||||
decompio_type.ext[0].protocol = &decompio_stream_p;
|
||||
decompio_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_read), MP_OBJ_FROM_PTR(&mp_stream_read_obj) };
|
||||
decompio_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_readinto), MP_OBJ_FROM_PTR(&mp_stream_readinto_obj) };
|
||||
decompio_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_readline), MP_OBJ_FROM_PTR(&mp_stream_unbuffered_readline_obj) };
|
||||
decompio_type.locals_dict = (void*)&decompio_locals_dict;
|
||||
|
||||
mp_store_global(MP_QSTR___name__, MP_OBJ_NEW_QSTR(MP_QSTR_uzlib));
|
||||
mp_store_global(MP_QSTR_decompress, MP_OBJ_FROM_PTR(&mod_uzlib_decompress_obj));
|
||||
mp_store_global(MP_QSTR_DecompIO, MP_OBJ_FROM_PTR(&decompio_type));
|
||||
|
||||
MP_DYNRUNTIME_INIT_EXIT
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
// Include MicroPython API.
|
||||
#include "py/runtime.h"
|
||||
|
||||
// This is the function which will be called from Python as cexample.add_ints(a, b).
|
||||
STATIC mp_obj_t example_add_ints(mp_obj_t a_obj, mp_obj_t b_obj) {
|
||||
// Extract the ints from the micropython input objects.
|
||||
int a = mp_obj_get_int(a_obj);
|
||||
int b = mp_obj_get_int(b_obj);
|
||||
|
||||
// Calculate the addition and convert to MicroPython object.
|
||||
return mp_obj_new_int(a + b);
|
||||
}
|
||||
// Define a Python reference to the function above.
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(example_add_ints_obj, example_add_ints);
|
||||
|
||||
// Define all properties of the module.
|
||||
// Table entries are key/value pairs of the attribute name (a string)
|
||||
// and the MicroPython object reference.
|
||||
// All identifiers and strings are written as MP_QSTR_xxx and will be
|
||||
// optimized to word-sized integers by the build system (interned strings).
|
||||
STATIC const mp_rom_map_elem_t example_module_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_cexample) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_add_ints), MP_ROM_PTR(&example_add_ints_obj) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(example_module_globals, example_module_globals_table);
|
||||
|
||||
// Define module object.
|
||||
const mp_obj_module_t example_user_cmodule = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t *)&example_module_globals,
|
||||
};
|
||||
|
||||
// Register the module to make it available in Python.
|
||||
// Note: the "1" in the third argument means this module is always enabled.
|
||||
// This "1" can be optionally replaced with a macro like MODULE_CEXAMPLE_ENABLED
|
||||
// which can then be used to conditionally enable this module.
|
||||
MP_REGISTER_MODULE(MP_QSTR_cexample, example_user_cmodule, 1);
|
@ -1,15 +0,0 @@
|
||||
# Create an INTERFACE library for our C module.
|
||||
add_library(usermod_cexample INTERFACE)
|
||||
|
||||
# Add our source files to the lib
|
||||
target_sources(usermod_cexample INTERFACE
|
||||
${CMAKE_CURRENT_LIST_DIR}/examplemodule.c
|
||||
)
|
||||
|
||||
# Add the current directory as an include directory.
|
||||
target_include_directories(usermod_cexample INTERFACE
|
||||
${CMAKE_CURRENT_LIST_DIR}
|
||||
)
|
||||
|
||||
# Link our INTERFACE library to the usermod target.
|
||||
target_link_libraries(usermod INTERFACE usermod_cexample)
|
@ -1,9 +0,0 @@
|
||||
EXAMPLE_MOD_DIR := $(USERMOD_DIR)
|
||||
|
||||
# Add all C files to SRC_USERMOD.
|
||||
SRC_USERMOD += $(EXAMPLE_MOD_DIR)/examplemodule.c
|
||||
|
||||
# We can add our module folder to include paths if needed
|
||||
# This is not actually needed in this example.
|
||||
CFLAGS_USERMOD += -I$(EXAMPLE_MOD_DIR)
|
||||
CEXAMPLE_MOD_DIR := $(USERMOD_DIR)
|
@ -1,17 +0,0 @@
|
||||
extern "C" {
|
||||
#include <examplemodule.h>
|
||||
|
||||
// Here we implement the function using C++ code, but since it's
|
||||
// declaration has to be compatible with C everything goes in extern "C" scope.
|
||||
mp_obj_t cppfunc(mp_obj_t a_obj, mp_obj_t b_obj) {
|
||||
// Prove we have (at least) C++11 features.
|
||||
const auto a = mp_obj_get_int(a_obj);
|
||||
const auto b = mp_obj_get_int(b_obj);
|
||||
const auto sum = [&]() {
|
||||
return mp_obj_new_int(a + b);
|
||||
} ();
|
||||
// Prove we're being scanned for QSTRs.
|
||||
mp_obj_t tup[] = {sum, MP_ROM_QSTR(MP_QSTR_hellocpp)};
|
||||
return mp_obj_new_tuple(2, tup);
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
#include <examplemodule.h>
|
||||
|
||||
// Define a Python reference to the function we'll make available.
|
||||
// See example.cpp for the definition.
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(cppfunc_obj, cppfunc);
|
||||
|
||||
// Define all properties of the module.
|
||||
// Table entries are key/value pairs of the attribute name (a string)
|
||||
// and the MicroPython object reference.
|
||||
// All identifiers and strings are written as MP_QSTR_xxx and will be
|
||||
// optimized to word-sized integers by the build system (interned strings).
|
||||
STATIC const mp_rom_map_elem_t cppexample_module_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_cppexample) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_cppfunc), MP_ROM_PTR(&cppfunc_obj) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(cppexample_module_globals, cppexample_module_globals_table);
|
||||
|
||||
// Define module object.
|
||||
const mp_obj_module_t cppexample_user_cmodule = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t *)&cppexample_module_globals,
|
||||
};
|
||||
|
||||
// Register the module to make it available in Python.
|
||||
// Note: the "1" in the third argument means this module is always enabled.
|
||||
// This "1" can be optionally replaced with a macro like MODULE_CPPEXAMPLE_ENABLED
|
||||
// which can then be used to conditionally enable this module.
|
||||
MP_REGISTER_MODULE(MP_QSTR_cppexample, cppexample_user_cmodule, 1);
|
@ -1,5 +0,0 @@
|
||||
// Include MicroPython API.
|
||||
#include "py/runtime.h"
|
||||
|
||||
// Declare the function we'll make available in Python as cppexample.cppfunc().
|
||||
extern mp_obj_t cppfunc(mp_obj_t a_obj, mp_obj_t b_obj);
|
@ -1,16 +0,0 @@
|
||||
# Create an INTERFACE library for our CPP module.
|
||||
add_library(usermod_cppexample INTERFACE)
|
||||
|
||||
# Add our source files to the library.
|
||||
target_sources(usermod_cppexample INTERFACE
|
||||
${CMAKE_CURRENT_LIST_DIR}/example.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/examplemodule.c
|
||||
)
|
||||
|
||||
# Add the current directory as an include directory.
|
||||
target_include_directories(usermod_cppexample INTERFACE
|
||||
${CMAKE_CURRENT_LIST_DIR}
|
||||
)
|
||||
|
||||
# Link our INTERFACE library to the usermod target.
|
||||
target_link_libraries(usermod INTERFACE usermod_cppexample)
|
@ -1,12 +0,0 @@
|
||||
CPPEXAMPLE_MOD_DIR := $(USERMOD_DIR)
|
||||
|
||||
# Add our source files to the respective variables.
|
||||
SRC_USERMOD += $(CPPEXAMPLE_MOD_DIR)/examplemodule.c
|
||||
SRC_USERMOD_CXX += $(CPPEXAMPLE_MOD_DIR)/example.cpp
|
||||
|
||||
# Add our module directory to the include path.
|
||||
CFLAGS_USERMOD += -I$(CPPEXAMPLE_MOD_DIR)
|
||||
CXXFLAGS_USERMOD += -I$(CPPEXAMPLE_MOD_DIR)
|
||||
|
||||
# We use C++ features so have to link against the standard library.
|
||||
LDFLAGS_USERMOD += -lstdc++
|
@ -1,10 +0,0 @@
|
||||
# This top-level micropython.cmake is responsible for listing
|
||||
# the individual modules we want to include.
|
||||
# Paths are absolute, and ${CMAKE_CURRENT_LIST_DIR} can be
|
||||
# used to prefix subdirectories.
|
||||
|
||||
# Add the C example.
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/cexample/micropython.cmake)
|
||||
|
||||
# Add the CPP example.
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/cppexample/micropython.cmake)
|
@ -26,7 +26,11 @@
|
||||
#ifndef AXTLS_OS_PORT_H
|
||||
#define AXTLS_OS_PORT_H
|
||||
|
||||
#ifndef __ets__
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#include <sys/time.h>
|
||||
#include "py/stream.h"
|
||||
#include "lib/crypto-algorithms/sha256.h"
|
||||
|
||||
|
@ -1,98 +0,0 @@
|
||||
# CMake fragment for MicroPython extmod component
|
||||
|
||||
set(MICROPY_EXTMOD_DIR "${MICROPY_DIR}/extmod")
|
||||
set(MICROPY_OOFATFS_DIR "${MICROPY_DIR}/lib/oofatfs")
|
||||
|
||||
set(MICROPY_SOURCE_EXTMOD
|
||||
${MICROPY_DIR}/shared/libc/abort_.c
|
||||
${MICROPY_DIR}/shared/libc/printf.c
|
||||
${MICROPY_EXTMOD_DIR}/machine_bitstream.c
|
||||
${MICROPY_EXTMOD_DIR}/machine_i2c.c
|
||||
${MICROPY_EXTMOD_DIR}/machine_mem.c
|
||||
${MICROPY_EXTMOD_DIR}/machine_pulse.c
|
||||
${MICROPY_EXTMOD_DIR}/machine_pwm.c
|
||||
${MICROPY_EXTMOD_DIR}/machine_signal.c
|
||||
${MICROPY_EXTMOD_DIR}/machine_spi.c
|
||||
${MICROPY_EXTMOD_DIR}/modbluetooth.c
|
||||
${MICROPY_EXTMOD_DIR}/modbtree.c
|
||||
${MICROPY_EXTMOD_DIR}/modframebuf.c
|
||||
${MICROPY_EXTMOD_DIR}/modnetwork.c
|
||||
${MICROPY_EXTMOD_DIR}/modonewire.c
|
||||
${MICROPY_EXTMOD_DIR}/moduasyncio.c
|
||||
${MICROPY_EXTMOD_DIR}/modubinascii.c
|
||||
${MICROPY_EXTMOD_DIR}/moducryptolib.c
|
||||
${MICROPY_EXTMOD_DIR}/moductypes.c
|
||||
${MICROPY_EXTMOD_DIR}/moduhashlib.c
|
||||
${MICROPY_EXTMOD_DIR}/moduheapq.c
|
||||
${MICROPY_EXTMOD_DIR}/modujson.c
|
||||
${MICROPY_EXTMOD_DIR}/moduplatform.c
|
||||
${MICROPY_EXTMOD_DIR}/modurandom.c
|
||||
${MICROPY_EXTMOD_DIR}/modure.c
|
||||
${MICROPY_EXTMOD_DIR}/moduselect.c
|
||||
${MICROPY_EXTMOD_DIR}/modusocket.c
|
||||
${MICROPY_EXTMOD_DIR}/modussl_axtls.c
|
||||
${MICROPY_EXTMOD_DIR}/modussl_mbedtls.c
|
||||
${MICROPY_EXTMOD_DIR}/modutimeq.c
|
||||
${MICROPY_EXTMOD_DIR}/moduwebsocket.c
|
||||
${MICROPY_EXTMOD_DIR}/moduzlib.c
|
||||
${MICROPY_EXTMOD_DIR}/modwebrepl.c
|
||||
${MICROPY_EXTMOD_DIR}/uos_dupterm.c
|
||||
${MICROPY_EXTMOD_DIR}/utime_mphal.c
|
||||
${MICROPY_EXTMOD_DIR}/vfs.c
|
||||
${MICROPY_EXTMOD_DIR}/vfs_blockdev.c
|
||||
${MICROPY_EXTMOD_DIR}/vfs_fat.c
|
||||
${MICROPY_EXTMOD_DIR}/vfs_fat_diskio.c
|
||||
${MICROPY_EXTMOD_DIR}/vfs_fat_file.c
|
||||
${MICROPY_EXTMOD_DIR}/vfs_lfs.c
|
||||
${MICROPY_EXTMOD_DIR}/vfs_posix.c
|
||||
${MICROPY_EXTMOD_DIR}/vfs_posix_file.c
|
||||
${MICROPY_EXTMOD_DIR}/vfs_reader.c
|
||||
${MICROPY_EXTMOD_DIR}/virtpin.c
|
||||
${MICROPY_EXTMOD_DIR}/nimble/modbluetooth_nimble.c
|
||||
)
|
||||
|
||||
# Library for btree module and associated code
|
||||
|
||||
set(MICROPY_LIB_BERKELEY_DIR "${MICROPY_DIR}/lib/berkeley-db-1.xx")
|
||||
|
||||
if(EXISTS "${MICROPY_LIB_BERKELEY_DIR}/btree/bt_close.c")
|
||||
add_library(micropy_extmod_btree OBJECT
|
||||
${MICROPY_LIB_BERKELEY_DIR}/btree/bt_close.c
|
||||
${MICROPY_LIB_BERKELEY_DIR}/btree/bt_conv.c
|
||||
${MICROPY_LIB_BERKELEY_DIR}/btree/bt_debug.c
|
||||
${MICROPY_LIB_BERKELEY_DIR}/btree/bt_delete.c
|
||||
${MICROPY_LIB_BERKELEY_DIR}/btree/bt_get.c
|
||||
${MICROPY_LIB_BERKELEY_DIR}/btree/bt_open.c
|
||||
${MICROPY_LIB_BERKELEY_DIR}/btree/bt_overflow.c
|
||||
${MICROPY_LIB_BERKELEY_DIR}/btree/bt_page.c
|
||||
${MICROPY_LIB_BERKELEY_DIR}/btree/bt_put.c
|
||||
${MICROPY_LIB_BERKELEY_DIR}/btree/bt_search.c
|
||||
${MICROPY_LIB_BERKELEY_DIR}/btree/bt_seq.c
|
||||
${MICROPY_LIB_BERKELEY_DIR}/btree/bt_split.c
|
||||
${MICROPY_LIB_BERKELEY_DIR}/btree/bt_utils.c
|
||||
${MICROPY_LIB_BERKELEY_DIR}/mpool/mpool.c
|
||||
)
|
||||
|
||||
target_include_directories(micropy_extmod_btree PRIVATE
|
||||
${MICROPY_LIB_BERKELEY_DIR}/PORT/include
|
||||
)
|
||||
|
||||
target_compile_definitions(micropy_extmod_btree PRIVATE
|
||||
__DBINTERFACE_PRIVATE=1
|
||||
mpool_error=printf
|
||||
abort=abort_
|
||||
"virt_fd_t=void*"
|
||||
)
|
||||
|
||||
# The include directories and compile definitions below are needed to build
|
||||
# modbtree.c and should be added to the main MicroPython target.
|
||||
|
||||
list(APPEND MICROPY_INC_CORE
|
||||
"${MICROPY_LIB_BERKELEY_DIR}/PORT/include"
|
||||
)
|
||||
|
||||
list(APPEND MICROPY_DEF_CORE
|
||||
__DBINTERFACE_PRIVATE=1
|
||||
"virt_fd_t=void*"
|
||||
)
|
||||
endif()
|
@ -28,8 +28,6 @@ SRC_MOD += $(addprefix $(LITTLEFS_DIR)/,\
|
||||
lfs1.c \
|
||||
lfs1_util.c \
|
||||
)
|
||||
else
|
||||
CFLAGS_MOD += -DMICROPY_VFS_LFS1=0
|
||||
endif
|
||||
|
||||
ifeq ($(MICROPY_VFS_LFS2),1)
|
||||
@ -39,8 +37,6 @@ SRC_MOD += $(addprefix $(LITTLEFS_DIR)/,\
|
||||
lfs2.c \
|
||||
lfs2_util.c \
|
||||
)
|
||||
else
|
||||
CFLAGS_MOD += -DMICROPY_VFS_LFS2=0
|
||||
|
||||
$(BUILD)/$(LITTLEFS_DIR)/lfs2.o: CFLAGS += -Wno-missing-field-initializers
|
||||
endif
|
||||
@ -232,3 +228,4 @@ CFLAGS_MOD += -DMICROPY_PY_BTREE=1
|
||||
$(BUILD)/$(BTREE_DIR)/%.o: CFLAGS += -Wno-old-style-definition -Wno-sign-compare -Wno-unused-parameter $(BTREE_DEFS)
|
||||
$(BUILD)/extmod/modbtree.o: CFLAGS += $(BTREE_DEFS)
|
||||
endif
|
||||
|
||||
|
@ -1,108 +1,128 @@
|
||||
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013, 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.
|
||||
*/
|
||||
#ifndef MICROPY_INCLUDED_STM32_FONT_PETME128_8X8_H
|
||||
#define MICROPY_INCLUDED_STM32_FONT_PETME128_8X8_H
|
||||
|
||||
static const uint8_t font_petme128_8x8[] = {
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 32=
|
||||
0x00,0x00,0x00,0x4f,0x4f,0x00,0x00,0x00, // 33=!
|
||||
0x00,0x07,0x07,0x00,0x00,0x07,0x07,0x00, // 34="
|
||||
0x14,0x7f,0x7f,0x14,0x14,0x7f,0x7f,0x14, // 35=#
|
||||
0x00,0x24,0x2e,0x6b,0x6b,0x3a,0x12,0x00, // 36=$
|
||||
0x00,0x63,0x33,0x18,0x0c,0x66,0x63,0x00, // 37=%
|
||||
0x00,0x32,0x7f,0x4d,0x4d,0x77,0x72,0x50, // 38=&
|
||||
0x00,0x00,0x00,0x04,0x06,0x03,0x01,0x00, // 39='
|
||||
0x00,0x00,0x1c,0x3e,0x63,0x41,0x00,0x00, // 40=(
|
||||
0x00,0x00,0x41,0x63,0x3e,0x1c,0x00,0x00, // 41=)
|
||||
0x08,0x2a,0x3e,0x1c,0x1c,0x3e,0x2a,0x08, // 42=*
|
||||
0x00,0x08,0x08,0x3e,0x3e,0x08,0x08,0x00, // 43=+
|
||||
0x00,0x00,0x80,0xe0,0x60,0x00,0x00,0x00, // 44=,
|
||||
0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x00, // 45=-
|
||||
0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00, // 46=.
|
||||
0x00,0x40,0x60,0x30,0x18,0x0c,0x06,0x02, // 47=/
|
||||
0x00,0x3e,0x7f,0x49,0x45,0x7f,0x3e,0x00, // 48=0
|
||||
0x00,0x40,0x44,0x7f,0x7f,0x40,0x40,0x00, // 49=1
|
||||
0x00,0x62,0x73,0x51,0x49,0x4f,0x46,0x00, // 50=2
|
||||
0x00,0x22,0x63,0x49,0x49,0x7f,0x36,0x00, // 51=3
|
||||
0x00,0x18,0x18,0x14,0x16,0x7f,0x7f,0x10, // 52=4
|
||||
0x00,0x27,0x67,0x45,0x45,0x7d,0x39,0x00, // 53=5
|
||||
0x00,0x3e,0x7f,0x49,0x49,0x7b,0x32,0x00, // 54=6
|
||||
0x00,0x03,0x03,0x79,0x7d,0x07,0x03,0x00, // 55=7
|
||||
0x00,0x36,0x7f,0x49,0x49,0x7f,0x36,0x00, // 56=8
|
||||
0x00,0x26,0x6f,0x49,0x49,0x7f,0x3e,0x00, // 57=9
|
||||
0x00,0x00,0x00,0x24,0x24,0x00,0x00,0x00, // 58=:
|
||||
0x00,0x00,0x80,0xe4,0x64,0x00,0x00,0x00, // 59=;
|
||||
0x00,0x08,0x1c,0x36,0x63,0x41,0x41,0x00, // 60=<
|
||||
0x00,0x14,0x14,0x14,0x14,0x14,0x14,0x00, // 61==
|
||||
0x00,0x41,0x41,0x63,0x36,0x1c,0x08,0x00, // 62=>
|
||||
0x00,0x02,0x03,0x51,0x59,0x0f,0x06,0x00, // 63=?
|
||||
0x00,0x3e,0x7f,0x41,0x4d,0x4f,0x2e,0x00, // 64=@
|
||||
0x00,0x7c,0x7e,0x0b,0x0b,0x7e,0x7c,0x00, // 65=A
|
||||
0x00,0x7f,0x7f,0x49,0x49,0x7f,0x36,0x00, // 66=B
|
||||
0x00,0x3e,0x7f,0x41,0x41,0x63,0x22,0x00, // 67=C
|
||||
0x00,0x7f,0x7f,0x41,0x63,0x3e,0x1c,0x00, // 68=D
|
||||
0x00,0x7f,0x7f,0x49,0x49,0x41,0x41,0x00, // 69=E
|
||||
0x00,0x7f,0x7f,0x09,0x09,0x01,0x01,0x00, // 70=F
|
||||
0x00,0x3e,0x7f,0x41,0x49,0x7b,0x3a,0x00, // 71=G
|
||||
0x00,0x7f,0x7f,0x08,0x08,0x7f,0x7f,0x00, // 72=H
|
||||
0x00,0x00,0x41,0x7f,0x7f,0x41,0x00,0x00, // 73=I
|
||||
0x00,0x20,0x60,0x41,0x7f,0x3f,0x01,0x00, // 74=J
|
||||
0x00,0x7f,0x7f,0x1c,0x36,0x63,0x41,0x00, // 75=K
|
||||
0x00,0x7f,0x7f,0x40,0x40,0x40,0x40,0x00, // 76=L
|
||||
0x00,0x7f,0x7f,0x06,0x0c,0x06,0x7f,0x7f, // 77=M
|
||||
0x00,0x7f,0x7f,0x0e,0x1c,0x7f,0x7f,0x00, // 78=N
|
||||
0x00,0x3e,0x7f,0x41,0x41,0x7f,0x3e,0x00, // 79=O
|
||||
0x00,0x7f,0x7f,0x09,0x09,0x0f,0x06,0x00, // 80=P
|
||||
0x00,0x1e,0x3f,0x21,0x61,0x7f,0x5e,0x00, // 81=Q
|
||||
0x00,0x7f,0x7f,0x19,0x39,0x6f,0x46,0x00, // 82=R
|
||||
0x00,0x26,0x6f,0x49,0x49,0x7b,0x32,0x00, // 83=S
|
||||
0x00,0x01,0x01,0x7f,0x7f,0x01,0x01,0x00, // 84=T
|
||||
0x00,0x3f,0x7f,0x40,0x40,0x7f,0x3f,0x00, // 85=U
|
||||
0x00,0x1f,0x3f,0x60,0x60,0x3f,0x1f,0x00, // 86=V
|
||||
0x00,0x7f,0x7f,0x30,0x18,0x30,0x7f,0x7f, // 87=W
|
||||
0x00,0x63,0x77,0x1c,0x1c,0x77,0x63,0x00, // 88=X
|
||||
0x00,0x07,0x0f,0x78,0x78,0x0f,0x07,0x00, // 89=Y
|
||||
0x00,0x61,0x71,0x59,0x4d,0x47,0x43,0x00, // 90=Z
|
||||
0x00,0x00,0x7f,0x7f,0x41,0x41,0x00,0x00, // 91=[
|
||||
0x00,0x02,0x06,0x0c,0x18,0x30,0x60,0x40, // 92='\'
|
||||
0x00,0x00,0x41,0x41,0x7f,0x7f,0x00,0x00, // 93=]
|
||||
0x00,0x08,0x0c,0x06,0x06,0x0c,0x08,0x00, // 94=^
|
||||
0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, // 95=_
|
||||
0x00,0x00,0x01,0x03,0x06,0x04,0x00,0x00, // 96=`
|
||||
0x00,0x20,0x74,0x54,0x54,0x7c,0x78,0x00, // 97=a
|
||||
0x00,0x7f,0x7f,0x44,0x44,0x7c,0x38,0x00, // 98=b
|
||||
0x00,0x38,0x7c,0x44,0x44,0x6c,0x28,0x00, // 99=c
|
||||
0x00,0x38,0x7c,0x44,0x44,0x7f,0x7f,0x00, // 100=d
|
||||
0x00,0x38,0x7c,0x54,0x54,0x5c,0x58,0x00, // 101=e
|
||||
0x00,0x08,0x7e,0x7f,0x09,0x03,0x02,0x00, // 102=f
|
||||
0x00,0x98,0xbc,0xa4,0xa4,0xfc,0x7c,0x00, // 103=g
|
||||
0x00,0x7f,0x7f,0x04,0x04,0x7c,0x78,0x00, // 104=h
|
||||
0x00,0x00,0x00,0x7d,0x7d,0x00,0x00,0x00, // 105=i
|
||||
0x00,0x40,0xc0,0x80,0x80,0xfd,0x7d,0x00, // 106=j
|
||||
0x00,0x7f,0x7f,0x30,0x38,0x6c,0x44,0x00, // 107=k
|
||||
0x00,0x00,0x41,0x7f,0x7f,0x40,0x00,0x00, // 108=l
|
||||
0x00,0x7c,0x7c,0x18,0x30,0x18,0x7c,0x7c, // 109=m
|
||||
0x00,0x7c,0x7c,0x04,0x04,0x7c,0x78,0x00, // 110=n
|
||||
0x00,0x38,0x7c,0x44,0x44,0x7c,0x38,0x00, // 111=o
|
||||
0x00,0xfc,0xfc,0x24,0x24,0x3c,0x18,0x00, // 112=p
|
||||
0x00,0x18,0x3c,0x24,0x24,0xfc,0xfc,0x00, // 113=q
|
||||
0x00,0x7c,0x7c,0x04,0x04,0x0c,0x08,0x00, // 114=r
|
||||
0x00,0x48,0x5c,0x54,0x54,0x74,0x20,0x00, // 115=s
|
||||
0x04,0x04,0x3f,0x7f,0x44,0x64,0x20,0x00, // 116=t
|
||||
0x00,0x3c,0x7c,0x40,0x40,0x7c,0x3c,0x00, // 117=u
|
||||
0x00,0x1c,0x3c,0x60,0x60,0x3c,0x1c,0x00, // 118=v
|
||||
0x00,0x1c,0x7c,0x30,0x18,0x30,0x7c,0x1c, // 119=w
|
||||
0x00,0x44,0x6c,0x38,0x38,0x6c,0x44,0x00, // 120=x
|
||||
0x00,0x9c,0xbc,0xa0,0xa0,0xfc,0x7c,0x00, // 121=y
|
||||
0x00,0x44,0x64,0x74,0x5c,0x4c,0x44,0x00, // 122=z
|
||||
0x00,0x08,0x08,0x3e,0x77,0x41,0x41,0x00, // 123={
|
||||
0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00, // 124=|
|
||||
0x00,0x41,0x41,0x77,0x3e,0x08,0x08,0x00, // 125=}
|
||||
0x00,0x02,0x03,0x01,0x03,0x02,0x03,0x01, // 126=~
|
||||
0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55, // 127
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 32=
|
||||
0x00, 0x00, 0x00, 0x4f, 0x4f, 0x00, 0x00, 0x00, // 33=!
|
||||
0x00, 0x07, 0x07, 0x00, 0x00, 0x07, 0x07, 0x00, // 34="
|
||||
0x14, 0x7f, 0x7f, 0x14, 0x14, 0x7f, 0x7f, 0x14, // 35=#
|
||||
0x00, 0x24, 0x2e, 0x6b, 0x6b, 0x3a, 0x12, 0x00, // 36=$
|
||||
0x00, 0x63, 0x33, 0x18, 0x0c, 0x66, 0x63, 0x00, // 37=%
|
||||
0x00, 0x32, 0x7f, 0x4d, 0x4d, 0x77, 0x72, 0x50, // 38=&
|
||||
0x00, 0x00, 0x00, 0x04, 0x06, 0x03, 0x01, 0x00, // 39='
|
||||
0x00, 0x00, 0x1c, 0x3e, 0x63, 0x41, 0x00, 0x00, // 40=(
|
||||
0x00, 0x00, 0x41, 0x63, 0x3e, 0x1c, 0x00, 0x00, // 41=)
|
||||
0x08, 0x2a, 0x3e, 0x1c, 0x1c, 0x3e, 0x2a, 0x08, // 42=*
|
||||
0x00, 0x08, 0x08, 0x3e, 0x3e, 0x08, 0x08, 0x00, // 43=+
|
||||
0x00, 0x00, 0x80, 0xe0, 0x60, 0x00, 0x00, 0x00, // 44=,
|
||||
0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, // 45=-
|
||||
0x00, 0x00, 0x00, 0x60, 0x60, 0x00, 0x00, 0x00, // 46=.
|
||||
0x00, 0x40, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x02, // 47=/
|
||||
0x00, 0x3e, 0x7f, 0x49, 0x45, 0x7f, 0x3e, 0x00, // 48=0
|
||||
0x00, 0x40, 0x44, 0x7f, 0x7f, 0x40, 0x40, 0x00, // 49=1
|
||||
0x00, 0x62, 0x73, 0x51, 0x49, 0x4f, 0x46, 0x00, // 50=2
|
||||
0x00, 0x22, 0x63, 0x49, 0x49, 0x7f, 0x36, 0x00, // 51=3
|
||||
0x00, 0x18, 0x18, 0x14, 0x16, 0x7f, 0x7f, 0x10, // 52=4
|
||||
0x00, 0x27, 0x67, 0x45, 0x45, 0x7d, 0x39, 0x00, // 53=5
|
||||
0x00, 0x3e, 0x7f, 0x49, 0x49, 0x7b, 0x32, 0x00, // 54=6
|
||||
0x00, 0x03, 0x03, 0x79, 0x7d, 0x07, 0x03, 0x00, // 55=7
|
||||
0x00, 0x36, 0x7f, 0x49, 0x49, 0x7f, 0x36, 0x00, // 56=8
|
||||
0x00, 0x26, 0x6f, 0x49, 0x49, 0x7f, 0x3e, 0x00, // 57=9
|
||||
0x00, 0x00, 0x00, 0x24, 0x24, 0x00, 0x00, 0x00, // 58=:
|
||||
0x00, 0x00, 0x80, 0xe4, 0x64, 0x00, 0x00, 0x00, // 59=;
|
||||
0x00, 0x08, 0x1c, 0x36, 0x63, 0x41, 0x41, 0x00, // 60=<
|
||||
0x00, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x00, // 61==
|
||||
0x00, 0x41, 0x41, 0x63, 0x36, 0x1c, 0x08, 0x00, // 62=>
|
||||
0x00, 0x02, 0x03, 0x51, 0x59, 0x0f, 0x06, 0x00, // 63=?
|
||||
0x00, 0x3e, 0x7f, 0x41, 0x4d, 0x4f, 0x2e, 0x00, // 64=@
|
||||
0x00, 0x7c, 0x7e, 0x0b, 0x0b, 0x7e, 0x7c, 0x00, // 65=A
|
||||
0x00, 0x7f, 0x7f, 0x49, 0x49, 0x7f, 0x36, 0x00, // 66=B
|
||||
0x00, 0x3e, 0x7f, 0x41, 0x41, 0x63, 0x22, 0x00, // 67=C
|
||||
0x00, 0x7f, 0x7f, 0x41, 0x63, 0x3e, 0x1c, 0x00, // 68=D
|
||||
0x00, 0x7f, 0x7f, 0x49, 0x49, 0x41, 0x41, 0x00, // 69=E
|
||||
0x00, 0x7f, 0x7f, 0x09, 0x09, 0x01, 0x01, 0x00, // 70=F
|
||||
0x00, 0x3e, 0x7f, 0x41, 0x49, 0x7b, 0x3a, 0x00, // 71=G
|
||||
0x00, 0x7f, 0x7f, 0x08, 0x08, 0x7f, 0x7f, 0x00, // 72=H
|
||||
0x00, 0x00, 0x41, 0x7f, 0x7f, 0x41, 0x00, 0x00, // 73=I
|
||||
0x00, 0x20, 0x60, 0x41, 0x7f, 0x3f, 0x01, 0x00, // 74=J
|
||||
0x00, 0x7f, 0x7f, 0x1c, 0x36, 0x63, 0x41, 0x00, // 75=K
|
||||
0x00, 0x7f, 0x7f, 0x40, 0x40, 0x40, 0x40, 0x00, // 76=L
|
||||
0x00, 0x7f, 0x7f, 0x06, 0x0c, 0x06, 0x7f, 0x7f, // 77=M
|
||||
0x00, 0x7f, 0x7f, 0x0e, 0x1c, 0x7f, 0x7f, 0x00, // 78=N
|
||||
0x00, 0x3e, 0x7f, 0x41, 0x41, 0x7f, 0x3e, 0x00, // 79=O
|
||||
0x00, 0x7f, 0x7f, 0x09, 0x09, 0x0f, 0x06, 0x00, // 80=P
|
||||
0x00, 0x1e, 0x3f, 0x21, 0x61, 0x7f, 0x5e, 0x00, // 81=Q
|
||||
0x00, 0x7f, 0x7f, 0x19, 0x39, 0x6f, 0x46, 0x00, // 82=R
|
||||
0x00, 0x26, 0x6f, 0x49, 0x49, 0x7b, 0x32, 0x00, // 83=S
|
||||
0x00, 0x01, 0x01, 0x7f, 0x7f, 0x01, 0x01, 0x00, // 84=T
|
||||
0x00, 0x3f, 0x7f, 0x40, 0x40, 0x7f, 0x3f, 0x00, // 85=U
|
||||
0x00, 0x1f, 0x3f, 0x60, 0x60, 0x3f, 0x1f, 0x00, // 86=V
|
||||
0x00, 0x7f, 0x7f, 0x30, 0x18, 0x30, 0x7f, 0x7f, // 87=W
|
||||
0x00, 0x63, 0x77, 0x1c, 0x1c, 0x77, 0x63, 0x00, // 88=X
|
||||
0x00, 0x07, 0x0f, 0x78, 0x78, 0x0f, 0x07, 0x00, // 89=Y
|
||||
0x00, 0x61, 0x71, 0x59, 0x4d, 0x47, 0x43, 0x00, // 90=Z
|
||||
0x00, 0x00, 0x7f, 0x7f, 0x41, 0x41, 0x00, 0x00, // 91=[
|
||||
0x00, 0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x40, // 92='\'
|
||||
0x00, 0x00, 0x41, 0x41, 0x7f, 0x7f, 0x00, 0x00, // 93=]
|
||||
0x00, 0x08, 0x0c, 0x06, 0x06, 0x0c, 0x08, 0x00, // 94=^
|
||||
0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, // 95=_
|
||||
0x00, 0x00, 0x01, 0x03, 0x06, 0x04, 0x00, 0x00, // 96=`
|
||||
0x00, 0x20, 0x74, 0x54, 0x54, 0x7c, 0x78, 0x00, // 97=a
|
||||
0x00, 0x7f, 0x7f, 0x44, 0x44, 0x7c, 0x38, 0x00, // 98=b
|
||||
0x00, 0x38, 0x7c, 0x44, 0x44, 0x6c, 0x28, 0x00, // 99=c
|
||||
0x00, 0x38, 0x7c, 0x44, 0x44, 0x7f, 0x7f, 0x00, // 100=d
|
||||
0x00, 0x38, 0x7c, 0x54, 0x54, 0x5c, 0x58, 0x00, // 101=e
|
||||
0x00, 0x08, 0x7e, 0x7f, 0x09, 0x03, 0x02, 0x00, // 102=f
|
||||
0x00, 0x98, 0xbc, 0xa4, 0xa4, 0xfc, 0x7c, 0x00, // 103=g
|
||||
0x00, 0x7f, 0x7f, 0x04, 0x04, 0x7c, 0x78, 0x00, // 104=h
|
||||
0x00, 0x00, 0x00, 0x7d, 0x7d, 0x00, 0x00, 0x00, // 105=i
|
||||
0x00, 0x40, 0xc0, 0x80, 0x80, 0xfd, 0x7d, 0x00, // 106=j
|
||||
0x00, 0x7f, 0x7f, 0x30, 0x38, 0x6c, 0x44, 0x00, // 107=k
|
||||
0x00, 0x00, 0x41, 0x7f, 0x7f, 0x40, 0x00, 0x00, // 108=l
|
||||
0x00, 0x7c, 0x7c, 0x18, 0x30, 0x18, 0x7c, 0x7c, // 109=m
|
||||
0x00, 0x7c, 0x7c, 0x04, 0x04, 0x7c, 0x78, 0x00, // 110=n
|
||||
0x00, 0x38, 0x7c, 0x44, 0x44, 0x7c, 0x38, 0x00, // 111=o
|
||||
0x00, 0xfc, 0xfc, 0x24, 0x24, 0x3c, 0x18, 0x00, // 112=p
|
||||
0x00, 0x18, 0x3c, 0x24, 0x24, 0xfc, 0xfc, 0x00, // 113=q
|
||||
0x00, 0x7c, 0x7c, 0x04, 0x04, 0x0c, 0x08, 0x00, // 114=r
|
||||
0x00, 0x48, 0x5c, 0x54, 0x54, 0x74, 0x20, 0x00, // 115=s
|
||||
0x04, 0x04, 0x3f, 0x7f, 0x44, 0x64, 0x20, 0x00, // 116=t
|
||||
0x00, 0x3c, 0x7c, 0x40, 0x40, 0x7c, 0x3c, 0x00, // 117=u
|
||||
0x00, 0x1c, 0x3c, 0x60, 0x60, 0x3c, 0x1c, 0x00, // 118=v
|
||||
0x00, 0x1c, 0x7c, 0x30, 0x18, 0x30, 0x7c, 0x1c, // 119=w
|
||||
0x00, 0x44, 0x6c, 0x38, 0x38, 0x6c, 0x44, 0x00, // 120=x
|
||||
0x00, 0x9c, 0xbc, 0xa0, 0xa0, 0xfc, 0x7c, 0x00, // 121=y
|
||||
0x00, 0x44, 0x64, 0x74, 0x5c, 0x4c, 0x44, 0x00, // 122=z
|
||||
0x00, 0x08, 0x08, 0x3e, 0x77, 0x41, 0x41, 0x00, // 123={
|
||||
0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, // 124=|
|
||||
0x00, 0x41, 0x41, 0x77, 0x3e, 0x08, 0x08, 0x00, // 125=}
|
||||
0x00, 0x02, 0x03, 0x01, 0x03, 0x02, 0x03, 0x01, // 126=~
|
||||
0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, // 127
|
||||
};
|
||||
|
||||
#endif // MICROPY_INCLUDED_STM32_FONT_PETME128_8X8_H
|
||||
|
@ -1,367 +0,0 @@
|
||||
// Copyright (c) 2016 Paul Sokolovsky
|
||||
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h> // for declaration of global errno variable
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "py/stream.h"
|
||||
|
||||
#if MICROPY_PY_BTREE
|
||||
|
||||
#include <db.h>
|
||||
#include <../../btree/btree.h>
|
||||
|
||||
typedef struct _mp_obj_btree_t {
|
||||
mp_obj_base_t base;
|
||||
mp_obj_t stream; // retain a reference to prevent GC from reclaiming it
|
||||
DB *db;
|
||||
mp_obj_t start_key;
|
||||
mp_obj_t end_key;
|
||||
#define FLAG_END_KEY_INCL 1
|
||||
#define FLAG_DESC 2
|
||||
#define FLAG_ITER_TYPE_MASK 0xc0
|
||||
#define FLAG_ITER_KEYS 0x40
|
||||
#define FLAG_ITER_VALUES 0x80
|
||||
#define FLAG_ITER_ITEMS 0xc0
|
||||
byte flags;
|
||||
byte next_flags;
|
||||
} mp_obj_btree_t;
|
||||
|
||||
#if !MICROPY_ENABLE_DYNRUNTIME
|
||||
STATIC const mp_obj_type_t btree_type;
|
||||
#endif
|
||||
|
||||
#define CHECK_ERROR(res) \
|
||||
if (res == RET_ERROR) { \
|
||||
mp_raise_OSError(errno); \
|
||||
}
|
||||
|
||||
void __dbpanic(DB *db) {
|
||||
mp_printf(&mp_plat_print, "__dbpanic(%p)\n", db);
|
||||
}
|
||||
|
||||
STATIC mp_obj_btree_t *btree_new(DB *db, mp_obj_t stream) {
|
||||
mp_obj_btree_t *o = m_new_obj(mp_obj_btree_t);
|
||||
o->base.type = (mp_obj_type_t *)&btree_type;
|
||||
o->stream = stream;
|
||||
o->db = db;
|
||||
o->start_key = mp_const_none;
|
||||
o->end_key = mp_const_none;
|
||||
o->next_flags = 0;
|
||||
return o;
|
||||
}
|
||||
|
||||
STATIC void btree_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
(void)kind;
|
||||
mp_obj_btree_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_printf(print, "<btree %p>", self->db);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t btree_flush(mp_obj_t self_in) {
|
||||
mp_obj_btree_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
return MP_OBJ_NEW_SMALL_INT(__bt_sync(self->db, 0));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(btree_flush_obj, btree_flush);
|
||||
|
||||
STATIC mp_obj_t btree_close(mp_obj_t self_in) {
|
||||
mp_obj_btree_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
return MP_OBJ_NEW_SMALL_INT(__bt_close(self->db));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(btree_close_obj, btree_close);
|
||||
|
||||
STATIC mp_obj_t btree_put(size_t n_args, const mp_obj_t *args) {
|
||||
(void)n_args;
|
||||
mp_obj_btree_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
DBT key, val;
|
||||
key.data = (void *)mp_obj_str_get_data(args[1], &key.size);
|
||||
val.data = (void *)mp_obj_str_get_data(args[2], &val.size);
|
||||
return MP_OBJ_NEW_SMALL_INT(__bt_put(self->db, &key, &val, 0));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(btree_put_obj, 3, 4, btree_put);
|
||||
|
||||
STATIC mp_obj_t btree_get(size_t n_args, const mp_obj_t *args) {
|
||||
mp_obj_btree_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
DBT key, val;
|
||||
key.data = (void *)mp_obj_str_get_data(args[1], &key.size);
|
||||
int res = __bt_get(self->db, &key, &val, 0);
|
||||
if (res == RET_SPECIAL) {
|
||||
if (n_args > 2) {
|
||||
return args[2];
|
||||
} else {
|
||||
return mp_const_none;
|
||||
}
|
||||
}
|
||||
CHECK_ERROR(res);
|
||||
return mp_obj_new_bytes(val.data, val.size);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(btree_get_obj, 2, 3, btree_get);
|
||||
|
||||
STATIC mp_obj_t btree_seq(size_t n_args, const mp_obj_t *args) {
|
||||
mp_obj_btree_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
int flags = MP_OBJ_SMALL_INT_VALUE(args[1]);
|
||||
DBT key, val;
|
||||
if (n_args > 2) {
|
||||
key.data = (void *)mp_obj_str_get_data(args[2], &key.size);
|
||||
}
|
||||
|
||||
int res = __bt_seq(self->db, &key, &val, flags);
|
||||
CHECK_ERROR(res);
|
||||
if (res == RET_SPECIAL) {
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t pair_o = mp_obj_new_tuple(2, NULL);
|
||||
mp_obj_tuple_t *pair = MP_OBJ_TO_PTR(pair_o);
|
||||
pair->items[0] = mp_obj_new_bytes(key.data, key.size);
|
||||
pair->items[1] = mp_obj_new_bytes(val.data, val.size);
|
||||
return pair_o;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(btree_seq_obj, 2, 4, btree_seq);
|
||||
|
||||
STATIC mp_obj_t btree_init_iter(size_t n_args, const mp_obj_t *args, byte type) {
|
||||
mp_obj_btree_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
self->next_flags = type;
|
||||
self->start_key = mp_const_none;
|
||||
self->end_key = mp_const_none;
|
||||
if (n_args > 1) {
|
||||
self->start_key = args[1];
|
||||
if (n_args > 2) {
|
||||
self->end_key = args[2];
|
||||
if (n_args > 3) {
|
||||
self->next_flags = type | MP_OBJ_SMALL_INT_VALUE(args[3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return args[0];
|
||||
}
|
||||
|
||||
STATIC mp_obj_t btree_keys(size_t n_args, const mp_obj_t *args) {
|
||||
return btree_init_iter(n_args, args, FLAG_ITER_KEYS);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(btree_keys_obj, 1, 4, btree_keys);
|
||||
|
||||
STATIC mp_obj_t btree_values(size_t n_args, const mp_obj_t *args) {
|
||||
return btree_init_iter(n_args, args, FLAG_ITER_VALUES);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(btree_values_obj, 1, 4, btree_values);
|
||||
|
||||
STATIC mp_obj_t btree_items(size_t n_args, const mp_obj_t *args) {
|
||||
return btree_init_iter(n_args, args, FLAG_ITER_ITEMS);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(btree_items_obj, 1, 4, btree_items);
|
||||
|
||||
STATIC mp_obj_t btree_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) {
|
||||
(void)iter_buf;
|
||||
mp_obj_btree_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
if (self->next_flags != 0) {
|
||||
// If we're called immediately after keys(), values(), or items(),
|
||||
// use their setup for iteration.
|
||||
self->flags = self->next_flags;
|
||||
self->next_flags = 0;
|
||||
} else {
|
||||
// Otherwise, iterate over all keys.
|
||||
self->flags = FLAG_ITER_KEYS;
|
||||
self->start_key = mp_const_none;
|
||||
self->end_key = mp_const_none;
|
||||
}
|
||||
|
||||
return self_in;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t btree_iternext(mp_obj_t self_in) {
|
||||
mp_obj_btree_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
DBT key, val;
|
||||
int res;
|
||||
bool desc = self->flags & FLAG_DESC;
|
||||
if (self->start_key != MP_OBJ_NULL) {
|
||||
int flags = R_FIRST;
|
||||
if (self->start_key != mp_const_none) {
|
||||
key.data = (void *)mp_obj_str_get_data(self->start_key, &key.size);
|
||||
flags = R_CURSOR;
|
||||
} else if (desc) {
|
||||
flags = R_LAST;
|
||||
}
|
||||
res = __bt_seq(self->db, &key, &val, flags);
|
||||
self->start_key = MP_OBJ_NULL;
|
||||
} else {
|
||||
res = __bt_seq(self->db, &key, &val, desc ? R_PREV : R_NEXT);
|
||||
}
|
||||
|
||||
if (res == RET_SPECIAL) {
|
||||
return MP_OBJ_STOP_ITERATION;
|
||||
}
|
||||
CHECK_ERROR(res);
|
||||
|
||||
if (self->end_key != mp_const_none) {
|
||||
DBT end_key;
|
||||
end_key.data = (void *)mp_obj_str_get_data(self->end_key, &end_key.size);
|
||||
BTREE *t = self->db->internal;
|
||||
int cmp = t->bt_cmp(&key, &end_key);
|
||||
if (desc) {
|
||||
cmp = -cmp;
|
||||
}
|
||||
if (self->flags & FLAG_END_KEY_INCL) {
|
||||
cmp--;
|
||||
}
|
||||
if (cmp >= 0) {
|
||||
self->end_key = MP_OBJ_NULL;
|
||||
return MP_OBJ_STOP_ITERATION;
|
||||
}
|
||||
}
|
||||
|
||||
switch (self->flags & FLAG_ITER_TYPE_MASK) {
|
||||
case FLAG_ITER_KEYS:
|
||||
return mp_obj_new_bytes(key.data, key.size);
|
||||
case FLAG_ITER_VALUES:
|
||||
return mp_obj_new_bytes(val.data, val.size);
|
||||
default: {
|
||||
mp_obj_t pair_o = mp_obj_new_tuple(2, NULL);
|
||||
mp_obj_tuple_t *pair = MP_OBJ_TO_PTR(pair_o);
|
||||
pair->items[0] = mp_obj_new_bytes(key.data, key.size);
|
||||
pair->items[1] = mp_obj_new_bytes(val.data, val.size);
|
||||
return pair_o;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_obj_t btree_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
|
||||
mp_obj_btree_t *self = mp_obj_cast_to_native_base(self_in, &btree_type);
|
||||
if (value == MP_OBJ_NULL) {
|
||||
// delete
|
||||
DBT key;
|
||||
key.data = (void *)mp_obj_str_get_data(index, &key.size);
|
||||
int res = __bt_delete(self->db, &key, 0);
|
||||
if (res == RET_SPECIAL) {
|
||||
mp_raise_type(&mp_type_KeyError);
|
||||
}
|
||||
CHECK_ERROR(res);
|
||||
return mp_const_none;
|
||||
} else if (value == MP_OBJ_SENTINEL) {
|
||||
// load
|
||||
DBT key, val;
|
||||
key.data = (void *)mp_obj_str_get_data(index, &key.size);
|
||||
int res = __bt_get(self->db, &key, &val, 0);
|
||||
if (res == RET_SPECIAL) {
|
||||
mp_raise_type(&mp_type_KeyError);
|
||||
}
|
||||
CHECK_ERROR(res);
|
||||
return mp_obj_new_bytes(val.data, val.size);
|
||||
} else {
|
||||
// store
|
||||
DBT key, val;
|
||||
key.data = (void *)mp_obj_str_get_data(index, &key.size);
|
||||
val.data = (void *)mp_obj_str_get_data(value, &val.size);
|
||||
int res = __bt_put(self->db, &key, &val, 0);
|
||||
CHECK_ERROR(res);
|
||||
return mp_const_none;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_obj_t btree_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
|
||||
mp_obj_btree_t *self = MP_OBJ_TO_PTR(lhs_in);
|
||||
switch (op) {
|
||||
case MP_BINARY_OP_CONTAINS: {
|
||||
DBT key, val;
|
||||
key.data = (void *)mp_obj_str_get_data(rhs_in, &key.size);
|
||||
int res = __bt_get(self->db, &key, &val, 0);
|
||||
CHECK_ERROR(res);
|
||||
return mp_obj_new_bool(res != RET_SPECIAL);
|
||||
}
|
||||
default:
|
||||
// op not supported
|
||||
return MP_OBJ_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#if !MICROPY_ENABLE_DYNRUNTIME
|
||||
STATIC const mp_rom_map_elem_t btree_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&btree_close_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&btree_flush_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_get), MP_ROM_PTR(&btree_get_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_put), MP_ROM_PTR(&btree_put_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_seq), MP_ROM_PTR(&btree_seq_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_keys), MP_ROM_PTR(&btree_keys_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_values), MP_ROM_PTR(&btree_values_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_items), MP_ROM_PTR(&btree_items_obj) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(btree_locals_dict, btree_locals_dict_table);
|
||||
|
||||
STATIC const mp_obj_type_t btree_type = {
|
||||
{ &mp_type_type },
|
||||
// Save on qstr's, reuse same as for module
|
||||
.flags = MP_TYPE_FLAG_EXTENDED,
|
||||
.name = MP_QSTR_btree,
|
||||
.print = btree_print,
|
||||
.locals_dict = (void *)&btree_locals_dict,
|
||||
MP_TYPE_EXTENDED_FIELDS(
|
||||
.getiter = btree_getiter,
|
||||
.iternext = btree_iternext,
|
||||
.binary_op = btree_binary_op,
|
||||
.subscr = btree_subscr,
|
||||
),
|
||||
};
|
||||
#endif
|
||||
|
||||
STATIC const FILEVTABLE btree_stream_fvtable = {
|
||||
mp_stream_posix_read,
|
||||
mp_stream_posix_write,
|
||||
mp_stream_posix_lseek,
|
||||
mp_stream_posix_fsync
|
||||
};
|
||||
|
||||
#if !MICROPY_ENABLE_DYNRUNTIME
|
||||
STATIC mp_obj_t mod_btree_open(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_flags, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_cachesize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_pagesize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_minkeypage, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
|
||||
};
|
||||
|
||||
// Make sure we got a stream object
|
||||
mp_get_stream_raise(pos_args[0], MP_STREAM_OP_READ | MP_STREAM_OP_WRITE | MP_STREAM_OP_IOCTL);
|
||||
|
||||
struct {
|
||||
mp_arg_val_t flags;
|
||||
mp_arg_val_t cachesize;
|
||||
mp_arg_val_t pagesize;
|
||||
mp_arg_val_t minkeypage;
|
||||
} args;
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args,
|
||||
MP_ARRAY_SIZE(allowed_args), allowed_args, (mp_arg_val_t *)&args);
|
||||
BTREEINFO openinfo = {0};
|
||||
openinfo.flags = args.flags.u_int;
|
||||
openinfo.cachesize = args.cachesize.u_int;
|
||||
openinfo.psize = args.pagesize.u_int;
|
||||
openinfo.minkeypage = args.minkeypage.u_int;
|
||||
|
||||
DB *db = __bt_open(MP_OBJ_TO_PTR(pos_args[0]), &btree_stream_fvtable, &openinfo, /*dflags*/ 0);
|
||||
if (db == NULL) {
|
||||
mp_raise_OSError(errno);
|
||||
}
|
||||
return MP_OBJ_FROM_PTR(btree_new(db, pos_args[0]));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_btree_open_obj, 1, mod_btree_open);
|
||||
|
||||
STATIC const mp_rom_map_elem_t mp_module_btree_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_btree) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&mod_btree_open_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_INCL), MP_ROM_INT(FLAG_END_KEY_INCL) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_DESC), MP_ROM_INT(FLAG_DESC) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_btree_globals, mp_module_btree_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_btree = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t *)&mp_module_btree_globals,
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif // MICROPY_PY_BTREE
|
@ -1,667 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2016 Damien P. George
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "py/objtype.h"
|
||||
#include "py/proto.h"
|
||||
|
||||
#if MICROPY_PY_FRAMEBUF
|
||||
|
||||
#include "font_petme128_8x8.h"
|
||||
|
||||
typedef struct _mp_obj_framebuf_t {
|
||||
mp_obj_base_t base;
|
||||
mp_obj_t buf_obj; // need to store this to prevent GC from reclaiming buf
|
||||
void *buf;
|
||||
uint16_t width, height, stride;
|
||||
uint8_t format;
|
||||
} mp_obj_framebuf_t;
|
||||
|
||||
#if !MICROPY_ENABLE_DYNRUNTIME
|
||||
STATIC const mp_obj_type_t mp_type_framebuf;
|
||||
#endif
|
||||
|
||||
typedef void (*setpixel_t)(const mp_obj_framebuf_t *, unsigned int, unsigned int, uint32_t);
|
||||
typedef uint32_t (*getpixel_t)(const mp_obj_framebuf_t *, unsigned int, unsigned int);
|
||||
typedef void (*fill_rect_t)(const mp_obj_framebuf_t *, unsigned int, unsigned int, unsigned int, unsigned int, uint32_t);
|
||||
|
||||
typedef struct _mp_framebuf_p_t {
|
||||
setpixel_t setpixel;
|
||||
getpixel_t getpixel;
|
||||
fill_rect_t fill_rect;
|
||||
} mp_framebuf_p_t;
|
||||
|
||||
// constants for formats
|
||||
#define FRAMEBUF_MVLSB (0)
|
||||
#define FRAMEBUF_RGB565 (1)
|
||||
#define FRAMEBUF_GS2_HMSB (5)
|
||||
#define FRAMEBUF_GS4_HMSB (2)
|
||||
#define FRAMEBUF_GS8 (6)
|
||||
#define FRAMEBUF_MHLSB (3)
|
||||
#define FRAMEBUF_MHMSB (4)
|
||||
|
||||
// Functions for MHLSB and MHMSB
|
||||
|
||||
STATIC void mono_horiz_setpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, uint32_t col) {
|
||||
size_t index = (x + y * fb->stride) >> 3;
|
||||
unsigned int offset = fb->format == FRAMEBUF_MHMSB ? x & 0x07 : 7 - (x & 0x07);
|
||||
((uint8_t *)fb->buf)[index] = (((uint8_t *)fb->buf)[index] & ~(0x01 << offset)) | ((col != 0) << offset);
|
||||
}
|
||||
|
||||
STATIC uint32_t mono_horiz_getpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y) {
|
||||
size_t index = (x + y * fb->stride) >> 3;
|
||||
unsigned int offset = fb->format == FRAMEBUF_MHMSB ? x & 0x07 : 7 - (x & 0x07);
|
||||
return (((uint8_t *)fb->buf)[index] >> (offset)) & 0x01;
|
||||
}
|
||||
|
||||
STATIC void mono_horiz_fill_rect(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, unsigned int w, unsigned int h, uint32_t col) {
|
||||
unsigned int reverse = fb->format == FRAMEBUF_MHMSB;
|
||||
unsigned int advance = fb->stride >> 3;
|
||||
while (w--) {
|
||||
uint8_t *b = &((uint8_t *)fb->buf)[(x >> 3) + y * advance];
|
||||
unsigned int offset = reverse ? x & 7 : 7 - (x & 7);
|
||||
for (unsigned int hh = h; hh; --hh) {
|
||||
*b = (*b & ~(0x01 << offset)) | ((col != 0) << offset);
|
||||
b += advance;
|
||||
}
|
||||
++x;
|
||||
}
|
||||
}
|
||||
|
||||
// Functions for MVLSB format
|
||||
|
||||
STATIC void mvlsb_setpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, uint32_t col) {
|
||||
size_t index = (y >> 3) * fb->stride + x;
|
||||
uint8_t offset = y & 0x07;
|
||||
((uint8_t *)fb->buf)[index] = (((uint8_t *)fb->buf)[index] & ~(0x01 << offset)) | ((col != 0) << offset);
|
||||
}
|
||||
|
||||
STATIC uint32_t mvlsb_getpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y) {
|
||||
return (((uint8_t *)fb->buf)[(y >> 3) * fb->stride + x] >> (y & 0x07)) & 0x01;
|
||||
}
|
||||
|
||||
STATIC void mvlsb_fill_rect(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, unsigned int w, unsigned int h, uint32_t col) {
|
||||
while (h--) {
|
||||
uint8_t *b = &((uint8_t *)fb->buf)[(y >> 3) * fb->stride + x];
|
||||
uint8_t offset = y & 0x07;
|
||||
for (unsigned int ww = w; ww; --ww) {
|
||||
*b = (*b & ~(0x01 << offset)) | ((col != 0) << offset);
|
||||
++b;
|
||||
}
|
||||
++y;
|
||||
}
|
||||
}
|
||||
|
||||
// Functions for RGB565 format
|
||||
|
||||
STATIC void rgb565_setpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, uint32_t col) {
|
||||
((uint16_t *)fb->buf)[x + y * fb->stride] = col;
|
||||
}
|
||||
|
||||
STATIC uint32_t rgb565_getpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y) {
|
||||
return ((uint16_t *)fb->buf)[x + y * fb->stride];
|
||||
}
|
||||
|
||||
STATIC void rgb565_fill_rect(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, unsigned int w, unsigned int h, uint32_t col) {
|
||||
uint16_t *b = &((uint16_t *)fb->buf)[x + y * fb->stride];
|
||||
while (h--) {
|
||||
for (unsigned int ww = w; ww; --ww) {
|
||||
*b++ = col;
|
||||
}
|
||||
b += fb->stride - w;
|
||||
}
|
||||
}
|
||||
|
||||
// Functions for GS2_HMSB format
|
||||
|
||||
STATIC void gs2_hmsb_setpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, uint32_t col) {
|
||||
uint8_t *pixel = &((uint8_t *)fb->buf)[(x + y * fb->stride) >> 2];
|
||||
uint8_t shift = (x & 0x3) << 1;
|
||||
uint8_t mask = 0x3 << shift;
|
||||
uint8_t color = (col & 0x3) << shift;
|
||||
*pixel = color | (*pixel & (~mask));
|
||||
}
|
||||
|
||||
STATIC uint32_t gs2_hmsb_getpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y) {
|
||||
uint8_t pixel = ((uint8_t *)fb->buf)[(x + y * fb->stride) >> 2];
|
||||
uint8_t shift = (x & 0x3) << 1;
|
||||
return (pixel >> shift) & 0x3;
|
||||
}
|
||||
|
||||
STATIC void gs2_hmsb_fill_rect(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, unsigned int w, unsigned int h, uint32_t col) {
|
||||
for (unsigned int xx = x; xx < x + w; xx++) {
|
||||
for (unsigned int yy = y; yy < y + h; yy++) {
|
||||
gs2_hmsb_setpixel(fb, xx, yy, col);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Functions for GS4_HMSB format
|
||||
|
||||
STATIC void gs4_hmsb_setpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, uint32_t col) {
|
||||
uint8_t *pixel = &((uint8_t *)fb->buf)[(x + y * fb->stride) >> 1];
|
||||
|
||||
if (x % 2) {
|
||||
*pixel = ((uint8_t)col & 0x0f) | (*pixel & 0xf0);
|
||||
} else {
|
||||
*pixel = ((uint8_t)col << 4) | (*pixel & 0x0f);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC uint32_t gs4_hmsb_getpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y) {
|
||||
if (x % 2) {
|
||||
return ((uint8_t *)fb->buf)[(x + y * fb->stride) >> 1] & 0x0f;
|
||||
}
|
||||
|
||||
return ((uint8_t *)fb->buf)[(x + y * fb->stride) >> 1] >> 4;
|
||||
}
|
||||
|
||||
STATIC void gs4_hmsb_fill_rect(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, unsigned int w, unsigned int h, uint32_t col) {
|
||||
col &= 0x0f;
|
||||
uint8_t *pixel_pair = &((uint8_t *)fb->buf)[(x + y * fb->stride) >> 1];
|
||||
uint8_t col_shifted_left = col << 4;
|
||||
uint8_t col_pixel_pair = col_shifted_left | col;
|
||||
unsigned int pixel_count_till_next_line = (fb->stride - w) >> 1;
|
||||
bool odd_x = (x % 2 == 1);
|
||||
|
||||
while (h--) {
|
||||
unsigned int ww = w;
|
||||
|
||||
if (odd_x && ww > 0) {
|
||||
*pixel_pair = (*pixel_pair & 0xf0) | col;
|
||||
pixel_pair++;
|
||||
ww--;
|
||||
}
|
||||
|
||||
memset(pixel_pair, col_pixel_pair, ww >> 1);
|
||||
pixel_pair += ww >> 1;
|
||||
|
||||
if (ww % 2) {
|
||||
*pixel_pair = col_shifted_left | (*pixel_pair & 0x0f);
|
||||
if (!odd_x) {
|
||||
pixel_pair++;
|
||||
}
|
||||
}
|
||||
|
||||
pixel_pair += pixel_count_till_next_line;
|
||||
}
|
||||
}
|
||||
|
||||
// Functions for GS8 format
|
||||
|
||||
STATIC void gs8_setpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, uint32_t col) {
|
||||
uint8_t *pixel = &((uint8_t *)fb->buf)[(x + y * fb->stride)];
|
||||
*pixel = col & 0xff;
|
||||
}
|
||||
|
||||
STATIC uint32_t gs8_getpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y) {
|
||||
return ((uint8_t *)fb->buf)[(x + y * fb->stride)];
|
||||
}
|
||||
|
||||
STATIC void gs8_fill_rect(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, unsigned int w, unsigned int h, uint32_t col) {
|
||||
uint8_t *pixel = &((uint8_t *)fb->buf)[(x + y * fb->stride)];
|
||||
while (h--) {
|
||||
memset(pixel, col, w);
|
||||
pixel += fb->stride;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC const mp_framebuf_p_t formats[] = {
|
||||
[FRAMEBUF_MVLSB] = {mvlsb_setpixel, mvlsb_getpixel, mvlsb_fill_rect},
|
||||
[FRAMEBUF_RGB565] = {rgb565_setpixel, rgb565_getpixel, rgb565_fill_rect},
|
||||
[FRAMEBUF_GS2_HMSB] = {gs2_hmsb_setpixel, gs2_hmsb_getpixel, gs2_hmsb_fill_rect},
|
||||
[FRAMEBUF_GS4_HMSB] = {gs4_hmsb_setpixel, gs4_hmsb_getpixel, gs4_hmsb_fill_rect},
|
||||
[FRAMEBUF_GS8] = {gs8_setpixel, gs8_getpixel, gs8_fill_rect},
|
||||
[FRAMEBUF_MHLSB] = {mono_horiz_setpixel, mono_horiz_getpixel, mono_horiz_fill_rect},
|
||||
[FRAMEBUF_MHMSB] = {mono_horiz_setpixel, mono_horiz_getpixel, mono_horiz_fill_rect},
|
||||
};
|
||||
|
||||
static inline void setpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, uint32_t col) {
|
||||
formats[fb->format].setpixel(fb, x, y, col);
|
||||
}
|
||||
|
||||
static inline uint32_t getpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y) {
|
||||
return formats[fb->format].getpixel(fb, x, y);
|
||||
}
|
||||
|
||||
STATIC void fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w, int h, uint32_t col) {
|
||||
if (h < 1 || w < 1 || x + w <= 0 || y + h <= 0 || y >= fb->height || x >= fb->width) {
|
||||
// No operation needed.
|
||||
return;
|
||||
}
|
||||
|
||||
// clip to the framebuffer
|
||||
int xend = MIN(fb->width, x + w);
|
||||
int yend = MIN(fb->height, y + h);
|
||||
x = MAX(x, 0);
|
||||
y = MAX(y, 0);
|
||||
|
||||
formats[fb->format].fill_rect(fb, x, y, xend - x, yend - y, col);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t framebuf_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 4, 5, false);
|
||||
|
||||
mp_obj_framebuf_t *o = m_new_obj(mp_obj_framebuf_t);
|
||||
o->base.type = type;
|
||||
o->buf_obj = args[0];
|
||||
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_WRITE);
|
||||
o->buf = bufinfo.buf;
|
||||
|
||||
o->width = mp_obj_get_int(args[1]);
|
||||
o->height = mp_obj_get_int(args[2]);
|
||||
o->format = mp_obj_get_int(args[3]);
|
||||
if (n_args >= 5) {
|
||||
o->stride = mp_obj_get_int(args[4]);
|
||||
} else {
|
||||
o->stride = o->width;
|
||||
}
|
||||
|
||||
switch (o->format) {
|
||||
case FRAMEBUF_MVLSB:
|
||||
case FRAMEBUF_RGB565:
|
||||
break;
|
||||
case FRAMEBUF_MHLSB:
|
||||
case FRAMEBUF_MHMSB:
|
||||
o->stride = (o->stride + 7) & ~7;
|
||||
break;
|
||||
case FRAMEBUF_GS2_HMSB:
|
||||
o->stride = (o->stride + 3) & ~3;
|
||||
break;
|
||||
case FRAMEBUF_GS4_HMSB:
|
||||
o->stride = (o->stride + 1) & ~1;
|
||||
break;
|
||||
case FRAMEBUF_GS8:
|
||||
break;
|
||||
default:
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("invalid format"));
|
||||
}
|
||||
|
||||
return MP_OBJ_FROM_PTR(o);
|
||||
}
|
||||
|
||||
#if !(defined(MICROPY_ENABLE_DYNRUNTIME) && MICROPY_ENABLE_DYNRUNTIME)
|
||||
STATIC const mp_obj_type_t mp_type_framebuf;
|
||||
#endif
|
||||
|
||||
// Helper to ensure we have the native super class instead of a subclass.
|
||||
static mp_obj_framebuf_t *native_framebuf(mp_obj_t framebuf_obj) {
|
||||
mp_obj_t native_framebuf = mp_obj_cast_to_native_base(framebuf_obj, &mp_type_framebuf);
|
||||
mp_obj_assert_native_inited(native_framebuf);
|
||||
if (native_framebuf == MP_OBJ_NULL) {
|
||||
mp_raise_TypeError(NULL);
|
||||
}
|
||||
return MP_OBJ_TO_PTR(native_framebuf);
|
||||
}
|
||||
|
||||
STATIC mp_int_t framebuf_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) {
|
||||
(void)flags;
|
||||
mp_obj_framebuf_t *self = native_framebuf(self_in);
|
||||
bufinfo->buf = self->buf;
|
||||
bufinfo->len = self->stride * self->height * (self->format == FRAMEBUF_RGB565 ? 2 : 1);
|
||||
bufinfo->typecode = 'B'; // view framebuf as bytes
|
||||
return 0;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t framebuf_fill(mp_obj_t self_in, mp_obj_t col_in) {
|
||||
mp_obj_framebuf_t *self = native_framebuf(self_in);
|
||||
mp_int_t col = mp_obj_get_int(col_in);
|
||||
formats[self->format].fill_rect(self, 0, 0, self->width, self->height, col);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(framebuf_fill_obj, framebuf_fill);
|
||||
|
||||
STATIC mp_obj_t framebuf_fill_rect(size_t n_args, const mp_obj_t *args) {
|
||||
(void)n_args;
|
||||
|
||||
mp_obj_framebuf_t *self = native_framebuf(args[0]);
|
||||
mp_int_t x = mp_obj_get_int(args[1]);
|
||||
mp_int_t y = mp_obj_get_int(args[2]);
|
||||
mp_int_t width = mp_obj_get_int(args[3]);
|
||||
mp_int_t height = mp_obj_get_int(args[4]);
|
||||
mp_int_t col = mp_obj_get_int(args[5]);
|
||||
|
||||
fill_rect(self, x, y, width, height, col);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_fill_rect_obj, 6, 6, framebuf_fill_rect);
|
||||
|
||||
STATIC mp_obj_t framebuf_pixel(size_t n_args, const mp_obj_t *args) {
|
||||
mp_obj_framebuf_t *self = native_framebuf(args[0]);
|
||||
mp_int_t x = mp_obj_get_int(args[1]);
|
||||
mp_int_t y = mp_obj_get_int(args[2]);
|
||||
if (0 <= x && x < self->width && 0 <= y && y < self->height) {
|
||||
if (n_args == 3) {
|
||||
// get
|
||||
return MP_OBJ_NEW_SMALL_INT(getpixel(self, x, y));
|
||||
} else {
|
||||
// set
|
||||
setpixel(self, x, y, mp_obj_get_int(args[3]));
|
||||
}
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_pixel_obj, 3, 4, framebuf_pixel);
|
||||
|
||||
STATIC mp_obj_t framebuf_hline(size_t n_args, const mp_obj_t *args) {
|
||||
(void)n_args;
|
||||
|
||||
mp_obj_framebuf_t *self = native_framebuf(args[0]);
|
||||
mp_int_t x = mp_obj_get_int(args[1]);
|
||||
mp_int_t y = mp_obj_get_int(args[2]);
|
||||
mp_int_t w = mp_obj_get_int(args[3]);
|
||||
mp_int_t col = mp_obj_get_int(args[4]);
|
||||
|
||||
fill_rect(self, x, y, w, 1, col);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_hline_obj, 5, 5, framebuf_hline);
|
||||
|
||||
STATIC mp_obj_t framebuf_vline(size_t n_args, const mp_obj_t *args) {
|
||||
(void)n_args;
|
||||
|
||||
mp_obj_framebuf_t *self = native_framebuf(args[0]);
|
||||
mp_int_t x = mp_obj_get_int(args[1]);
|
||||
mp_int_t y = mp_obj_get_int(args[2]);
|
||||
mp_int_t h = mp_obj_get_int(args[3]);
|
||||
mp_int_t col = mp_obj_get_int(args[4]);
|
||||
|
||||
fill_rect(self, x, y, 1, h, col);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_vline_obj, 5, 5, framebuf_vline);
|
||||
|
||||
STATIC mp_obj_t framebuf_rect(size_t n_args, const mp_obj_t *args) {
|
||||
(void)n_args;
|
||||
|
||||
mp_obj_framebuf_t *self = native_framebuf(args[0]);
|
||||
mp_int_t x = mp_obj_get_int(args[1]);
|
||||
mp_int_t y = mp_obj_get_int(args[2]);
|
||||
mp_int_t w = mp_obj_get_int(args[3]);
|
||||
mp_int_t h = mp_obj_get_int(args[4]);
|
||||
mp_int_t col = mp_obj_get_int(args[5]);
|
||||
|
||||
fill_rect(self, x, y, w, 1, col);
|
||||
fill_rect(self, x, y + h - 1, w, 1, col);
|
||||
fill_rect(self, x, y, 1, h, col);
|
||||
fill_rect(self, x + w - 1, y, 1, h, col);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_rect_obj, 6, 6, framebuf_rect);
|
||||
|
||||
STATIC mp_obj_t framebuf_line(size_t n_args, const mp_obj_t *args) {
|
||||
(void)n_args;
|
||||
|
||||
mp_obj_framebuf_t *self = native_framebuf(args[0]);
|
||||
mp_int_t x1 = mp_obj_get_int(args[1]);
|
||||
mp_int_t y1 = mp_obj_get_int(args[2]);
|
||||
mp_int_t x2 = mp_obj_get_int(args[3]);
|
||||
mp_int_t y2 = mp_obj_get_int(args[4]);
|
||||
mp_int_t col = mp_obj_get_int(args[5]);
|
||||
|
||||
mp_int_t dx = x2 - x1;
|
||||
mp_int_t sx;
|
||||
if (dx > 0) {
|
||||
sx = 1;
|
||||
} else {
|
||||
dx = -dx;
|
||||
sx = -1;
|
||||
}
|
||||
|
||||
mp_int_t dy = y2 - y1;
|
||||
mp_int_t sy;
|
||||
if (dy > 0) {
|
||||
sy = 1;
|
||||
} else {
|
||||
dy = -dy;
|
||||
sy = -1;
|
||||
}
|
||||
|
||||
bool steep;
|
||||
if (dy > dx) {
|
||||
mp_int_t temp;
|
||||
temp = x1;
|
||||
x1 = y1;
|
||||
y1 = temp;
|
||||
temp = dx;
|
||||
dx = dy;
|
||||
dy = temp;
|
||||
temp = sx;
|
||||
sx = sy;
|
||||
sy = temp;
|
||||
steep = true;
|
||||
} else {
|
||||
steep = false;
|
||||
}
|
||||
|
||||
mp_int_t e = 2 * dy - dx;
|
||||
for (mp_int_t i = 0; i < dx; ++i) {
|
||||
if (steep) {
|
||||
if (0 <= y1 && y1 < self->width && 0 <= x1 && x1 < self->height) {
|
||||
setpixel(self, y1, x1, col);
|
||||
}
|
||||
} else {
|
||||
if (0 <= x1 && x1 < self->width && 0 <= y1 && y1 < self->height) {
|
||||
setpixel(self, x1, y1, col);
|
||||
}
|
||||
}
|
||||
while (e >= 0) {
|
||||
y1 += sy;
|
||||
e -= 2 * dx;
|
||||
}
|
||||
x1 += sx;
|
||||
e += 2 * dy;
|
||||
}
|
||||
|
||||
if (0 <= x2 && x2 < self->width && 0 <= y2 && y2 < self->height) {
|
||||
setpixel(self, x2, y2, col);
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_line_obj, 6, 6, framebuf_line);
|
||||
|
||||
STATIC mp_obj_t framebuf_blit(size_t n_args, const mp_obj_t *args) {
|
||||
mp_obj_framebuf_t *self = native_framebuf(args[0]);
|
||||
mp_obj_framebuf_t *source = native_framebuf(args[1]);
|
||||
mp_int_t x = mp_obj_get_int(args[2]);
|
||||
mp_int_t y = mp_obj_get_int(args[3]);
|
||||
mp_int_t key = -1;
|
||||
if (n_args > 4) {
|
||||
key = mp_obj_get_int(args[4]);
|
||||
}
|
||||
mp_obj_framebuf_t *palette = NULL;
|
||||
if (n_args > 5 && args[5] != mp_const_none) {
|
||||
palette = MP_OBJ_TO_PTR(mp_obj_cast_to_native_base(args[5], MP_OBJ_FROM_PTR(&mp_type_framebuf)));
|
||||
}
|
||||
|
||||
if (
|
||||
(x >= self->width) ||
|
||||
(y >= self->height) ||
|
||||
(-x >= source->width) ||
|
||||
(-y >= source->height)
|
||||
) {
|
||||
// Out of bounds, no-op.
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
// Clip.
|
||||
int x0 = MAX(0, x);
|
||||
int y0 = MAX(0, y);
|
||||
int x1 = MAX(0, -x);
|
||||
int y1 = MAX(0, -y);
|
||||
int x0end = MIN(self->width, x + source->width);
|
||||
int y0end = MIN(self->height, y + source->height);
|
||||
|
||||
for (; y0 < y0end; ++y0) {
|
||||
int cx1 = x1;
|
||||
for (int cx0 = x0; cx0 < x0end; ++cx0) {
|
||||
uint32_t col = getpixel(source, cx1, y1);
|
||||
if (palette) {
|
||||
col = getpixel(palette, col, 0);
|
||||
}
|
||||
if (col != (uint32_t)key) {
|
||||
setpixel(self, cx0, y0, col);
|
||||
}
|
||||
++cx1;
|
||||
}
|
||||
++y1;
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_blit_obj, 4, 6, framebuf_blit);
|
||||
|
||||
STATIC mp_obj_t framebuf_scroll(mp_obj_t self_in, mp_obj_t xstep_in, mp_obj_t ystep_in) {
|
||||
mp_obj_framebuf_t *self = native_framebuf(self_in);
|
||||
mp_int_t xstep = mp_obj_get_int(xstep_in);
|
||||
mp_int_t ystep = mp_obj_get_int(ystep_in);
|
||||
int sx, y, xend, yend, dx, dy;
|
||||
if (xstep < 0) {
|
||||
sx = 0;
|
||||
xend = self->width + xstep;
|
||||
dx = 1;
|
||||
} else {
|
||||
sx = self->width - 1;
|
||||
xend = xstep - 1;
|
||||
dx = -1;
|
||||
}
|
||||
if (ystep < 0) {
|
||||
y = 0;
|
||||
yend = self->height + ystep;
|
||||
dy = 1;
|
||||
} else {
|
||||
y = self->height - 1;
|
||||
yend = ystep - 1;
|
||||
dy = -1;
|
||||
}
|
||||
for (; y != yend; y += dy) {
|
||||
for (int x = sx; x != xend; x += dx) {
|
||||
setpixel(self, x, y, getpixel(self, x - xstep, y - ystep));
|
||||
}
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_3(framebuf_scroll_obj, framebuf_scroll);
|
||||
|
||||
STATIC mp_obj_t framebuf_text(size_t n_args, const mp_obj_t *args) {
|
||||
// extract arguments
|
||||
mp_obj_framebuf_t *self = native_framebuf(args[0]);
|
||||
const char *str = mp_obj_str_get_str(args[1]);
|
||||
mp_int_t x0 = mp_obj_get_int(args[2]);
|
||||
mp_int_t y0 = mp_obj_get_int(args[3]);
|
||||
mp_int_t col = 1;
|
||||
if (n_args >= 5) {
|
||||
col = mp_obj_get_int(args[4]);
|
||||
}
|
||||
|
||||
// loop over chars
|
||||
for (; *str; ++str) {
|
||||
// get char and make sure its in range of font
|
||||
int chr = *(uint8_t *)str;
|
||||
if (chr < 32 || chr > 127) {
|
||||
chr = 127;
|
||||
}
|
||||
// get char data
|
||||
const uint8_t *chr_data = &font_petme128_8x8[(chr - 32) * 8];
|
||||
// loop over char data
|
||||
for (int j = 0; j < 8; j++, x0++) {
|
||||
if (0 <= x0 && x0 < self->width) { // clip x
|
||||
uint vline_data = chr_data[j]; // each byte is a column of 8 pixels, LSB at top
|
||||
for (int y = y0; vline_data; vline_data >>= 1, y++) { // scan over vertical column
|
||||
if (vline_data & 1) { // only draw if pixel set
|
||||
if (0 <= y && y < self->height) { // clip y
|
||||
setpixel(self, x0, y, col);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_text_obj, 4, 5, framebuf_text);
|
||||
|
||||
#if !MICROPY_ENABLE_DYNRUNTIME
|
||||
STATIC const mp_rom_map_elem_t framebuf_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_fill), MP_ROM_PTR(&framebuf_fill_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_fill_rect), MP_ROM_PTR(&framebuf_fill_rect_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_pixel), MP_ROM_PTR(&framebuf_pixel_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_hline), MP_ROM_PTR(&framebuf_hline_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_vline), MP_ROM_PTR(&framebuf_vline_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_rect), MP_ROM_PTR(&framebuf_rect_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_line), MP_ROM_PTR(&framebuf_line_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_blit), MP_ROM_PTR(&framebuf_blit_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_scroll), MP_ROM_PTR(&framebuf_scroll_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_text), MP_ROM_PTR(&framebuf_text_obj) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(framebuf_locals_dict, framebuf_locals_dict_table);
|
||||
|
||||
STATIC const mp_obj_type_t mp_type_framebuf = {
|
||||
{ &mp_type_type },
|
||||
.flags = MP_TYPE_FLAG_EXTENDED,
|
||||
.name = MP_QSTR_FrameBuffer,
|
||||
.make_new = framebuf_make_new,
|
||||
.locals_dict = (mp_obj_dict_t *)&framebuf_locals_dict,
|
||||
MP_TYPE_EXTENDED_FIELDS(
|
||||
.buffer_p = { .get_buffer = framebuf_get_buffer },
|
||||
),
|
||||
};
|
||||
#endif
|
||||
|
||||
// this factory function is provided for backwards compatibility with old FrameBuffer1 class
|
||||
STATIC mp_obj_t legacy_framebuffer1(size_t n_args, const mp_obj_t *args) {
|
||||
mp_obj_framebuf_t *o = m_new_obj(mp_obj_framebuf_t);
|
||||
o->base.type = (mp_obj_type_t *)&mp_type_framebuf;
|
||||
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_WRITE);
|
||||
o->buf = bufinfo.buf;
|
||||
|
||||
o->width = mp_obj_get_int(args[1]);
|
||||
o->height = mp_obj_get_int(args[2]);
|
||||
o->format = FRAMEBUF_MVLSB;
|
||||
if (n_args >= 4) {
|
||||
o->stride = mp_obj_get_int(args[3]);
|
||||
} else {
|
||||
o->stride = o->width;
|
||||
}
|
||||
|
||||
return MP_OBJ_FROM_PTR(o);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(legacy_framebuffer1_obj, 3, 4, legacy_framebuffer1);
|
||||
|
||||
#if !MICROPY_ENABLE_DYNRUNTIME
|
||||
STATIC const mp_rom_map_elem_t framebuf_module_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_framebuf) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_FrameBuffer), MP_ROM_PTR(&mp_type_framebuf) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_FrameBuffer1), MP_ROM_PTR(&legacy_framebuffer1_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_MVLSB), MP_ROM_INT(FRAMEBUF_MVLSB) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_MONO_VLSB), MP_ROM_INT(FRAMEBUF_MVLSB) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_RGB565), MP_ROM_INT(FRAMEBUF_RGB565) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_GS2_HMSB), MP_ROM_INT(FRAMEBUF_GS2_HMSB) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_GS4_HMSB), MP_ROM_INT(FRAMEBUF_GS4_HMSB) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_GS8), MP_ROM_INT(FRAMEBUF_GS8) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_MONO_HLSB), MP_ROM_INT(FRAMEBUF_MHLSB) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_MONO_HMSB), MP_ROM_INT(FRAMEBUF_MHMSB) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(framebuf_module_globals, framebuf_module_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_framebuf = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t *)&framebuf_module_globals,
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif // MICROPY_PY_FRAMEBUF
|
@ -1,145 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2015-2017 Damien P. George
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "py/obj.h"
|
||||
#include "py/mphal.h"
|
||||
|
||||
#if MICROPY_PY_ONEWIRE
|
||||
|
||||
/******************************************************************************/
|
||||
// Low-level 1-Wire routines
|
||||
|
||||
#define TIMING_RESET1 (480)
|
||||
#define TIMING_RESET2 (70)
|
||||
#define TIMING_RESET3 (410)
|
||||
#define TIMING_READ1 (5)
|
||||
#define TIMING_READ2 (5)
|
||||
#define TIMING_READ3 (40)
|
||||
#define TIMING_WRITE1 (10)
|
||||
#define TIMING_WRITE2 (50)
|
||||
#define TIMING_WRITE3 (10)
|
||||
|
||||
STATIC int onewire_bus_reset(mp_hal_pin_obj_t pin) {
|
||||
mp_hal_pin_od_low(pin);
|
||||
mp_hal_delay_us(TIMING_RESET1);
|
||||
uint32_t i = mp_hal_quiet_timing_enter();
|
||||
mp_hal_pin_od_high(pin);
|
||||
mp_hal_delay_us_fast(TIMING_RESET2);
|
||||
int status = !mp_hal_pin_read(pin);
|
||||
mp_hal_quiet_timing_exit(i);
|
||||
mp_hal_delay_us(TIMING_RESET3);
|
||||
return status;
|
||||
}
|
||||
|
||||
STATIC int onewire_bus_readbit(mp_hal_pin_obj_t pin) {
|
||||
mp_hal_pin_od_high(pin);
|
||||
uint32_t i = mp_hal_quiet_timing_enter();
|
||||
mp_hal_pin_od_low(pin);
|
||||
mp_hal_delay_us_fast(TIMING_READ1);
|
||||
mp_hal_pin_od_high(pin);
|
||||
mp_hal_delay_us_fast(TIMING_READ2);
|
||||
int value = mp_hal_pin_read(pin);
|
||||
mp_hal_quiet_timing_exit(i);
|
||||
mp_hal_delay_us_fast(TIMING_READ3);
|
||||
return value;
|
||||
}
|
||||
|
||||
STATIC void onewire_bus_writebit(mp_hal_pin_obj_t pin, int value) {
|
||||
uint32_t i = mp_hal_quiet_timing_enter();
|
||||
mp_hal_pin_od_low(pin);
|
||||
mp_hal_delay_us_fast(TIMING_WRITE1);
|
||||
if (value) {
|
||||
mp_hal_pin_od_high(pin);
|
||||
}
|
||||
mp_hal_delay_us_fast(TIMING_WRITE2);
|
||||
mp_hal_pin_od_high(pin);
|
||||
mp_hal_delay_us_fast(TIMING_WRITE3);
|
||||
mp_hal_quiet_timing_exit(i);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
// MicroPython bindings
|
||||
|
||||
STATIC mp_obj_t onewire_reset(mp_obj_t pin_in) {
|
||||
return mp_obj_new_bool(onewire_bus_reset(mp_hal_get_pin_obj(pin_in)));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(onewire_reset_obj, onewire_reset);
|
||||
|
||||
STATIC mp_obj_t onewire_readbit(mp_obj_t pin_in) {
|
||||
return MP_OBJ_NEW_SMALL_INT(onewire_bus_readbit(mp_hal_get_pin_obj(pin_in)));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(onewire_readbit_obj, onewire_readbit);
|
||||
|
||||
STATIC mp_obj_t onewire_readbyte(mp_obj_t pin_in) {
|
||||
mp_hal_pin_obj_t pin = mp_hal_get_pin_obj(pin_in);
|
||||
uint8_t value = 0;
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
value |= onewire_bus_readbit(pin) << i;
|
||||
}
|
||||
return MP_OBJ_NEW_SMALL_INT(value);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(onewire_readbyte_obj, onewire_readbyte);
|
||||
|
||||
STATIC mp_obj_t onewire_writebit(mp_obj_t pin_in, mp_obj_t value_in) {
|
||||
onewire_bus_writebit(mp_hal_get_pin_obj(pin_in), mp_obj_get_int(value_in));
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(onewire_writebit_obj, onewire_writebit);
|
||||
|
||||
STATIC mp_obj_t onewire_writebyte(mp_obj_t pin_in, mp_obj_t value_in) {
|
||||
mp_hal_pin_obj_t pin = mp_hal_get_pin_obj(pin_in);
|
||||
int value = mp_obj_get_int(value_in);
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
onewire_bus_writebit(pin, value & 1);
|
||||
value >>= 1;
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(onewire_writebyte_obj, onewire_writebyte);
|
||||
|
||||
STATIC mp_obj_t onewire_crc8(mp_obj_t data) {
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ);
|
||||
uint8_t crc = 0;
|
||||
for (size_t i = 0; i < bufinfo.len; ++i) {
|
||||
uint8_t byte = ((uint8_t *)bufinfo.buf)[i];
|
||||
for (int b = 0; b < 8; ++b) {
|
||||
uint8_t fb_bit = (crc ^ byte) & 0x01;
|
||||
if (fb_bit == 0x01) {
|
||||
crc = crc ^ 0x18;
|
||||
}
|
||||
crc = (crc >> 1) & 0x7f;
|
||||
if (fb_bit == 0x01) {
|
||||
crc = crc | 0x80;
|
||||
}
|
||||
byte = byte >> 1;
|
||||
}
|
||||
}
|
||||
return MP_OBJ_NEW_SMALL_INT(crc);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(onewire_crc8_obj, onewire_crc8);
|
||||
|
||||
STATIC const mp_rom_map_elem_t onewire_module_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_onewire) },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&onewire_reset_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_readbit), MP_ROM_PTR(&onewire_readbit_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_readbyte), MP_ROM_PTR(&onewire_readbyte_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_writebit), MP_ROM_PTR(&onewire_writebit_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_writebyte), MP_ROM_PTR(&onewire_writebyte_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_crc8), MP_ROM_PTR(&onewire_crc8_obj) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(onewire_module_globals, onewire_module_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_onewire = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t *)&onewire_module_globals,
|
||||
};
|
||||
|
||||
#endif // MICROPY_PY_ONEWIRE
|
@ -70,6 +70,7 @@ STATIC mp_obj_t task_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf);
|
||||
/******************************************************************************/
|
||||
// Ticks for task ordering in pairing heap
|
||||
|
||||
// CIRCUITPY-style ticks
|
||||
#define _TICKS_PERIOD (1lu << 29)
|
||||
#define _TICKS_MAX (_TICKS_PERIOD - 1)
|
||||
#define _TICKS_HALFPERIOD (_TICKS_PERIOD >> 1)
|
||||
@ -105,8 +106,7 @@ STATIC int task_lt(mp_pairheap_t *n1, mp_pairheap_t *n2) {
|
||||
STATIC mp_obj_t task_queue_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
(void)args;
|
||||
mp_arg_check_num(n_args, n_kw, 0, 0, false);
|
||||
mp_obj_task_queue_t *self = m_new_obj(mp_obj_task_queue_t);
|
||||
self->base.type = type;
|
||||
mp_obj_task_queue_t *self = mp_obj_malloc(mp_obj_task_queue_t, type);
|
||||
self->heap = (mp_obj_task_t *)mp_pairheap_new(task_lt);
|
||||
return MP_OBJ_FROM_PTR(self);
|
||||
}
|
||||
@ -121,7 +121,7 @@ STATIC mp_obj_t task_queue_peek(mp_obj_t self_in) {
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(task_queue_peek_obj, task_queue_peek);
|
||||
|
||||
STATIC mp_obj_t task_queue_push_sorted(size_t n_args, const mp_obj_t *args) {
|
||||
STATIC mp_obj_t task_queue_push(size_t n_args, const mp_obj_t *args) {
|
||||
mp_obj_task_queue_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
mp_obj_task_t *task = MP_OBJ_TO_PTR(args[1]);
|
||||
task->data = mp_const_none;
|
||||
@ -134,9 +134,9 @@ STATIC mp_obj_t task_queue_push_sorted(size_t n_args, const mp_obj_t *args) {
|
||||
self->heap = (mp_obj_task_t *)mp_pairheap_push(task_lt, TASK_PAIRHEAP(self->heap), TASK_PAIRHEAP(task));
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(task_queue_push_sorted_obj, 2, 3, task_queue_push_sorted);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(task_queue_push_obj, 2, 3, task_queue_push);
|
||||
|
||||
STATIC mp_obj_t task_queue_pop_head(mp_obj_t self_in) {
|
||||
STATIC mp_obj_t task_queue_pop(mp_obj_t self_in) {
|
||||
mp_obj_task_queue_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_obj_task_t *head = (mp_obj_task_t *)mp_pairheap_peek(task_lt, &self->heap->pairheap);
|
||||
if (head == NULL) {
|
||||
@ -145,7 +145,7 @@ STATIC mp_obj_t task_queue_pop_head(mp_obj_t self_in) {
|
||||
self->heap = (mp_obj_task_t *)mp_pairheap_pop(task_lt, &self->heap->pairheap);
|
||||
return MP_OBJ_FROM_PTR(head);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(task_queue_pop_head_obj, task_queue_pop_head);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(task_queue_pop_obj, task_queue_pop);
|
||||
|
||||
STATIC mp_obj_t task_queue_remove(mp_obj_t self_in, mp_obj_t task_in) {
|
||||
mp_obj_task_queue_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
@ -157,9 +157,8 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(task_queue_remove_obj, task_queue_remove);
|
||||
|
||||
STATIC const mp_rom_map_elem_t task_queue_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_peek), MP_ROM_PTR(&task_queue_peek_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_push_sorted), MP_ROM_PTR(&task_queue_push_sorted_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_push_head), MP_ROM_PTR(&task_queue_push_sorted_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_pop_head), MP_ROM_PTR(&task_queue_pop_head_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_push), MP_ROM_PTR(&task_queue_push_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_pop), MP_ROM_PTR(&task_queue_pop_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&task_queue_remove_obj) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(task_queue_locals_dict, task_queue_locals_dict_table);
|
||||
@ -223,18 +222,18 @@ STATIC mp_obj_t task_cancel(mp_obj_t self_in) {
|
||||
// Not on the main running queue, remove the task from the queue it's on.
|
||||
dest[2] = MP_OBJ_FROM_PTR(self);
|
||||
mp_call_method_n_kw(1, 0, dest);
|
||||
// _task_queue.push_head(self)
|
||||
// _task_queue.push(self)
|
||||
dest[0] = _task_queue;
|
||||
dest[1] = MP_OBJ_FROM_PTR(self);
|
||||
task_queue_push_sorted(2, dest);
|
||||
task_queue_push(2, dest);
|
||||
} else if (ticks_diff(self->ph_key, ticks()) > 0) {
|
||||
// On the main running queue but scheduled in the future, so bring it forward to now.
|
||||
// _task_queue.remove(self)
|
||||
task_queue_remove(_task_queue, MP_OBJ_FROM_PTR(self));
|
||||
// _task_queue.push_head(self)
|
||||
// _task_queue.push(self)
|
||||
dest[0] = _task_queue;
|
||||
dest[1] = MP_OBJ_FROM_PTR(self);
|
||||
task_queue_push_sorted(2, dest);
|
||||
task_queue_push(2, dest);
|
||||
}
|
||||
|
||||
self->data = mp_obj_dict_get(uasyncio_context, MP_OBJ_NEW_QSTR(MP_QSTR_CancelledError));
|
||||
@ -243,6 +242,7 @@ STATIC mp_obj_t task_cancel(mp_obj_t self_in) {
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(task_cancel_obj, task_cancel);
|
||||
|
||||
// CIRCUITPY provides __await__().
|
||||
STATIC mp_obj_t task_await(mp_obj_t self_in) {
|
||||
return task_getiter(self_in, NULL);
|
||||
}
|
||||
@ -266,6 +266,7 @@ STATIC void task_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
|
||||
dest[1] = self_in;
|
||||
} else if (attr == MP_QSTR_ph_key) {
|
||||
dest[0] = self->ph_key;
|
||||
// CIRCUITPY provides __await__().
|
||||
} else if (attr == MP_QSTR___await__) {
|
||||
dest[0] = MP_OBJ_FROM_PTR(&task_await_obj);
|
||||
dest[1] = self_in;
|
||||
@ -291,6 +292,9 @@ STATIC mp_obj_t task_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) {
|
||||
} else if (self->state == TASK_STATE_RUNNING_NOT_WAITED_ON) {
|
||||
// Allocate the waiting queue.
|
||||
self->state = task_queue_make_new(&task_queue_type, 0, 0, NULL);
|
||||
} else if (mp_obj_get_type(self->state) != &task_queue_type) {
|
||||
// Task has state used for another purpose, so can't also wait on it.
|
||||
mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("can't wait"));
|
||||
}
|
||||
return self_in;
|
||||
}
|
||||
@ -298,6 +302,7 @@ STATIC mp_obj_t task_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) {
|
||||
STATIC mp_obj_t task_iternext(mp_obj_t self_in) {
|
||||
mp_obj_task_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
if (TASK_IS_DONE(self)) {
|
||||
// CIRCUITPY
|
||||
if (self->data == mp_const_none) {
|
||||
// Task finished but has already been sent to the loop's exception handler.
|
||||
mp_raise_StopIteration(MP_OBJ_NULL);
|
||||
@ -309,7 +314,7 @@ STATIC mp_obj_t task_iternext(mp_obj_t self_in) {
|
||||
// Put calling task on waiting queue.
|
||||
mp_obj_t cur_task = mp_obj_dict_get(uasyncio_context, MP_OBJ_NEW_QSTR(MP_QSTR_cur_task));
|
||||
mp_obj_t args[2] = { self->state, cur_task };
|
||||
task_queue_push_sorted(2, args);
|
||||
task_queue_push(2, args);
|
||||
// Set calling task's data to this task that it waits on, to double-link it.
|
||||
((mp_obj_task_t *)MP_OBJ_TO_PTR(cur_task))->data = self_in;
|
||||
}
|
||||
@ -347,6 +352,6 @@ const mp_obj_module_t mp_module_uasyncio = {
|
||||
.globals = (mp_obj_dict_t *)&mp_module_uasyncio_globals,
|
||||
};
|
||||
|
||||
MP_REGISTER_MODULE(MP_QSTR__asyncio, mp_module_uasyncio, MICROPY_PY_UASYNCIO);
|
||||
MP_REGISTER_MODULE(MP_QSTR__uasyncio, mp_module_uasyncio);
|
||||
|
||||
#endif // MICROPY_PY_UASYNCIO
|
||||
|
@ -1,8 +1,28 @@
|
||||
// Copyright (c) 2014 Paul Sokolovsky
|
||||
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||
// SPDX-FileCopyrightText: 2022 Beat Ludin for Adafruit Industries
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014 Paul Sokolovsky
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
@ -20,6 +40,7 @@ static void check_not_unicode(const mp_obj_t arg) {
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#if MICROPY_PY_UBINASCII
|
||||
|
||||
STATIC mp_obj_t mod_binascii_hexlify(size_t n_args, const mp_obj_t *args) {
|
||||
// First argument is the data to convert.
|
||||
@ -154,13 +175,20 @@ STATIC mp_obj_t mod_binascii_a2b_base64(mp_obj_t data) {
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_binascii_a2b_base64_obj, mod_binascii_a2b_base64);
|
||||
|
||||
STATIC mp_obj_t mod_binascii_b2a_base64(mp_obj_t data) {
|
||||
check_not_unicode(data);
|
||||
STATIC mp_obj_t mod_binascii_b2a_base64(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_newline };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_newline, MP_ARG_BOOL, {.u_bool = true} },
|
||||
};
|
||||
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
uint8_t newline = args[ARG_newline].u_bool;
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ);
|
||||
mp_get_buffer_raise(pos_args[0], &bufinfo, MP_BUFFER_READ);
|
||||
|
||||
vstr_t vstr;
|
||||
vstr_init_len(&vstr, ((bufinfo.len != 0) ? (((bufinfo.len - 1) / 3) + 1) * 4 : 0) + 1);
|
||||
vstr_init_len(&vstr, ((bufinfo.len != 0) ? (((bufinfo.len - 1) / 3) + 1) * 4 : 0) + newline);
|
||||
|
||||
// First pass, we convert input buffer to numeric base 64 values
|
||||
byte *in = bufinfo.buf, *out = (byte *)vstr.buf;
|
||||
@ -186,7 +214,7 @@ STATIC mp_obj_t mod_binascii_b2a_base64(mp_obj_t data) {
|
||||
|
||||
// Second pass, we convert number base 64 values to actual base64 ascii encoding
|
||||
out = (byte *)vstr.buf;
|
||||
for (mp_uint_t j = vstr.len - 1; j--;) {
|
||||
for (mp_uint_t j = vstr.len - newline; j--;) {
|
||||
if (*out < 26) {
|
||||
*out += 'A';
|
||||
} else if (*out < 52) {
|
||||
@ -202,10 +230,15 @@ STATIC mp_obj_t mod_binascii_b2a_base64(mp_obj_t data) {
|
||||
}
|
||||
out++;
|
||||
}
|
||||
*out = '\n';
|
||||
if (newline) {
|
||||
*out = '\n';
|
||||
}
|
||||
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_binascii_b2a_base64_obj, mod_binascii_b2a_base64);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_binascii_b2a_base64_obj, 1, mod_binascii_b2a_base64);
|
||||
|
||||
// CIRCUITPY uses a self-contained implementation of CRC32,
|
||||
// instead of depending on uzlib, like MicroPython.
|
||||
|
||||
/*
|
||||
* CRC32 checksum
|
||||
@ -296,4 +329,6 @@ const mp_obj_module_t mp_module_ubinascii = {
|
||||
.globals = (mp_obj_dict_t *)&mp_module_binascii_globals,
|
||||
};
|
||||
|
||||
MP_REGISTER_MODULE(MP_QSTR_binascii, mp_module_ubinascii, MICROPY_PY_UBINASCII);
|
||||
MP_REGISTER_MODULE(MP_QSTR_ubinascii, mp_module_ubinascii);
|
||||
|
||||
#endif // MICROPY_PY_UBINASCII
|
||||
|
@ -1,7 +1,28 @@
|
||||
// Copyright (c) 2014-2018 Paul Sokolovsky
|
||||
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014-2018 Paul Sokolovsky
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
@ -76,8 +97,7 @@ STATIC NORETURN void syntax_error(void) {
|
||||
|
||||
STATIC mp_obj_t uctypes_struct_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 2, 3, false);
|
||||
mp_obj_uctypes_struct_t *o = m_new_obj(mp_obj_uctypes_struct_t);
|
||||
o->base.type = type;
|
||||
mp_obj_uctypes_struct_t *o = mp_obj_malloc(mp_obj_uctypes_struct_t, type);
|
||||
o->addr = (void *)(uintptr_t)mp_obj_int_get_truncated(args[0]);
|
||||
o->desc = args[1];
|
||||
o->flags = LAYOUT_NATIVE;
|
||||
@ -444,8 +464,7 @@ STATIC mp_obj_t uctypes_struct_attr_op(mp_obj_t self_in, qstr attr, mp_obj_t set
|
||||
|
||||
switch (agg_type) {
|
||||
case STRUCT: {
|
||||
mp_obj_uctypes_struct_t *o = m_new_obj(mp_obj_uctypes_struct_t);
|
||||
o->base.type = &uctypes_struct_type;
|
||||
mp_obj_uctypes_struct_t *o = mp_obj_malloc(mp_obj_uctypes_struct_t, &uctypes_struct_type);
|
||||
o->desc = sub->items[1];
|
||||
o->addr = self->addr + offset;
|
||||
o->flags = self->flags;
|
||||
@ -460,8 +479,7 @@ STATIC mp_obj_t uctypes_struct_attr_op(mp_obj_t self_in, qstr attr, mp_obj_t set
|
||||
MP_FALLTHROUGH
|
||||
}
|
||||
case PTR: {
|
||||
mp_obj_uctypes_struct_t *o = m_new_obj(mp_obj_uctypes_struct_t);
|
||||
o->base.type = &uctypes_struct_type;
|
||||
mp_obj_uctypes_struct_t *o = mp_obj_malloc(mp_obj_uctypes_struct_t, &uctypes_struct_type);
|
||||
o->desc = MP_OBJ_FROM_PTR(sub);
|
||||
o->addr = self->addr + offset;
|
||||
o->flags = self->flags;
|
||||
@ -533,8 +551,7 @@ STATIC mp_obj_t uctypes_struct_subscr(mp_obj_t base_in, mp_obj_t index_in, mp_ob
|
||||
} else if (value == MP_OBJ_SENTINEL) {
|
||||
mp_uint_t dummy = 0;
|
||||
mp_uint_t size = uctypes_struct_size(t->items[2], self->flags, &dummy);
|
||||
mp_obj_uctypes_struct_t *o = m_new_obj(mp_obj_uctypes_struct_t);
|
||||
o->base.type = &uctypes_struct_type;
|
||||
mp_obj_uctypes_struct_t *o = mp_obj_malloc(mp_obj_uctypes_struct_t, &uctypes_struct_type);
|
||||
o->desc = t->items[2];
|
||||
o->addr = self->addr + size * index;
|
||||
o->flags = self->flags;
|
||||
@ -551,8 +568,7 @@ STATIC mp_obj_t uctypes_struct_subscr(mp_obj_t base_in, mp_obj_t index_in, mp_ob
|
||||
} else {
|
||||
mp_uint_t dummy = 0;
|
||||
mp_uint_t size = uctypes_struct_size(t->items[1], self->flags, &dummy);
|
||||
mp_obj_uctypes_struct_t *o = m_new_obj(mp_obj_uctypes_struct_t);
|
||||
o->base.type = &uctypes_struct_type;
|
||||
mp_obj_uctypes_struct_t *o = mp_obj_malloc(mp_obj_uctypes_struct_t, &uctypes_struct_type);
|
||||
o->desc = t->items[1];
|
||||
o->addr = p + size * index;
|
||||
o->flags = self->flags;
|
||||
@ -706,4 +722,6 @@ const mp_obj_module_t mp_module_uctypes = {
|
||||
.globals = (mp_obj_dict_t *)&mp_module_uctypes_globals,
|
||||
};
|
||||
|
||||
MP_REGISTER_MODULE(MP_QSTR_uctypes, mp_module_uctypes);
|
||||
|
||||
#endif
|
||||
|
@ -1,7 +1,28 @@
|
||||
// Copyright (c) 2014 Paul Sokolovsky
|
||||
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014 Paul Sokolovsky
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
@ -39,7 +60,6 @@
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct _mp_obj_hash_t {
|
||||
mp_obj_base_t base;
|
||||
bool final; // if set, update and digest raise an exception
|
||||
@ -65,8 +85,7 @@ STATIC mp_obj_t uhashlib_sha256_update(mp_obj_t self_in, mp_obj_t arg);
|
||||
|
||||
STATIC mp_obj_t uhashlib_sha256_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 0, 1, false);
|
||||
mp_obj_hash_t *o = m_new_obj_var(mp_obj_hash_t, char, sizeof(mbedtls_sha256_context));
|
||||
o->base.type = type;
|
||||
mp_obj_hash_t *o = mp_obj_malloc_var(mp_obj_hash_t, char, sizeof(mbedtls_sha256_context), type);
|
||||
o->final = false;
|
||||
mbedtls_sha256_init((mbedtls_sha256_context *)&o->state);
|
||||
mbedtls_sha256_starts_ret((mbedtls_sha256_context *)&o->state, 0);
|
||||
@ -110,8 +129,7 @@ static void check_not_unicode(const mp_obj_t arg) {
|
||||
|
||||
STATIC mp_obj_t uhashlib_sha256_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 0, 1, false);
|
||||
mp_obj_hash_t *o = m_new_obj_var(mp_obj_hash_t, char, sizeof(CRYAL_SHA256_CTX));
|
||||
o->base.type = type;
|
||||
mp_obj_hash_t *o = mp_obj_malloc_var(mp_obj_hash_t, char, sizeof(CRYAL_SHA256_CTX), type);
|
||||
o->final = false;
|
||||
sha256_init((CRYAL_SHA256_CTX *)o->state);
|
||||
if (n_args == 1) {
|
||||
@ -159,16 +177,13 @@ STATIC const mp_obj_type_t uhashlib_sha256_type = {
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_UHASHLIB_SHA1
|
||||
STATIC mp_obj_t uhashlib_sha1_update(mp_obj_t self_in, mp_obj_t arg);
|
||||
|
||||
#if MICROPY_SSL_AXTLS
|
||||
STATIC mp_obj_t uhashlib_sha1_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
|
||||
mp_arg_check_num(n_args, kw_args, 0, 1, false);
|
||||
mp_obj_hash_t *o = m_new_obj_var(mp_obj_hash_t, char, sizeof(SHA1_CTX));
|
||||
o->base.type = type;
|
||||
STATIC mp_obj_t uhashlib_sha1_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 0, 1, false);
|
||||
mp_obj_hash_t *o = mp_obj_malloc_var(mp_obj_hash_t, char, sizeof(SHA1_CTX), type);
|
||||
o->final = false;
|
||||
SHA1_Init((SHA1_CTX *)o->state);
|
||||
if (n_args == 1) {
|
||||
@ -178,7 +193,6 @@ STATIC mp_obj_t uhashlib_sha1_make_new(const mp_obj_type_t *type, size_t n_args,
|
||||
}
|
||||
|
||||
STATIC mp_obj_t uhashlib_sha1_update(mp_obj_t self_in, mp_obj_t arg) {
|
||||
check_not_unicode(arg);
|
||||
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
uhashlib_ensure_not_final(self);
|
||||
mp_buffer_info_t bufinfo;
|
||||
@ -208,8 +222,7 @@ STATIC mp_obj_t uhashlib_sha1_digest(mp_obj_t self_in) {
|
||||
|
||||
STATIC mp_obj_t uhashlib_sha1_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 0, 1, false);
|
||||
mp_obj_hash_t *o = m_new_obj_var(mp_obj_hash_t, char, sizeof(mbedtls_sha1_context));
|
||||
o->base.type = type;
|
||||
mp_obj_hash_t *o = mp_obj_malloc_var(mp_obj_hash_t, char, sizeof(mbedtls_sha1_context), type);
|
||||
o->final = false;
|
||||
mbedtls_sha1_init((mbedtls_sha1_context *)o->state);
|
||||
mbedtls_sha1_starts_ret((mbedtls_sha1_context *)o->state);
|
||||
@ -263,8 +276,7 @@ STATIC mp_obj_t uhashlib_md5_update(mp_obj_t self_in, mp_obj_t arg);
|
||||
#if MICROPY_SSL_AXTLS
|
||||
STATIC mp_obj_t uhashlib_md5_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 0, 1, false);
|
||||
mp_obj_hash_t *o = m_new_obj_var(mp_obj_hash_t, char, sizeof(MD5_CTX));
|
||||
o->base.type = type;
|
||||
mp_obj_hash_t *o = mp_obj_malloc_var(mp_obj_hash_t, char, sizeof(MD5_CTX), type);
|
||||
o->final = false;
|
||||
MD5_Init((MD5_CTX *)o->state);
|
||||
if (n_args == 1) {
|
||||
@ -303,8 +315,7 @@ STATIC mp_obj_t uhashlib_md5_digest(mp_obj_t self_in) {
|
||||
|
||||
STATIC mp_obj_t uhashlib_md5_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 0, 1, false);
|
||||
mp_obj_hash_t *o = m_new_obj_var(mp_obj_hash_t, char, sizeof(mbedtls_md5_context));
|
||||
o->base.type = type;
|
||||
mp_obj_hash_t *o = mp_obj_malloc_var(mp_obj_hash_t, char, sizeof(mbedtls_md5_context), type);
|
||||
o->final = false;
|
||||
mbedtls_md5_init((mbedtls_md5_context *)o->state);
|
||||
mbedtls_md5_starts_ret((mbedtls_md5_context *)o->state);
|
||||
@ -372,4 +383,6 @@ const mp_obj_module_t mp_module_uhashlib = {
|
||||
.globals = (mp_obj_dict_t *)&mp_module_uhashlib_globals,
|
||||
};
|
||||
|
||||
MP_REGISTER_MODULE(MP_QSTR_uhashlib, mp_module_uhashlib, MICROPY_PY_UHASHLIB);
|
||||
|
||||
#endif // MICROPY_PY_UHASHLIB
|
||||
|
@ -1,7 +1,28 @@
|
||||
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2014 Damien P. George
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* This file is part of the MicroPython 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 "py/objlist.h"
|
||||
#include "py/runtime.h"
|
||||
@ -98,6 +119,8 @@ const mp_obj_module_t mp_module_uheapq = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t *)&mp_module_uheapq_globals,
|
||||
};
|
||||
|
||||
MP_REGISTER_MODULE(MP_QSTR_uheapq, mp_module_uheapq);
|
||||
#endif
|
||||
|
||||
#endif // MICROPY_PY_UHEAPQ
|
||||
|
@ -1,7 +1,28 @@
|
||||
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2014-2019 Damien P. George
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014-2019 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
@ -112,6 +133,7 @@ typedef struct _ujson_stream_t {
|
||||
mp_obj_t stream_obj;
|
||||
mp_uint_t (*read)(mp_obj_t obj, void *buf, mp_uint_t size, int *errcode);
|
||||
int errcode;
|
||||
// CIRCUITPY
|
||||
mp_obj_t python_readinto[2 + 1];
|
||||
mp_obj_array_t bytearray_obj;
|
||||
size_t start;
|
||||
@ -136,6 +158,8 @@ STATIC byte ujson_stream_next(ujson_stream_t *s) {
|
||||
return s->cur;
|
||||
}
|
||||
|
||||
// CIRCUITPY
|
||||
|
||||
// We read from an object's `readinto` method in chunks larger than the json
|
||||
// parser needs to reduce the number of function calls done.
|
||||
|
||||
@ -375,6 +399,8 @@ STATIC mp_obj_t _mod_ujson_load(mp_obj_t stream_obj, bool return_first_json) {
|
||||
}
|
||||
}
|
||||
success:
|
||||
// CIRCUITPY
|
||||
|
||||
// It is legal for a stream to have contents after JSON.
|
||||
// E.g., A UART is not closed after receiving an object; in load() we will
|
||||
// return the first complete JSON object, while in loads() we will retain
|
||||
@ -432,6 +458,6 @@ const mp_obj_module_t mp_module_ujson = {
|
||||
.globals = (mp_obj_dict_t *)&mp_module_ujson_globals,
|
||||
};
|
||||
|
||||
MP_REGISTER_MODULE(MP_QSTR_json, mp_module_ujson, MICROPY_PY_UJSON);
|
||||
MP_REGISTER_MODULE(MP_QSTR_ujson, mp_module_ujson);
|
||||
|
||||
#endif // MICROPY_PY_UJSON
|
||||
|
181
extmod/moduos.c
Normal file
181
extmod/moduos.c
Normal file
@ -0,0 +1,181 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016-2022 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "py/objstr.h"
|
||||
#include "py/runtime.h"
|
||||
|
||||
#if MICROPY_PY_UOS
|
||||
|
||||
#include "extmod/misc.h"
|
||||
#include "extmod/vfs.h"
|
||||
|
||||
#if MICROPY_VFS_FAT
|
||||
#include "extmod/vfs_fat.h"
|
||||
#endif
|
||||
|
||||
#if MICROPY_VFS_LFS1 || MICROPY_VFS_LFS2
|
||||
#include "extmod/vfs_lfs.h"
|
||||
#endif
|
||||
|
||||
#if MICROPY_VFS_POSIX
|
||||
#include "extmod/vfs_posix.h"
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_UOS_UNAME
|
||||
#include "genhdr/mpversion.h"
|
||||
#endif
|
||||
|
||||
#ifdef MICROPY_PY_UOS_INCLUDEFILE
|
||||
#include MICROPY_PY_UOS_INCLUDEFILE
|
||||
#endif
|
||||
|
||||
#ifdef MICROPY_BUILD_TYPE
|
||||
#define MICROPY_BUILD_TYPE_PAREN " (" MICROPY_BUILD_TYPE ")"
|
||||
#else
|
||||
#define MICROPY_BUILD_TYPE_PAREN
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_UOS_UNAME
|
||||
|
||||
#if MICROPY_PY_UOS_UNAME_RELEASE_DYNAMIC
|
||||
#define CONST_RELEASE
|
||||
#else
|
||||
#define CONST_RELEASE const
|
||||
#endif
|
||||
|
||||
STATIC const qstr mp_uos_uname_info_fields[] = {
|
||||
MP_QSTR_sysname,
|
||||
MP_QSTR_nodename,
|
||||
MP_QSTR_release,
|
||||
MP_QSTR_version,
|
||||
MP_QSTR_machine
|
||||
};
|
||||
STATIC const MP_DEFINE_STR_OBJ(mp_uos_uname_info_sysname_obj, MICROPY_PY_SYS_PLATFORM);
|
||||
STATIC const MP_DEFINE_STR_OBJ(mp_uos_uname_info_nodename_obj, MICROPY_PY_SYS_PLATFORM);
|
||||
STATIC CONST_RELEASE MP_DEFINE_STR_OBJ(mp_uos_uname_info_release_obj, MICROPY_VERSION_STRING);
|
||||
STATIC const MP_DEFINE_STR_OBJ(mp_uos_uname_info_version_obj, MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE MICROPY_BUILD_TYPE_PAREN);
|
||||
STATIC const MP_DEFINE_STR_OBJ(mp_uos_uname_info_machine_obj, MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME);
|
||||
|
||||
STATIC MP_DEFINE_ATTRTUPLE(
|
||||
mp_uos_uname_info_obj,
|
||||
mp_uos_uname_info_fields,
|
||||
5,
|
||||
MP_ROM_PTR(&mp_uos_uname_info_sysname_obj),
|
||||
MP_ROM_PTR(&mp_uos_uname_info_nodename_obj),
|
||||
MP_ROM_PTR(&mp_uos_uname_info_release_obj),
|
||||
MP_ROM_PTR(&mp_uos_uname_info_version_obj),
|
||||
MP_ROM_PTR(&mp_uos_uname_info_machine_obj)
|
||||
);
|
||||
|
||||
STATIC mp_obj_t mp_uos_uname(void) {
|
||||
#if MICROPY_PY_UOS_UNAME_RELEASE_DYNAMIC
|
||||
const char *release = mp_uos_uname_release();
|
||||
mp_uos_uname_info_release_obj.len = strlen(release);
|
||||
mp_uos_uname_info_release_obj.data = (const byte *)release;
|
||||
#endif
|
||||
return MP_OBJ_FROM_PTR(&mp_uos_uname_info_obj);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_uos_uname_obj, mp_uos_uname);
|
||||
|
||||
#endif
|
||||
|
||||
STATIC const mp_rom_map_elem_t os_module_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uos) },
|
||||
|
||||
#if MICROPY_PY_UOS_GETENV_PUTENV_UNSETENV
|
||||
{ MP_ROM_QSTR(MP_QSTR_getenv), MP_ROM_PTR(&mp_uos_getenv_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_putenv), MP_ROM_PTR(&mp_uos_putenv_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_unsetenv), MP_ROM_PTR(&mp_uos_unsetenv_obj) },
|
||||
#endif
|
||||
#if MICROPY_PY_UOS_SEP
|
||||
{ MP_ROM_QSTR(MP_QSTR_sep), MP_ROM_QSTR(MP_QSTR__slash_) },
|
||||
#endif
|
||||
#if MICROPY_PY_UOS_SYNC
|
||||
{ MP_ROM_QSTR(MP_QSTR_sync), MP_ROM_PTR(&mp_uos_sync_obj) },
|
||||
#endif
|
||||
#if MICROPY_PY_UOS_SYSTEM
|
||||
{ MP_ROM_QSTR(MP_QSTR_system), MP_ROM_PTR(&mp_uos_system_obj) },
|
||||
#endif
|
||||
#if MICROPY_PY_UOS_UNAME
|
||||
{ MP_ROM_QSTR(MP_QSTR_uname), MP_ROM_PTR(&mp_uos_uname_obj) },
|
||||
#endif
|
||||
#if MICROPY_PY_UOS_URANDOM
|
||||
{ MP_ROM_QSTR(MP_QSTR_urandom), MP_ROM_PTR(&mp_uos_urandom_obj) },
|
||||
#endif
|
||||
|
||||
#if MICROPY_VFS
|
||||
{ MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&mp_vfs_chdir_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&mp_vfs_getcwd_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&mp_vfs_listdir_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&mp_vfs_mkdir_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&mp_vfs_remove_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_rename), MP_ROM_PTR(&mp_vfs_rename_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_rmdir), MP_ROM_PTR(&mp_vfs_rmdir_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&mp_vfs_stat_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&mp_vfs_statvfs_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_unlink), MP_ROM_PTR(&mp_vfs_remove_obj) }, // unlink aliases to remove
|
||||
#endif
|
||||
|
||||
// The following are MicroPython extensions.
|
||||
|
||||
#if MICROPY_PY_OS_DUPTERM
|
||||
{ MP_ROM_QSTR(MP_QSTR_dupterm), MP_ROM_PTR(&mp_uos_dupterm_obj) },
|
||||
#endif
|
||||
#if MICROPY_PY_UOS_DUPTERM_NOTIFY
|
||||
{ MP_ROM_QSTR(MP_QSTR_dupterm_notify), MP_ROM_PTR(&mp_uos_dupterm_notify_obj) },
|
||||
#endif
|
||||
#if MICROPY_PY_UOS_ERRNO
|
||||
{ MP_ROM_QSTR(MP_QSTR_errno), MP_ROM_PTR(&mp_uos_errno_obj) },
|
||||
#endif
|
||||
|
||||
#if MICROPY_VFS
|
||||
{ MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&mp_vfs_ilistdir_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&mp_vfs_mount_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&mp_vfs_umount_obj) },
|
||||
#if MICROPY_VFS_FAT
|
||||
{ MP_ROM_QSTR(MP_QSTR_VfsFat), MP_ROM_PTR(&mp_fat_vfs_type) },
|
||||
#endif
|
||||
#if MICROPY_VFS_LFS1
|
||||
{ MP_ROM_QSTR(MP_QSTR_VfsLfs1), MP_ROM_PTR(&mp_type_vfs_lfs1) },
|
||||
#endif
|
||||
#if MICROPY_VFS_LFS2
|
||||
{ MP_ROM_QSTR(MP_QSTR_VfsLfs2), MP_ROM_PTR(&mp_type_vfs_lfs2) },
|
||||
#endif
|
||||
#if MICROPY_VFS_POSIX
|
||||
{ MP_ROM_QSTR(MP_QSTR_VfsPosix), MP_ROM_PTR(&mp_type_vfs_posix) },
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(os_module_globals, os_module_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_uos = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t *)&os_module_globals,
|
||||
};
|
||||
|
||||
MP_REGISTER_MODULE(MP_QSTR_uos, mp_module_uos);
|
||||
|
||||
#endif // MICROPY_PY_UOS
|
@ -29,87 +29,19 @@
|
||||
#include "py/objtuple.h"
|
||||
#include "py/objstr.h"
|
||||
#include "py/mphal.h"
|
||||
#include "extmod/moduplatform.h"
|
||||
#include "genhdr/mpversion.h"
|
||||
|
||||
#if MICROPY_PY_UPLATFORM
|
||||
|
||||
// platform - Access to underlying platform's identifying data
|
||||
|
||||
// TODO: Add more architectures, compilers and libraries.
|
||||
// See: https://sourceforge.net/p/predef/wiki/Home/
|
||||
|
||||
#if defined(__ARM_ARCH)
|
||||
#define PLATFORM_ARCH "arm"
|
||||
#elif defined(__x86_64__) || defined(_WIN64)
|
||||
#define PLATFORM_ARCH "x86_64"
|
||||
#elif defined(__i386__) || defined(_M_IX86)
|
||||
#define PLATFORM_ARCH "x86"
|
||||
#elif defined(__xtensa__) || defined(_M_IX86)
|
||||
#define PLATFORM_ARCH "xtensa"
|
||||
#else
|
||||
#define PLATFORM_ARCH ""
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#define PLATFORM_COMPILER \
|
||||
"GCC " \
|
||||
MP_STRINGIFY(__GNUC__) "." \
|
||||
MP_STRINGIFY(__GNUC_MINOR__) "." \
|
||||
MP_STRINGIFY(__GNUC_PATCHLEVEL__)
|
||||
#elif defined(__ARMCC_VERSION)
|
||||
#define PLATFORM_COMPILER \
|
||||
"ARMCC " \
|
||||
MP_STRINGIFY((__ARMCC_VERSION / 1000000)) "." \
|
||||
MP_STRINGIFY((__ARMCC_VERSION / 10000 % 100)) "." \
|
||||
MP_STRINGIFY((__ARMCC_VERSION % 10000))
|
||||
#elif defined(_MSC_VER)
|
||||
#if defined(_WIN64)
|
||||
#define COMPILER_BITS "64 bit"
|
||||
#elif defined(_M_IX86)
|
||||
#define COMPILER_BITS "32 bit"
|
||||
#else
|
||||
#define COMPILER_BITS ""
|
||||
#endif
|
||||
#define PLATFORM_COMPILER \
|
||||
"MSC v." MP_STRINGIFY(_MSC_VER) " " COMPILER_BITS
|
||||
#else
|
||||
#define PLATFORM_COMPILER ""
|
||||
#endif
|
||||
|
||||
#if defined(__GLIBC__)
|
||||
#define PLATFORM_LIBC_LIB "glibc"
|
||||
#define PLATFORM_LIBC_VER \
|
||||
MP_STRINGIFY(__GLIBC__) "." \
|
||||
MP_STRINGIFY(__GLIBC_MINOR__)
|
||||
#elif defined(__NEWLIB__)
|
||||
#define PLATFORM_LIBC_LIB "newlib"
|
||||
#define PLATFORM_LIBC_VER _NEWLIB_VERSION
|
||||
#else
|
||||
#define PLATFORM_LIBC_LIB ""
|
||||
#define PLATFORM_LIBC_VER ""
|
||||
#endif
|
||||
|
||||
#if defined(__linux)
|
||||
#define PLATFORM_SYSTEM "Linux"
|
||||
#elif defined(__unix__)
|
||||
#define PLATFORM_SYSTEM "Unix"
|
||||
#elif defined(__CYGWIN__)
|
||||
#define PLATFORM_SYSTEM "Cygwin"
|
||||
#elif defined(_WIN32)
|
||||
#define PLATFORM_SYSTEM "Windows"
|
||||
#else
|
||||
#define PLATFORM_SYSTEM "MicroPython"
|
||||
#endif
|
||||
|
||||
#ifndef MICROPY_PLATFORM_VERSION
|
||||
#define MICROPY_PLATFORM_VERSION ""
|
||||
#endif
|
||||
|
||||
STATIC const MP_DEFINE_STR_OBJ(info_platform_obj, PLATFORM_SYSTEM "-" MICROPY_VERSION_STRING "-" \
|
||||
PLATFORM_ARCH "-" MICROPY_PLATFORM_VERSION "-with-" PLATFORM_LIBC_LIB "" PLATFORM_LIBC_VER);
|
||||
STATIC const MP_DEFINE_STR_OBJ(info_python_compiler_obj, PLATFORM_COMPILER);
|
||||
STATIC const MP_DEFINE_STR_OBJ(info_libc_lib_obj, PLATFORM_LIBC_LIB);
|
||||
STATIC const MP_DEFINE_STR_OBJ(info_libc_ver_obj, PLATFORM_LIBC_VER);
|
||||
STATIC const MP_DEFINE_STR_OBJ(info_platform_obj, MICROPY_PLATFORM_SYSTEM "-" \
|
||||
MICROPY_VERSION_STRING "-" MICROPY_PLATFORM_ARCH "-" MICROPY_PLATFORM_VERSION "-with-" \
|
||||
MICROPY_PLATFORM_LIBC_LIB "" MICROPY_PLATFORM_LIBC_VER);
|
||||
STATIC const MP_DEFINE_STR_OBJ(info_python_compiler_obj, MICROPY_PLATFORM_COMPILER);
|
||||
STATIC const MP_DEFINE_STR_OBJ(info_libc_lib_obj, MICROPY_PLATFORM_LIBC_LIB);
|
||||
STATIC const MP_DEFINE_STR_OBJ(info_libc_ver_obj, MICROPY_PLATFORM_LIBC_VER);
|
||||
STATIC const mp_rom_obj_tuple_t info_libc_tuple_obj = {
|
||||
{&mp_type_tuple}, 2, {MP_ROM_PTR(&info_libc_lib_obj), MP_ROM_PTR(&info_libc_ver_obj)}
|
||||
};
|
||||
@ -143,4 +75,6 @@ const mp_obj_module_t mp_module_uplatform = {
|
||||
.globals = (mp_obj_dict_t *)&modplatform_globals,
|
||||
};
|
||||
|
||||
MP_REGISTER_MODULE(MP_QSTR_uplatform, mp_module_uplatform);
|
||||
|
||||
#endif // MICROPY_PY_UPLATFORM
|
||||
|
105
extmod/moduplatform.h
Normal file
105
extmod/moduplatform.h
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013-2021 Ibrahim Abdelkader <iabdalkader@openmv.io>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef MICROPY_INCLUDED_MODUPLATFORM_H
|
||||
#define MICROPY_INCLUDED_MODUPLATFORM_H
|
||||
|
||||
#include "py/misc.h" // For MP_STRINGIFY.
|
||||
#include "py/mpconfig.h"
|
||||
|
||||
// Preprocessor directives indentifying the platform.
|
||||
// The (u)platform module itself is guarded by MICROPY_PY_UPLATFORM, see the
|
||||
// .c file, but these are made available because they're generally usable.
|
||||
// TODO: Add more architectures, compilers and libraries.
|
||||
// See: https://sourceforge.net/p/predef/wiki/Home/
|
||||
|
||||
#if defined(__ARM_ARCH)
|
||||
#define MICROPY_PLATFORM_ARCH "arm"
|
||||
#elif defined(__x86_64__) || defined(_WIN64)
|
||||
#define MICROPY_PLATFORM_ARCH "x86_64"
|
||||
#elif defined(__i386__) || defined(_M_IX86)
|
||||
#define MICROPY_PLATFORM_ARCH "x86"
|
||||
#elif defined(__xtensa__) || defined(_M_IX86)
|
||||
#define MICROPY_PLATFORM_ARCH "xtensa"
|
||||
#else
|
||||
#define MICROPY_PLATFORM_ARCH ""
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#define MICROPY_PLATFORM_COMPILER \
|
||||
"GCC " \
|
||||
MP_STRINGIFY(__GNUC__) "." \
|
||||
MP_STRINGIFY(__GNUC_MINOR__) "." \
|
||||
MP_STRINGIFY(__GNUC_PATCHLEVEL__)
|
||||
#elif defined(__ARMCC_VERSION)
|
||||
#define MICROPY_PLATFORM_COMPILER \
|
||||
"ARMCC " \
|
||||
MP_STRINGIFY((__ARMCC_VERSION / 1000000)) "." \
|
||||
MP_STRINGIFY((__ARMCC_VERSION / 10000 % 100)) "." \
|
||||
MP_STRINGIFY((__ARMCC_VERSION % 10000))
|
||||
#elif defined(_MSC_VER)
|
||||
#if defined(_WIN64)
|
||||
#define MICROPY_PLATFORM_COMPILER_BITS "64 bit"
|
||||
#elif defined(_M_IX86)
|
||||
#define MICROPY_PLATFORM_COMPILER_BITS "32 bit"
|
||||
#else
|
||||
#define MICROPY_PLATFORM_COMPILER_BITS ""
|
||||
#endif
|
||||
#define MICROPY_PLATFORM_COMPILER \
|
||||
"MSC v." MP_STRINGIFY(_MSC_VER) " " MICROPY_PLATFORM_COMPILER_BITS
|
||||
#else
|
||||
#define MICROPY_PLATFORM_COMPILER ""
|
||||
#endif
|
||||
|
||||
#if defined(__GLIBC__)
|
||||
#define MICROPY_PLATFORM_LIBC_LIB "glibc"
|
||||
#define MICROPY_PLATFORM_LIBC_VER \
|
||||
MP_STRINGIFY(__GLIBC__) "." \
|
||||
MP_STRINGIFY(__GLIBC_MINOR__)
|
||||
#elif defined(__NEWLIB__)
|
||||
#define MICROPY_PLATFORM_LIBC_LIB "newlib"
|
||||
#define MICROPY_PLATFORM_LIBC_VER _NEWLIB_VERSION
|
||||
#else
|
||||
#define MICROPY_PLATFORM_LIBC_LIB ""
|
||||
#define MICROPY_PLATFORM_LIBC_VER ""
|
||||
#endif
|
||||
|
||||
#if defined(__linux)
|
||||
#define MICROPY_PLATFORM_SYSTEM "Linux"
|
||||
#elif defined(__unix__)
|
||||
#define MICROPY_PLATFORM_SYSTEM "Unix"
|
||||
#elif defined(__CYGWIN__)
|
||||
#define MICROPY_PLATFORM_SYSTEM "Cygwin"
|
||||
#elif defined(_WIN32)
|
||||
#define MICROPY_PLATFORM_SYSTEM "Windows"
|
||||
#else
|
||||
#define MICROPY_PLATFORM_SYSTEM "MicroPython"
|
||||
#endif
|
||||
|
||||
#ifndef MICROPY_PLATFORM_VERSION
|
||||
#define MICROPY_PLATFORM_VERSION ""
|
||||
#endif
|
||||
|
||||
#endif // MICROPY_INCLUDED_MODUPLATFORM_H
|
@ -1,7 +1,28 @@
|
||||
// Copyright (c) 2016 Paul Sokolovsky
|
||||
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Paul Sokolovsky
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
@ -195,7 +216,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_urandom_uniform_obj, mod_urandom_uniform);
|
||||
#endif // MICROPY_PY_URANDOM_EXTRA_FUNCS
|
||||
|
||||
#if SEED_ON_IMPORT
|
||||
STATIC mp_obj_t mod_urandom___init__() {
|
||||
STATIC mp_obj_t mod_urandom___init__(void) {
|
||||
// This module may be imported by more than one name so need to ensure
|
||||
// that it's only ever seeded once.
|
||||
static bool seeded = false;
|
||||
@ -233,6 +254,8 @@ const mp_obj_module_t mp_module_urandom = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t *)&mp_module_urandom_globals,
|
||||
};
|
||||
|
||||
MP_REGISTER_MODULE(MP_QSTR_urandom, mp_module_urandom);
|
||||
#endif
|
||||
|
||||
#endif // MICROPY_PY_URANDOM
|
||||
|
@ -1,7 +1,28 @@
|
||||
// Copyright (c) 2014 Paul Sokolovsky
|
||||
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014 Paul Sokolovsky
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
@ -18,6 +39,7 @@
|
||||
|
||||
#include "lib/re1.5/re1.5.h"
|
||||
|
||||
//CIRCUITPY
|
||||
#if MICROPY_PY_URE_DEBUG
|
||||
#define FLAG_DEBUG 0x1000
|
||||
#endif
|
||||
@ -168,7 +190,7 @@ STATIC mp_obj_t ure_exec(bool is_anchored, uint n_args, const mp_obj_t *args) {
|
||||
}
|
||||
Subject subj;
|
||||
size_t len;
|
||||
subj.begin = mp_obj_str_get_data(args[1], &len);
|
||||
subj.begin_line = subj.begin = mp_obj_str_get_data(args[1], &len);
|
||||
subj.end = subj.begin + len;
|
||||
#if MICROPY_PY_URE_MATCH_SPAN_START_END && !(defined(MICROPY_ENABLE_DYNRUNTIME) && MICROPY_ENABLE_DYNRUNTIME)
|
||||
|
||||
@ -231,7 +253,7 @@ STATIC mp_obj_t re_split(size_t n_args, const mp_obj_t *args) {
|
||||
Subject subj;
|
||||
size_t len;
|
||||
const mp_obj_type_t *str_type = mp_obj_get_type(args[1]);
|
||||
subj.begin = mp_obj_str_get_data(args[1], &len);
|
||||
subj.begin_line = subj.begin = mp_obj_str_get_data(args[1], &len);
|
||||
subj.end = subj.begin + len;
|
||||
int caps_num = (self->re.sub + 1) * 2;
|
||||
|
||||
@ -291,7 +313,7 @@ STATIC mp_obj_t re_sub_helper(size_t n_args, const mp_obj_t *args) {
|
||||
size_t where_len;
|
||||
const char *where_str = mp_obj_str_get_data(where, &where_len);
|
||||
Subject subj;
|
||||
subj.begin = where_str;
|
||||
subj.begin_line = subj.begin = where_str;
|
||||
subj.end = subj.begin + where_len;
|
||||
int caps_num = (self->re.sub + 1) * 2;
|
||||
|
||||
@ -421,8 +443,7 @@ STATIC mp_obj_t mod_re_compile(size_t n_args, const mp_obj_t *args) {
|
||||
if (size == -1) {
|
||||
goto error;
|
||||
}
|
||||
mp_obj_re_t *o = m_new_obj_var(mp_obj_re_t, char, size);
|
||||
o->base.type = &re_type;
|
||||
mp_obj_re_t *o = mp_obj_malloc_var(mp_obj_re_t, char, size, &re_type);
|
||||
#if MICROPY_PY_URE_DEBUG
|
||||
int flags = 0;
|
||||
if (n_args > 1) {
|
||||
@ -470,7 +491,7 @@ const mp_obj_module_t mp_module_ure = {
|
||||
.globals = (mp_obj_dict_t *)&mp_module_re_globals,
|
||||
};
|
||||
|
||||
MP_REGISTER_MODULE(MP_QSTR_re, mp_module_ure, MICROPY_PY_URE);
|
||||
MP_REGISTER_MODULE(MP_QSTR_ure, mp_module_ure);
|
||||
#endif
|
||||
|
||||
// Source files #include'd here to make sure they're compiled in
|
||||
|
@ -1,8 +1,29 @@
|
||||
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2014 Damien P. George
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2015-2017 Paul Sokolovsky
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014 Damien P. George
|
||||
* Copyright (c) 2015-2017 Paul Sokolovsky
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "py/mpconfig.h"
|
||||
#if MICROPY_PY_USELECT
|
||||
@ -151,6 +172,7 @@ STATIC mp_obj_t select_select(size_t n_args, const mp_obj_t *args) {
|
||||
mp_map_deinit(&poll_map);
|
||||
return mp_obj_new_tuple(3, list_array);
|
||||
}
|
||||
// CIRCUITPY
|
||||
RUN_BACKGROUND_TASKS;
|
||||
}
|
||||
}
|
||||
@ -230,6 +252,7 @@ STATIC mp_uint_t poll_poll_internal(uint n_args, const mp_obj_t *args) {
|
||||
if (n_ready > 0 || (timeout != (mp_uint_t)-1 && mp_hal_ticks_ms() - start_tick >= timeout)) {
|
||||
break;
|
||||
}
|
||||
// CIRCUITPY
|
||||
RUN_BACKGROUND_TASKS;
|
||||
if (mp_hal_is_interrupted()) {
|
||||
return 0;
|
||||
@ -324,6 +347,8 @@ STATIC const mp_obj_type_t mp_type_poll = {
|
||||
{ &mp_type_type },
|
||||
.flags = MP_TYPE_FLAG_EXTENDED,
|
||||
.name = MP_QSTR_poll,
|
||||
.getiter = mp_identity_getiter,
|
||||
.iternext = poll_iternext,
|
||||
.locals_dict = (void *)&poll_locals_dict,
|
||||
MP_TYPE_EXTENDED_FIELDS(
|
||||
.getiter = mp_identity_getiter,
|
||||
@ -333,8 +358,7 @@ STATIC const mp_obj_type_t mp_type_poll = {
|
||||
|
||||
// poll()
|
||||
STATIC mp_obj_t select_poll(void) {
|
||||
mp_obj_poll_t *poll = m_new_obj(mp_obj_poll_t);
|
||||
poll->base.type = &mp_type_poll;
|
||||
mp_obj_poll_t *poll = mp_obj_malloc(mp_obj_poll_t, &mp_type_poll);
|
||||
mp_map_init(&poll->poll_map, 0);
|
||||
poll->iter_cnt = 0;
|
||||
poll->ret_tuple = MP_OBJ_NULL;
|
||||
@ -361,6 +385,6 @@ const mp_obj_module_t mp_module_uselect = {
|
||||
.globals = (mp_obj_dict_t *)&mp_module_select_globals,
|
||||
};
|
||||
|
||||
MP_REGISTER_MODULE(MP_QSTR_select, mp_module_uselect, MICROPY_PY_USELECT);
|
||||
MP_REGISTER_MODULE(MP_QSTR_uselect, mp_module_uselect);
|
||||
|
||||
#endif // MICROPY_PY_USELECT
|
||||
|
@ -1,8 +1,29 @@
|
||||
// Copyright (c) 2016-2017 Paul Sokolovsky
|
||||
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2014 Damien P. George
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014 Damien P. George
|
||||
* Copyright (c) 2016-2017 Paul Sokolovsky
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@ -58,8 +79,7 @@ STATIC bool time_less_than(struct qentry *item, struct qentry *parent) {
|
||||
STATIC mp_obj_t utimeq_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 1, 1, false);
|
||||
mp_uint_t alloc = mp_obj_get_int(args[0]);
|
||||
mp_obj_utimeq_t *o = m_new_obj_var(mp_obj_utimeq_t, struct qentry, alloc);
|
||||
o->base.type = type;
|
||||
mp_obj_utimeq_t *o = mp_obj_malloc_var(mp_obj_utimeq_t, struct qentry, alloc, type);
|
||||
memset(o->items, 0, sizeof(*o->items) * alloc);
|
||||
o->alloc = alloc;
|
||||
o->len = 0;
|
||||
@ -214,4 +234,6 @@ const mp_obj_module_t mp_module_utimeq = {
|
||||
.globals = (mp_obj_dict_t *)&mp_module_utimeq_globals,
|
||||
};
|
||||
|
||||
MP_REGISTER_MODULE(MP_QSTR_utimeq, mp_module_utimeq);
|
||||
|
||||
#endif // MICROPY_PY_UTIMEQ
|
||||
|
@ -1,7 +1,28 @@
|
||||
// Copyright (c) 2014-2016 Paul Sokolovsky
|
||||
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014-2016 Paul Sokolovsky
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@ -51,15 +72,14 @@ STATIC int read_src_stream(TINF_DATA *data) {
|
||||
STATIC mp_obj_t decompio_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 1, 2, false);
|
||||
mp_get_stream_raise(args[0], MP_STREAM_OP_READ);
|
||||
mp_obj_decompio_t *o = m_new_obj(mp_obj_decompio_t);
|
||||
o->base.type = type;
|
||||
mp_obj_decompio_t *o = mp_obj_malloc(mp_obj_decompio_t, type);
|
||||
memset(&o->decomp, 0, sizeof(o->decomp));
|
||||
o->decomp.readSource = read_src_stream;
|
||||
o->src_stream = args[0];
|
||||
o->eof = false;
|
||||
|
||||
mp_int_t dict_opt = 0;
|
||||
int dict_sz;
|
||||
uint dict_sz;
|
||||
if (n_args > 1) {
|
||||
dict_opt = mp_obj_get_int(args[1]);
|
||||
}
|
||||
@ -76,7 +96,10 @@ STATIC mp_obj_t decompio_make_new(const mp_obj_type_t *type, size_t n_args, size
|
||||
header_error:
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("compression header"));
|
||||
}
|
||||
dict_sz = 1 << dict_opt;
|
||||
// RFC 1950 section 2.2:
|
||||
// CINFO is the base-2 logarithm of the LZ77 window size,
|
||||
// minus eight (CINFO=7 indicates a 32K window size)
|
||||
dict_sz = 1 << (dict_opt + 8);
|
||||
} else {
|
||||
dict_sz = 1 << -dict_opt;
|
||||
}
|
||||
@ -92,12 +115,13 @@ STATIC mp_uint_t decompio_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *er
|
||||
}
|
||||
|
||||
o->decomp.dest = buf;
|
||||
o->decomp.dest_limit = (unsigned char *)buf + size;
|
||||
o->decomp.dest_limit = (byte *)buf + size;
|
||||
int st = uzlib_uncompress_chksum(&o->decomp);
|
||||
if (st == TINF_DONE) {
|
||||
o->eof = true;
|
||||
}
|
||||
if (st < 0) {
|
||||
DEBUG_printf("uncompress error=" INT_FMT "\n", st);
|
||||
*errcode = MP_EINVAL;
|
||||
return MP_STREAM_ERROR;
|
||||
}
|
||||
@ -146,9 +170,10 @@ STATIC mp_obj_t mod_uzlib_decompress(size_t n_args, const mp_obj_t *args) {
|
||||
|
||||
decomp->dest = dest_buf;
|
||||
decomp->dest_limit = dest_buf + dest_buf_size;
|
||||
DEBUG_printf("uzlib: Initial out buffer: " UINT_FMT " bytes\n", decomp->destSize);
|
||||
DEBUG_printf("uzlib: Initial out buffer: " UINT_FMT " bytes\n", dest_buf_size);
|
||||
decomp->source = bufinfo.buf;
|
||||
decomp->source_limit = (unsigned char *)bufinfo.buf + bufinfo.len;
|
||||
decomp->source_limit = (byte *)bufinfo.buf + bufinfo.len;
|
||||
|
||||
int st;
|
||||
bool is_zlib = true;
|
||||
|
||||
@ -175,7 +200,7 @@ STATIC mp_obj_t mod_uzlib_decompress(size_t n_args, const mp_obj_t *args) {
|
||||
dest_buf = m_renew(byte, dest_buf, dest_buf_size, dest_buf_size + 256);
|
||||
dest_buf_size += 256;
|
||||
decomp->dest = dest_buf + offset;
|
||||
decomp->dest_limit = dest_buf + offset + 256;
|
||||
decomp->dest_limit = decomp->dest + 256;
|
||||
}
|
||||
|
||||
mp_uint_t final_sz = decomp->dest - dest_buf;
|
||||
@ -203,6 +228,9 @@ const mp_obj_module_t mp_module_uzlib = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t *)&mp_module_uzlib_globals,
|
||||
};
|
||||
|
||||
|
||||
MP_REGISTER_MODULE(MP_QSTR_uzlib, mp_module_uzlib);
|
||||
#endif
|
||||
|
||||
// Source files #include'd here to make sure they're compiled in
|
||||
|
@ -1,30 +0,0 @@
|
||||
# MicroPython uasyncio module
|
||||
# MIT license; Copyright (c) 2019 Damien P. George
|
||||
|
||||
from .core import *
|
||||
|
||||
__version__ = (3, 0, 0)
|
||||
|
||||
_attrs = {
|
||||
"wait_for": "funcs",
|
||||
"wait_for_ms": "funcs",
|
||||
"gather": "funcs",
|
||||
"Event": "event",
|
||||
"ThreadSafeFlag": "event",
|
||||
"Lock": "lock",
|
||||
"open_connection": "stream",
|
||||
"start_server": "stream",
|
||||
"StreamReader": "stream",
|
||||
"StreamWriter": "stream",
|
||||
}
|
||||
|
||||
# Lazy loader, effectively does:
|
||||
# global attr
|
||||
# from .mod import attr
|
||||
def __getattr__(attr):
|
||||
mod = _attrs.get(attr, None)
|
||||
if mod is None:
|
||||
raise AttributeError(attr)
|
||||
value = getattr(__import__(mod, None, None, True, 1), attr)
|
||||
globals()[attr] = value
|
||||
return value
|
@ -1,295 +0,0 @@
|
||||
# MicroPython uasyncio module
|
||||
# MIT license; Copyright (c) 2019 Damien P. George
|
||||
|
||||
from time import ticks_ms as ticks, ticks_diff, ticks_add
|
||||
import sys, select
|
||||
|
||||
# Import TaskQueue and Task, preferring built-in C code over Python code
|
||||
try:
|
||||
from _uasyncio import TaskQueue, Task
|
||||
except:
|
||||
from .task import TaskQueue, Task
|
||||
|
||||
|
||||
################################################################################
|
||||
# Exceptions
|
||||
|
||||
|
||||
class CancelledError(BaseException):
|
||||
pass
|
||||
|
||||
|
||||
class TimeoutError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
# Used when calling Loop.call_exception_handler
|
||||
_exc_context = {"message": "Task exception wasn't retrieved", "exception": None, "future": None}
|
||||
|
||||
|
||||
################################################################################
|
||||
# Sleep functions
|
||||
|
||||
# "Yield" once, then raise StopIteration
|
||||
class SingletonGenerator:
|
||||
def __init__(self):
|
||||
self.state = None
|
||||
self.exc = StopIteration()
|
||||
|
||||
def __await__(self):
|
||||
return self
|
||||
|
||||
def __next__(self):
|
||||
if self.state is not None:
|
||||
_task_queue.push_sorted(cur_task, self.state)
|
||||
self.state = None
|
||||
return None
|
||||
else:
|
||||
self.exc.__traceback__ = None
|
||||
raise self.exc
|
||||
|
||||
|
||||
# Pause task execution for the given time (integer in milliseconds, uPy extension)
|
||||
# Use a SingletonGenerator to do it without allocating on the heap
|
||||
def sleep_ms(t, sgen=SingletonGenerator()):
|
||||
assert sgen.state is None
|
||||
sgen.state = ticks_add(ticks(), max(0, t))
|
||||
return sgen
|
||||
|
||||
|
||||
# Pause task execution for the given time (in seconds)
|
||||
def sleep(t):
|
||||
return sleep_ms(int(t * 1000))
|
||||
|
||||
|
||||
################################################################################
|
||||
# Queue and poller for stream IO
|
||||
|
||||
|
||||
class IOQueue:
|
||||
def __init__(self):
|
||||
self.poller = select.poll()
|
||||
self.map = {} # maps id(stream) to [task_waiting_read, task_waiting_write, stream]
|
||||
|
||||
def _enqueue(self, s, idx):
|
||||
if id(s) not in self.map:
|
||||
entry = [None, None, s]
|
||||
entry[idx] = cur_task
|
||||
self.map[id(s)] = entry
|
||||
self.poller.register(s, select.POLLIN if idx == 0 else select.POLLOUT)
|
||||
else:
|
||||
sm = self.map[id(s)]
|
||||
assert sm[idx] is None
|
||||
assert sm[1 - idx] is not None
|
||||
sm[idx] = cur_task
|
||||
self.poller.modify(s, select.POLLIN | select.POLLOUT)
|
||||
# Link task to this IOQueue so it can be removed if needed
|
||||
cur_task.data = self
|
||||
|
||||
def _dequeue(self, s):
|
||||
del self.map[id(s)]
|
||||
self.poller.unregister(s)
|
||||
|
||||
def queue_read(self, s):
|
||||
self._enqueue(s, 0)
|
||||
|
||||
def queue_write(self, s):
|
||||
self._enqueue(s, 1)
|
||||
|
||||
def remove(self, task):
|
||||
while True:
|
||||
del_s = None
|
||||
for k in self.map: # Iterate without allocating on the heap
|
||||
q0, q1, s = self.map[k]
|
||||
if q0 is task or q1 is task:
|
||||
del_s = s
|
||||
break
|
||||
if del_s is not None:
|
||||
self._dequeue(s)
|
||||
else:
|
||||
break
|
||||
|
||||
def wait_io_event(self, dt):
|
||||
for s, ev in self.poller.ipoll(dt):
|
||||
sm = self.map[id(s)]
|
||||
# print('poll', s, sm, ev)
|
||||
if ev & ~select.POLLOUT and sm[0] is not None:
|
||||
# POLLIN or error
|
||||
_task_queue.push_head(sm[0])
|
||||
sm[0] = None
|
||||
if ev & ~select.POLLIN and sm[1] is not None:
|
||||
# POLLOUT or error
|
||||
_task_queue.push_head(sm[1])
|
||||
sm[1] = None
|
||||
if sm[0] is None and sm[1] is None:
|
||||
self._dequeue(s)
|
||||
elif sm[0] is None:
|
||||
self.poller.modify(s, select.POLLOUT)
|
||||
else:
|
||||
self.poller.modify(s, select.POLLIN)
|
||||
|
||||
|
||||
################################################################################
|
||||
# Main run loop
|
||||
|
||||
# Ensure the awaitable is a task
|
||||
def _promote_to_task(aw):
|
||||
return aw if isinstance(aw, Task) else create_task(aw)
|
||||
|
||||
|
||||
# Create and schedule a new task from a coroutine
|
||||
def create_task(coro):
|
||||
if not hasattr(coro, "send"):
|
||||
raise TypeError("coroutine expected")
|
||||
t = Task(coro, globals())
|
||||
_task_queue.push_head(t)
|
||||
return t
|
||||
|
||||
|
||||
# Keep scheduling tasks until there are none left to schedule
|
||||
def run_until_complete(main_task=None):
|
||||
global cur_task
|
||||
excs_all = (CancelledError, Exception) # To prevent heap allocation in loop
|
||||
excs_stop = (CancelledError, StopIteration) # To prevent heap allocation in loop
|
||||
while True:
|
||||
# Wait until the head of _task_queue is ready to run
|
||||
dt = 1
|
||||
while dt > 0:
|
||||
dt = -1
|
||||
t = _task_queue.peek()
|
||||
if t:
|
||||
# A task waiting on _task_queue; "ph_key" is time to schedule task at
|
||||
dt = max(0, ticks_diff(t.ph_key, ticks()))
|
||||
elif not _io_queue.map:
|
||||
# No tasks can be woken so finished running
|
||||
return
|
||||
# print('(poll {})'.format(dt), len(_io_queue.map))
|
||||
_io_queue.wait_io_event(dt)
|
||||
|
||||
# Get next task to run and continue it
|
||||
t = _task_queue.pop_head()
|
||||
cur_task = t
|
||||
try:
|
||||
# Continue running the coroutine, it's responsible for rescheduling itself
|
||||
exc = t.data
|
||||
if not exc:
|
||||
t.coro.send(None)
|
||||
else:
|
||||
# If the task is finished and on the run queue and gets here, then it
|
||||
# had an exception and was not await'ed on. Throwing into it now will
|
||||
# raise StopIteration and the code below will catch this and run the
|
||||
# call_exception_handler function.
|
||||
t.data = None
|
||||
t.coro.throw(exc)
|
||||
except excs_all as er:
|
||||
# Check the task is not on any event queue
|
||||
assert t.data is None
|
||||
# This task is done, check if it's the main task and then loop should stop
|
||||
if t is main_task:
|
||||
if isinstance(er, StopIteration):
|
||||
return er.value
|
||||
raise er
|
||||
if t.state:
|
||||
# Task was running but is now finished.
|
||||
waiting = False
|
||||
if t.state is True:
|
||||
# "None" indicates that the task is complete and not await'ed on (yet).
|
||||
t.state = None
|
||||
else:
|
||||
# Schedule any other tasks waiting on the completion of this task.
|
||||
while t.state.peek():
|
||||
_task_queue.push_head(t.state.pop_head())
|
||||
waiting = True
|
||||
# "False" indicates that the task is complete and has been await'ed on.
|
||||
t.state = False
|
||||
if not waiting and not isinstance(er, excs_stop):
|
||||
# An exception ended this detached task, so queue it for later
|
||||
# execution to handle the uncaught exception if no other task retrieves
|
||||
# the exception in the meantime (this is handled by Task.throw).
|
||||
_task_queue.push_head(t)
|
||||
# Save return value of coro to pass up to caller.
|
||||
t.data = er
|
||||
elif t.state is None:
|
||||
# Task is already finished and nothing await'ed on the task,
|
||||
# so call the exception handler.
|
||||
_exc_context["exception"] = exc
|
||||
_exc_context["future"] = t
|
||||
Loop.call_exception_handler(_exc_context)
|
||||
|
||||
|
||||
# Create a new task from a coroutine and run it until it finishes
|
||||
def run(coro):
|
||||
return run_until_complete(create_task(coro))
|
||||
|
||||
|
||||
################################################################################
|
||||
# Event loop wrapper
|
||||
|
||||
|
||||
async def _stopper():
|
||||
pass
|
||||
|
||||
|
||||
_stop_task = None
|
||||
|
||||
|
||||
class Loop:
|
||||
_exc_handler = None
|
||||
|
||||
def create_task(coro):
|
||||
return create_task(coro)
|
||||
|
||||
def run_forever():
|
||||
global _stop_task
|
||||
_stop_task = Task(_stopper(), globals())
|
||||
run_until_complete(_stop_task)
|
||||
# TODO should keep running until .stop() is called, even if there're no tasks left
|
||||
|
||||
def run_until_complete(aw):
|
||||
return run_until_complete(_promote_to_task(aw))
|
||||
|
||||
def stop():
|
||||
global _stop_task
|
||||
if _stop_task is not None:
|
||||
_task_queue.push_head(_stop_task)
|
||||
# If stop() is called again, do nothing
|
||||
_stop_task = None
|
||||
|
||||
def close():
|
||||
pass
|
||||
|
||||
def set_exception_handler(handler):
|
||||
Loop._exc_handler = handler
|
||||
|
||||
def get_exception_handler():
|
||||
return Loop._exc_handler
|
||||
|
||||
def default_exception_handler(loop, context):
|
||||
print(context["message"])
|
||||
print("future:", context["future"], "coro=", context["future"].coro)
|
||||
sys.print_exception(context["exception"])
|
||||
|
||||
def call_exception_handler(context):
|
||||
(Loop._exc_handler or Loop.default_exception_handler)(Loop, context)
|
||||
|
||||
|
||||
# The runq_len and waitq_len arguments are for legacy uasyncio compatibility
|
||||
def get_event_loop(runq_len=0, waitq_len=0):
|
||||
return Loop
|
||||
|
||||
|
||||
def current_task():
|
||||
return cur_task
|
||||
|
||||
|
||||
def new_event_loop():
|
||||
global _task_queue, _io_queue
|
||||
# TaskQueue of Task instances
|
||||
_task_queue = TaskQueue()
|
||||
# Task queue and poller for stream IO
|
||||
_io_queue = IOQueue()
|
||||
return Loop
|
||||
|
||||
|
||||
# Initialise default event loop
|
||||
new_event_loop()
|
@ -1,33 +0,0 @@
|
||||
# MicroPython uasyncio module
|
||||
# MIT license; Copyright (c) 2019-2020 Damien P. George
|
||||
|
||||
from . import core
|
||||
|
||||
# Event class for primitive events that can be waited on, set, and cleared
|
||||
class Event:
|
||||
def __init__(self):
|
||||
self.state = False # False=unset; True=set
|
||||
self.waiting = core.TaskQueue() # Queue of Tasks waiting on completion of this event
|
||||
|
||||
def is_set(self):
|
||||
return self.state
|
||||
|
||||
def set(self):
|
||||
# Event becomes set, schedule any tasks waiting on it
|
||||
# Note: This must not be called from anything except the thread running
|
||||
# the asyncio loop (i.e. neither hard or soft IRQ, or a different thread).
|
||||
while self.waiting.peek():
|
||||
core._task_queue.push_head(self.waiting.pop_head())
|
||||
self.state = True
|
||||
|
||||
def clear(self):
|
||||
self.state = False
|
||||
|
||||
async def wait(self):
|
||||
if not self.state:
|
||||
# Event not set, put the calling task on the event's waiting queue
|
||||
self.waiting.push_head(core.cur_task)
|
||||
# Set calling task's data to the event's queue so it can be removed if needed
|
||||
core.cur_task.data = self.waiting
|
||||
yield
|
||||
return True
|
@ -1,74 +0,0 @@
|
||||
# MicroPython uasyncio module
|
||||
# MIT license; Copyright (c) 2019-2020 Damien P. George
|
||||
|
||||
from . import core
|
||||
|
||||
|
||||
async def wait_for(aw, timeout, sleep=core.sleep):
|
||||
aw = core._promote_to_task(aw)
|
||||
if timeout is None:
|
||||
return await aw
|
||||
|
||||
def runner(waiter, aw):
|
||||
nonlocal status, result
|
||||
try:
|
||||
result = await aw
|
||||
s = True
|
||||
except BaseException as er:
|
||||
s = er
|
||||
if status is None:
|
||||
# The waiter is still waiting, set status for it and cancel it.
|
||||
status = s
|
||||
waiter.cancel()
|
||||
|
||||
# Run aw in a separate runner task that manages its exceptions.
|
||||
status = None
|
||||
result = None
|
||||
runner_task = core.create_task(runner(core.cur_task, aw))
|
||||
|
||||
try:
|
||||
# Wait for the timeout to elapse.
|
||||
await sleep(timeout)
|
||||
except core.CancelledError as er:
|
||||
if status is True:
|
||||
# aw completed successfully and cancelled the sleep, so return aw's result.
|
||||
return result
|
||||
elif status is None:
|
||||
# This wait_for was cancelled externally, so cancel aw and re-raise.
|
||||
status = True
|
||||
runner_task.cancel()
|
||||
raise er
|
||||
else:
|
||||
# aw raised an exception, propagate it out to the caller.
|
||||
raise status
|
||||
|
||||
# The sleep finished before aw, so cancel aw and raise TimeoutError.
|
||||
status = True
|
||||
runner_task.cancel()
|
||||
await runner_task
|
||||
raise core.TimeoutError
|
||||
|
||||
|
||||
def wait_for_ms(aw, timeout):
|
||||
return wait_for(aw, timeout, core.sleep_ms)
|
||||
|
||||
|
||||
async def gather(*aws, return_exceptions=False):
|
||||
ts = [core._promote_to_task(aw) for aw in aws]
|
||||
for i in range(len(ts)):
|
||||
try:
|
||||
# TODO handle cancel of gather itself
|
||||
# if ts[i].coro:
|
||||
# iter(ts[i]).waiting.push_head(cur_task)
|
||||
# try:
|
||||
# yield
|
||||
# except CancelledError as er:
|
||||
# # cancel all waiting tasks
|
||||
# raise er
|
||||
ts[i] = await ts[i]
|
||||
except (core.CancelledError, Exception) as er:
|
||||
if return_exceptions:
|
||||
ts[i] = er
|
||||
else:
|
||||
raise er
|
||||
return ts
|
@ -1,53 +0,0 @@
|
||||
# MicroPython uasyncio module
|
||||
# MIT license; Copyright (c) 2019-2020 Damien P. George
|
||||
|
||||
from . import core
|
||||
|
||||
# Lock class for primitive mutex capability
|
||||
class Lock:
|
||||
def __init__(self):
|
||||
# The state can take the following values:
|
||||
# - 0: unlocked
|
||||
# - 1: locked
|
||||
# - <Task>: unlocked but this task has been scheduled to acquire the lock next
|
||||
self.state = 0
|
||||
# Queue of Tasks waiting to acquire this Lock
|
||||
self.waiting = core.TaskQueue()
|
||||
|
||||
def locked(self):
|
||||
return self.state == 1
|
||||
|
||||
def release(self):
|
||||
if self.state != 1:
|
||||
raise RuntimeError("Lock not acquired")
|
||||
if self.waiting.peek():
|
||||
# Task(s) waiting on lock, schedule next Task
|
||||
self.state = self.waiting.pop_head()
|
||||
core._task_queue.push_head(self.state)
|
||||
else:
|
||||
# No Task waiting so unlock
|
||||
self.state = 0
|
||||
|
||||
async def acquire(self):
|
||||
if self.state != 0:
|
||||
# Lock unavailable, put the calling Task on the waiting queue
|
||||
self.waiting.push_head(core.cur_task)
|
||||
# Set calling task's data to the lock's queue so it can be removed if needed
|
||||
core.cur_task.data = self.waiting
|
||||
try:
|
||||
yield
|
||||
except core.CancelledError as er:
|
||||
if self.state == core.cur_task:
|
||||
# Cancelled while pending on resume, schedule next waiting Task
|
||||
self.state = 1
|
||||
self.release()
|
||||
raise er
|
||||
# Lock available, set it as locked
|
||||
self.state = 1
|
||||
return True
|
||||
|
||||
async def __aenter__(self):
|
||||
return await self.acquire()
|
||||
|
||||
async def __aexit__(self, exc_type, exc, tb):
|
||||
return self.release()
|
@ -1,13 +0,0 @@
|
||||
# This list of frozen files doesn't include task.py because that's provided by the C module.
|
||||
freeze(
|
||||
"..",
|
||||
(
|
||||
"uasyncio/__init__.py",
|
||||
"uasyncio/core.py",
|
||||
"uasyncio/event.py",
|
||||
"uasyncio/funcs.py",
|
||||
"uasyncio/lock.py",
|
||||
"uasyncio/stream.py",
|
||||
),
|
||||
opt=3,
|
||||
)
|
@ -1,164 +0,0 @@
|
||||
# MicroPython uasyncio module
|
||||
# MIT license; Copyright (c) 2019-2020 Damien P. George
|
||||
|
||||
from . import core
|
||||
|
||||
|
||||
class Stream:
|
||||
def __init__(self, s, e={}):
|
||||
self.s = s
|
||||
self.e = e
|
||||
self.out_buf = b""
|
||||
|
||||
def get_extra_info(self, v):
|
||||
return self.e[v]
|
||||
|
||||
async def __aenter__(self):
|
||||
return self
|
||||
|
||||
async def __aexit__(self, exc_type, exc, tb):
|
||||
await self.close()
|
||||
|
||||
def close(self):
|
||||
pass
|
||||
|
||||
async def wait_closed(self):
|
||||
# TODO yield?
|
||||
self.s.close()
|
||||
|
||||
async def read(self, n):
|
||||
yield core._io_queue.queue_read(self.s)
|
||||
return self.s.read(n)
|
||||
|
||||
async def readinto(self, buf):
|
||||
yield core._io_queue.queue_read(self.s)
|
||||
return self.s.readinto(buf)
|
||||
|
||||
async def readexactly(self, n):
|
||||
r = b""
|
||||
while n:
|
||||
yield core._io_queue.queue_read(self.s)
|
||||
r2 = self.s.read(n)
|
||||
if r2 is not None:
|
||||
if not len(r2):
|
||||
raise EOFError
|
||||
r += r2
|
||||
n -= len(r2)
|
||||
return r
|
||||
|
||||
async def readline(self):
|
||||
l = b""
|
||||
while True:
|
||||
yield core._io_queue.queue_read(self.s)
|
||||
l2 = self.s.readline() # may do multiple reads but won't block
|
||||
l += l2
|
||||
if not l2 or l[-1] == 10: # \n (check l in case l2 is str)
|
||||
return l
|
||||
|
||||
def write(self, buf):
|
||||
self.out_buf += buf
|
||||
|
||||
async def drain(self):
|
||||
mv = memoryview(self.out_buf)
|
||||
off = 0
|
||||
while off < len(mv):
|
||||
yield core._io_queue.queue_write(self.s)
|
||||
ret = self.s.write(mv[off:])
|
||||
if ret is not None:
|
||||
off += ret
|
||||
self.out_buf = b""
|
||||
|
||||
|
||||
# Stream can be used for both reading and writing to save code size
|
||||
StreamReader = Stream
|
||||
StreamWriter = Stream
|
||||
|
||||
|
||||
# Create a TCP stream connection to a remote host
|
||||
async def open_connection(host, port):
|
||||
from uerrno import EINPROGRESS
|
||||
import usocket as socket
|
||||
|
||||
ai = socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM)[0] # TODO this is blocking!
|
||||
s = socket.socket(ai[0], ai[1], ai[2])
|
||||
s.setblocking(False)
|
||||
ss = Stream(s)
|
||||
try:
|
||||
s.connect(ai[-1])
|
||||
except OSError as er:
|
||||
if er.errno != EINPROGRESS:
|
||||
raise er
|
||||
yield core._io_queue.queue_write(s)
|
||||
return ss, ss
|
||||
|
||||
|
||||
# Class representing a TCP stream server, can be closed and used in "async with"
|
||||
class Server:
|
||||
async def __aenter__(self):
|
||||
return self
|
||||
|
||||
async def __aexit__(self, exc_type, exc, tb):
|
||||
self.close()
|
||||
await self.wait_closed()
|
||||
|
||||
def close(self):
|
||||
self.task.cancel()
|
||||
|
||||
async def wait_closed(self):
|
||||
await self.task
|
||||
|
||||
async def _serve(self, s, cb):
|
||||
# Accept incoming connections
|
||||
while True:
|
||||
try:
|
||||
yield core._io_queue.queue_read(s)
|
||||
except core.CancelledError:
|
||||
# Shutdown server
|
||||
s.close()
|
||||
return
|
||||
try:
|
||||
s2, addr = s.accept()
|
||||
except:
|
||||
# Ignore a failed accept
|
||||
continue
|
||||
s2.setblocking(False)
|
||||
s2s = Stream(s2, {"peername": addr})
|
||||
core.create_task(cb(s2s, s2s))
|
||||
|
||||
|
||||
# Helper function to start a TCP stream server, running as a new task
|
||||
# TODO could use an accept-callback on socket read activity instead of creating a task
|
||||
async def start_server(cb, host, port, backlog=5):
|
||||
import usocket as socket
|
||||
|
||||
# Create and bind server socket.
|
||||
host = socket.getaddrinfo(host, port)[0] # TODO this is blocking!
|
||||
s = socket.socket()
|
||||
s.setblocking(False)
|
||||
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
s.bind(host[-1])
|
||||
s.listen(backlog)
|
||||
|
||||
# Create and return server object and task.
|
||||
srv = Server()
|
||||
srv.task = core.create_task(srv._serve(s, cb))
|
||||
return srv
|
||||
|
||||
|
||||
################################################################################
|
||||
# Legacy uasyncio compatibility
|
||||
|
||||
|
||||
async def stream_awrite(self, buf, off=0, sz=-1):
|
||||
if off != 0 or sz != -1:
|
||||
buf = memoryview(buf)
|
||||
if sz == -1:
|
||||
sz = len(buf)
|
||||
buf = buf[off : off + sz]
|
||||
self.write(buf)
|
||||
await self.drain()
|
||||
|
||||
|
||||
Stream.aclose = Stream.wait_closed
|
||||
Stream.awrite = stream_awrite
|
||||
Stream.awritestr = stream_awrite # TODO explicitly convert to bytes?
|
@ -1,179 +0,0 @@
|
||||
# MicroPython uasyncio module
|
||||
# MIT license; Copyright (c) 2019-2020 Damien P. George
|
||||
|
||||
# This file contains the core TaskQueue based on a pairing heap, and the core Task class.
|
||||
# They can optionally be replaced by C implementations.
|
||||
|
||||
from . import core
|
||||
|
||||
|
||||
# pairing-heap meld of 2 heaps; O(1)
|
||||
def ph_meld(h1, h2):
|
||||
if h1 is None:
|
||||
return h2
|
||||
if h2 is None:
|
||||
return h1
|
||||
lt = core.ticks_diff(h1.ph_key, h2.ph_key) < 0
|
||||
if lt:
|
||||
if h1.ph_child is None:
|
||||
h1.ph_child = h2
|
||||
else:
|
||||
h1.ph_child_last.ph_next = h2
|
||||
h1.ph_child_last = h2
|
||||
h2.ph_next = None
|
||||
h2.ph_rightmost_parent = h1
|
||||
return h1
|
||||
else:
|
||||
h1.ph_next = h2.ph_child
|
||||
h2.ph_child = h1
|
||||
if h1.ph_next is None:
|
||||
h2.ph_child_last = h1
|
||||
h1.ph_rightmost_parent = h2
|
||||
return h2
|
||||
|
||||
|
||||
# pairing-heap pairing operation; amortised O(log N)
|
||||
def ph_pairing(child):
|
||||
heap = None
|
||||
while child is not None:
|
||||
n1 = child
|
||||
child = child.ph_next
|
||||
n1.ph_next = None
|
||||
if child is not None:
|
||||
n2 = child
|
||||
child = child.ph_next
|
||||
n2.ph_next = None
|
||||
n1 = ph_meld(n1, n2)
|
||||
heap = ph_meld(heap, n1)
|
||||
return heap
|
||||
|
||||
|
||||
# pairing-heap delete of a node; stable, amortised O(log N)
|
||||
def ph_delete(heap, node):
|
||||
if node is heap:
|
||||
child = heap.ph_child
|
||||
node.ph_child = None
|
||||
return ph_pairing(child)
|
||||
# Find parent of node
|
||||
parent = node
|
||||
while parent.ph_next is not None:
|
||||
parent = parent.ph_next
|
||||
parent = parent.ph_rightmost_parent
|
||||
# Replace node with pairing of its children
|
||||
if node is parent.ph_child and node.ph_child is None:
|
||||
parent.ph_child = node.ph_next
|
||||
node.ph_next = None
|
||||
return heap
|
||||
elif node is parent.ph_child:
|
||||
child = node.ph_child
|
||||
next = node.ph_next
|
||||
node.ph_child = None
|
||||
node.ph_next = None
|
||||
node = ph_pairing(child)
|
||||
parent.ph_child = node
|
||||
else:
|
||||
n = parent.ph_child
|
||||
while node is not n.ph_next:
|
||||
n = n.ph_next
|
||||
child = node.ph_child
|
||||
next = node.ph_next
|
||||
node.ph_child = None
|
||||
node.ph_next = None
|
||||
node = ph_pairing(child)
|
||||
if node is None:
|
||||
node = n
|
||||
else:
|
||||
n.ph_next = node
|
||||
node.ph_next = next
|
||||
if next is None:
|
||||
node.ph_rightmost_parent = parent
|
||||
parent.ph_child_last = node
|
||||
return heap
|
||||
|
||||
|
||||
# TaskQueue class based on the above pairing-heap functions.
|
||||
class TaskQueue:
|
||||
def __init__(self):
|
||||
self.heap = None
|
||||
|
||||
def peek(self):
|
||||
return self.heap
|
||||
|
||||
def push_sorted(self, v, key):
|
||||
v.data = None
|
||||
v.ph_key = key
|
||||
v.ph_child = None
|
||||
v.ph_next = None
|
||||
self.heap = ph_meld(v, self.heap)
|
||||
|
||||
def push_head(self, v):
|
||||
self.push_sorted(v, core.ticks())
|
||||
|
||||
def pop_head(self):
|
||||
v = self.heap
|
||||
self.heap = ph_pairing(self.heap.ph_child)
|
||||
return v
|
||||
|
||||
def remove(self, v):
|
||||
self.heap = ph_delete(self.heap, v)
|
||||
|
||||
|
||||
# Task class representing a coroutine, can be waited on and cancelled.
|
||||
class Task:
|
||||
def __init__(self, coro, globals=None):
|
||||
self.coro = coro # Coroutine of this Task
|
||||
self.data = None # General data for queue it is waiting on
|
||||
self.state = True # None, False, True or a TaskQueue instance
|
||||
self.ph_key = 0 # Pairing heap
|
||||
self.ph_child = None # Paring heap
|
||||
self.ph_child_last = None # Paring heap
|
||||
self.ph_next = None # Paring heap
|
||||
self.ph_rightmost_parent = None # Paring heap
|
||||
|
||||
def __await__(self):
|
||||
if not self.state:
|
||||
# Task finished, signal that is has been await'ed on.
|
||||
self.state = False
|
||||
elif self.state is True:
|
||||
# Allocated head of linked list of Tasks waiting on completion of this task.
|
||||
self.state = TaskQueue()
|
||||
return self
|
||||
|
||||
def __next__(self):
|
||||
if not self.state:
|
||||
if self.data is None:
|
||||
# Task finished but has already been sent to the loop's exception handler.
|
||||
raise StopIteration
|
||||
else:
|
||||
# Task finished, raise return value to caller so it can continue.
|
||||
raise self.data
|
||||
else:
|
||||
# Put calling task on waiting queue.
|
||||
self.state.push_head(core.cur_task)
|
||||
# Set calling task's data to this task that it waits on, to double-link it.
|
||||
core.cur_task.data = self
|
||||
|
||||
def done(self):
|
||||
return not self.state
|
||||
|
||||
def cancel(self):
|
||||
# Check if task is already finished.
|
||||
if not self.state:
|
||||
return False
|
||||
# Can't cancel self (not supported yet).
|
||||
if self is core.cur_task:
|
||||
raise RuntimeError("can't cancel self")
|
||||
# If Task waits on another task then forward the cancel to the one it's waiting on.
|
||||
while isinstance(self.data, Task):
|
||||
self = self.data
|
||||
# Reschedule Task as a cancelled task.
|
||||
if hasattr(self.data, "remove"):
|
||||
# Not on the main running queue, remove the task from the queue it's on.
|
||||
self.data.remove(self)
|
||||
core._task_queue.push_head(self)
|
||||
elif core.ticks_diff(self.ph_key, core.ticks()) > 0:
|
||||
# On the main running queue but scheduled in the future, so bring it forward to now.
|
||||
core._task_queue.remove(self)
|
||||
core._task_queue.push_head(self)
|
||||
self.data = core.CancelledError
|
||||
return True
|
@ -1,8 +1,29 @@
|
||||
// Copyright (c) 2016 Paul Sokolovsky
|
||||
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2013-2016 Damien P. George
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013-2016 Damien P. George
|
||||
* Copyright (c) 2016 Paul Sokolovsky
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "py/mpconfig.h"
|
||||
#if MICROPY_PY_UTIME_MP_HAL
|
||||
|
@ -1,9 +1,29 @@
|
||||
// Copyright (c) 2016 Paul Sokolovsky
|
||||
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2013-2016 Damien P. George
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013-2016 Damien P. George
|
||||
* Copyright (c) 2016 Paul Sokolovsky
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef MICROPY_INCLUDED_EXTMOD_UTIME_MPHAL_H
|
||||
#define MICROPY_INCLUDED_EXTMOD_UTIME_MPHAL_H
|
||||
|
||||
|
32
extmod/vfs.c
32
extmod/vfs.c
@ -1,7 +1,28 @@
|
||||
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2017 Damien P. George
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
@ -386,8 +407,7 @@ mp_obj_t mp_vfs_ilistdir(size_t n_args, const mp_obj_t *args) {
|
||||
|
||||
if (vfs == MP_VFS_ROOT) {
|
||||
// list the root directory
|
||||
mp_vfs_ilistdir_it_t *iter = m_new_obj(mp_vfs_ilistdir_it_t);
|
||||
iter->base.type = &mp_type_polymorph_iter;
|
||||
mp_vfs_ilistdir_it_t *iter = mp_obj_malloc(mp_vfs_ilistdir_it_t, &mp_type_polymorph_iter);
|
||||
iter->iternext = mp_vfs_ilistdir_it_iternext;
|
||||
iter->cur.vfs = MP_STATE_VM(vfs_mount_table);
|
||||
iter->is_str = mp_obj_get_type(path_in) == &mp_type_str;
|
||||
|
32
extmod/vfs.h
32
extmod/vfs.h
@ -1,12 +1,32 @@
|
||||
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2017 Damien P. George
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef MICROPY_INCLUDED_EXTMOD_VFS_H
|
||||
#define MICROPY_INCLUDED_EXTMOD_VFS_H
|
||||
|
||||
#include "py/lexer.h"
|
||||
#include "py/builtin.h"
|
||||
#include "py/obj.h"
|
||||
#include "py/proto.h"
|
||||
|
||||
|
@ -1,8 +1,29 @@
|
||||
// Copyright (c) 2016 Paul Sokolovsky
|
||||
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2014 Damien P. George
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014 Damien P. George
|
||||
* Copyright (c) 2016 Paul Sokolovsky
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "py/mpconfig.h"
|
||||
#if MICROPY_VFS_FAT
|
||||
@ -54,8 +75,7 @@ STATIC mp_obj_t fat_vfs_make_new(const mp_obj_type_t *type, size_t n_args, size_
|
||||
mp_arg_check_num(n_args, n_kw, 1, 1, false);
|
||||
|
||||
// create new object
|
||||
fs_user_mount_t *vfs = m_new_obj(fs_user_mount_t);
|
||||
vfs->base.type = type;
|
||||
fs_user_mount_t *vfs = mp_obj_malloc(fs_user_mount_t, type);
|
||||
vfs->fatfs.drv = vfs;
|
||||
|
||||
// Initialise underlying block device
|
||||
@ -171,8 +191,7 @@ STATIC mp_obj_t fat_vfs_ilistdir_func(size_t n_args, const mp_obj_t *args) {
|
||||
}
|
||||
|
||||
// Create a new iterator object to list the dir
|
||||
mp_vfs_fat_ilistdir_it_t *iter = m_new_obj(mp_vfs_fat_ilistdir_it_t);
|
||||
iter->base.type = &mp_type_polymorph_iter;
|
||||
mp_vfs_fat_ilistdir_it_t *iter = mp_obj_malloc(mp_vfs_fat_ilistdir_it_t, &mp_type_polymorph_iter);
|
||||
iter->iternext = mp_vfs_fat_ilistdir_it_iternext;
|
||||
iter->is_str = is_str_type;
|
||||
FRESULT res = f_opendir(&self->fatfs, &iter->dir, path);
|
||||
|
@ -1,8 +1,28 @@
|
||||
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013, 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.
|
||||
*/
|
||||
#ifndef MICROPY_INCLUDED_EXTMOD_VFS_FAT_H
|
||||
#define MICROPY_INCLUDED_EXTMOD_VFS_FAT_H
|
||||
|
||||
|
@ -1,7 +1,31 @@
|
||||
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* Original template for this file comes from:
|
||||
* Low level disk I/O module skeleton for FatFs, (C)ChaN, 2013
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013, 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 "py/mpconfig.h"
|
||||
#if MICROPY_VFS && MICROPY_VFS_FAT
|
||||
|
@ -1,7 +1,28 @@
|
||||
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013, 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 "py/mpconfig.h"
|
||||
#if MICROPY_VFS && MICROPY_VFS_FAT
|
||||
@ -136,6 +157,7 @@ STATIC const mp_arg_t file_open_args[] = {
|
||||
};
|
||||
#define FILE_OPEN_NUM_ARGS MP_ARRAY_SIZE(file_open_args)
|
||||
|
||||
// CIRCUITPY is more careful about validating the open mode.
|
||||
STATIC mp_obj_t file_open(fs_user_mount_t *vfs, const mp_obj_type_t *type, mp_arg_val_t *args) {
|
||||
int mode = 0;
|
||||
const char *mode_s = mp_obj_str_get_str(args[1].u_obj);
|
||||
|
@ -203,8 +203,7 @@ STATIC mp_obj_t MP_VFS_LFSx(ilistdir_func)(size_t n_args, const mp_obj_t *args)
|
||||
path = vstr_null_terminated_str(&self->cur_dir);
|
||||
}
|
||||
|
||||
MP_VFS_LFSx(ilistdir_it_t) * iter = m_new_obj(MP_VFS_LFSx(ilistdir_it_t));
|
||||
iter->base.type = &mp_type_polymorph_iter;
|
||||
MP_VFS_LFSx(ilistdir_it_t) * iter = mp_obj_malloc(MP_VFS_LFSx(ilistdir_it_t), &mp_type_polymorph_iter);
|
||||
iter->iternext = MP_VFS_LFSx(ilistdir_it_iternext);
|
||||
iter->is_str = is_str_type;
|
||||
iter->vfs = self;
|
||||
|
@ -1,7 +1,28 @@
|
||||
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2017-2018 Damien P. George
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2017-2018 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "py/mperrno.h"
|
||||
@ -16,6 +37,9 @@
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <dirent.h>
|
||||
#ifdef _MSC_VER
|
||||
#include <direct.h> // For mkdir etc.
|
||||
#endif
|
||||
|
||||
typedef struct _mp_obj_vfs_posix_t {
|
||||
mp_obj_base_t base;
|
||||
@ -74,8 +98,7 @@ STATIC mp_import_stat_t mp_vfs_posix_import_stat(void *self_in, const char *path
|
||||
STATIC mp_obj_t vfs_posix_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 0, 1, false);
|
||||
|
||||
mp_obj_vfs_posix_t *vfs = m_new_obj(mp_obj_vfs_posix_t);
|
||||
vfs->base.type = type;
|
||||
mp_obj_vfs_posix_t *vfs = mp_obj_malloc(mp_obj_vfs_posix_t, type);
|
||||
vstr_init(&vfs->root, 0);
|
||||
if (n_args == 1) {
|
||||
vstr_add_str(&vfs->root, mp_obj_str_get_str(args[0]));
|
||||
@ -205,8 +228,7 @@ STATIC mp_obj_t vfs_posix_ilistdir_it_iternext(mp_obj_t self_in) {
|
||||
|
||||
STATIC mp_obj_t vfs_posix_ilistdir(mp_obj_t self_in, mp_obj_t path_in) {
|
||||
mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
vfs_posix_ilistdir_it_t *iter = m_new_obj(vfs_posix_ilistdir_it_t);
|
||||
iter->base.type = &mp_type_polymorph_iter;
|
||||
vfs_posix_ilistdir_it_t *iter = mp_obj_malloc(vfs_posix_ilistdir_it_t, &mp_type_polymorph_iter);
|
||||
iter->iternext = vfs_posix_ilistdir_it_iternext;
|
||||
iter->is_str = mp_obj_get_type(path_in) == &mp_type_str;
|
||||
const char *path = vfs_posix_get_path_str(self, path_in);
|
||||
@ -233,7 +255,11 @@ STATIC mp_obj_t vfs_posix_mkdir(mp_obj_t self_in, mp_obj_t path_in) {
|
||||
mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
const char *path = vfs_posix_get_path_str(self, path_in);
|
||||
MP_THREAD_GIL_EXIT();
|
||||
#ifdef _WIN32
|
||||
int ret = mkdir(path);
|
||||
#else
|
||||
int ret = mkdir(path, 0777);
|
||||
#endif
|
||||
MP_THREAD_GIL_ENTER();
|
||||
if (ret != 0) {
|
||||
mp_raise_OSError(errno);
|
||||
@ -287,6 +313,8 @@ STATIC mp_obj_t vfs_posix_stat(mp_obj_t self_in, mp_obj_t path_in) {
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(vfs_posix_stat_obj, vfs_posix_stat);
|
||||
|
||||
#if MICROPY_PY_UOS_STATVFS
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#define USE_STATFS 1
|
||||
#endif
|
||||
@ -328,6 +356,8 @@ STATIC mp_obj_t vfs_posix_statvfs(mp_obj_t self_in, mp_obj_t path_in) {
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(vfs_posix_statvfs_obj, vfs_posix_statvfs);
|
||||
|
||||
#endif
|
||||
|
||||
STATIC const mp_rom_map_elem_t vfs_posix_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&vfs_posix_mount_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&vfs_posix_umount_obj) },
|
||||
@ -341,7 +371,9 @@ STATIC const mp_rom_map_elem_t vfs_posix_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_rename), MP_ROM_PTR(&vfs_posix_rename_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_rmdir), MP_ROM_PTR(&vfs_posix_rmdir_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&vfs_posix_stat_obj) },
|
||||
#if MICROPY_PY_UOS_STATVFS
|
||||
{ MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&vfs_posix_statvfs_obj) },
|
||||
#endif
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(vfs_posix_locals_dict, vfs_posix_locals_dict_table);
|
||||
|
||||
|
@ -1,8 +1,28 @@
|
||||
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2018 Damien P. George
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef MICROPY_INCLUDED_EXTMOD_VFS_POSIX_H
|
||||
#define MICROPY_INCLUDED_EXTMOD_VFS_POSIX_H
|
||||
|
||||
|
@ -1,7 +1,28 @@
|
||||
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2013-2018 Damien P. George
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013-2018 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "py/mphal.h"
|
||||
#include "py/mpthread.h"
|
||||
|
@ -1,7 +1,28 @@
|
||||
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2013-2017 Damien P. George
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013-2017 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
@ -1,7 +1,28 @@
|
||||
// SPDX-FileCopyrightText: Copyright (c) 2016 Paul Sokolovsky
|
||||
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Paul Sokolovsky
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "extmod/virtpin.h"
|
||||
#include "py/proto.h"
|
||||
|
@ -1,8 +1,28 @@
|
||||
// Copyright (c) 2016 Paul Sokolovsky
|
||||
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Paul Sokolovsky
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef MICROPY_INCLUDED_EXTMOD_VIRTPIN_H
|
||||
#define MICROPY_INCLUDED_EXTMOD_VIRTPIN_H
|
||||
|
||||
|
1546
lib/littlefs/lfs2.c
1546
lib/littlefs/lfs2.c
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,7 @@
|
||||
/*
|
||||
* The little filesystem
|
||||
*
|
||||
* Copyright (c) 2022, The littlefs authors.
|
||||
* Copyright (c) 2017, Arm Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
@ -22,7 +23,7 @@ extern "C"
|
||||
// Software library version
|
||||
// Major (top-nibble), incremented on backwards incompatible changes
|
||||
// Minor (bottom-nibble), incremented on feature additions
|
||||
#define LFS2_VERSION 0x00020003
|
||||
#define LFS2_VERSION 0x00020005
|
||||
#define LFS2_VERSION_MAJOR (0xffff & (LFS2_VERSION >> 16))
|
||||
#define LFS2_VERSION_MINOR (0xffff & (LFS2_VERSION >> 0))
|
||||
|
||||
@ -159,49 +160,49 @@ struct lfs2_config {
|
||||
// information to the block device operations
|
||||
void *context;
|
||||
|
||||
// Read a region in a block. Negative error codes are propogated
|
||||
// Read a region in a block. Negative error codes are propagated
|
||||
// to the user.
|
||||
int (*read)(const struct lfs2_config *c, lfs2_block_t block,
|
||||
lfs2_off_t off, void *buffer, lfs2_size_t size);
|
||||
|
||||
// Program a region in a block. The block must have previously
|
||||
// been erased. Negative error codes are propogated to the user.
|
||||
// been erased. Negative error codes are propagated to the user.
|
||||
// May return LFS2_ERR_CORRUPT if the block should be considered bad.
|
||||
int (*prog)(const struct lfs2_config *c, lfs2_block_t block,
|
||||
lfs2_off_t off, const void *buffer, lfs2_size_t size);
|
||||
|
||||
// Erase a block. A block must be erased before being programmed.
|
||||
// The state of an erased block is undefined. Negative error codes
|
||||
// are propogated to the user.
|
||||
// are propagated to the user.
|
||||
// May return LFS2_ERR_CORRUPT if the block should be considered bad.
|
||||
int (*erase)(const struct lfs2_config *c, lfs2_block_t block);
|
||||
|
||||
// Sync the state of the underlying block device. Negative error codes
|
||||
// are propogated to the user.
|
||||
// are propagated to the user.
|
||||
int (*sync)(const struct lfs2_config *c);
|
||||
|
||||
#ifdef LFS2_THREADSAFE
|
||||
// Lock the underlying block device. Negative error codes
|
||||
// are propogated to the user.
|
||||
// are propagated to the user.
|
||||
int (*lock)(const struct lfs2_config *c);
|
||||
|
||||
// Unlock the underlying block device. Negative error codes
|
||||
// are propogated to the user.
|
||||
// are propagated to the user.
|
||||
int (*unlock)(const struct lfs2_config *c);
|
||||
#endif
|
||||
|
||||
// Minimum size of a block read. All read operations will be a
|
||||
// Minimum size of a block read in bytes. All read operations will be a
|
||||
// multiple of this value.
|
||||
lfs2_size_t read_size;
|
||||
|
||||
// Minimum size of a block program. All program operations will be a
|
||||
// multiple of this value.
|
||||
// Minimum size of a block program in bytes. All program operations will be
|
||||
// a multiple of this value.
|
||||
lfs2_size_t prog_size;
|
||||
|
||||
// Size of an erasable block. This does not impact ram consumption and
|
||||
// may be larger than the physical erase size. However, non-inlined files
|
||||
// take up at minimum one block. Must be a multiple of the read
|
||||
// and program sizes.
|
||||
// Size of an erasable block in bytes. This does not impact ram consumption
|
||||
// and may be larger than the physical erase size. However, non-inlined
|
||||
// files take up at minimum one block. Must be a multiple of the read and
|
||||
// program sizes.
|
||||
lfs2_size_t block_size;
|
||||
|
||||
// Number of erasable blocks on the device.
|
||||
@ -215,11 +216,11 @@ struct lfs2_config {
|
||||
// Set to -1 to disable block-level wear-leveling.
|
||||
int32_t block_cycles;
|
||||
|
||||
// Size of block caches. Each cache buffers a portion of a block in RAM.
|
||||
// The littlefs needs a read cache, a program cache, and one additional
|
||||
// Size of block caches in bytes. Each cache buffers a portion of a block in
|
||||
// RAM. The littlefs needs a read cache, a program cache, and one additional
|
||||
// cache per file. Larger caches can improve performance by storing more
|
||||
// data and reducing the number of disk accesses. Must be a multiple of
|
||||
// the read and program sizes, and a factor of the block size.
|
||||
// data and reducing the number of disk accesses. Must be a multiple of the
|
||||
// read and program sizes, and a factor of the block size.
|
||||
lfs2_size_t cache_size;
|
||||
|
||||
// Size of the lookahead buffer in bytes. A larger lookahead buffer
|
||||
@ -256,6 +257,12 @@ struct lfs2_config {
|
||||
// larger attributes size but must be <= LFS2_ATTR_MAX. Defaults to
|
||||
// LFS2_ATTR_MAX when zero.
|
||||
lfs2_size_t attr_max;
|
||||
|
||||
// Optional upper limit on total space given to metadata pairs in bytes. On
|
||||
// devices with large blocks (e.g. 128kB) setting this to a low size (2-8kB)
|
||||
// can help bound the metadata compaction time. Must be <= block_size.
|
||||
// Defaults to block_size when zero.
|
||||
lfs2_size_t metadata_max;
|
||||
};
|
||||
|
||||
// File info structure
|
||||
@ -479,7 +486,7 @@ int lfs2_stat(lfs2_t *lfs2, const char *path, struct lfs2_info *info);
|
||||
// Returns the size of the attribute, or a negative error code on failure.
|
||||
// Note, the returned size is the size of the attribute on disk, irrespective
|
||||
// of the size of the buffer. This can be used to dynamically allocate a buffer
|
||||
// or check for existance.
|
||||
// or check for existence.
|
||||
lfs2_ssize_t lfs2_getattr(lfs2_t *lfs2, const char *path,
|
||||
uint8_t type, void *buffer, lfs2_size_t size);
|
||||
|
||||
@ -507,6 +514,7 @@ int lfs2_removeattr(lfs2_t *lfs2, const char *path, uint8_t type);
|
||||
|
||||
/// File operations ///
|
||||
|
||||
#ifndef LFS2_NO_MALLOC
|
||||
// Open a file
|
||||
//
|
||||
// The mode that the file is opened in is determined by the flags, which
|
||||
@ -516,6 +524,10 @@ int lfs2_removeattr(lfs2_t *lfs2, const char *path, uint8_t type);
|
||||
int lfs2_file_open(lfs2_t *lfs2, lfs2_file_t *file,
|
||||
const char *path, int flags);
|
||||
|
||||
// if LFS2_NO_MALLOC is defined, lfs2_file_open() will fail with LFS2_ERR_NOMEM
|
||||
// thus use lfs2_file_opencfg() with config.buffer set.
|
||||
#endif
|
||||
|
||||
// Open a file with extra configuration
|
||||
//
|
||||
// The mode that the file is opened in is determined by the flags, which
|
||||
|
@ -1,6 +1,7 @@
|
||||
/*
|
||||
* lfs2 util functions
|
||||
*
|
||||
* Copyright (c) 2022, The littlefs authors.
|
||||
* Copyright (c) 2017, Arm Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
@ -1,6 +1,7 @@
|
||||
/*
|
||||
* lfs2 utility functions
|
||||
*
|
||||
* Copyright (c) 2022, The littlefs authors.
|
||||
* Copyright (c) 2017, Arm Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
@ -49,6 +50,7 @@ extern "C"
|
||||
// code footprint
|
||||
|
||||
// Logging functions
|
||||
#ifndef LFS2_TRACE
|
||||
#ifdef LFS2_YES_TRACE
|
||||
#define LFS2_TRACE_(fmt, ...) \
|
||||
printf("%s:%d:trace: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
|
||||
@ -56,7 +58,9 @@ extern "C"
|
||||
#else
|
||||
#define LFS2_TRACE(...)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef LFS2_DEBUG
|
||||
#ifndef LFS2_NO_DEBUG
|
||||
#define LFS2_DEBUG_(fmt, ...) \
|
||||
printf("%s:%d:debug: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
|
||||
@ -64,7 +68,9 @@ extern "C"
|
||||
#else
|
||||
#define LFS2_DEBUG(...)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef LFS2_WARN
|
||||
#ifndef LFS2_NO_WARN
|
||||
#define LFS2_WARN_(fmt, ...) \
|
||||
printf("%s:%d:warn: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
|
||||
@ -72,7 +78,9 @@ extern "C"
|
||||
#else
|
||||
#define LFS2_WARN(...)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef LFS2_ERROR
|
||||
#ifndef LFS2_NO_ERROR
|
||||
#define LFS2_ERROR_(fmt, ...) \
|
||||
printf("%s:%d:error: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
|
||||
@ -80,13 +88,16 @@ extern "C"
|
||||
#else
|
||||
#define LFS2_ERROR(...)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Runtime assertions
|
||||
#ifndef LFS2_ASSERT
|
||||
#ifndef LFS2_NO_ASSERT
|
||||
#define LFS2_ASSERT(test) assert(test)
|
||||
#else
|
||||
#define LFS2_ASSERT(test)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
// Builtin functions, these may be replaced by more efficient
|
||||
|
@ -6,7 +6,7 @@
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2013-2019 Damien P. George
|
||||
* Copyright (c) 2013-2019 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
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user