Compare commits

...

460 Commits

Author SHA1 Message Date
Lephenixnoir 8c5f68f16e
fxcg50/modion: rename file ion.c -> modion.c 2024-03-18 22:41:16 +01:00
Lephenixnoir fc9026798d
fxcg50/modion: clean up module implementation 2024-03-18 22:40:39 +01:00
Lephenixnoir 3775f28536
fxcg50/modkandinsky: use QSTRs to identify common colors 2024-03-18 22:34:48 +01:00
Lephenixnoir 5d51f205b9
fxcg50: officialize reserving 300 kB from _uram for the uPy GC 2024-03-18 22:10:41 +01:00
Lephenixnoir 3e2f7f0aa0
sh: slight cleanup of scheduled dupdate mechanism
Mostly renaming and integrating pe_dupdate() it with existing modules.
2024-03-18 22:08:37 +01:00
Lephenixnoir 71ddfff567
sh: switch add-in icon based on auto-detected dev builds
A dev build is detected if:
- There are dirty tracked files: "git status -uno --porcelain" nonempty
- We are not on main: "git describe" != "git describe main"
2024-03-18 22:07:59 +01:00
Lephenixnoir 4bec7be97f
numworks: extend timer tracking into autofree resource header
I imagine that we're going to use this more later, be it for serial/USB,
in-memory files, and maybe more.
2024-03-09 16:10:44 +01:00
Lephenixnoir fff06099a1
numworks: don't set global dwindow in kandinsky
This interferes with the shell and gives fairly bad results with print()
and input(). This way of doing things lets the shell print correctly.
The shell will override the borders, however. It's not immediately
obvious how to fix that properly with the auto-update system in main.c.
I'll try to move the auto screen update back to modkandinsky.c.
2024-03-05 07:28:57 +00:00
Lephenixnoir e7349aa227
numworks: replace custom time module with extension of official one 2024-03-04 22:40:32 +00:00
Lephenixnoir dfb73611f9
Merge remote-tracking branch 'slyvtt/numworks' into dev
This merges PR #14 with SlyVTT's Numworks support.
2024-03-03 13:17:10 +00:00
Lephenixnoir b804cb7583
docs: second pass on casiplot module 2024-03-03 13:10:20 +00:00
Lephenixnoir 38c0ec1d15
docs: add casioplot module (first pass) 2024-03-03 07:28:47 +00:00
Lephenixnoir eaf5f43da4
modgint: add dpoly() function (no doc yet) 2024-03-01 22:47:35 +00:00
Lephenixnoir c14f770483
docs: add example for drect(), dline() and the like 2024-02-26 22:38:10 +01:00
Lephenixnoir 430fe06adc
docs: add documentation for gint.getkey_opt() 2024-02-26 09:04:53 +01:00
Sylvain PILLOT d298d0538d added the full U+00A characters table for NW module Kandinsky 2024-02-25 19:40:53 +01:00
Lephenixnoir 3523a83bda
docs: first version of gint image documentation (fr+en) 2024-02-25 17:13:23 +01:00
Lephenixnoir ae3a135a81
docs: start of image documentation in gint (French only so far) 2024-02-25 16:31:19 +01:00
Lephenixnoir 30fcf592d1
docs: more modgint doc including first images 2024-02-25 14:45:30 +01:00
Lephenixnoir f9f94c999a
ports/fxcg50: provide basic memory status view on SHIFT+VARS 2024-02-25 12:46:01 +01:00
Lephenixnoir 7abbcc1dfc
ports/fx9860g3: reduce console scrollback to 50 lines / 4kB 2024-02-25 12:45:43 +01:00
Lephenixnoir a1848c0920
ports/sh: reduce console memory usage
Includes 2 previous commits.

So far simply by freezing old console lines and removing edition
metadata. Plus a little bit of compaction.

Benchmark: _uram memory free after startup and help() on G-III.
- Before this change: 2880
- After adding stredit_t in every line: 1880
- After keeping stredit_t only for last line: 4596

There's more to be done (double buffer), but later. I'm also gonna cut
down on the history size, probably.
2024-02-25 11:11:48 +01:00
Lephenixnoir 3f02fd86ea
ports/sh: WIP console memory usage: use stredit_t only on last line 2024-02-25 09:11:05 +01:00
Lephenixnoir 95eb40e25d
ports/sh: WIP console memory usage: introduce stredit_t
Currently takes more memory because I kept an stredit_t in every single
line but once I remove it from all but the last one we'll see some
progress.
2024-02-25 08:49:49 +01:00
Lephenixnoir 93e021f144
ports/sh: fix long-standing console line counting bug
The computation of how many screen lines at given console lines takes
used the globally-configured font instead of the widget's font. This
cause certain lines to have their size over-estimated on fx-9860G III,
leading to weird scrolling and too few lines being displayed in some
situations.

The bug was present on the fx-CG 50 but did not occur because the font
used for rendering the console is the default font.
2024-02-24 15:43:13 +01:00
Lephenixnoir c84caa533d
ports/fx9860g3: memory info view on SHIFT+VARS 2024-02-24 15:02:33 +01:00
Lephenixnoir bcdb3b74ca
ports/fx9860g3: smaller banner 2024-02-24 14:33:02 +01:00
Sylvain PILLOT 35b73ba954 added better (ie. cleaner) support for unicode characters in Kandinsky module 2024-02-24 10:49:28 +01:00
Sylvain PILLOT 5f385d8bcc convert NW font to unicode and added main letters with accent - WIP 2024-02-24 09:14:12 +01:00
Sylvain PILLOT 05bfce99d6 added a better mechanism for differentiating compilation of modules between FxCG50 and fx9860G 2024-02-13 19:56:28 +01:00
Sylvain PILLOT 3e302b1b34 Merge branch 'dev' into numworks 2024-02-13 18:31:03 +01:00
Sylvain PILLOT 26afb31ff2 added some extra verification on get_pixel() after validation on actual hardware 2024-02-13 18:27:47 +01:00
Lephenixnoir a2b9c32cea
ports/sh: seed random module (untested) 2024-02-13 14:32:58 +01:00
Sylvain PILLOT 6225b1d667 added more examples using Kandinsky/Ion/Time modules from NW + reorganisation of NW examples 2024-02-10 10:39:24 +01:00
Sylvain PILLOT 0f386bd779 made fully compatible Ion::keydown() function with key number support + update of documentation accordingly 2024-02-10 10:33:44 +01:00
Sylvain PILLOT 7fdf3aeb2e added automatic refresh and video output support on Kandinsky module 2024-02-08 21:01:31 +01:00
Sylvain PILLOT 263b9e83c8 Merge branch 'dev' into numworks 2024-02-08 08:02:21 +01:00
Sylvain PILLOT 2cb2bc6e67 add CGEXT_Set_Margin_Color() function in Kandinsky module 2024-02-07 21:30:59 +01:00
Lephenixnoir 0f867e9f72
WIP 2024-02-07 08:08:10 +01:00
Sylvain PILLOT d4dcc59d71 Translated NW modules documentation in English 2024-02-05 16:37:26 +01:00
Sylvain PILLOT 9bc05bbf03 Improved NW modules documentation 2024-02-05 09:20:35 +01:00
Lephenixnoir b1e39d3ab6
sh: add videocapture function (x² key) in debug mode 2024-02-04 23:03:05 +01:00
Lephenixnoir af8bacd271
fx9860g3: move console_line_t allocation to new PRAM0 allocator 2024-02-04 22:59:54 +01:00
Lephenixnoir d4501baadb
ports/sh: monitor memory usage at load and execution 2024-02-04 21:49:08 +01:00
Lephenixnoir 627c81c1b6
ports/sh: show current folder + proper errors if file browsing fails
The second half is from the latest commits on gint and JustUI.
2024-02-04 20:19:11 +01:00
Lephenixnoir 262a90f15c
ports/sh: disable unstable use of random memory 2024-02-04 20:00:47 +01:00
Sylvain PILLOT 9156a21afa Added missing safegard #ifdef FXCG50 for correct build of fx9860G version without NW modules 2024-02-04 19:38:12 +01:00
Sylvain PILLOT 226f82ec8c Add Kandinsky Extension for fxCG to be able to use wide screen - bugfix NW sreen is 222px high usable, not 240px 2024-02-04 17:29:36 +01:00
Sylvain PILLOT ba515dc168 Add Kandinsky Extension for fxCG to be able to use wide screen 2024-02-04 16:00:40 +01:00
Lephenixnoir 6ab101e1bd
modgint: refresh screen during getkey() + getkey_opt() delay + example 2024-02-03 20:44:45 +01:00
Sylvain PILLOT 6ae6d06387 Additional RAM - but a bit less greedy in the approach ;) 2024-02-03 20:11:17 +01:00
Sylvain PILLOT e7ad1e267d Add extra memory for fxCG50 hardware and fxCG emulator - todo for fxCG10/20 2024-02-03 18:09:48 +01:00
Lephenixnoir 6969309cd7
modgint: image support for fx-CG 2024-02-03 15:52:46 +01:00
Lephenixnoir eeb392a833
ports/sh: fix fx_image rendering control race condition 2024-02-03 10:17:53 +01:00
Lephenixnoir 00f009e0c2
docs: fix key listings, remove aliases 2024-02-03 09:53:12 +01:00
Sylvain PILLOT 0fb961768a Added examples in ports/sh/examples + documentation in docs/sh 2024-02-03 09:05:00 +01:00
Sylvain PILLOT 8072e5b1a9 added monotonic() function in NW time module 2024-02-02 22:16:56 +01:00
Lephenixnoir 7f647b57d7
docs: basic start to gint module documentation 2024-02-02 21:44:02 +01:00
Lephenixnoir b1ec8bcde4
modgint: more complete fx_image example 2024-02-02 21:43:45 +01:00
Sylvain PILLOT e3fd785200 Huge Cleaning - NW modules on fxCG50 - Ready for PR - Phase II 2024-02-02 20:36:19 +01:00
Sylvain PILLOT 12565ba8d2 Huge Cleaning - NW modules on fxCG50 - Ready for PR 2024-02-02 20:32:15 +01:00
Sylvain PILLOT 96077c1653 updated .gitignore 2024-01-30 22:55:23 +01:00
Lephenixnoir b9a457680b
modgint: basic image support, starting to work on G-III 2024-01-30 22:24:35 +01:00
Sylvain PILLOT 226d94494f NW modules for fxCG50 PythonExtra - Ok, now working correctly 2024-01-30 22:05:37 +01:00
Sylvain PILLOT bca7048525 WIP : NW modules for fxCG50 - corrected Kandinsky Draw_String when string contains \n char 2024-01-30 20:36:31 +01:00
Sylvain PILLOT 0868d96d2b WIP NW module on Casio - Restoration of correct dwindow and timers at module exit 2024-01-30 18:49:17 +01:00
Sylvain PILLOT 2ac213cae0 pursue NW support with dedicated modules (Ion, Time and Kandinsky now working) (only for fxCG50) 2024-01-29 23:16:01 +01:00
Sylvain PILLOT c207c7b6f7 start NW support with dedicated modules (only for fxCG50) 2024-01-29 07:43:24 +01:00
Sylvain PILLOT 774c8d0f44 added dpoly() function 2024-01-20 12:59:04 +01:00
Lephenixnoir 3a3ad0e155
ports/sh: enable delayed SHIFT/ALPHA
This little trick is necessary to have them in JustUI.
2024-01-16 19:48:26 +01:00
Lephenixnoir 6af6f97df4
meta: add a release zip generation target 2024-01-07 16:28:40 +01:00
Lephenixnoir f3424c60a5
meta: add CASIO's turtle/matplotl modules 2024-01-07 16:11:18 +01:00
Lephenixnoir 9f860bd58a
meta: add turtle/matplotlib examples by Critor 2024-01-07 16:05:40 +01:00
Lephenixnoir b6efd9ed31
modcasioplot, modgint: more cleanup at import 2024-01-07 15:49:58 +01:00
Lephenixnoir e1bda048d0
meta: organize examples (2/2) 2024-01-07 15:49:08 +01:00
Lephenixnoir 727b7fb032
meta: organize examples (1/) 2024-01-07 11:42:38 +01:00
Lephenixnoir 6547cf5fbc
modcasioplot: add original fonts for ASCII on CG-50 2024-01-07 11:41:28 +01:00
Lephenixnoir 2dddd209a0
modgint: revert dcircle/dellipse to positional prototype 2024-01-06 13:37:07 +01:00
Lephenixnoir f71cad03cf
meta: merge from upstream 1.12.0 into dev 2024-01-04 19:25:14 +01:00
Lephenixnoir 5e2b33b148
ports/sh: enable two-argument round() function 2024-01-04 13:12:34 +01:00
Lephenixnoir c3dc438b82
modgint: add dcircle(), dellipse(), and [cg50] C_RGB() 2024-01-04 12:56:29 +01:00
Damien George dc2a4e3cbd rp2/mpthreadport: Fix race with IRQ when entering atomic section.
Prior to this commit there is a potential deadlock in
mp_thread_begin_atomic_section(), when obtaining the atomic_mutex, in the
following situation:
- main thread calls mp_thread_begin_atomic_section() (for whatever reason,
  doesn't matter)
- the second core is running so the main thread grabs the mutex via the
  call mp_thread_mutex_lock(&atomic_mutex, 1), and this succeeds
- before the main thread has a chance to run save_and_disable_interrupts()
  a USB IRQ comes in and the main thread jumps off to process this IRQ
- that USB processing triggers a call to the dcd_event_handler() wrapper
  from commit bcbdee2357
- that then calls mp_sched_schedule_node()
- that then attempts to obtain the atomic section, calling
  mp_thread_begin_atomic_section()
- that call then blocks trying to obtain atomic_mutex
- core0 is now deadlocked on itself, because the main thread has the mutex
  but the IRQ handler (which preempted the main thread) is blocked waiting
  for the mutex, which will never be free

The solution in this commit is to use mutex enter/exit functions that also
atomically disable/restore interrupts.

Fixes issues #12980 and #13288.

Signed-off-by: Damien George <damien@micropython.org>
2024-01-03 15:59:11 +11:00
Damien George 8438c8790c rp2/mutex_extra: Implement additional mutex functions.
These allow entering/exiting a mutex and also disabling/restoring
interrupts, in an atomic way.

Signed-off-by: Damien George <damien@micropython.org>
2024-01-03 15:59:02 +11:00
Damien George c3989e398f rp2/rp2_flash: Lockout second core only when doing flash erase/write.
Using the multicore lockout feature in the general atomic section makes it
much more difficult to get correct.

Signed-off-by: Damien George <damien@micropython.org>
2024-01-03 15:58:39 +11:00
robert-hh 3d0b6276f3 samd/mcu: Fix wrong EIC table entries in pin-af-table.csv.
Fixes:
- SAMD21: PB16
- SAMD51: PB03, PB22 and PB00.

Signed-off-by: robert-hh <robert@hammelrath.com>
2024-01-02 18:48:17 +11:00
robert-hh aea93a88f8 samd/mcu/samd21: Reorganize and enable more firmware features.
This commit enables additional features for SAMD21 with external flash:
- Viper and native code support.  On a relatively slow devices, viper and
  native code can be helpful.
- Freeze the asyncio scripts and add the select module.
- Enable Framebuffer support.
- Enable UART flow control.
- Enable a few more features from the extra features set.

Drop onewire and asyncio support from SAMD21 firmware without external
flash, leaving a little bit more room for future extensions.  Asyncio was
anyhow incomplete.

Signed-off-by: robert-hh <robert@hammelrath.com>
2024-01-02 18:46:33 +11:00
robert-hh 36d9e98fc6 samd: Remove the MICROPY_PY_MACHINE_RTC config option.
RTC is enabled on all boards.  Therefore the conditional compile is not
needed.  Removing it simplifies the source code a little bit.

Signed-off-by: robert-hh <robert@hammelrath.com>
2024-01-02 18:46:11 +11:00
robert-hh 8498b0b13e docs/samd/pinout: Update pinout docs with fixed pin assignment.
Fixes a wrong assignment for Sparkfun SAMD51 Thing Plus, and updates the
sample script for printing the pin info table.

Signed-off-by: robert-hh <robert@hammelrath.com>
2024-01-02 18:44:45 +11:00
iabdalkader f34e27f178 mimxrt/mpbthciport: Add missing extmod/modmachine.h header.
Include extmod/modmachine.h for machine_uart_type declaration.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2024-01-02 18:24:19 +11:00
iabdalkader 87d3f8b367 mimxrt/mphalport: Remove redundant NVIC/IRQ defines.
These are already defined in `irq.h`.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2024-01-02 18:19:58 +11:00
Damien George 2037edb5a2 all: Bump version to 1.23.0-preview.
Signed-off-by: Damien George <damien@micropython.org>
2024-01-02 18:11:41 +11:00
Lephenixnoir 8823d1f473
modgint: add keypressed/keyreleased 2023-12-29 11:05:14 +01:00
Lephenixnoir cccc2787b5
ports/sh: fix relative imports for sub-subfolders 2023-12-27 15:43:04 +01:00
Damien George 9feb0689ee all: Bump version to 1.22.0.
Signed-off-by: Damien George <damien@micropython.org>
2023-12-27 15:35:31 +11:00
Lephenixnoir 347e463e17
fx9860g3: rename to PythonEx.g1a 2023-12-23 12:04:03 +01:00
Lephenixnoir 61b2360b16
ports/sh: make filesystem imports relative to current file 2023-12-23 12:01:46 +01:00
Daniël van de Giessen d014c82826 extmod/nimble: Do not set GAP device name after sync.
Instead, configure the default once at compile-time. This means the GAP
name will no longer be set to default after re-initializing Bluetooth.

Signed-off-by: Daniël van de Giessen <daniel@dvdgiessen.nl>
2023-12-22 16:07:02 +11:00
Damien George 0b2676db5c lib/micropython-lib: Update submodule to latest.
Signed-off-by: Damien George <damien@micropython.org>
2023-12-22 14:18:09 +11:00
Nicko van Someren cfc212b108 rp2/rp2_dma: Introduce a new rp2.DMA class for control over DMA xfers.
This commit implements fairly complete support for the DMA controller in
the rp2 series of microcontrollers.  It provides a class for accessing the
DMA channels through a high-level, Pythonic interface, and functions for
setting and manipulating the DMA channel configurations.

Creating an instance of the rp2.DMA class claims one of the processor's DMA
channels.  A sensible, per-channel default value for the ctrl register can
be fetched from the DMA.pack_ctrl() function, and the components of this
register can be set via keyword arguments to pack_ctrl().

The read, write, count and ctrl attributes of the DMA class provide
read/write access to the respective registers of the DMA controller.  The
config() method allows any or all of these values to be set simultaneously
and adds a trigger keyword argument to allow the setup to immediately be
triggered.  The read and write attributes (or keywords in config()) accept
either actual addresses or any object that supports the buffer interface.
The active() method provides read/write control of the channel's activity,
allowing the user to start and stop the channel and test if it is running.

Standard MicroPython interrupt handlers are supported through the irq()
method and the channel can be released either by deleting it and allowing
it to be garbage-collected or with the explicit close() method.

Direct, unfettered access to the DMA controllers registers is provided
through a proxy memoryview() object returned by the DMA.registers attribute
that maps directly onto the memory-mapped registers.  This is necessary for
more fine-grained control and is helpful for allowing chaining of DMA
channels.

As a simple example, using DMA to do a fast memory copy just needs:

    src = bytearray(32*1024)
    dest = bytearray(32*1024)
    dma = rp2.DMA()
    dma.config(read=src, write=dest, count=len(src) // 4,
        ctrl=dma.pack_ctrl(), trigger=True)

    # Wait for completion
    while dma.active():
        pass

This API aims to strike a balance between simplicity and comprehensiveness.

Signed-off-by: Nicko van Someren <nicko@nicko.org>
Signed-off-by: Damien George <damien@micropython.org>
2023-12-22 13:04:51 +11:00
Sebastian Romero e4d3ab3304 nrf/main: Add /flash and /flash/lib to sys.path.
This allows to follow good practice and have libraries live in the lib
folder which means they will be found by the runtime without adding this
path manually at runtime.

Signed-off-by: Sebastian Romero <s.romero@arduino.cc>
2023-12-22 11:15:19 +11:00
Peter Züger d69e69adb6 py/mkrules.mk: Fix dependency file generation for compiler wrappers.
When compiling with distcc, it does not understand the -MD flag on its own.
This fixes the interaction by explicitly adding the -MF option.

The error in distcc is described here under "Problems with gcc -MD":
https://www.distcc.org/faq.html

Signed-off-by: Peter Züger <zueger.peter@icloud.com>
2023-12-22 11:07:59 +11:00
Peter Züger ce42c9ee16 extmod/vfs_lfs: Fix lfs cache_size calculation.
The calculation of the lfs2 cache_size was incorrect, the maximum allowed
size is block_size.

The cache size must be: "a multiple of the read and program sizes, and a
factor of the block size".

Signed-off-by: Peter Züger <zueger.peter@icloud.com>
2023-12-22 11:03:23 +11:00
Maarten van der Schrieck 3bca93b2d0 ports: Fix sys.stdout.buffer.write() return value.
MicroPython code may rely on the return value of sys.stdout.buffer.write()
to reflect the number of bytes actually written. While in most scenarios a
write() operation is successful, there are cases where it fails, leading to
data loss. This problem arises because, currently, write() merely returns
the number of bytes it was supposed to write, without indication of
failure.

One scenario where write() might fail, is where USB is used and the
receiving end doesn't read quickly enough to empty the receive buffer. In
that case, write() on the MicroPython side can timeout, resulting in the
loss of data without any indication, a behavior observed notably in
communication between a Pi Pico as a client and a Linux host using the ACM
driver.

A complex issue arises with mp_hal_stdout_tx_strn() when it involves
multiple outputs, such as USB, dupterm and hardware UART. The challenge is
in handling cases where writing to one output is successful, but another
fails, either fully or partially. This patch implements the following
solution:

mp_hal_stdout_tx_strn() attempts to write len bytes to all of the possible
destinations for that data, and returns the minimum successful write
length.

The implementation of this is complicated by several factors:
- multiple outputs may be enabled or disabled at compiled time
- multiple outputs may be enabled or disabled at runtime
- mp_os_dupterm_tx_strn() is one such output, optionally containing
  multiple additional outputs
- each of these outputs may or may not be able to report success
- each of these outputs may or may not be able to report partial writes

As a result, there's no single strategy that fits all ports, necessitating
unique logic for each instance of mp_hal_stdout_tx_strn().

Note that addressing sys.stdout.write() is more complex due to its data
modification process ("cooked" output), and it remains unchanged in this
patch. Developers who are concerned about accurate return values from
write operations should use sys.stdout.buffer.write().

This patch might disrupt some existing code, but it's also expected to
resolve issues, considering that the peculiar return value behavior of
sys.stdout.buffer.write() is not well-documented and likely not widely
known. Therefore, it's improbable that much existing code relies on the
previous behavior.

Signed-off-by: Maarten van der Schrieck <maarten@thingsconnected.nl>
2023-12-22 10:32:46 +11:00
Maarten van der Schrieck 91ee8ac894 extmod/os_dupterm: Let mp_os_dupterm_tx_strn() return num bytes written.
In case of multiple outputs, the minimum successful write length is
returned.  In line with this, in case any output has a write error, zero is
returned.

In case of no outputs, -1 is returned.

The return value can be used to assess whether writes were attempted, and
if so, whether they succeeded.

Signed-off-by: Maarten van der Schrieck <maarten@thingsconnected.nl>
2023-12-22 10:26:52 +11:00
Jim Mussared 5d28bb4adb tools/manifestfile.py: Add support for external libraries.
This adds a `add_library(name, path)` method for use in manifest.py that
allows registering an external path (e.g. to another repo) by name.

This name can then be passed to `require("package", library="name")` to
reference packages in that repo/library rather than micropython-lib.

Within the external library, `require()` continues to work as normal
(referencing micropython-lib) by default, but they can also specify the
library name to require another package from that repo/library.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-12-21 15:28:32 +11:00
IhorNehrutsa 5552896ca8 esp32/mpconfigport: Enable MICROPY_PY_HASHLIB_MD5.
Signed-off-by: IhorNehrutsa <Ihor.Nehrutsa@gmail.com>
2023-12-21 11:33:05 +11:00
IhorNehrutsa b31eef6094 extmod/modhashlib: Support MD5 with mbedtls 3.x.
This change was missd in e7ae3ad92d.

Signed-off-by: IhorNehrutsa <Ihor.Nehrutsa@gmail.com>
2023-12-21 11:30:52 +11:00
Jim Mussared 74fd7b3d32 tools/ci.sh: Set `ulimit -n` for unix CI.
Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-12-21 11:05:31 +11:00
Jim Mussared 8b24aa36ba extmod/modselect: Handle growing the pollfds allocation correctly.
The poll_obj_t instances have their pollfd field point into this
allocation.  So if re-allocating results in a move, we need to update the
existing poll_obj_t's.

Update the test to cover this case.

Fixes issue #12887.

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-12-21 11:04:59 +11:00
Damien George e9bcd49b3e stm32/mboot: Add support for Microsoft WCID.
This adds support to stm32's mboot for the Microsoft WCID USB 0xee string
and Compatible ID Feature Descriptor.  This allows the USB device to
automatically set the default USB driver, so that when the device is
plugged in Windows will assign the winusb driver to it.  This means that
USB DFU mode can be used without installing any drivers.

For example this page will work (allow the board to be updated over DFU)
with zero install: https://devanlai.github.io/webdfu/dfu-util/

Tested on Windows 10, Windows can read the 0xee string correctly, and
requests the second special descriptor, which then configures the USB
device to use the winusb driver.

Signed-off-by: Damien George <damien@micropython.org>
2023-12-20 19:40:03 +11:00
Damien George 49d0c22b11 stm32/mboot: Expand device descriptor to make it easier to understand.
Signed-off-by: Damien George <damien@micropython.org>
2023-12-20 19:31:15 +11:00
Damien George 859f219690 stm32/mboot: Guard use of tx_pending with USE_USB_POLLING option.
Signed-off-by: Damien George <damien@micropython.org>
2023-12-20 17:25:57 +11:00
Damien George 7cf1118831 stm32/usbdev: Optionally pass through vendor requests to Setup function.
Signed-off-by: Damien George <damien@micropython.org>
2023-12-20 17:25:10 +11:00
Damien George f46269a1d1 extmod/asyncio: Remove non-working Stream __aenter__/__aexit__ methods.
It looks like these never worked and there are no tests for this
functionality.  Furthermore, CPython doesn't support this.

Fixes #12995.

Signed-off-by: Damien George <damien@micropython.org>
2023-12-20 15:56:23 +11:00
Lephenixnoir 5b52671c50
ports/sh: improve USB debugging behavior
- Set MP_DEBUG_PRINTER to go through DEBUG_printf instead of the
  console, which is important when the former is USB.
- Disable malloc/gc_alloc messages to avoid spamming USB debug log.
2023-12-19 22:20:12 +01:00
Damien George f6d630877c esp32: Add MICROPY_GC_INITIAL_HEAP_SIZE option and tune it.
This gets back the old heap-size behaviour on ESP32, before auto-split-heap
was introduced: after the heap is grown one time the size is 111936 bytes,
with about 40k left for the IDF.  That's enough to start WiFi and do a
HTTPS request.

Signed-off-by: Damien George <damien@micropython.org>
2023-12-19 18:34:23 +11:00
Damien George 97b13132b1 py/gc: Improve calculation of new heap size in split-heap-auto mode.
There are two main changes here to improve the calculation of the size of
the next heap area when automatically expanding the heap:
- Compute the existing total size by counting the total number of GC
  blocks, and then using that to compute the corresponding number of bytes.
- Round the bytes value up to the nearest multiple of BYTES_PER_BLOCK.

This makes the calculation slightly simpler and more accurate, and makes
sure that, in the case of growing from one area to two areas, the number
of bytes allocated from the system for the second area is the same as the
first.  For example on esp32 with an initial area size of 65536 bytes, the
subsequent allocation is also 65536 bytes.  Previously it was a number that
was not even a multiple of 2.

Signed-off-by: Damien George <damien@micropython.org>
2023-12-19 18:34:23 +11:00
Patrick Van Oosterwijck 3270d856fd rp2/boards: Add SIL_RP2040_SHIM board by Silicognition LLC.
Add new board Silicognition RP2040-Shim, RP2040 with 4 MB of flash
and W5500 drivers included and configured by default for use with
the Silicognition PoE-FeatherWing.

Co-authored-by: Matt Trentini <matt.trentini@gmail.com>

Signed-off-by: Patrick Van Oosterwijck <patrick@silicognition.com>
2023-12-18 16:32:20 +11:00
Paul Grayson c51081c604 rp2/boards: Add support for Pololu 3pi+ and Zumo robots.
Signed-off-by: Paul Grayson <paul@pololu.com>
2023-12-18 14:08:04 +11:00
Paul Grayson fbf079d773 rp2: Add new NO_DEFAULT_PINS config options for i2c, spi, and uart.
Some boards have multiple options for these pins, and they don't want to
allow users to initialize a port without explicitly specifying pin numbers.

Signed-off-by: Paul Grayson <paul@pololu.com>
2023-12-18 14:07:03 +11:00
Damien George a78ec4ef7b rp2/mpconfigport: Enable MICROPY_PY_OS_DUPTERM_NOTIFY.
Signed-off-by: Damien George <damien@micropython.org>
2023-12-18 12:20:47 +11:00
Damien George 1f2ec4583d extmod/os_dupterm: Prevent recursive execution of mp_os_dupterm_rx_chr.
Signed-off-by: Damien George <damien@micropython.org>
2023-12-18 12:20:47 +11:00
Damien George 395886caa3 extmod/modos: Factor os.dupterm_notify() function to common extmod code.
esp8266 doesn't need ets task because the notify is now scheduled (see
commits 7d57037906 and
c60caf1995 for relevant history).

Signed-off-by: Damien George <damien@micropython.org>
2023-12-18 12:20:47 +11:00
Trent Piepho 0e706a62b1 py/makeqstrdefs.py: Stop generating temporary intermediate file.
In "cat" mode, output was written to a file named "out", then moved to the
location of the real output file.  There was no reason for this.

While makeqstrdefs.py does make an effort to not update the timestamp on an
existing output file that has not changed, the intermediate "out" file
isn't part of the that process.

Signed-off-by: Trent Piepho <tpiepho@gmail.com>
2023-12-14 22:55:08 -08:00
Elias Wimmer 2e101a8e44 extmod/modonewire: Improve write timings for better reliability.
When using long cables for sensors on onewire e.g. ds18b20, the current
default timings are too optimistic, leading to bus failures and CRC errors.

Stable results are achieved with the timings given by
https://www.analog.com/en/technical-articles/1wire-communication-through-software.html
2023-12-15 17:08:09 +11:00
Patrick Van Oosterwijck 06df3b2925 extmod/modonewire: Adopt Maxim recommended read timings.
The timing of the onewire module was way too fast when reading.  This
commit adopts read timings as recommended in Maxim application note 126:
6 us (pulse) / 9 us (sample) / 55 us (bit slot).  See also:
https://www.analog.com/en/technical-articles/1wire-communication-through-software.html

Signed-off-by: Damien George <damien@micropython.org>
2023-12-15 17:04:33 +11:00
dependabot[bot] de3e83aa4d github/workflows: Bump actions/upload-artifact from 3 to 4.
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact)
from 3 to 4.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-15 16:14:43 +11:00
dependabot[bot] be64641210 github/workflows: Bump actions/setup-python from 4 to 5.
Bumps [actions/setup-python](https://github.com/actions/setup-python) from
4 to 5.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-15 16:13:15 +11:00
dependabot[bot] d506b53377 github/workflows: Bump actions/github-script from 6 to 7.
Bumps [actions/github-script](https://github.com/actions/github-script)
from 6 to 7.
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](https://github.com/actions/github-script/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/github-script
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-15 16:09:55 +11:00
Trent Piepho f22e88611d py/makeqstrdefs.py: Don't skip output for stale hash file.
In "cat" mode a "$output_file.hash" file is checked to see if the hash of
the new output is the same as the existing, and if so the output file isn't
updated.

However, it's possible that the output file has been deleted but the hash
file has not.  In this case the output file is not created.

Change the logic so that a hash file is considered stale if there is no
output file and still create the output.

Signed-off-by: Trent Piepho <tpiepho@gmail.com>
2023-12-15 15:48:07 +11:00
Trent Piepho 0d93392f10 py/mkrules.mk: List hash files as byproducts.
These are produced by the "cat" command to makeqstrdefs.py, to allow it to
not update unchanged files.  cmake doesn't know about them and so they are
not removed on a "clean".

This triggered a bug in makeqstrdefs.py where it would not recreate a
deleted output file (which is removed by clean) if a stale hash file with a
valid hash still existed.

Listing them as byproducts will cause them to be deleted on clean.

Signed-off-by: Trent Piepho <tpiepho@gmail.com>
2023-12-15 15:48:07 +11:00
stijn 85c02166ca py/modsys: Implement optional sys.intern.
Signed-off-by: stijn <stijn@ignitron.net>
2023-12-15 11:43:39 +11:00
Carlosgg 05d3b22301 docs/library: Document SSLContext cert methods and asyncio support.
Add `load_cert_chain`, `load_verify_locations`, `get_ciphers` and
`set_ciphers` SSLContext methods in ssl library, and update asyncio
`open_connection` and `start_server` methods with ssl support.

Signed-off-by: Carlos Gil <carlosgilglez@gmail.com>
2023-12-14 13:06:39 +11:00
Carlosgg bfd6ad94ff extmod/asyncio: Add ssl support with SSLContext.
This adds asyncio ssl support with SSLContext and the corresponding
tests in `tests/net_inet` and `tests/multi_net`.

Note that not doing the handshake on connect will delegate the handshake to
the following `mbedtls_ssl_read/write` calls.  However if the handshake
fails when a client certificate is required and not presented by the peer,
it needs to be notified of this handshake error (otherwise it will hang
until timeout if any).  Finally at MicroPython side raise the proper
mbedtls error code and message.

Signed-off-by: Carlos Gil <carlosgilglez@gmail.com>
2023-12-14 12:20:19 +11:00
Damien George f33dfb966a extmod/modssl_mbedtls: Fix parsing of ciphers in set_ciphers method.
Fixes two issues:
- None should not be allowed in the list, otherwise the corresponding entry
  in ciphersuites[i] will have an undefined value.
- The terminating 0 needs to be put in ciphersuites[len].

Signed-off-by: Damien George <damien@micropython.org>
2023-12-14 12:03:36 +11:00
Damien George bba8a673d5 tests: Update SSL network tests to use SSLContext, and work on CPython.
Changes are:
- use ssl.SSLContext.wrap_socket instead of ssl.wrap_socket
- disable check_hostname and call load_default_certs() where appropriate,
  to get CPython to run the tests correctly
- pass socket.AF_INET to getaddrinfo and socket.socket(), to force IPv4
- change tests to use github.com instead of google.com, because certificate
  validation was failing with google.com

Signed-off-by: Damien George <damien@micropython.org>
2023-12-12 21:22:10 +11:00
Damien George ef996d15b9 extmod/modssl_mbedtls: Make SSLSocket.getpeercert() optional.
And only enable this method when the relevant feature is available in
mbedtls.  Otherwise, if mbedtls doesn't support getting the peer
certificate, this method always returns None and it's confusing why it does
that.  It's better to remove the method altogether, so the error trying to
use it is more obvious.

Signed-off-by: Damien George <damien@micropython.org>
2023-12-12 21:21:54 +11:00
Damien George c9eb6bc601 esp32: Re-enable custom mbedtls error string tables.
To match other ports that use mbedtls.

Signed-off-by: Damien George <damien@micropython.org>
2023-12-12 16:25:07 +11:00
Damien George 58e75264c1 lib/mbedtls_errors: Update error list for latest esp32 mbedtls.
Running `./do-esp32.sh` now generates this esp32_mbedtls_errors.c file,
with IDF v5.0.4.

Signed-off-by: Damien George <damien@micropython.org>
2023-12-12 16:25:07 +11:00
Carlosgg f3f215e9bd extmod/modssl_mbedtls: Add SSLContext certificate methods.
This commit adds:

1) Methods to SSLContext class that match CPython signature:

	- `SSLContext.load_cert_chain(certfile, keyfile)`
	- `SSLContext.load_verify_locations(cafile=, cadata=)`
	- `SSLContext.get_ciphers()` --> ["CIPHERSUITE"]
	- `SSLContext.set_ciphers(["CIPHERSUITE"])`

2) `sslsocket.cipher()` to get current ciphersuite and protocol
   version.

3) `ssl.MBEDTLS_VERSION` string constant.

4) Certificate verification errors info instead of
   `MBEDTLS_ERR_X509_CERT_VERIFY_FAILED`.

5) Tests in `net_inet` and `multi_net` to test these new methods.

`SSLContext.load_cert_chain` method allows loading key and cert from disk
passing a filepath in `certfile` or `keyfile` options.

`SSLContext.load_verify_locations`'s `cafile` option enables the same
functionality for ca files.

Signed-off-by: Carlos Gil <carlosgilglez@gmail.com>
2023-12-12 16:25:07 +11:00
IhorNehrutsa 4365edb810 esp32: Change minimum supported IDF version to v5.0.4.
Also, IDF v5.1.2 is now supported, just not used by default.

IDF v5.0.2 still builds but we cannot guarantee continued support for this
version moving forward.

Signed-off-by: IhorNehrutsa <IhorNehrutsa@gmail.com>
2023-12-11 13:00:09 +11:00
Damien George d0758d8a33 esp32/boards/ESP32_GENERIC: Disable network.LAN and VM-opt on D2WD.
To reduce firmware size, because IDF v5.0.4 has increased in size.

Signed-off-by: Damien George <damien@micropython.org>
2023-12-11 13:00:06 +11:00
Damien George b4b77c17b5 esp32/mpconfigport: Keep some funcs out of IRAM for ESP32-SPIRAM builds.
To make sure the build fits.

Signed-off-by: Damien George <damien@micropython.org>
2023-12-11 12:59:51 +11:00
Ihor Nehrutsa 3069fee386 esp32/machine_i2s: Fix deprecated fields and constants.
Signed-off-by: IhorNehrutsa <Ihor.Nehrutsa@gmail.com>
2023-12-11 12:59:29 +11:00
Ihor Nehrutsa a427117d03 esp32/modmachine: Fix deprecated esp_pm_config_XXX_t.
Co-Authored-By: Trent Piepho <35062987+xyzzy42@users.noreply.github.com>

Signed-off-by: IhorNehrutsa <Ihor.Nehrutsa@gmail.com>
2023-12-11 12:59:14 +11:00
Ihor Nehrutsa e423b3c0ba docs/esp32/quickref: Add DAC example.
Signed-off-by: IhorNehrutsa <Ihor.Nehrutsa@gmail.com>
2023-12-11 12:58:22 +11:00
IhorNehrutsa 495be71d56 esp32/machine_dac: Support one-shot mode of driver.
And simplify board configuration of DAC by using SOC_DAC_SUPPORTED.

Signed-off-by: IhorNehrutsa <Ihor.Nehrutsa@gmail.com>
2023-12-11 12:57:43 +11:00
IhorNehrutsa 3106ee4885 esp32/modnetwork: Add WiFi AUTH_WPA3_ENT_192 authenticate mode.
Available in newer versions of the IDF.

Signed-off-by: IhorNehrutsa <IhorNehrutsa@gmail.com>
2023-12-11 12:57:05 +11:00
IhorNehrutsa 88778be73a esp32/machine_i2c: Use APB_CLK_FREQ instead of I2C_APB_CLK_FREQ.
Signed-off-by: IhorNehrutsa <Ihor.Nehrutsa@gmail.com>
2023-12-11 12:56:38 +11:00
Carlosgg c393cd7e48 esp32/boards/sdkconfig.base: Disable unused mbedtls options.
Disable unused EC curves and default certificate bundle which is not
implemented in MicroPython.  This reduces the firmware size significantly.

This follows commit 68f166dae9.

Signed-off-by: Carlos Gil Gonzalez <carlosgilglez@gmail.com>
2023-12-11 12:06:35 +11:00
Damien George e1a7aa23fd ports: Switch build to use common lib/libm list of source files.
Signed-off-by: Damien George <damien@micropython.org>
2023-12-08 15:42:41 +11:00
Damien George 241dbac928 extmod: Add lists of libm/libm_dbl source files for ports to use.
So that ports don't need to specify each of these files, they can simply
refer to the appropriate make/cmake variable.

Signed-off-by: Damien George <damien@micropython.org>
2023-12-08 15:39:28 +11:00
Angus Gratton 2c828a8815 unix: Update port to use the new event functions.
Necessary to get coverage of the new event functions.

Deletes the case that called usleep(delay) for mp_hal_delay_ms(), it seems
like this wouldn't have ever happened anyhow (MICROPY_EVENT_POOL_HOOK is
always defined for the unix port).

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2023-12-08 13:17:15 +11:00
Angus Gratton 73879734d9 esp8266: Update port to use new event functions.
This is necessary to avoid watchdog timeout in long i2c.scan(), as
previously machine_i2c.c would call MICROPY_EVENT_POLL_HOOK if
MICROPY_EVENT_POLL_HOOK_FAST was not available.

Compared to previous implementation, this implementation removes the
ets_event_poll() function and calls the SDK function ets_loop_iter() from
MICROPY_INTERNAL_EVENT_HOOK instead.  This allows using the port-agnostic
functions in more places.

There is a small behaviour change, which is that the event loop gets
iterated in a few more places (i.e. anywhere that mp_event_handle_nowait()
is called).  However, this looks like maybe only modselect.c - and is
probably good to process Wi-Fi events in that polling loop.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2023-12-08 12:50:38 +11:00
Angus Gratton c393f5c123 windows: Implement MICROPY_INTERNAL_WFE() macro.
This should be the equivalent of the previous event poll hook macro.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2023-12-08 12:49:54 +11:00
Angus Gratton 393938b3e6 rp2/main: Enable SEVONPEND CPU interrupt bit.
Previously this was not set, so potential for race conditions in interrupt
handlers this didn't issue SEV.  (Which is currently all of them, as far as
I can see.)

Eventually we might be able to augment the interrupt handlers that wake the
main thread to call SEV, and leave the others as-is to suspend the CPU
slightly faster, but this will solve the issue for now.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2023-12-08 12:49:49 +11:00
Angus Gratton 28529351ae rp2: Switch rp2 and drivers to use new event functions.
This commit changes all uses in the rp2 port, and drivers that are
optionally supported by that port.

The old MICROPY_EVENT_POLL_HOOK and MICROPY_EVENT_POLL_HOOK_FAST macros are
no longer used for rp2 builds and are removed (C user code will need to be
changed to suit).

Also take the opportunity to change some timeouts that used 64-bit
arithmetic to 32-bit, to hopefully claw back a little code size.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2023-12-08 12:49:43 +11:00
Angus Gratton df3948d3c2 extmod: Switch to use new event functions.
See previous commit for details of these functions.  As of this commit,
these still call the old hook macros on all ports.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2023-12-08 12:48:50 +11:00
Angus Gratton f5be0128e4 py: Add port-agnostic inline functions for event handling.
These are intended to replace MICROPY_EVENT_POLL_HOOK and
MICROPY_EVENT_POLL_HOOK_FAST, which are insufficient for tickless ports.

This implementation is along the lines suggested here:
https://github.com/micropython/micropython/issues/12925#issuecomment-1803038430

Currently any usage of these functions expands to use the existing hook
macros, but this can be switched over port by port.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2023-12-08 12:47:00 +11:00
Angus Gratton 66be82da7c esp8266: Avoid including ep_mphal.h directly.
This header has no include guards and is apparently only supposed to be
included from py/mphal.h.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2023-12-07 14:07:21 +11:00
iabdalkader 0960d64d3b extmod/network_ninaw10: Switch to using soft-timer for polling.
This patch simplifies the connection and sockets polling code, by switching
to a soft-timer to schedule polling code, and by using one node for
scheduling.  This also fixes any issues that could result from using a heap
allocated machine_timer, and includes better handling of the sockets poll
list.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2023-12-06 17:32:21 +11:00
iabdalkader 50f31cc902 extmod/modnetwork: Add deinit function to NIC protocol.
This is usually called on soft-reboot, a NIC can implement this to do any
necessary cleaning up (such as invalidating root pointers).

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2023-12-06 17:32:00 +11:00
Damien George d30d5c99af tests/run-tests.py: Skip Thumb2 tests if target doesn't support them.
Signed-off-by: Damien George <damien@micropython.org>
2023-12-06 16:05:37 +11:00
Damien George b796f1e3f1 tests/float/inf_nan_arith.py: Include -inf in argument combos.
This adds tests for, eg, -inf + inf which should be nan.

Signed-off-by: Damien George <damien@micropython.org>
2023-12-06 14:06:01 +11:00
Damien George 3f2c423686 rp2: Switch to locally provided math library.
This commit fixes all known floating-point bugs with the pico-sdk.  There
are two things going on here:
- Use a custom pico float component so that the pico-sdk doesn't include
  its math functions, and then provide our own from lib/libm.
- Provide a wrapper for __aeabi_fadd to fix the infinity addition bug.

Prior to this commit, the following tests failed on the rp2 port: cmath_fun
float_parse math_domain math_domain_special math_fun_special.  With this
commit, all these tests pass.

Thanks to @projectgus for how to approach this fix.

Signed-off-by: Damien George <damien@micropython.org>
2023-12-06 14:00:07 +11:00
Scott Zhao 1323a71823 esp32/boards/UM_TINYPICO: Fix typo in baudrate instructions.
The installation instructions for ESP32 TinyPICO board contained a typo
that used a non-standard baud rate 912600 instead of 921600.  This made the
upload command fail on some Windows computers.

Signed-off-by: Scott Zhao <zhaomh1998@outlook.com>
2023-12-06 13:46:04 +11:00
Thomas Wenrich 78b3fe5689 esp32/machine_rtc: Preserve RTC user memory over most reset causes.
The user memory area - accessible by machine.RTC.memory() -- will now
survive most reboot causes.  A power-on reset (also caused by the EN pin on
some boards) will clean the memory.  When this happens, the magic number
not found in the user memory will cause initialization.

After other resets (triggered by watchdogs, machine.reset(), ...), the user
is responsible to check and validate the contents of the user area.

This new behaviour can be changed by enabling
MICROPY_HW_RTC_MEM_INIT_ALWAYS: in that case the RTC memory is always
cleared on boot.

Signed-off-by: Thomas Wenrich <twenrich@gmail.com>
2023-12-06 13:31:13 +11:00
Damien George d3595fed2b tools/ci.sh: Build ESP32_GENERIC-SPIRAM as part of esp32 CI.
Signed-off-by: Damien George <damien@micropython.org>
2023-12-06 12:37:25 +11:00
Damien George 69089a532e esp32/boards: Enable further IRAM saving opts to fit ESP32-SPIRAM fw.
The amount of free IRAM in ESP32 SPIRAM builds is very small and went over
the limit due to commit 30b0ee34d3.  This
commit enables further optimisations to reduce IRAM usage.

Signed-off-by: Damien George <damien@micropython.org>
2023-12-06 12:35:45 +11:00
Angus Gratton 527c4b0497 github/workflows: Enable ccache for esp32 build.
CCaches are scoped per-job.

Uses https://github.com/hendrikmuhs/ccache-action to get desired behaviour
(updating the cache on each run).

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2023-12-06 12:15:33 +11:00
Angus Gratton 731a1f5233 github/workflows: Enable build matrix for stm32 port.
This is for consistency with the previous commit that uses this approach
for esp32.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2023-12-06 12:15:20 +11:00
Angus Gratton b6df8f8452 github/workflows: Use build matrix for esp32 port.
Allows splitting the esp32 job into multiple parts without too much
boilerplate.  The matrix is parameterised using the name of the function to
call in tools/ci.sh, to minimise the dependency on GitHub Actions.

This can get esp32 build times down around 3m if IDF is cached already.

If the cache is cold, the cache preparation step on each job can double up
against each other.  However, restructuring the workflow to not do this
seems either complex or requires copy-pasting the entire cache step.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2023-12-06 12:13:56 +11:00
Angus Gratton 9f620d2819 github/workflows: Cache ESP-IDF checkout and installation.
Cache is keyed on the ESP-IDF version used in CI, so there shouldn't be any
cache invalidation issues when ESP-IDF version changes.

Restoring from cache takes approx 15s, compared to 2-3m to perform these
steps (ESP-IDF tools install, ESP-IDF clone, ESP-IDF submodule clone) the
first time.

Cache size is approx 1.6GB, the git clone is tweaked as much as possible to
keep the size down.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2023-12-06 12:12:52 +11:00
MikeTeachman 58112fc49a stm32/machine_i2s: Improve accuracy of SCK frequency.
Configures the I2S PLL to produce a frequency that the I2S clock generator
can use to create an optimal SCK frequency.  The I2S PLL configuration
table is automatically generated at build time.

Fixes issue #10280.

Signed-off-by: Mike Teachman <mike.teachman@gmail.com>
2023-12-06 11:48:03 +11:00
Damien George f3889db265 stm32/usbd_cdc_interface: Include header to get machine_bootloader decl.
This was broken by commit 48b5a7b060.

Signed-off-by: Damien George <damien@micropython.org>
2023-12-04 22:19:59 +11:00
Damien George 20af857f52 nrf/boards/ARDUINO_NANO_33_BLE_SENSE: Don't enable MICROPY_MBFS.
This board has MICROPY_VFS enabled, which should take precedence over
MICROPY_MBFS (and did prior to 22d9116c8c).

Signed-off-by: Damien George <damien@micropython.org>
2023-12-04 22:18:14 +11:00
Damien George d422b68d10 nrf/mpconfigport: Enable MICROPY_PY_MACHINE_BOOTLOADER.
This should have been enabled in 48b5a7b060
but was missed.

Signed-off-by: Damien George <damien@micropython.org>
2023-12-04 22:17:18 +11:00
Carlosgg 30b0ee34d3 esp32: Enable mbedtls cert time validation.
Signed-off-by: Carlos Gil <carlosgilglez@gmail.com>
2023-12-04 10:50:42 +11:00
Damien George b5449b0f09 extmod/mbedtls: Enable certificate time/date validation by default.
All ports using this common configuration already enable time/date
validation, so this commit is a no-op change.

Signed-off-by: Damien George <damien@micropython.org>
2023-12-01 15:08:11 +11:00
Carlosgg 20ffbe1a41 unix/mbedtls: Enable mbedtls cert time validation.
To match other ports.

Signed-off-by: Carlos Gil <carlosgilglez@gmail.com>
2023-12-01 15:08:11 +11:00
Damien George ad806df857 ports: Move definitions of ATOMIC_SECTION macros to mphalport.h.
Also move MICROPY_PY_PENDSV_ENTER/REENTER/EXIT to mphalport.h, for ports
where these are not already there.

This helps separate the hardware implementation of these macros from the
MicroPython configuration (eg for renesas-ra and stm32, the IRQ static
inline helper functions can now be moved to irq.h).

Signed-off-by: Damien George <damien@micropython.org>
2023-12-01 14:37:48 +11:00
Damien George bfdf500ea5 py/mphal: Move configuration of ATOMIC_SECTION macros to mphal.h.
MICROPY_BEGIN_ATOMIC_SECTION/MICROPY_END_ATOMIC_SECTION belong more to the
MicroPython HAL rather than build configuration settings, so move their
default configuration to py/mphal.h, and require all users of these macros
to include py/mphal.h (here, py/objexcept.c and py/scheduler.c).

This helps ports separate configuration from their HAL implementations, and
can improve build times (because mpconfig.h is included everywhere, whereas
mphal.h is not).

Signed-off-by: Damien George <damien@micropython.org>
2023-12-01 14:14:08 +11:00
Damien George 7d784e5385 cc3200/application.mk: Don't add stm32 to build include path.
Or this port may end up accidentally including unwanted headers from stm32.

Signed-off-by: Damien George <damien@micropython.org>
2023-12-01 14:13:34 +11:00
Damien George 7a6489aaa5 cc3200: Eliminate dependency on stm32's irq.h.
Signed-off-by: Damien George <damien@micropython.org>
2023-12-01 14:12:59 +11:00
Damien George 49fa3ce65d cc3200: Convert os module to use extmod version.
Changes:
- os.uname() is removed to save space; sys.version and sys.implementation
  can be used instead.
- os.sync() now uses the common extmod version and syncs by calling the FAT
  FS sync function, which eventually calls sflash_disk_flush().

Signed-off-by: Damien George <damien@micropython.org>
2023-11-30 17:35:26 +11:00
Damien George 1c0e4644c7 cc3200: Convert dupterm to use common extmod implementation.
Tested on a WIPY.

Signed-off-by: Damien George <damien@micropython.org>
2023-11-30 17:35:06 +11:00
Damien George 22d9116c8c nrf: Convert os module to use extmod version.
The os.dupterm() function has changed on this port, it now matches the
semantics used by all other ports (except it's restricted to accept only
machine.UART objects).

Signed-off-by: Damien George <damien@micropython.org>
2023-11-30 16:33:56 +11:00
Damien George e3c4c32c64 nrf: Use dupterm_objs[0] instead of board_stdio_uart.
To make this a little more consistent with other ports.

Signed-off-by: Damien George <damien@micropython.org>
2023-11-30 16:33:56 +11:00
Damien George cc8fc450a6 esp8266/modmachine: Use common implementation of disable/enable_irq.
Now that the MICROPY_BEGIN_ATOMIC_SECTION/MICROPY_END_ATOMIC_SECTION macros
act the same as disable_irq/enable_irq, it's possible to use the common
extmod implementation of these machine functions.

Signed-off-by: Damien George <damien@micropython.org>
2023-11-30 16:11:11 +11:00
Damien George 39d4153a8d esp8266/esp_mphal: Make atomic section more atomic.
By disabling ets_loop_iter when the atomic section is active.

Signed-off-by: Damien George <damien@micropython.org>
2023-11-30 16:11:11 +11:00
Damien George 4bf7987f0a cc3200/mods/modmachine: Use common implementation of disable/enable_irq.
This commit changes the cc3200 port to use the common machine
implementation of machine.disable_irq() and machine.enable_irq().  This
eliminates its dependency on the stm32 port's code.  The behaviour of
cc3200 for these functions is changed:
- disable_irq() now returns an (opaque) integer rather than a bool
- enable_irq(state) must be passed and argument, which is the return value
  of disable_irq() rather than a bool

Signed-off-by: Damien George <damien@micropython.org>
2023-11-30 16:11:11 +11:00
Damien George f523b86541 extmod/modmachine: Provide common implementation of disable/enable_irq.
The ports esp32, mimxrt, rp2 and samd all shared exactly the same
implementation of machine.disable_irq() and machine.enable_irq(),
implemented in terms of MICROPY_{BEGIN,END}_ATOMIC_SECTION.  This commit
factors these implementations into extmod/modmachine.c.

The cc3200, esp8266, nrf, renesas-ra and stm32 ports do not yet use this
common implementation.

Signed-off-by: Damien George <damien@micropython.org>
2023-11-30 16:11:11 +11:00
Damien George e1ec6af654 extmod/modmachine: Provide common bindings for 6 bare-metal functions.
Minor changes for consistency are:
- nrf gains: unique_id(), freq() [they do nothing]
- samd: deepsleep() now resets after calling lightsleep()
- esp32: lightsleep()/deepsleep() no longer take kw arg "sleep", instead
  it's positional to match others.  also, passing 0 here will now do a 0ms
  sleep instead of acting like nothing was passed.
  reset_cause() no longer takes any args (before it would just ignore them)
- mimxrt: freq() with an argument and lightsleep() both raise
  NotImplementedError

Signed-off-by: Damien George <damien@micropython.org>
2023-11-30 16:11:11 +11:00
Damien George 48b5a7b060 extmod/modmachine: Provide common Python bindings for bootloader().
Signed-off-by: Damien George <damien@micropython.org>
2023-11-30 16:11:11 +11:00
Damien George e68aa40d2a extmod/modmachine: Add MICROPY_PY_MACHINE_PIN_BASE option.
And use it in qemu-arm, unix and windows ports to enable PinBase.

Signed-off-by: Damien George <damien@micropython.org>
2023-11-30 16:11:11 +11:00
Damien George 30a63a204d extmod/modmachine: Provide common Python bindings for machine.idle().
And use it in all ports.  The ports are unchanged, except esp8266 which now
just returns None from this function instead of the time elapsed (to match
other ports), and qemu-arm which gains this function.

Signed-off-by: Damien George <damien@micropython.org>
2023-11-30 16:11:11 +11:00
Damien George 7d39db2503 extmod/modmachine: Factor ports' machine module dict to common code.
This is a code factoring to have the dict for the machine module in one
location, and all the ports use that same dict.  The machine.soft_reset()
function implementation is also factored because it's the same for all
ports that did already implement it.  Eventually more functions/bindings
can be factored.

All ports remain functionally the same, except:
- cc3200 port: gains soft_reset, mem8, mem16, mem32, Signal; loses POWER_ON
  (which was a legacy constant, replaced long ago by PWRON_RESET)
- nrf port: gains Signal
- qemu-arm port: gains soft_reset
- unix port: gains soft_reset
- zephyr port: gains soft_reset, mem8, mem16, mem32

Signed-off-by: Damien George <damien@micropython.org>
2023-11-30 16:11:11 +11:00
Damien George 14432b5da0 extmod/modmachine: Make I2C/SPI defns available when soft impl enabled.
Signed-off-by: Damien George <damien@micropython.org>
2023-11-30 16:11:11 +11:00
Damien George 7b2f13fb69 renesas-ra: Consolidate MICROPY_PY_MACHINE_I2C option.
MICROPY_HW_ENABLE_HW_I2C and MICROPY_PY_MACHINE_I2C are equivalent, so
just use the latter.

Signed-off-by: Damien George <damien@micropython.org>
2023-11-30 16:11:11 +11:00
Damien George e120c00c95 stm32/modmachine: Only enable machine.I2C if hardware I2C is enabled.
Prior to this change, if a board did not define any hardware I2C pins, via
MICROPY_HW_I2Cx_SCL, then machine.I2C would alias to machine.SoftI2C.

That doesn't really make sense, and SoftI2C should always be used if there
is no hardware implementation.  So this commit makes it so that machine.I2C
is only available if at least one set of I2C hardware pins are defined via
the MICROPY_HW_I2Cx_SCL/SDA macros.

For all boards that define at least one set of I2C hardware pins (which is
most of them) this commit is a no-op.  The only boards that change are:
LEGO_HUB_NO6, LEGO_HUB_NO7, STM32H7B3I_DK.

Signed-off-by: Damien George <damien@micropython.org>
2023-11-30 16:11:11 +11:00
Damien George b4d288ae44 nrf: Use MICROPY_PY_MACHINE_SPI instead of MICROPY_PY_MACHINE_HW_SPI.
MICROPY_PY_MACHINE_SPI is defined in mpconfigport.h to be equal to
MICROPY_PY_MACHINE_HW_SPI, so they are equivalent options.  The former one
is preferred because it's used by all other ports.

The default in mpconfigport.h is to enable this option, and all boards that
enable SPI have this removed from their mpconfigboard.h file so they pick
up the default.

Signed-off-by: Damien George <damien@micropython.org>
2023-11-30 16:10:10 +11:00
Damien George 911662cc10 esp8266/machine_spi: Rename machine_hspi to machine_spi.
This renames the type, functions and file to match other ports.

Signed-off-by: Damien George <damien@micropython.org>
2023-11-30 15:58:56 +11:00
Damien George c554df57f6 tests/extmod/deflate_compress.py: Add a test for optimal compression.
Signed-off-by: Damien George <damien@micropython.org>
2023-11-30 12:13:29 +11:00
Damien George 6ba57f760c lib/uzlib: For matches of the same length, take the closest one.
Signed-off-by: Damien George <damien@micropython.org>
2023-11-30 12:13:29 +11:00
Damien George e182f3862e rp2/cyw43_configport: Implement cyw43_delay_ms as mp_hal_delay_ms.
They do the same thing.

Signed-off-by: Damien George <damien@micropython.org>
2023-11-29 16:25:28 +11:00
Damien George 12ef8a5ba2 rp2/mphalport: Optimise exit of mp_hal_delay_ms loop.
best_effort_wfe_or_timeout() already calls time_reached() and returns the
result of it, so no need to call it again.

Signed-off-by: Damien George <damien@micropython.org>
2023-11-29 16:25:28 +11:00
Damien George fc94399ffe rp2/mpnetworkport: Rework lwIP polling to use soft_timer.
Signed-off-by: Damien George <damien@micropython.org>
2023-11-29 16:25:20 +11:00
Damien George 633c604722 rp2/mpbthciport: Rework HCI polling timer to use soft_timer.
Signed-off-by: Damien George <damien@micropython.org>
2023-11-29 16:23:52 +11:00
Damien George c9a9b2e682 rp2: Integrate soft_timer using the alarm pool.
The alarm pool is used to schedule the callback to soft_timer_handler().

Signed-off-by: Damien George <damien@micropython.org>
2023-11-29 16:23:49 +11:00
Damien George 516cc280e0 shared/runtime/softtimer: Generalise soft_timer to work without SysTick.
If a port defines MICROPY_SOFT_TIMER_TICKS_MS then soft_timer assumes a
SysTick back end, and provides a soft_timer_next variable that sets when
the next call to soft_timer_handler() should occur.

Otherwise, a port should provide soft_timer_get_ms() and
soft_timer_schedule_at_ms() with appropriate semantics (see comments).

Existing users of soft_timer should continue to work as they did.

Signed-off-by: Damien George <damien@micropython.org>
2023-11-29 16:17:12 +11:00
Jeff Epler 9c7067d9ad py/modbuiltins: Share vstr_add_char's implementation of utf8 encoding.
This saves ~84 bytes on trinket m0, and saves 112 bytes on PYBV10.

Signed-off-by: Jeff Epler <jepler@gmail.com>
2023-11-28 23:34:56 +11:00
iabdalkader cfcd0c4022 stm32: Add missing header include for debug builds.
Debug build fails if string.h header is not included.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2023-11-28 23:32:52 +11:00
Jim Mussared 992cd64555 py/mkrules: Add support for custom manifest variables.
This allows e.g. a board (or make command line) to set

    MICROPY_MANIFEST_MY_VARIABLE = path/to/somewhere
    set(MICROPY_MANIFEST_MY_VARIABLE path/to/somewhere)

and then in the manifest.py they can query this, e.g. via

    include("$(MY_VARIABLE)/path/manifest.py")

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-11-28 23:28:15 +11:00
Mark Blakeney 094b52b8ad esp32/esp32_rmt: Fix RMT looping.
Commit 7ea06a3e26 moved the
`rmt_write_items()` call to fix RMT looping for ESP32-S3, but broke it for
the other ESP32s.  This commit conditionally compiles the location of that
call.

Signed-off-by: Mark Blakeney <mark.blakeney@bullet-systems.net>
2023-11-23 12:21:28 +11:00
Ihor Nehrutsa d6154925d5 esp32/network_wlan: Fix network.WLAN.status() to return better info.
Prior to this change, after calling connect() the status() method for the
STA interface would either return STAT_GOT_IP or STAT_CONNECTION.  The
latter would be returned because wifi_sta_connect_requested==true and
conf_wifi_sta_reconnects==0 by default.  As such there was no way to know
anything about errors when attempting to connect, such as a bad password.

Now, status() can return STAT_NO_AP_FOUND and STAT_WRONG_PASSWORD when
those conditions are met.

Fixes issue #12930.

Signed-off-by: IhorNehrutsa <Ihor.Nehrutsa@gmail.com>
2023-11-23 12:11:42 +11:00
Angus Gratton 960eef70e8 esp32/network_wlan: Reduce RAM usage if SPIRAM fails to initialise.
In ESP-IDF, enabling SPIRAM in menuconfig sets some Kconfig options:

- "Wi-Fi Cache TX Buffers" enabled. By default this tries to allocate 32 of
these when Wi-Fi is initialised, which requires 54,400 bytes of free heap.

- Switches "Type of WiFi TX buffers" from Dynamic to Static. This
pre-allocates all of the Wi-Fi transmit buffers.

Not a problem if PSRAM is initialised, but it's quite a lot of RAM if PSRAM
failed to initialise! As we use the same config for PSRAM & no-PSRAM builds
now, this either causes Wi-Fi to fail to initialise (seen on S2) or will
eat quite a lot of RAM.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2023-11-23 11:53:39 +11:00
Trent Piepho 92f0469711 esp32/uart: Make compatible with sclk type change in ESP-IDF 5.3.
This type changes when they add LP-UART support for the ESP32-C6 in the dev
version of ESP-IDF 5.3.

Signed-off-by: Trent Piepho <tpiepho@gmail.com>
2023-11-23 11:51:06 +11:00
Trent Piepho f72a7dde18 esp32/uart: Preserve console UART clock, fix UART console with DFS.
In commit 7c929d44 the console UART was changed to use the UART HAL.
Starting the UART HAL will change the UART clock from whatever it was
already configured at to UART_SCLK_DEFAULT.  There is no "initialize at
existing settings" option.

This clock doesn't work with DFS.

The ESP-IDF code already takes this into account, and when DFS is enabled
it will configure the console UART to use the correct platform-specific
clock that will work with DFS.

The UART HAL init undoes this and sets it back to default.

This change will query the clock before the HAL init, then use the HAL
function to restore it back.  Thus keeping the clock at the "correct"
value, which depends on platform, DFS status, and so on.

The clock frequency will be found using the UART driver function ESP-IDF
code uses for this.  The existing code hard-coded a path that worked if the
clock was the APB clock and would fail otherwise.

The UART_NUM_0 define is removed because driver/uart.h already provides
this same macro.

Signed-off-by: Trent Piepho <tpiepho@gmail.com>
2023-11-23 11:49:08 +11:00
Damien George a85c3c45a6 esp32/boards/ESP32_GENERIC: Reduce size of D2WD variant to fit in flash.
Signed-off-by: Damien George <damien@micropython.org>
2023-11-23 10:39:12 +11:00
Angus Gratton a800ed5ae3 docs/library/esp: Correct the description of esp.osdebug().
The behaviour described in the docs was not correct for either port.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2023-11-22 16:48:35 +11:00
Angus Gratton 917b56137f esp32/boards/sdkconfig.base: Fix increasing log level via esp.osdebug().
At some point the config changed such that no messages above Error level
were compiled into the final binary.

Fixes issue #12815.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2023-11-22 16:48:15 +11:00
Damien George f397a3ec31 py/objslice: Validate that the argument to indices() is an integer.
Otherwise passing in a non-integer can lead to an invalid memory access.

Thanks to Junwha Hong and Wonil Jang @S2Lab, UNIST for finding the issue.

Fixes issue #13007.

Signed-off-by: Damien George <damien@micropython.org>
2023-11-21 22:28:57 +11:00
Angus Gratton fce8d9fd55 esp32/modsocket: Try garbage collection if the socket limit is reached.
If the hard socket limit (default 16) is reached then it's possible that
socket allocation fails but garbage collection would allow it to succeed.

Perform a GC pass and try again before giving up, similar to the logic
elsewhere in MicroPython that tries a GC pass before raising MemoryError.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2023-11-20 19:16:16 +11:00
Angus Gratton 57cce79a46 esp32/modsocket: Implement socket connect timeout.
LWIP doesn't implement a timeout for blocking connect(), and such a timeout
is not required by POSIX.  However, CPython will use the socket timeout for
blocking connect on most platforms.  The "principle of least surprise"
suggests we should support it on ESP32 as well (not to mention it's
useful!).

This provides the additional improvement that external exceptions (like
KeyboardInterrupt) are now handled immediately if they happen during
connect().  Previously Ctrl-C would not terminate a blocking connect until
connect() returned, but now it will.

Fixes issue #8326.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2023-11-20 18:48:25 +11:00
Sebastian Romero 6117aa686f renesas-ra/boards/ARDUINO_PORTENTA_C33: Fix incorrect I2C pins.
Also change the number of the interface to 0 as it's connected to IIC0.

Signed-off-by: Sebastian Romero <s.romero@arduino.cc>
2023-11-17 15:40:33 +11:00
Sebastian Romero 6f0193335a ports: Fix incorrect identifiers on Arduino boards.
This commit changes the Arduino board identifiers to correspond to their
official names.  This helps to identify boards at runtime.  At the moment
the Arduino Portenta H7 is reported as PORTENTA which is unfortunate as now
there is another Portenta board (Portenta C33) supported in MicroPython.

Also made the other identifiers for flash and network name consistent,
removed the incorrectly used MICROPY_PY_SYS_PLATFORM identifiers, and added
missing MICROPY_PY_NETWORK_HOSTNAME_DEFAULT identifiers.

Boards affected:
- stm32: ARDUINO_PORTENTA_H7, ARDUINO_GIGA, ARDUINO_NICLA_VISION
- renesas-ra: ARDUINO_PORTENTA_C33
- esp32: ARDUINO_NANO_ESP32
- rp2: ARDUINO_NANO_RP2040_CONNECT

Signed-off-by: Sebastian Romero <s.romero@arduino.cc>
2023-11-17 15:24:15 +11:00
stijn a968888f69 py/obj: Fix mp_obj_is_type compilation with C++.
Fixes issue #12951.

Signed-off-by: stijn <stijn@ignitron.net>
2023-11-17 14:31:42 +11:00
Damien George 92741a3438 stm32/boards/STM32H573I_DK: Enable the SD card.
Signed-off-by: Damien George <damien@micropython.org>
2023-11-17 14:17:49 +11:00
Damien George c34941109f stm32/sdcard: Add SD card support for H5 MCUs.
Signed-off-by: Damien George <damien@micropython.org>
2023-11-17 14:17:37 +11:00
Rene Straub 0cc100be2c stm32/boards/NUCLEO_H563ZI: Add new NUCLEO-H563ZI board definition.
Configuration:
- Clock is HSE, CPU runs at 250MHz.
- REPL on USB and UART connected to the ST-Link interface.
- Storage is configured for internal flash memory.
- Three LEDs and one user button.
- Ethernet is enabled.

Signed-off-by: Rene Straub <rene@see5.ch>
2023-11-17 13:53:01 +11:00
ThomHPL 70feb123bf stm32/boards/NUCLEO_F446RE: Add UARTs 1, 3 and 4.
Signed-off-by: ThomHPL <thomas.herpoel@gmail.com>
2023-11-17 13:43:11 +11:00
Peter Züger 36e162f116 tests/net_hosted/asyncio_loopback.py: Add loopback test.
Signed-off-by: Peter Züger <zueger.peter@icloud.com>
2023-11-17 13:37:43 +11:00
Peter Züger a23dbdca79 stm32: Add optional lwip loopback support.
MICROPY_PY_LWIP_LOOPBACK must be set at the make level to enable this.

Signed-off-by: Peter Züger <zueger.peter@icloud.com>
2023-11-17 13:37:04 +11:00
Peter Züger 1879db7105 extmod/extmod.mk: Allow enabling lwip loopback support.
Enabling MICROPY_PY_LWIP_LOOPBACK via make will turn on loopback support.

Signed-off-by: Peter Züger <zueger.peter@icloud.com>
2023-11-17 13:35:47 +11:00
Andrew Leech 37c1c5fa49 stm32/mpu: Enable STM32WB mpu use to support qspi flash.
Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
2023-11-17 13:17:13 +11:00
Angus Gratton 8b1980ad45 samd: Use unique id for USB serial number.
Replaces the previous all-zeroes "TODO" serial number.

Requires refactoring the low-level unique_id routine out from modmachine.c.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2023-11-16 15:03:09 +11:00
Angus Gratton f567a9255a shared/tinyusb: Add a helper for hex string conversion.
Change the rp2 and renesas-ra ports to use the helper function.

Saves copy-pasta, at the small cost of one more function call in the
firmware (if not using LTO).

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2023-11-16 14:59:48 +11:00
Angus Gratton 5e3f0e7f85 samd: Switch to shared TinyUSB implementation.
Functionality and code size don't really change, but removes port-specific
code in favour of shared code.

(The MSC implemented in shared/tinyusb depends on some functions in the
pico-sdk, so this change doesn't make this available for samd.)

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2023-11-16 14:54:29 +11:00
Angus Gratton 033361da4a samd/mphalport: Run TinyUSB stack while waiting for CDC input/output.
See the commit a00c9d56db for a detailed description of the problem, a
regression introduced in 26d503298.

Same approach here as the linked fix for rp2 (applied unconditionally here
as this port only supports USB-CDC for stdin/stdout).

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2023-11-10 08:04:26 +11:00
Damien George a00c9d56db rp2/mphalport: Run TinyUSB stack while waiting for CDC input/output.
The recent change in bcbdee2357 means that
TinyUSB can no longer be run from within a soft (or hard) IRQ handler, ie
when the scheduler is locked.  That means that Python code that calls
`print(...)` from within a scheduled function may block indefinitely if the
USB CDC buffers are full.

This commit fixes that problem by explicitly running the TinyUSB stack when
waiting within stdio tx/rx functions.

Signed-off-by: Damien George <damien@micropython.org>
2023-11-09 17:56:58 +11:00
Damien George d46dc5e173 shared/tinyusb: Expose mp_usbd_task as a public function.
Signed-off-by: Damien George <damien@micropython.org>
2023-11-09 17:56:58 +11:00
stijn 365913953a extmod/vfs_posix_file: Make standard file objects non-const.
Fixes undefined behavior when calling vfs_posix_file_ioctl with
MP_STREAM_CLOSE as request because that casts away the constness and
assigns -1 to the object's fd member.

Fixes issue #12670.

Signed-off-by: stijn <stijn@ignitron.net>
2023-11-09 15:01:34 +11:00
Daniël van de Giessen 3b954698fa extmod/modbluetooth: Initialise nlr_jump_callback_top for IRQ handlers.
Similar to 3883f29485 where this change was
implemented for threads: when the Bluetooth IRQ handler is called the
thread state is not not zero-initialized and thus we need to manually set
this to NULL.

Fixes issue #12239.

Signed-off-by: Daniël van de Giessen <daniel@dvdgiessen.nl>
2023-11-09 14:51:20 +11:00
Jim Mussared af52e1ff24 stm32/boards/NUCLEO_WL55: Freeze LoRa driver.
This adds the sync version of the LoRa driver (and the base WL55 driver).

Adds +13.6kiB (212.6 -> 226.2). Limit for this board is 232kiB.

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-11-09 14:47:53 +11:00
Mark Blakeney 2888c5b230 esp32/esp32_rmt: Add RMT.PULSE_MAX constant.
If you have a variable frequency and pulse width, and you want to optimize
pulse resolution, then you must do a calculation beforehand to ensure you
normalize the array to keep all list values within bound.  That calculation
requires RMT.source_freq(), RMT.clock_div(), and this 32767 constant.

Signed-off-by: Mark Blakeney <mark.blakeney@bullet-systems.net>
2023-11-09 13:51:52 +11:00
Mark Blakeney fbb7c32040 esp32/esp32_rmt: Change RMT.source_freq() to class method.
To create an esp32.RMT() instance with an optimum (i.e. highest resolution)
clock_div is currently awkward because you need to know the source clock
frequency to calculate the best clock_div, but unfortunately that is only
currently available as an source_freq() method on the instance after you
have already created it.  So RMT.source_freq() should really be a class
method, not an instance method.  This change is backwards compatible for
existing code because you can still reference that function from an
instance, or now also, from the class.

Signed-off-by: Mark Blakeney <mark.blakeney@bullet-systems.net>
2023-11-09 13:51:47 +11:00
robert-hh f07f90f1ab mimxrt/boards/OLIMEX_RT1010: Adjust the UART pin assignment.
Olimex asked for that, getting a UART at the UEXT1 connector as well.

Signed-off-by: robert-hh <robert@hammelrath.com>
2023-11-09 13:41:44 +11:00
Andrew Leech 4679a90097 CODECONVENTIONS: Update for change from black to ruff format.
Also add notes on running pre-commit manually.

Signed-off-by: Andrew Leech <andrew@alelec.net>
2023-11-09 13:36:21 +11:00
Angus Gratton 26d5032980 samd: Switch TinyUSB to run via a scheduled task.
Previously the TinyUSB task was run in the ISR immediately after the
interrupt handler.  This approach gives very similar performance (no change
in CDC throughput tests) but reduces the amount of time spent in the ISR,
and allows TinyUSB callbacks to run in thread mode.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2023-11-09 12:30:04 +11:00
Angus Gratton bcbdee2357 rp2: Change to use TinyUSB dcd_event_handler hook.
This change:
- Has a small code size reduction.
- Should slightly improve overall performance.  The old hook code
  seemed to use between 0.1% and 1.6% of the total CPU time doing no-op
  calls even when no USB work was required.
- USB performance is mostly the same, there is a small increase in
  latency for some workloads that seems to because sometimes the hook
  usbd_task() is called at the right time to line up with the next USB host
  request.  This only happened semi-randomly due to the timing of the hook.
  Improving the wakeup latency by switching rp2 to tickless WFE allows the
  usbd_task() to run in time for the next USB host request almost always,
  improving performance and more than offsetting this impact.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2023-11-09 12:28:28 +11:00
Angus Gratton 2d363a23cb shared/tinyusb: Schedule TinyUSB task function from dcd_event_handler.
dcd_event_handler() is called from the IRQ when a new DCD event is queued
for processing by the TinyUSB thread mode task.  This lets us queue the
handler to run immediately when MicroPython resumes.

Currently this relies on a linker --wrap hack to work, but a PR has been
submitted to TinyUSB to allow the function to be called inline from
dcd_event_handler() itself.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2023-11-09 12:27:33 +11:00
Andrew Leech bbc5a18d09 tools/mpremote: Add ioctl to specify large read buffer size.
Speeds up importing files from mounted filesystem.

Also fix the return code for invalid / unsupported ioctl requests.

Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
2023-11-09 11:30:11 +11:00
Andrew Leech 4cf741062b extmod/vfs_reader: Add file ioctl to set read buffer size.
Can be used to speed up importing a file from a vfs based filesystem.

Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
2023-11-09 11:20:31 +11:00
Damien George dff293840e extmod/machine_i2c: Do a fast poll during I2C.scan().
Fixes issue #12912.

Signed-off-by: Damien George <damien@micropython.org>
2023-11-08 23:34:08 +11:00
stijn 958c6d917d windows: Use the MicroPython logo as application icon.
Add a .ico file with common icon image size, created from
vector-logo-2.png, and embed it into the resulting executable.

Signed-off-by: stijn <stijn@ignitron.net>
2023-11-07 17:22:52 +11:00
Damien George 03eae48847 extmod/machine_adc_block: Factor esp32 ADCBlock bindings to common code.
This is a code factoring to have the Python bindings in one location, and
all the ports use those same bindings.  At this stage only esp32 implements
this class, so the code for the bindings comes from that port.

The documentation is also updated to reflect the esp32's behaviour of
ADCBlock.connect().

Signed-off-by: Damien George <damien@micropython.org>
2023-11-07 16:44:35 +11:00
Jim Mussared 4212799fd8 py/qstr: Special case qstr_find_strn for empty string.
This handles the case where an empty bytes/bytearray/str could pass in
NULL as the str argument (with length zero). This would result in UB in
strncmp. Even though our bare-metal implementation of strncmp handles
this, best to avoid it for when we're using system strncmp.

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-11-07 16:01:50 +11:00
Jim Mussared 9be0623d4c shared/libc/string0: Don't deref args for n==0 case.
C99 says that strncmp has UB for either string being NULL, so the
current behavior is technically correct, but it's an easy fix to handle
this case correctly.

7.1.4: "unless explicitly stated otherwise in the detailed
description... if an argument to a function has ...null pointer.. the
behavior is undefined".

7.21.1: "Unless explicitly stated otherwise in the description of a
particular function in this subclause, pointer arguments on such a call
shall still have valid values, as described in 7.1.4".

Also make the same change for the minimal version in bare-arm/lib.c.

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-11-07 16:01:50 +11:00
Alessandro Gatti bea6ff82fa tools/tinytest-codegen.py: Externalise tests list.
Remove port-specific test directories and excluded tests from
tinytest-codegen, and let it read said information from an external file.
This way tinytest-codegen is not limited to always generate tests for the
`qemu-arm` target.

This allows having port-specific test directory and excluded tests for more
than one QEMU bare-metal target.

The `qemu-arm` port Makefile was modified to work with the generator
changes and a tests profile file was added to said port.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2023-11-07 15:53:27 +11:00
robert-hh c35cc63366 samd/pin_af: Fix a typo in a conditional compile.
Thanks to @ricksorensen for finding it.

Signed-off-by: robert-hh <robert@hammelrath.com>
2023-11-06 11:11:18 +11:00
robert-hh 59afeb056a samd/machine_uart: Add machine_uart_set_baudrate() function.
Changing the baudrate requires a complete re-configuration of the Sercom
device, which is put into a separate rather large function.  This new
machine_uart_set_baudrate() function will be useful for future drivers such
as Bluetooth.

Signed-off-by: robert-hh <robert@hammelrath.com>
2023-11-06 11:10:11 +11:00
robert-hh 2c1f238205 samd/mpconfigport: Set MICROPY_USE_INTERNAL_ERRNO to 1.
Without this, error codes can be misleading.

Signed-off-by: robert-hh <robert@hammelrath.com>
2023-11-06 11:09:16 +11:00
robert-hh 6866d17d8f docs/samd: Fix the pinout for SAMD21 Itsy Bitsy Express M0.
And the "Pin", "GPIO" and "Name" key explanations.

Signed-off-by: robert-hh <robert@hammelrath.com>
2023-11-06 11:09:09 +11:00
Jim Mussared 47ed06bda2 stm32/boards/make-pins.py: Only support ADC1-3.
e.g. The STM32G4 includes ADC4 & ADC5 which is not currently supported
by the stm32 driver.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-11-05 08:33:49 +11:00
robert-hh e63d7189bc docs/mimxrt: Change the examples which denote a Pin with a number.
This option was removed in PR #12211.

Signed-off-by: robert-hh <robert@hammelrath.com>
2023-11-05 08:30:34 +11:00
robert-hh ae3b1cfab1 mimxrt/modmachine: Fix settings for the MIMXRT1170 board.
These were not changed with commit c0b64a3f2 for using tools/boardgen.py.

Signed-off-by: robert-hh <robert@hammelrath.com>
2023-11-05 08:30:18 +11:00
Jim Mussared 09c9c8ac30 stm32/boards/stm32g474_af.csv: Fix final row ADC column.
The original file was missing a trailing , on the final row.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-11-04 11:00:06 +11:00
Jim Mussared c028f956fc stm32/boards/stm32f4x9_af.csv: Fix DCMI_VSYNC.
This incorrectly had a `(1)` on the end.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-11-04 09:01:40 +11:00
Jim Mussared 841422817e stm32/boards/make-pins.py: Fix H7 ADC generation.
Fixes are:
- Only emit ADC table entries for pins that aren't cpu-hidden
  (i.e. ignore `X,-Y` rows).
- Only use the P channels on H7.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-11-03 19:34:54 +11:00
Angus Gratton 8c432ea2d4 rp2: Remove 1ms timeout to make idle waiting tickless.
The main motivation for doing this was to reduce the latency when the
system is woken by a USB interrupt.  The best_effort_wfe_or_timeout()
function calls into the pico-sdk dynamic timer framework which sets up a
new dynamic timer instance each time, and then has to tear it down before
continuing after a WFE.

Testing Python interrupt latency, it seems to be improved by about 12us
(from average of 46us to 34us running a Pin IRQ).  C-based "scheduled
nodes" should see even lower latency.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2023-11-03 18:26:51 +11:00
iabdalkader b41055a5a3 rp2/machine_adc: Refactor channel/pin validation code.
This patch ensures that integer channel numbers passed to the ADC
constructor (including temperature sensor) are interpreted as raw
channel numbers, and not cause any GPIO pins to be initialized.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2023-11-03 18:20:31 +11:00
Maarten van der Schrieck d95f5aa011 rp2/machine_uart: Fix handling of serial break condition.
The FIFO reports not only the bytes read, but also 4 error bits. These were
not checked, leading to NUL value read in case of break and possible
garbage bytes being written on parity/framing error.

This patch addresses the issue that NUL bytes are incorrectly read on
break, and at least provides the boilerplate code and comments for error
handling, that may be implemented in the future.

Signed-off-by: Maarten van der Schrieck <maarten@thingsconnected.nl>
2023-11-03 17:33:28 +11:00
Rene Straub 47ea831c0e stm32: Add STM32H5 support for sleep mode.
Update rtc, machine and powerctrl drivers to support STM32H5 sleep
modes. This makes RTC alarm wakeup working from lightsleep() and
deepsleep().

Changes:
- Determine start reason for machine.reset_cause() in modmachine.c.
- Add proper interrupt clear code in rtc.c.
- Add wakeup functionality in powerctrl_enter_stop_mode(). Remember
  and restore voltage scaling level. Restart HSI48 if it was on before
  entering sleep mode.
- Clear DBGMCU_CR in SystemClock_Config() as for other variants.
  Otherwise debug flags prevent entering sleep mode.

Implementation Notes:
- rtc.c: EXTI_RTSTR1 bits are not present for H5. Code sequence from
  G0/G4/L4/WB/WL would be invalid. RTSTR is only defined for external
  (GPIO) interrupts. Maybe this is also true for other STM32 variants.
- powerctrl_enter_stop_mode() uses complicated, nested conditionals
  to select STM32 variants. To make code slightly better readable,
  comment have been added. A non-nested, #if/#elif sequence would
  make the code more readable. I leave this to the original authors.

Signed-off-by: Rene Straub <rene@see5.ch>
2023-11-03 17:14:05 +11:00
iabdalkader e5014a4d79 stm32: Add configuration options for analog switches.
Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2023-11-03 16:27:10 +11:00
Jim Mussared b6a9778484 py/misc: Change sizeof to offsetof for variable-length alloc.
This fixes the case where e.g.

    struct foo_t {
      mp_obj_t x;
      uint16_t y;
      char buf[];
    };

will have `sizeof(struct foo_t)==8`, but `offsetof(struct foo_t, buf)==6`.

When computing the size to allocate for `m_new_obj_var` we need to use
offsetof to avoid over-allocating. This is important especially when it
might cause it to spill over into another GC block.

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-11-03 16:03:18 +11:00
Mathieu Serandour c85db05244 py/lexer: Change token position for new lines.
Set the position of new line tokens as the end of the preceding line
instead of the beginning of the next line.  This is done by first moving
the pointer to the end of the current line to skip any whitespace, record
the position for the token, then finaly skip any other line and whitespace.

The previous behavior was to skip every new line and whitespace, including
the indent of the next line, before recording the token position.

(Note that both lex->emit_dent and lex->nested_bracket_level equal 0 if
had_physical_newline == true, which allows simplifying the if-logic for
MP_TOKEN_NEWLINE.)

And update the cmd_parsetree.py test expected output, because the position
of the new-line token has changed.

Fixes issue #12792.

Signed-off-by: Mathieu Serandour <mathieu.serandour@numworks.fr>
2023-11-03 15:56:10 +11:00
Damien George 9a4d4db3a1 py/runtime: Remove declaration of function from inside function.
Signed-off-by: Damien George <damien@micropython.org>
2023-11-03 15:21:51 +11:00
Jim Mussared 6ef9b29f88 {cc3200,nrf}/boards/make-pins.py: Add a note about tools/boardgen.py.
It's not worth the effort to update these ports to use boardgen.py, but
put a note just in case anyone uses this as a reference for a new port.

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-11-03 14:18:54 +11:00
Jim Mussared 1f804e03f6 renesas-ra/boards/make-pins.py: Update to use tools/boardgen.py.
This removes previously unused functionality to generate pins_ad_const.h,
as well as the unused handling of pin AF in machine_pin.c.

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-11-03 14:18:54 +11:00
Jim Mussared c0b64a3f23 mimxrt/boards/make-pins.py: Update to use tools/boardgen.py.
Minor change to remove support for using numeric IDs for machine.Pin.  This
was previously based on the index of the pin in the board csv, but this is
different (and incompatible) with other ports.

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-11-03 14:18:54 +11:00
Jim Mussared 4d568a5bd7 samd/boards/make-pins.py: Update to use tools/boardgen.py.
This replaces the previous make-pin-table.py with an implementation based
on boardgen.py.

- MICROPY_PY_MACHINE_PIN_BOARD_CPU macro is removed. This isn't optional
  on other ports, so no need for it to be optional on SAMD.
- pin_af_table is removed, and lookups just search the cpu dict instead
  (this saves N*wordsize bytes of firmware size to have this extra table).
- pins.csv is now BOARD,CPU to match other ports.

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-11-03 14:18:32 +11:00
Jim Mussared ff6c2adfd7 stm32/boards/make-pins.py: Add initial support for H7 dual-pad pins.
This fixes the H7 af.csv files to include the dual-pad information, by
listing the ADCs supported on the _C pad with a C_ADC prefix.

Minimal change to make-pins.py to ignore these entries. This will be
implemented later to emit constants (similar to ADC.CORE_TEMP) to access
these channels.

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-11-03 14:18:32 +11:00
Jim Mussared 724ebb9916 stm32/boards/make-pins.py: Update to use tools/boardgen.py.
Requires additions to tools/boardgen.py for stm32 pin generation.

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-11-03 14:16:49 +11:00
Jim Mussared b4236c7368 stm32: Rename pin_obj_t to machine_pin_obj_t.
This is now consistent with other ports.

Also renamed `pin_{board/cpu}_pins_locals_dict` to
`machine_pin_{board/cpu}_pins_locals_dict`.

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-11-03 14:09:08 +11:00
Jim Mussared 286b1b3ed9 stm32/boards: Format stm32 alternate function csv files.
Changes are:
- Pad all cells to make them easier to read.
- Ensure all files have exactly 19 columns (Port,Pin,AF0-15,ADC)

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-11-03 14:08:39 +11:00
Jim Mussared 98dff07bb4 stm32/boards: Fix errors in pins.csv and af.csv.
Fixes are:
- Comment out lines in pins.csv that do not have valid CPU pins.
  It's useful to keep these in the file as "documentation" but in order to
  make make-pins.py stricter they need to be commented out.
- Fix some typos (missing P prefix) in pins.csv.
  This resulted in some missing board pins.
- Fix some typos in af.csv files.
  Some typos of "ADC" and some other that were previously ignored.

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-11-03 14:07:10 +11:00
Jim Mussared 4bd6ec9ae4 tools/boardgen.py: Add initial implementation of a common make-pins.py.
For now, this implements the functionality required for esp32 and rp2,
including support for numeric pins, rp2 alternate functions, and rp2
extended pins.

This also updates the rp2 port to use the same structure for pins.h and
pins.csv as for esp32, and moves the pin definitions directly into the
table (rather than having a table of pointers), which is a small code size
improvement.

Support for "hidden" pins in pins.csv is added (matching the stm32
implementation).

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-11-03 14:06:27 +11:00
Jim Mussared b0aec6a0ff esp32/machine_pin: Make irq object a sub-field of pin object.
This simplifies pin generation.

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-11-03 14:05:47 +11:00
Jim Mussared 9cabee8252 ports: Standardise arguments and output for make-pins.py script.
All ports now use `--board-csv`, `--prefix`, `--output-souce`,
`--output-header` and no longer write to stdout.  This matches the esp32
implementation.

Ports that have an AF input use `--af-csv` (to match `--board-csv`).

Any additional output files are now prefixed with `output-` (e.g.
`--output-af-const`).

Default arguments are removed (all makefiles should always specify all
arguments, using default values is likely an error).

Replaced the `af-defs-cmp-strings` and `hdr-obj-decls` args for stm32 with
just `mboot-mode`.  Previously they were set on the regular build, now the
logic is reversed so mboot sets it.

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-11-03 14:04:35 +11:00
Jim Mussared 1ee5731122 ports: Remove SRC_QSTR_AUTO_DEPS from all ports' Makefiles.
It's unused.

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-11-03 14:04:17 +11:00
Jim Mussared 59f3c7facb examples/pins.py: Remove this pins printing example.
It's not supported on all ports, adds complexity to the build to generate
pins_af.py, and can mostly be replicated just by printing the pin objects.

Remove support for generating pins_af.py from all ports (nrf, stm32,
renesas-ra, mimxrt, rp2).

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-11-03 14:03:28 +11:00
Jim Mussared cb37b7bba7 cc3200/boards/make-pins.py: Don't generate qstrs.
The output pins.c can be processed for qstrs like any other C file.

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-11-03 14:02:58 +11:00
Jim Mussared df28aa1a59 renesas-ra/boards/make-pins.py: Don't generate qstrs.
The output pins.c can be processed for qstrs like any other C file.

Also remove af_const from Makefile (unimplemented in make-pins.py) and fix
target dependency on ad_const.

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-11-03 14:01:30 +11:00
Jim Mussared 3f99dbd634 nrf/boards/make-pins.py: Don't generate qstrs.
The output pins.c can be processed for qstrs like any other C file.

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-11-03 14:01:04 +11:00
Jim Mussared fc54d25a45 stm32/boards/make-pins.py: Don't generate qstrs.
Qstrs are picked up from the generated pin source files in the usual qstr
processing stage.

Similarly for the stm constant qstrs.

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-11-03 13:59:19 +11:00
Jim Mussared c3c7c602da rp2/boards/make-pins.py: Don't generate qstrs.
Also remove af-const header, as this is left over from the STM32 version
and unused.

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-11-03 13:58:07 +11:00
Jim Mussared 2eda513870 py/mkrules.mk: Add rule for compiling auto-generated source files.
This prevents each port Makefile from having to add an explicit rule for
`build-BOARD/pins_BOARD.c`.

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-11-03 13:57:47 +11:00
Damien George aa329d11ea top: Update .git-blame-ignore-revs for latest formatting commit.
Signed-off-by: Damien George <damien@micropython.org>
2023-11-03 13:32:19 +11:00
Jim Mussared bbd8760bd9 all: Update Python formatting to ruff-format.
This updates a small number of files that change with ruff-format's (vs
black's) rules.

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-11-03 13:30:41 +11:00
Jim Mussared 303ccca7c6 all: Replace "black" with "ruff format".
- Add config for [tool.ruff.format] to pyproject.toml.
- Update pre-commit to run both ruff and ruff-format (and only check C
  files when running codeformat.py)
- Update CI.
- Simplify codeformat.py to remove all the Python-specific logic (just run
  "ruff format" directly).

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-11-03 13:30:38 +11:00
Daniël van de Giessen 7ad84e0422
lib/littlefs: Update LittleFS to v2.8.1.
Signed-off-by: Daniël van de Giessen <daniel@dvdgiessen.nl>
2023-11-01 17:07:18 +01:00
Andrew Leech 06a7bf967c esp32/usb: Wake main thread when USB receives data.
This improves (decreases) the latency on stdin, on SoCs with built-in USB
and using TinyUSB, like S2 and S3.

Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
2023-11-01 16:27:10 +11:00
Andrew Leech d8a263435f esp32/mphalport: Add function to wake main from separate FreeRTOS task.
Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
2023-11-01 16:24:57 +11:00
Alessandro Gatti 95ce61d0ad esp32: Use better build settings for ESP32-C3.
ESP32-C3 is not Xtensa-based, so build settings are now tailored a bit
better following that fact.  ESP-IDF 5.x already adds architecture-specific
modules by itself so there is no need to specify either the `xtensa` or the
`riscv` module in the build settings.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2023-11-01 11:38:09 +11:00
Damien George 4cffa848f6 esp32/boards: Reduce size of D2WD and OTA firmware.
Commit c4e63ace66 enabled the SPI Ethernet
driver and that cost about 13k of firwmare size, pushing the firmware over
the limit of the D2WD and OTA board variants available size.

To fix, disable SPI Ethernet on the D2WD variant, and build the OTA variant
with size optimisation rather than performance optimisation.

Signed-off-by: Damien George <damien@micropython.org>
2023-11-01 10:38:52 +11:00
Damien George a614c1d501 extmod: Remove empty utime_mphal.h file.
Signed-off-by: Damien George <damien@micropython.org>
2023-10-31 13:31:54 +11:00
Jim Mussared e579ebb11b teensy: Remove the teensy port.
This port is largely unmaintained, has limited features (the only hardware
support is for GPIO and timer, and no machine module), only supports a
small number of Teensy boards, and can be confused with the mimxrt support
for Teensy 4.x.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
Signed-off-by: Damien George <damien@micropython.org>
2023-10-31 13:04:41 +11:00
Pascal Brunot a8dd69f206 esp32/modmachine: Fix deepsleep() when previous sleep delay was set.
Fixes issue #7158.

Signed-off-by: Pascal Brunot <pascal.brunot@gmail.com>
2023-10-31 12:48:32 +11:00
robert-hh bbbd484f5b esp32/network_lan: Register the hostname setting for Ethernet.
Fixes issue #12817.

Signed-off-by: robert-hh <robert@hammelrath.com>
2023-10-31 12:42:36 +11:00
robert-hh 9c244134fb esp32/network_lan: Fix LAN.isconnected().
nic.isconnected() returns now "True", if a) the physical link is up and b)
an IP address is assigned.  The latter happens often by DHCP, in which case
an active connection can be assumed.  If the IP address is set manually,
nic.isconnected() would report "True" as well, if at least the physical
link is up.  This matches WLAN behaviour which returns "True" when the WLAN
has an IP address.

Before, the behaviour of nic.isconneceted() was erratic, returning "True"
sometimes even without a Ethernet cable attached.

Fixes issue #12741.

Signed-off-by: robert-hh <robert@hammelrath.com>
2023-10-31 12:42:33 +11:00
robert-hh c4e63ace66 esp32/network_lan: Fix and simplify the code for ETH-SPI devices.
SPI support was not enabled, and was not adapted for esp-idf v5.x.  This
change enables SPI ethernet for all boards and adapts the code for esp-idf
v5.x.  The change follows the sample implementation of @hemakumarm72, but
adds the changes for the other adapters as well.  Further, it simplifies
the code by removing actions from netwwork_lan.c which are done in the
esp-idf drivers later, like setting the default values for .command_bits
and .address_bits, and registering the SPI interface.

Tested with a Wiznet W5500 breakout.

Signed-off-by: robert-hh <robert@hammelrath.com>
2023-10-31 12:35:22 +11:00
Daniël van de Giessen b2f220dff8 esp32/boards: Disable ALPN support.
Signed-off-by: Daniël van de Giessen <daniel@dvdgiessen.nl>
2023-10-31 12:18:16 +11:00
Daniël van de Giessen a1d20e0747 esp32/network_ppp: Reduce PPP thread CPU usage.
Reduces the CPU usage by the PPP thread by sleeping for one tick if
there was nothing to read; preventing the loop using 100% CPU when the
read operation has a zero timeout and immediately returns.

Signed-off-by: Daniël van de Giessen <daniel@dvdgiessen.nl>
2023-10-31 12:10:36 +11:00
Daniël van de Giessen f1d6af9819 esp32/machine_uart: Add error checking for IDF API's.
Signed-off-by: Daniël van de Giessen <daniel@dvdgiessen.nl>
2023-10-31 12:04:33 +11:00
Daniël van de Giessen e676edac79 esp32/mpconfigport: Remove port-specific GAP name.
Instead use the generic default defined in modbluetooth_nimble.c.
This then also allows custom boards to easily override the default
Bluetooth GAP name.

Signed-off-by: Daniël van de Giessen <daniel@dvdgiessen.nl>
2023-10-31 12:01:47 +11:00
Daniël van de Giessen f74131134c esp32: Poll serial/JTAG for unread data to prevent blocking.
If data is pushed over serial/JTAG too fast we may fill up stdin_ringbuf
and not be able to read all the data out of the serial/JTAG buffer. Thus
we need to explicitly poll and read the serial/JTAG RX buffer to prevent
blocking (since if the serial/JTAG buffer is already filled, we will not
get another interrupt to transfer it to the stdin ringbuffer).

Signed-off-by: Daniël van de Giessen <daniel@dvdgiessen.nl>
2023-10-31 11:59:15 +11:00
Alessandro Gatti 1cf3085c57 esp32/network_ppp: Allow building with IPv6 disabled.
PPP code assumes that IPv6 support is enabled.  Whilst this is the default,
certain applications may want to disable IPv6 support if not needed (or to
reduce code size).

This makes the code build with CONFIG_LWIP_IPV6 disabled, reducing code by
about 30k in that case.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2023-10-31 11:54:25 +11:00
Seon Rozenblum c146017f8a esp32/boards: Update UM board settings to use custom PID/VID.
Signed-off-by: Seon Rozenblum <seon@unexpectedmaker.com>
2023-10-30 17:31:44 +11:00
Seon Rozenblum bdae847082 esp32/boards/UM_TINYWATCHS3: Add new UM TinyWATCH S3 board.
Signed-off-by: Seon Rozenblum <seon@unexpectedmaker.com>
2023-10-30 17:31:21 +11:00
Jim Mussared 64c79a5423 py/qstr: Add support for sorted qstr pools.
This provides a significant performance boost for qstr_find_strn, which is
called a lot during parsing and loading of .mpy files, as well as interning
of string objects (which happens in most string methods that return new
strings).

Also adds comments to explain the "static" qstrs.  These are part of the
.mpy ABI and avoid needing to duplicate string data for QSTRs known to
already be in the firmware.  The static pool isn't currently sorted, but in
the future we could either split the static pool into the sorted regions,
or in the next .mpy version just sort them.

Based on initial work done by @amirgon in #6896.

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-10-30 11:10:02 +11:00
Jim Mussared e910533012 bare-arm/lib: Add minimal strncmp implementation.
Required by upcoming qstr sorting.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-10-30 11:10:02 +11:00
Jim Mussared 78f4f30cb1 tests/extmod/asyncio_as_uasyncio.py: Fix qstr order dependency.
This test depends on the order in which qstrs are stored in ROM, which
affects the order in which `dir()` will probe the object to see what it
supports.  Because of the lazy-loading in asyncio/__init__.py, if it
tries to do e.g. `wait_for_ms` before `funcs` then it will import funcs,
making `funcs` later succeed. But in the other way around, `funcs` will
initially not be found.

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-10-30 11:10:02 +11:00
Jim Mussared 1a017511d0 tests/perf_bench: Add string/qstr/map tests.
These tests are designed to measure changes in performance relating to:
 - string interning / searching for existing strings
 - map lookup
 - string operations
 - string hashing

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-10-27 16:16:08 +11:00
iabdalkader 2fda94c286 extmod/network_ninaw10: Fix select flags handling in socket poll.
The flags returned from `select()` were misinterpreted to mean an error had
occurred for the socket, when it's actually just an exceptional condition
for the socket, such as OOB data.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2023-10-27 15:49:17 +11:00
Alessandro Gatti b6c369a396 py/asm{arm,thumb,x64,x86,xtensa}: Remove unused macros.
`ASM_MOV_REG_IMM_FIX_U16` and `ASM_MOV_REG_IMM_FIX_WORD` are no longer
used anywhere in the code.

See discussion in #12771.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
2023-10-27 15:41:02 +11:00
Jim Mussared 6cd99910cd docs/reference/micropython2_migration: Add migration guide.
This is just scaffolding for now, but the idea is that there should be an
addition to this file for every commit that uses the
`MICROPY_PREVIEW_VERSION_2` macro.

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-10-27 15:28:46 +11:00
Jim Mussared 3bf70f16e9 py/mkrules.mk: Add MICROPY_PREVIEW_VERSION_2.
This provides a way to enable features and changes slated for MicroPython
2.x, by running `make MICROPY_PREVIEW_VERSION_2=1`. Also supported for
the cmake ports (except Zephyr).

This is an alternative to having a 2.x development branch (or equivalently,
keeping a 1.x release branch). Any feature or change that needs to be
"hidden" until 2.x can use this flag (either in the Makefile or the
preprocessor).

A good example is changing function arguments or other public API features,
in particular to aid in improving consistency between ports.

When `MICROPY_PREVIEW_VERSION_2` is enabled, the REPL banner is amended to
say "MicroPython (with v2.0 preview) vX.Y.Z", and sys.implementation gets a
new field `_v2` set to `True`.

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-10-27 15:28:46 +11:00
Damien George 3e2706a18d extmod/modmachine: Consolidate mem, i2c and spi headers to modmachine.h.
The contents of machine_mem.h, machine_i2c.h and machine_spi.h have been
moved into extmod/modmachine.h.

Signed-off-by: Damien George <damien@micropython.org>
2023-10-26 17:40:22 +11:00
Damien George 6989aba93b nrf/modules/machine: Use SPI Python bindings provided by extmod.
Signed-off-by: Damien George <damien@micropython.org>
2023-10-26 17:37:39 +11:00
Damien George d336c1b79b extmod/modmachine: Consolidate simple machine headers into modmachine.h.
The contents of machine_bitstream.h, machine_pinbase.h, machine_pulse.h and
machine_signal.h have been moved into extmod/modmachine.h.

Signed-off-by: Damien George <damien@micropython.org>
2023-10-26 16:49:27 +11:00
Damien George 90023b4dcf extmod/modmachine: Clean up decls of machine types to use common ones.
The machine_i2c_type, machine_spi_type and machine_timer_type symbols are
already declared in extmod/modmachine.h and should not be declared anywhere
else.

Also move declarations of machine_pin_type and machine_rtc_type to the
common header in extmod.

Signed-off-by: Damien George <damien@micropython.org>
2023-10-26 16:20:53 +11:00
Damien George 5b4a2baff6 extmod/machine_uart: Factor ports' UART Python bindings to common code.
This is a code factoring to have the Python bindings in one location, and
all the ports use those same bindings.  For all ports except the two listed
below there is no functional change.

The nrf port has UART.sendbreak() removed, but this method previously did
nothing.

The zephyr port has the following methods added:
- UART.init(): supports setting timeout and timeout_char.
- UART.deinit(): does nothing, just returns None.
- UART.flush(): raises OSError(EINVAL) because it's not implemented.
- UART.any() and UART.txdone(): raise NotImplementedError.

Signed-off-by: Damien George <damien@micropython.org>
2023-10-26 10:46:42 +11:00
Damien George 95d8b5fd55 extmod/machine_adc: Factor ports' ADC Python bindings to common code.
No functional change, just code factoring to have the Python bindings in
one location, and all the ports use those same bindings.

Signed-off-by: Damien George <damien@micropython.org>
2023-10-23 17:16:45 +11:00
Damien George 48e0986666 nrf/boards: Automatically configure MICROPY_PY_MACHINE_PWM.
This commit makes it so that MICROPY_PY_MACHINE_PWM is enabled if at least
one of MICROPY_PY_MACHINE_HW_PWM and/or MICROPY_PY_MACHINE_SOFT_PWM are
enabled.  This simplifies the configuration for boards, and fixes DVK_BL652
which enabled PWM without selecting software or hardware implementations.

With this change, DVK_BL652 and EVK_NINA_B1 now enable (hardware) PWM.

Signed-off-by: Damien George <damien@micropython.org>
2023-10-23 11:20:49 +11:00
Damien George bb4be837c3 py/makeqstrdefs.py: Print a nicer error when preprocessing stage fails.
Signed-off-by: Damien George <damien@micropython.org>
2023-10-23 10:39:39 +11:00
Damien George 91a3f18391 extmod/machine_i2s: Factor comments, some enums and macros.
Signed-off-by: Damien George <damien@micropython.org>
2023-10-20 17:40:17 +11:00
Damien George 46ae3b5a34 extmod/machine_i2s: Factor init_helper argument parsing.
Signed-off-by: Damien George <damien@micropython.org>
2023-10-20 17:40:17 +11:00
Damien George 676f9bb78c extmod/machine_i2s: Factor print function.
Signed-off-by: Damien George <damien@micropython.org>
2023-10-20 17:40:17 +11:00
Damien George 1477986815 extmod/machine_i2s: Factor I2S.irq method.
Signed-off-by: Damien George <damien@micropython.org>
2023-10-20 17:40:17 +11:00
Damien George cdd9ad8d62 extmod/machine_i2s: Factor I2S.shift method.
It's exactly the same for all four port implementations.

Signed-off-by: Damien George <damien@micropython.org>
2023-10-20 17:40:17 +11:00
Damien George a2d7e0da0b extmod/machine_i2s: Factor stream and ring-buf code.
Signed-off-by: Damien George <damien@micropython.org>
2023-10-20 17:40:17 +11:00
Damien George f2f3ef162d extmod/machine_i2s: Factor ports' I2S Python bindings to common code.
This factors the basic top-level I2S class code from the ports into
extmod/machine_i2s.c:
- I2S class definition and method table.
- The init and deinit method wrappers.
- The make_new code.

Further factoring will follow.

Signed-off-by: Damien George <damien@micropython.org>
2023-10-20 17:39:57 +11:00
Damien George 7e7af71527 extmod/machine_pwm: Remove header file and move decls to .c file.
With public declarations moved to extmod/modmachine.h.  It's now mandatory
for a port to define MICROPY_PY_MACHINE_PWM_INCLUDEFILE if it enables
MICROPY_PY_MACHINE_PWM.  This follows how extmod/machine_wdt.c works.

All ports have been updated to work with this modified scheme.

Signed-off-by: Damien George <damien@micropython.org>
2023-10-20 16:24:46 +11:00
Damien George 60929ec7e2 extmod/machine_wdt: Factor ports' WDT Python bindings to common code.
There are currently 7 ports that implement machine.WDT and a lot of code is
duplicated across these implementations.  This commit factors the common
parts of all these implementations to a single location in
extmod/machine_wdt.c.  This common code provides the top-level Python
bindings (class and method wrappers), and then each port implements the
back end specific to that port.

With this refactor the ports remain functionally the same except for:

- The esp8266 WDT constructor now takes keyword arguments, and accepts the
  "timeout" argument but raises an exception if it's not the default value
  (this port doesn't support changing the timeout).

- The mimxrt and samd ports now interpret the argument to WDT.timeout_ms()
  as signed and if it's negative truncate it to the minimum timeout (rather
  than it being unsigned and a negative value truncating to the maximum
  timeout).

Signed-off-by: Damien George <damien@micropython.org>
2023-10-20 15:36:09 +11:00
iabdalkader 2590a34ed7 rp2/boards/ARDUINO_NANO_RP2040_CONNECT: Add external analog pins.
Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2023-10-20 12:18:41 +11:00
iabdalkader 5e52389f99 rp2/machine_adc: Add support for external ADC channels.
Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2023-10-20 12:18:33 +11:00
iabdalkader 4358faab0c drivers/ninaw10: Add support for external ADC channels.
Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2023-10-20 12:18:29 +11:00
iabdalkader 7bbf7910fe extmod/network_ninaw10: Raise an error if nina_ioctl fails.
Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2023-10-20 12:18:00 +11:00
iabdalkader 9ed39553f2 drivers/ninaw10: Add ioctl for reading analog pins.
Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2023-10-20 12:17:55 +11:00
Christian Walther 7be16e0540 extmod/vfs_posix: Additional tests for coverage of error cases.
Signed-off-by: Christian Walther <cwalther@gmx.ch>
2023-10-19 16:21:09 +02:00
Christian Walther be28829ae8 extmod/vfs_posix: Fix getcwd() on non-root VFS.
The unwritten API contract expected of a VFS.getcwd() by mp_vfs_getcwd()
is that its return value should be either "" or "/" when the CWD is at
the root of the VFS and otherwise start with a slash and not end with a
slash. This was not correctly implemented in VfsPosix for instances with
a non-empty root - the required leading slash, if any, was cut off
because the root length includes a trailing slash. This would result in
missing slashes in the middle of the return value of os.getcwd() or in
uninitialized garbage from beyond a string's null terminator when the
CWD was at the VFS root.

Signed-off-by: Christian Walther <cwalther@gmx.ch>
2023-10-19 16:21:09 +02:00
Christian Walther 0c4fb16871 extmod/vfs_posix: Fix relative paths on non-root VFS.
The unwritten API contract expected of a VFS by mp_vfs_lookup_path() is
that paths passed in are relative to the root of the VFS if they start
with '/' and relative to the current directory of the VFS otherwise.
This was not correctly implemented in VfsPosix for instances with a
non-empty root - all paths were interpreted relative to the root. Fix
that. Since VfsPosix tracks its CWD using the "external" CWD of the Unix
process, the correct handling for relative paths is to pass them through
unmodified.

Also, when concatenating absolute paths, fix an off-by-one resulting in
a harmless double slash (the root path already has a trailing slash).

Signed-off-by: Christian Walther <cwalther@gmx.ch>
2023-10-19 16:21:09 +02:00
Christian Walther 5f7065f57a extmod/vfs_posix: Fix accidentally passing tests.
These tests test an unrealistic situation and only pass by accident due
to a bug. The upcoming fix for the bug would make them fail.

The unrealistic situation is that VfsPosix methods are called with
relative paths while the current working directory is somewhere outside
of the root of the VFS. In the intended use of VFS objects via
os.mount() (as opposed to calling methods directly as the tests do),
this never happens, as mp_vfs_lookup_path() directs incoming calls to
the VFS that contains the CWD.

Make the testing situation realistic by changing the working directory
to the root of the VFS before calling methods on it, as the subsequent
relative path accesses expect.

Thanks to the preceding commit, the tests still pass, but still for the
wrong reason. The following commit "Fix relative paths on non-root VFS"
will make them pass for the correct reason.

Signed-off-by: Christian Walther <cwalther@gmx.ch>
2023-10-19 16:21:08 +02:00
Christian Walther e3ba6f952b extmod/vfs_posix: Fix relative root path.
A VfsPosix created with a relative root path would get confused when
chdir() was called on it and become unable to properly resolve absolute
paths, because changing directories effectively shifted its root. The
simplest fix for that would be to say "don't do that", but since the
unit tests themselves do it, fix it by making a relative path absolute
before storing it.

Signed-off-by: Christian Walther <cwalther@gmx.ch>
2023-10-19 16:21:08 +02:00
Seon Rozenblum 86c7b957a8 esp32/boards: Update UM board image names for consistency.
Signed-off-by: Seon Rozenblum <seon@unexpectedmaker.com>
2023-10-19 18:21:09 +11:00
Jim Mussared 3883f29485 py/modthread: Initialise nlr_jump_callback_top on threads.
The main thread gets this because the thread state is in bss, but
subsequent threads need this field to be initialised.

Also added a note to mpstate.h to help avoid missing this in the future.

Fixes issue #12695.

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-10-18 09:18:23 +11:00
Kwabena W. Agyeman e78471416b mimxrt/modmachine: Add support for machine.deepsleep.
Signed-off-by: "Kwabena W. Agyeman" <kwagyeman@live.com>
2023-10-17 22:52:18 +11:00
Kwabena W. Agyeman 433158076f mimxrt/machine_rtc: Add RTC alarm/wakeup functionality.
Following the documented Python machine.RTC API.

Signed-off-by: "Kwabena W. Agyeman" <kwagyeman@live.com>
2023-10-17 22:51:53 +11:00
Kwabena W. Agyeman 64ad676424 mimxrt/boards: Define missing SNVS pins for all processors.
Signed-off-by: "Kwabena W. Agyeman" <kwagyeman@live.com>
2023-10-17 22:51:42 +11:00
Jim Mussared c2361328e1 github/workflows: Pin ruff to 0.1.0 and change flags for new version.
The `--format` flag was changed to `--output-format` in the recent update.

Pin to this version to prevent further updates from breaking (e.g. through
new rules or other changes).

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-10-17 13:56:33 +11:00
Damien George 971f1cf987 stm32/powerctrl: Add support for frequency scaling with HSI on H5 MCUs.
Signed-off-by: Damien George <damien@micropython.org>
2023-10-17 12:41:47 +11:00
Damien George e15882ad2b stm32/boards/STM32H573I_DK: Enable ETH and DAC peripherals.
Signed-off-by: Damien George <damien@micropython.org>
2023-10-17 11:44:16 +11:00
Rene Straub 51da8cc28b stm32/eth: Add Ethernet support for H5 MCUs.
This commit implements Ethernet support for STM32H5.  Changes are:

- Add Cortex-M33 MPU code.  Ethernet driver requires MPU to define cache
  strategy for DMA buffers (descriptors and frames).
- Add support for STM32H5 Ethernet controller.  The controller is mostly
  compatible with the STM32H7.  However the descriptor layout is different.
- Adapt clocking and reset for STM32H5.

Tested on NUCLEO-H563ZI and STM32H573I-DK, using ping and iperf3.  TCP
rates of 80-90 Mbits/sec were achievable.

Signed-off-by: Rene Straub <rene@see5.ch>
Signed-off-by: Damien George <damien@micropython.org>
2023-10-17 11:40:54 +11:00
iabdalkader 8b12923da2 stm32/boards/ARDUINO_GIGA: Fix name of pins in board init.
Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2023-10-17 00:35:16 +11:00
robert-hh f84b4617cb rp2/cyw43_configport: Use m_tracked_calloc and m_tracked_free.
When using malloc and free there were out-of-memory situations depending on
the arm-none-eabi package version.  This commit changes malloc/free to use
the MicroPython GC heap instead.

Signed-off-by: robert-hh <robert@hammelrath.com>
Signed-off-by: Damien George <damien@micropython.org>
2023-10-16 23:36:54 +11:00
iabdalkader 4074f828dd stm32/boards/ARDUINO_GIGA: Add QSPI fix/workaround to early init.
This workaround fixes an issue with some production boards that have
an older QSPI flash part revision, which can't handle floating pins.
Note those pins can be reconfigured and reused later.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2023-10-16 23:14:13 +11:00
Thomas Ackermann ac4f79592b docs/library/io: Remove io.FileIO and io.TextIOWrapper.
FileIO and TextIOWrapper were removed in
e65d1e69e8.  Remove them also from the
documentation.

Signed-off-by: Thomas Ackermann <th.acker@arcor.de>
2023-10-16 23:07:13 +11:00
Jim Mussared 8eb7721b4a extmod/modframebuf: Remove FrameBuffer1 from natmod build.
This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-10-16 12:18:43 +11:00
Jim Mussared 03a9fa227d extmod/modframebuf: Fix FrameBuffer get-buffer implementation.
This wasn't correctly accounting for the bits-per-pixel and was returning a
bufinfo struct with the incorrect length.  Instead, just forward directly
to the underlying buffer object.

Fixes issue #12563.

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-10-16 12:18:08 +11:00
Jim Mussared d040478d8a extmod/modframebuf: Validate FrameBuffer bounds against input buffer.
This ensures that the buffer is large enough for the specified width,
height, bits-per-pixel, and stride.

Also makes the legacy FrameBuffer1 constructor re-use the FrameBuffer
make_new to save some code size.

Fixes issue #12562.

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-10-16 12:17:51 +11:00
Damien George a1be5e1439 docs/reference/mpyfiles: Document change in .mpy sub-version.
Signed-off-by: Damien George <damien@micropython.org>
2023-10-16 11:28:32 +11:00
Damien George 6967ff3c58 py/persistentcode: Bump .mpy sub-version.
This is required because the previous commit changed the .mpy native ABI.

Signed-off-by: Damien George <damien@micropython.org>
2023-10-16 11:25:31 +11:00
Damien George 9b63421fb3 py/dynruntime: Add mp_get_buffer.
Signed-off-by: Damien George <damien@micropython.org>
2023-10-16 11:23:11 +11:00
Damien George 9c7ea9b14a py/obj: Generalise mp_get_buffer so it can raise if a flag is set.
This allows mp_get_buffer_raise() to be changed to a simple inline function
that in the majority of cases costs the same (in code size) to call as the
original mp_get_buffer_raise(), because the flags argument is a constant.

Signed-off-by: Damien George <damien@micropython.org>
2023-10-16 11:22:55 +11:00
Damien George 516385c4cc py/objboundmeth: Optimise check for types in binary_op.
Signed-off-by: Damien George <damien@micropython.org>
2023-10-13 15:29:09 +11:00
Ned Konz 66c62353ce tests/basics/boundmeth1.py: Add tests for bound method equality/hash.
This commit adds tests for bound method comparison and hashing to support
the changes in the previous commit.

Signed-off-by: Ned Konz <ned@productcreationstudio.com>
2023-10-13 15:15:49 +11:00
Daniël van de Giessen 4f5e165d0b py/objboundmeth: Support comparing and hashing bound methods.
This behaviour matches CPython.  It's useful to be able to store bound
method objects in dicts/sets, and compare for equality, eg when storing
them in a list and using list.remove().

Signed-off-by: Daniël van de Giessen <daniel@dvdgiessen.nl>
2023-10-13 15:11:49 +11:00
Matthias Urlichs 5f0bd33b73 extmod/asyncio: Emit errors to stderr, not stdout.
Sometimes these are different file descriptors, not to mention the Unix
port, so use stderr to distinguish these error messages.

CPython prints to stdout, but it does it via a call to the logging module.
We don't want to introduce a dependency on logging, so printing to stderr
is a good alternative.  One can override default_exception_handler() if
needed.
2023-10-13 14:55:54 +11:00
Damien George 05cb1406ad extmod/moductypes: Validate that uctypes.struct addr argument is an int.
Fixes issue #12660.

Signed-off-by: Damien George <damien@micropython.org>
2023-10-12 15:47:15 +11:00
Jim Mussared 5015779a6f py/builtinevex: Handle invalid filenames for execfile.
If a non-string buffer was passed to execfile, then it would be passed
as a non-null-terminated char* to mp_lexer_new_from_file.

This changes mp_lexer_new_from_file to take a qstr instead (as in almost
all cases a qstr will be created from this input anyway to set the
`__file__` attribute on the module).

This now makes execfile require a string (not generic buffer) argument,
which is probably a good fix to make anyway.

Fixes issue #12522.

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-10-12 15:17:59 +11:00
robert-hh 480659b1ac ports: Make all ports skip execution of main.py if boot.py fails.
That can be caused e.g. by an exception.  This feature is implemented in
some way already for the stm32, renesas-ra, mimxrt and samd ports.  This
commit adds it for the rp2, esp8266, esp32 and nrf ports.  No change for
the cc3200 and teensy ports.

Signed-off-by: robert-hh <robert@hammelrath.com>
2023-10-12 11:53:29 +11:00
Andrew Leech d2a9d70c09 tools/ci.sh: Ensure enough commits are fetched for a common ancestor.
This commit updates the ci script to automatically fetch all upstream if
the common commit hasn't been found; this should preserve the speed of CI
checks for most PR's, and use a reliable but slow fetch if needed for older
ones.

Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
2023-10-11 14:05:14 +11:00
Glenn Moloney 9f835df35e esp32,esp8266: Rename MICROPY_ESPNOW to MICROPY_PY_ESPNOW.
For consistency with other Python-level modules.

Also add the corresponding missing preprocessor guard to esp32/modespnow.c,
so that this port compiles if MICROPY_PY_ESPNOW and MICROPY_PY_NETWORK_WLAN
are set to 0.

Fixes #12622.

Signed-off-by: Glenn Moloney <glenn.moloney@gmail.com>
2023-10-10 17:56:36 +11:00
robert-hh a06f4c8df4 mimxrt/led: Fix LED init call from main, and simplify led_init.
led_init() was not called, and therefore the machine.LED class seemed not
to work.  led_init() now uses mp_hal_pin_output() to configure the pin.

Signed-off-by: robert-hh <robert@hammelrath.com>
2023-10-09 17:10:45 +11:00
Matthias Urlichs 3fb1bb131f py/vm: Don't emit warning when using "raise ... from None".
"Raise SomeException() from None" is a common Python idiom to suppress
chained exceptions and thus shouldn't trigger a warning on a version of
Python that doesn't support them in the first place.
2023-10-09 09:46:02 +11:00
Jim Mussared 5232847771 README.md: Update CI badges.
- Fix URL for the unix badge.
- Add stm32 CI badge.
- Add docs CI badge (linking to the documentation)
- Make docs CI run on push (so we get a badge generated).

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
2023-10-06 16:39:55 +11:00
Lephenixnoir 70e15e9ed1
ports/sh: slightly more memory on G-III (32 kB -> ~45 kB) 2023-08-20 21:42:27 +02:00
Lephenixnoir 01036c9611
meta: normalize line endings 2023-08-20 13:06:28 +02:00
Lephenixnoir e35ed0c2fb
ports/sh: enable overloaded operators 2023-08-20 12:59:25 +02:00
mibi88 814b226158 Added scripts where casioplot is not working properly 2023-07-19 12:18:40 +02:00
mibi88 7b7c00842f examples: Bug fix 2022-12-24 11:43:47 +01:00
mibi88 0b74e8cfb1 A better gint flappy bird 2022-12-23 13:11:25 +01:00
mibi88 553af9b9c9 examples: A super fast flappy bird for fx and a shitty script
A super fast flappy bird for fx and a shitty flappy bird for fx that can do a SysERROR.
2022-12-22 23:27:02 +01:00
mibi88 38f340cecd examples: add a gint based Flappy Bird for fx 2022-12-22 19:35:04 +01:00
Lephenixnoir 3df7eae26c
examples: examples: add Synchro-Donjon
Only AI mode has been tested. Graphical mode suffers from single VRAM
combined with naive updates. A custom version would solve that.
2022-12-21 19:37:39 +01:00
Lephenixnoir 7ecc558700
examples: add Chute tridimensionnelle 2022-12-21 18:11:15 +01:00
Lephenixnoir 8a498563b8
modgint: fix rendering conflict with shell; more constants
* dupdate() will now cancel pending shell renders
* import gint will also do that (can be avoided with a single print())
* Provide DWIDTH, DHEIGHT, and some more basic colors
2022-12-21 18:10:39 +01:00
Lephenixnoir 4f63ac05d3
meta: add gint-based Flappy Bird and update README 2022-12-19 08:40:52 +01:00
Lephenixnoir 63c4c8f609
ports/sh: clean up all RAM when resetting the interpreter 2022-12-19 08:37:56 +01:00
Lephenixnoir e001880d5b
pe: disable π input (which freezes) 2022-12-19 08:37:19 +01:00
Lephenixnoir da416f067f
pe: fix incorrect line wrapping precomputation 2022-12-18 21:11:17 +01:00
mibi88 81d4bbdb1a Added fx-9860g colors 2022-12-18 19:39:59 +01:00
mibi88 16bd85a754 Python extra RAM was not disabled correctly. 2022-12-17 22:05:48 +01:00
Lephenixnoir 53b2e6bfed
modgint: add most of <gint/display.h> 2022-12-17 20:19:50 +01:00
Lephenixnoir b5d7c61c91
meta: update README and upload test files 2022-12-17 18:43:26 +01:00
Lephenixnoir 0d20ae7929
ports/sh: provide pe_readline() and enable proper input() 2022-12-17 18:30:02 +01:00
Lephenixnoir ddab477c3e
ports/sh: redraw shell periodically during execution (if changed) 2022-12-17 16:10:27 +01:00
Lephenixnoir 189aadff1c
pe: rotating console lines and basic benchmarks 2022-12-17 16:09:32 +01:00
Lephenixnoir 0da3395e89
pe: take over the REPL from pyexec.c 2022-12-15 18:38:03 +01:00
Lephenixnoir dc062623da
casioplot: clear screen upon import 2022-12-12 07:34:23 +01:00
Lephenixnoir a4d5bc0752
casioplot: replace newlines with spaces in draw_string() 2022-12-12 07:14:56 +01:00
Lephenixnoir dff23463b0
meta: update README 2022-12-12 07:01:56 +01:00
Lephenixnoir e85d84e802 Merge pull request 'Better casioplot.' (#1) from mibi88/PythonExtra:main into main
Reviewed-on: https://gitea.planet-casio.com/Lephenixnoir/PythonExtra/pulls/1
2022-12-12 06:52:50 +01:00
Lephenixnoir 49e3f6a6af
ports/sh: reset shell before GUI import
This allows programs to be started several times from the GUI. Otherwise
MicroPython would just skip importing the already-imported module.
2022-12-12 06:48:52 +01:00
Lephenixnoir 9bdb18f49f
ports/sh: clear keyboard events after shell execution
This helps a lot when running interactive games that don't read their
input (apart from eg. AC/ON). Previously all the events accumulated
during the execution would be executed once the program returns. Now the
queue is reset after execution.
2022-12-12 06:34:53 +01:00
Lephenixnoir 9684b6893f pe: delete old shell lines to avoid filling RAM with history 2022-12-11 20:42:53 +01:00
Lephenixnoir 46ca19aece
pe: delete old shell lines to avoid filling RAM with history 2022-12-11 19:17:43 +01:00
mibi88 cb887885b9 Cleanup in casioplot, Python ram only with PE_DEBUG 2022-12-11 18:04:14 +01:00
Lephenixnoir d7d1df46bb pe: add scrolling in shell 2022-12-11 17:33:27 +01:00
Lephenixnoir 40a2de1a5f pe: add shell scrollbar (render only) 2022-12-11 17:33:27 +01:00
Lephenixnoir 8f5af62f9f ports/sh: fix AC/ON locking after some time
The Python program being run is in charge of keyboard events with the
gint module. Most programs don't care though, and simply let events
accumulate until the queue is full.

The async filter is able to receive events even when the queue is full.
However, it filtered only AC/ON presses, not releases, so the releases
were sent back to the driver to queue. This was impossible as the queue
was full, so the release was never recorded. This failure then repeated
at every tick, forever.

Since the key was never properly released, further presses were just
seen as a continuation of the current press and thus did not produce
any new event, so the async filter was no longer called and the Python
program could no longer be interrupted.
2022-12-11 17:33:27 +01:00
Lephenixnoir edf57c6f07 ports/sh: basic improvements to USB debugging (not quite ready yet)
The USB driver isn't stable enough to support funky uncontrolled async
messages yet. Tends to freeze and need a reconnect. Future problem.
2022-12-11 17:33:27 +01:00
Lephenixnoir e40f8cba15
pe: add scrolling in shell 2022-12-11 17:23:33 +01:00
Lephenixnoir 5051323860
pe: add shell scrollbar (render only) 2022-12-04 17:52:18 +01:00
Lephenixnoir 2cc8fe63e5
ports/sh: fix AC/ON locking after some time
The Python program being run is in charge of keyboard events with the
gint module. Most programs don't care though, and simply let events
accumulate until the queue is full.

The async filter is able to receive events even when the queue is full.
However, it filtered only AC/ON presses, not releases, so the releases
were sent back to the driver to queue. This was impossible as the queue
was full, so the release was never recorded. This failure then repeated
at every tick, forever.

Since the key was never properly released, further presses were just
seen as a continuation of the current press and thus did not produce
any new event, so the async filter was no longer called and the Python
program could no longer be interrupted.
2022-12-04 14:43:33 +01:00
Lephenixnoir ed66b0d6a7
ports/sh: basic improvements to USB debugging (not quite ready yet)
The USB driver isn't stable enough to support funky uncontrolled async
messages yet. Tends to freeze and need a reconnect. Future problem.
2022-12-04 14:34:47 +01:00
mibi88 b664e0ab9c Proper python ram use 2022-11-23 17:11:41 +01:00
mibi88 e3bda720ff 1 more test. 2022-11-23 16:27:27 +01:00
mibi88 b39dc00203 Added python ram in a dirty way 2022-11-23 13:56:48 +01:00
mibi88 f9d6f55625 Forgot to change the default font. 2022-11-21 17:31:22 +01:00
mibi88 c6e1666918 Little fixes 2022-11-20 16:47:22 +01:00
mibi88 2ace52aff9 Fixed draw_string(), font size not ignored anymore on fx9860 2022-11-20 15:49:10 +01:00
mibi88 a6fb6122db Fixed set_pixel() 2022-11-20 13:13:40 +01:00
mibi88 6fcce03e5c Fixed get_pixel() 2022-11-20 12:44:43 +01:00
Lephenixnoir eeae10abc5
ports/sh: start adding decent memory on fx-CG 50 (~ 350 kB) 2022-11-10 23:02:20 +01:00
Lephenixnoir c1d2ca5048
pe: debugging tools 2022-11-10 22:37:04 +01:00
Lephenixnoir 524562e8bc
pe: casioplot: make the final argument of draw_string() optional
(note: it is currently ignored even when specified)
2022-11-09 21:21:34 +01:00
Lephenixnoir ab0f70effc
pe: fix clear_screeb typo in modcasioplot 2022-11-09 13:57:13 +01:00
Lephenixnoir 99f2156e5e
pe: interrupt computations with AC/ON 2022-11-08 22:24:18 +01:00
Lephenixnoir bfa5de2cf9
meta: exclude ports/sh/exclude from git 2022-11-08 22:24:17 +01:00
Lephenixnoir 9ea4c17112
pe: import modules selected in file browser 2022-11-08 22:21:42 +01:00
Lephenixnoir 5f1a066c94
pe: add rough casioplot module 2022-11-08 22:20:18 +01:00
Lephenixnoir 6c2aa39e56
pe: show shell modifier state in GUI 2022-11-06 17:08:17 +01:00
Lephenixnoir 404d69aea4
pe: smaller, proportional 4x6 font on fx 2022-11-06 00:08:57 +01:00
Lephenixnoir 27822c2461
pe: make the GUI friendly on the fx-9860G 2022-11-05 20:58:18 +01:00
Lephenixnoir fa6aa00dae
pe: basic GUI setup
Adds a file browser (selected files are not loaded yet) and a shell
widget with an input system that is still better than the previous
VT-100 emulation scheme (with locked modifiers mainly).

A lot of small things still need to be done to make the UI functional.
2022-11-05 18:25:54 +01:00
Lephenixnoir 4e529b5788
meta: add project headers
On all but a few files that are not going to stay there.
2022-10-30 18:52:54 +01:00
Lephenixnoir 2c238906e7
pe: enable the time module
Based on the UNIX port version, and extmod/utime_mphal.c.
2022-10-30 18:37:02 +01:00
Lephenixnoir 8809f3eee4
pe: cap shell refresh rate at 30 FPS 2022-10-30 17:53:13 +01:00
Lephenixnoir d0654fc5e7
meta: basic build instructions 2022-10-30 11:07:33 +01:00
Lephenixnoir d6334be488
meta: cleanup 2022-10-29 21:48:01 +02:00
Lephenixnoir 3431000d2f
meta: README file with basic TODO list 2022-10-29 20:56:10 +02:00
Lephenixnoir ce4fefebbe
pe: split fx-CG 50 and fx-9860G III versions
Both working although with terrible UI.
2022-10-29 20:42:43 +02:00
Lephenixnoir e1df7e5f0b
ports/sh: enable split GC 2022-10-29 11:32:43 +02:00
Lephenixnoir f930ff95db
modgint: basic gint module with some of <gint/keyboard.h> 2022-10-29 10:57:15 +02:00
Lephenixnoir 1992ec0a49
ports/sh: module loading and first attempt at open()
But I'm pretty sure there should be a ready-to-use POSIX version of
open() that I can enable instead of rewriting it.
2022-10-29 10:55:57 +02:00
Lephenixnoir c237e9874f
ports/sh: clean mpconfigport.h and enable modules 2022-10-27 19:07:22 +02:00
Lephenixnoir a0d6c33275
meta: move original README.md 2022-10-27 17:20:32 +02:00
Lephenixnoir f9b4c1f844
pe: decent console with erasing, scrolling and more unused potential 2022-10-24 00:53:53 +02:00
Lephenixnoir e33d85b1de
ports/sh: first functional version, can compute in REPL 2022-10-24 00:48:14 +02:00
940 changed files with 30635 additions and 30075 deletions

View File

@ -1,3 +1,6 @@
# all: Update Python formatting to ruff-format.
bbd8760bd9a2302e5abee29db279102bb11d7732
# all: Fix various spelling mistakes found by codespell 2.2.6.
cf490a70917a1b2d38ba9b58e763e0837d0f7ca7

2
.gitattributes vendored
View File

@ -8,10 +8,12 @@
# These are binary so should never be modified by git.
*.a binary
*.ico binary
*.png binary
*.jpg binary
*.dxf binary
*.mpy binary
*.der binary
# These should also not be modified by git.
tests/basics/string_cr_conversion.py -text

View File

@ -11,11 +11,11 @@ jobs:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
- uses: actions/setup-python@v5
- name: Install packages
run: source tools/ci.sh && ci_code_formatting_setup
run: source tools/ci.sh && ci_c_code_formatting_setup
- name: Run code formatting
run: source tools/ci.sh && ci_code_formatting_run
run: source tools/ci.sh && ci_c_code_formatting_run
- name: Check code formatting
run: git diff --exit-code
@ -23,7 +23,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
- uses: actions/setup-python@v5
- name: Install packages
run: source tools/ci.sh && ci_code_spell_setup
- name: Run spell checker

View File

@ -36,7 +36,7 @@ jobs:
run: echo $PR_NUMBER > pr_number
- name: Upload diff
if: github.event_name == 'pull_request'
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: code-size-report
path: |

View File

@ -15,7 +15,7 @@ jobs:
steps:
- name: 'Download artifact'
id: download-artifact
uses: actions/github-script@v6
uses: actions/github-script@v7
with:
result-encoding: string
script: |
@ -56,7 +56,7 @@ jobs:
run: unzip code-size-report.zip
- name: Post comment to pull request
if: steps.download-artifact.outputs.result == 'ok'
uses: actions/github-script@v6
uses: actions/github-script@v7
with:
github-token: ${{secrets.GITHUB_TOKEN}}
script: |

View File

@ -13,6 +13,6 @@ jobs:
- uses: actions/checkout@v4
with:
fetch-depth: '100'
- uses: actions/setup-python@v4
- uses: actions/setup-python@v5
- name: Check commit message formatting
run: source tools/ci.sh && ci_commit_formatting_run

View File

@ -1,6 +1,7 @@
name: Build docs
on:
push:
pull_request:
paths:
- docs/**
@ -15,7 +16,7 @@ jobs:
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
- uses: actions/setup-python@v5
- name: Install Python packages
run: pip install -r docs/requirements.txt
- name: Build docs

View File

@ -16,13 +16,13 @@ jobs:
# Setting this to zero means fetch all history and tags,
# which hatch-vcs can use to discover the version tag.
fetch-depth: 0
- uses: actions/setup-python@v4
- uses: actions/setup-python@v5
- name: Install build tools
run: pip install build
- name: Build mpremote wheel
run: cd tools/mpremote && python -m build --wheel
- name: Archive mpremote wheel
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: mpremote
path: |

View File

@ -18,11 +18,40 @@ concurrency:
cancel-in-progress: true
jobs:
build_idf50:
build_idf:
strategy:
fail-fast: false
matrix:
ci_func: # names are functions in ci.sh
- esp32_build_cmod_spiram_s2
- esp32_build_s3_c3
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v4
- name: Install packages
run: source tools/ci.sh && ci_esp32_idf50_setup
- name: Build
run: source tools/ci.sh && ci_esp32_build
- id: idf_ver
name: Read the ESP-IDF version
run: source tools/ci.sh && echo "IDF_VER=$IDF_VER" | tee "$GITHUB_OUTPUT"
- name: Cached ESP-IDF install
id: cache_esp_idf
uses: actions/cache@v3
with:
path: |
./esp-idf/
~/.espressif/
!~/.espressif/dist/
~/.cache/pip/
key: esp-idf-${{ steps.idf_ver.outputs.IDF_VER }}
- name: Install ESP-IDF packages
if: steps.cache_esp_idf.outputs.cache-hit != 'true'
run: source tools/ci.sh && ci_esp32_idf_setup
- name: ccache
uses: hendrikmuhs/ccache-action@v1.2
with:
key: esp32-${{ matrix.ci_func }}
- name: Build ci_${{matrix.ci_func }}
run: source tools/ci.sh && ci_${{ matrix.ci_func }}

View File

@ -18,20 +18,18 @@ concurrency:
cancel-in-progress: true
jobs:
build_pyb:
build_stm32:
strategy:
fail-fast: false
matrix:
ci_func: # names are functions in ci.sh
- stm32_pyb_build
- stm32_nucleo_build
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v4
- name: Install packages
run: source tools/ci.sh && ci_stm32_setup
- name: Build
run: source tools/ci.sh && ci_stm32_pyb_build
- name: Build ci_${{matrix.ci_func }}
run: source tools/ci.sh && ci_${{ matrix.ci_func }}
build_nucleo:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v4
- name: Install packages
run: source tools/ci.sh && ci_stm32_setup
- name: Build
run: source tools/ci.sh && ci_stm32_nucleo_build

View File

@ -1,28 +0,0 @@
name: teensy port
on:
push:
pull_request:
paths:
- '.github/workflows/*.yml'
- 'tools/**'
- 'py/**'
- 'extmod/**'
- 'shared/**'
- 'lib/**'
- 'drivers/**'
- 'ports/teensy/**'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install packages
run: source tools/ci.sh && ci_teensy_setup
- name: Build
run: source tools/ci.sh && ci_teensy_build

View File

@ -55,6 +55,18 @@ jobs:
if: failure()
run: tests/run-tests.py --print-failures
standard_v2:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build
run: source tools/ci.sh && ci_unix_standard_v2_build
- name: Run main test suite
run: source tools/ci.sh && ci_unix_standard_v2_run_tests
- name: Print failures
if: failure()
run: tests/run-tests.py --print-failures
coverage:
runs-on: ubuntu-latest
steps:
@ -184,7 +196,7 @@ jobs:
runs-on: macos-11.0
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
- uses: actions/setup-python@v5
with:
python-version: '3.8'
- name: Build

View File

@ -1,10 +1,11 @@
# https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
name: Python code lint with ruff
name: Python code lint and formatting with ruff
on: [push, pull_request]
jobs:
ruff:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: pip install --user ruff
- run: ruff --format=github .
- run: pip install --user ruff==0.1.3
- run: ruff check --output-format=github .
- run: ruff format --diff .

3
.gitignore vendored
View File

@ -23,3 +23,6 @@ user.props
# MacOS desktop metadata files
.DS_Store
# vscode
.vscode/

View File

@ -2,8 +2,8 @@ repos:
- repo: local
hooks:
- id: codeformat
name: MicroPython codeformat.py for changed files
entry: tools/codeformat.py -v -f
name: MicroPython codeformat.py for changed C files
entry: tools/codeformat.py -v -c -f
language: python
- id: verifygitlog
name: MicroPython git commit message format checker
@ -12,6 +12,7 @@ repos:
verbose: true
stages: [commit-msg]
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.0.265
rev: v0.1.3
hooks:
- id: ruff
- id: ruff-format

View File

@ -53,13 +53,16 @@ are then certifying and signing off against the following:
Code auto-formatting
====================
Both C and Python code are auto-formatted using the `tools/codeformat.py`
script. This uses [uncrustify](https://github.com/uncrustify/uncrustify) to
format C code and [black](https://github.com/psf/black) to format Python code.
After making changes, and before committing, run this tool to reformat your
changes to the correct style. Without arguments this tool will reformat all
source code (and may take some time to run). Otherwise pass as arguments to
the tool the files that changed and it will only reformat those.
Both C and Python code formatting are controlled for consistency across the
MicroPython codebase. C code is formatted using the `tools/codeformat.py`
script which uses [uncrustify](https://github.com/uncrustify/uncrustify).
Python code is linted and formatted using
[ruff & ruff format](https://github.com/astral-sh/ruff).
After making changes, and before committing, run `tools/codeformat.py` to
reformat your C code and `ruff format` for any Python code. Without
arguments this tool will reformat all source code (and may take some time
to run). Otherwise pass as arguments to the tool the files that changed,
and it will only reformat those.
uncrustify
==========
@ -151,12 +154,22 @@ Tips:
* To ignore the pre-commit message format check temporarily, start the commit
message subject line with "WIP" (for "Work In Progress").
Running pre-commit manually
===========================
Once pre-commit is installed as per the previous section it can be manually
run against the MicroPython python codebase to update file formatting on
demand, with either:
* `pre-commit run --all-files` to fix all files in the MicroPython codebase
* `pre-commit run --file ./path/to/my/file` to fix just one file
* `pre-commit run --file ./path/to/my/folder/*` to fix just one folder
Python code conventions
=======================
Python code follows [PEP 8](https://legacy.python.org/dev/peps/pep-0008/) and
is auto-formatted using [black](https://github.com/psf/black) with a line-length
of 99 characters.
is auto-formatted using [ruff format](https://docs.astral.sh/ruff/formatter)
with a line-length of 99 characters.
Naming conventions:
- Module names are short and all lowercase; eg pyb, stm.

View File

@ -69,6 +69,8 @@ used during the build process and is not part of the compiled source code.
/FreeRTOS (GPL-2.0 with FreeRTOS exception)
/esp32
/ppp_set_auth.* (Apache-2.0)
/rp2
/mutex_extra.c (BSD-3-clause)
/stm32
/usbd*.c (MCD-ST Liberty SW License Agreement V2)
/stm32_it.* (MIT + BSD-3-clause)
@ -78,8 +80,6 @@ used during the build process and is not part of the compiled source code.
/*/stm32*.h (BSD-3-clause)
/usbdev (MCD-ST Liberty SW License Agreement V2)
/usbhost (MCD-ST Liberty SW License Agreement V2)
/teensy
/core (PJRC.COM)
/zephyr
/src (Apache-2.0)
/tools

147
README-MicroPython.md Normal file
View File

@ -0,0 +1,147 @@
[![Unix CI badge](https://github.com/micropython/micropython/actions/workflows/ports_unix.yml/badge.svg)](https://github.com/micropython/micropython/actions?query=branch%3Amaster+event%3Apush) [![STM32 CI badge](https://github.com/micropython/micropython/actions/workflows/ports_stm32.yml/badge.svg)](https://github.com/micropython/micropython/actions?query=branch%3Amaster+event%3Apush) [![Docs CI badge](https://github.com/micropython/micropython/actions/workflows/docs.yml/badge.svg)](https://docs.micropython.org/) [![codecov](https://codecov.io/gh/micropython/micropython/branch/master/graph/badge.svg?token=I92PfD05sD)](https://codecov.io/gh/micropython/micropython)
The MicroPython project
=======================
<p align="center">
<img src="https://raw.githubusercontent.com/micropython/micropython/master/logo/upython-with-micro.jpg" alt="MicroPython Logo"/>
</p>
This is the MicroPython project, which aims to put an implementation
of Python 3.x on microcontrollers and small embedded systems.
You can find the official website at [micropython.org](http://www.micropython.org).
WARNING: this project is in beta stage and is subject to changes of the
code-base, including project-wide name changes and API changes.
MicroPython implements the entire Python 3.4 syntax (including exceptions,
`with`, `yield from`, etc., and additionally `async`/`await` keywords from
Python 3.5 and some select features from later versions). The following core
datatypes are provided: `str`(including basic Unicode support), `bytes`,
`bytearray`, `tuple`, `list`, `dict`, `set`, `frozenset`, `array.array`,
`collections.namedtuple`, classes and instances. Builtin modules include
`os`, `sys`, `time`, `re`, and `struct`, etc. Select ports have support for
`_thread` module (multithreading), `socket` and `ssl` for networking, and
`asyncio`. Note that only a subset of Python 3 functionality is implemented
for the data types and modules.
MicroPython can execute scripts in textual source form (.py files) or from
precompiled bytecode (.mpy files), in both cases either from an on-device
filesystem or "frozen" into the MicroPython executable.
MicroPython also provides a set of MicroPython-specific modules to access
hardware-specific functionality and peripherals such as GPIO, Timers, ADC,
DAC, PWM, SPI, I2C, CAN, Bluetooth, and USB.
Getting started
---------------
See the [online documentation](https://docs.micropython.org/) for API
references and information about using MicroPython and information about how
it is implemented.
We use [GitHub Discussions](https://github.com/micropython/micropython/discussions)
as our forum, and [Discord](https://discord.gg/RB8HZSAExQ) for chat. These
are great places to ask questions and advice from the community or to discuss your
MicroPython-based projects.
For bugs and feature requests, please [raise an issue](https://github.com/micropython/micropython/issues/new/choose)
and follow the templates there.
For information about the [MicroPython pyboard](https://store.micropython.org/pyb-features),
the officially supported board from the
[original Kickstarter campaign](https://www.kickstarter.com/projects/214379695/micro-python-python-for-microcontrollers),
see the [schematics and pinouts](http://github.com/micropython/pyboard) and
[documentation](https://docs.micropython.org/en/latest/pyboard/quickref.html).
Contributing
------------
MicroPython is an open-source project and welcomes contributions. To be
productive, please be sure to follow the
[Contributors' Guidelines](https://github.com/micropython/micropython/wiki/ContributorGuidelines)
and the [Code Conventions](https://github.com/micropython/micropython/blob/master/CODECONVENTIONS.md).
Note that MicroPython is licenced under the MIT license, and all contributions
should follow this license.
About this repository
---------------------
This repository contains the following components:
- [py/](py/) -- the core Python implementation, including compiler, runtime, and
core library.
- [mpy-cross/](mpy-cross/) -- the MicroPython cross-compiler which is used to turn scripts
into precompiled bytecode.
- [ports/](ports/) -- platform-specific code for the various ports and architectures that MicroPython runs on.
- [lib/](lib/) -- submodules for external dependencies.
- [tests/](tests/) -- test framework and test scripts.
- [docs/](docs/) -- user documentation in Sphinx reStructuredText format. This is used to generate the [online documentation](http://docs.micropython.org).
- [extmod/](extmod/) -- additional (non-core) modules implemented in C.
- [tools/](tools/) -- various tools, including the pyboard.py module.
- [examples/](examples/) -- a few example Python scripts.
"make" is used to build the components, or "gmake" on BSD-based systems.
You will also need bash, gcc, and Python 3.3+ available as the command `python3`
(if your system only has Python 2.7 then invoke make with the additional option
`PYTHON=python2`). Some ports (rp2 and esp32) additionally use CMake.
Supported platforms & architectures
-----------------------------------
MicroPython runs on a wide range of microcontrollers, as well as on Unix-like
(including Linux, BSD, macOS, WSL) and Windows systems.
Microcontroller targets can be as small as 256kiB flash + 16kiB RAM, although
devices with at least 512kiB flash + 128kiB RAM allow a much more
full-featured experience.
The [Unix](ports/unix) and [Windows](ports/windows) ports allow both
development and testing of MicroPython itself, as well as providing
lightweight alternative to CPython on these platforms (in particular on
embedded Linux systems).
The ["minimal"](ports/minimal) port provides an example of a very basic
MicroPython port and can be compiled as both a standalone Linux binary as
well as for ARM Cortex M4. Start with this if you want to port MicroPython to
another microcontroller. Additionally the ["bare-arm"](ports/bare-arm) port
is an example of the absolute minimum configuration, and is used to keep
track of the code size of the core runtime and VM.
In addition, the following ports are provided in this repository:
- [cc3200](ports/cc3200) -- Texas Instruments CC3200 (including PyCom WiPy).
- [esp32](ports/esp32) -- Espressif ESP32 SoC (including ESP32S2, ESP32S3, ESP32C3).
- [esp8266](ports/esp8266) -- Espressif ESP8266 SoC.
- [mimxrt](ports/mimxrt) -- NXP m.iMX RT (including Teensy 4.x).
- [nrf](ports/nrf) -- Nordic Semiconductor nRF51 and nRF52.
- [pic16bit](ports/pic16bit) -- Microchip PIC 16-bit.
- [powerpc](ports/powerpc) -- IBM PowerPC (including Microwatt)
- [qemu-arm](ports/qemu-arm) -- QEMU-based emulated target, for testing)
- [renesas-ra](ports/renesas-ra) -- Renesas RA family.
- [rp2](ports/rp2) -- Raspberry Pi RP2040 (including Pico and Pico W).
- [samd](ports/samd) -- Microchip (formerly Atmel) SAMD21 and SAMD51.
- [stm32](ports/stm32) -- STMicroelectronics STM32 family (including F0, F4, F7, G0, G4, H7, L0, L4, WB)
- [webassembly](ports/webassembly) -- Emscripten port targeting browsers and NodeJS.
- [zephyr](ports/zephyr) -- Zephyr RTOS.
The MicroPython cross-compiler, mpy-cross
-----------------------------------------
Most ports require the [MicroPython cross-compiler](mpy-cross) to be built
first. This program, called mpy-cross, is used to pre-compile Python scripts
to .mpy files which can then be included (frozen) into the
firmware/executable for a port. To build mpy-cross use:
$ cd mpy-cross
$ make
External dependencies
---------------------
The core MicroPython VM and runtime has no external dependencies, but a given
port might depend on third-party drivers or vendor HALs. This repository
includes [several submodules](lib/) linking to these external dependencies.
Before compiling a given port, use
$ cd ports/name
$ make submodules
to ensure that all required submodules are initialised.

191
README.md
View File

@ -1,148 +1,87 @@
[![CI badge](https://github.com/micropython/micropython/workflows/unix%20port/badge.svg)](https://github.com/micropython/micropython/actions?query=branch%3Amaster+event%3Apush) [![codecov](https://codecov.io/gh/micropython/micropython/branch/master/graph/badge.svg?token=I92PfD05sD)](https://codecov.io/gh/micropython/micropython)
# PythonExtra - A community MicroPython for CASIO calculators
The MicroPython project
=======================
<p align="center">
<img src="https://raw.githubusercontent.com/micropython/micropython/master/logo/upython-with-micro.jpg" alt="MicroPython Logo"/>
</p>
*Original MicroPython README: [`README-MicroPython.md`](README-MicroPython.md).*
This is the MicroPython project, which aims to put an implementation
of Python 3.x on microcontrollers and small embedded systems.
You can find the official website at [micropython.org](http://www.micropython.org).
This is a MicroPython port for fx-CG 50, fx-9860G III and related CASIO calculators.
WARNING: this project is in beta stage and is subject to changes of the
code-base, including project-wide name changes and API changes.
**Build instructions**
MicroPython implements the entire Python 3.4 syntax (including exceptions,
`with`, `yield from`, etc., and additionally `async`/`await` keywords from
Python 3.5 and some select features from later versions). The following core
datatypes are provided: `str`(including basic Unicode support), `bytes`,
`bytearray`, `tuple`, `list`, `dict`, `set`, `frozenset`, `array.array`,
`collections.namedtuple`, classes and instances. Builtin modules include
`os`, `sys`, `time`, `re`, and `struct`, etc. Select ports have support for
`_thread` module (multithreading), `socket` and `ssl` for networking, and
`asyncio`. Note that only a subset of Python 3 functionality is implemented
for the data types and modules.
Requires the [fxSDK](/Lephenixnoir/fxsdk). Go to `ports/fxcg50` or `ports/fx9860g3` and run `make`. If it doesn't build, first try to use the `dev` branches for [fxSDK](/Lephenixnoir/fxSDK), [gint](/Lephenixnoir/gint), [fxlibc](/Lephenixnoir/fxlib) and [JustUI](/Lephenixnoir/JustUI). Rebuilds don't always work especially when checking out other commits (maybe my fault), so try to delete `build` if you think that's related.
MicroPython can execute scripts in textual source form (.py files) or from
precompiled bytecode (.mpy files), in both cases either from an on-device
filesystem or "frozen" into the MicroPython executable.
Most of the code is in `ports/sh` and is shared between the platforms.
MicroPython also provides a set of MicroPython-specific modules to access
hardware-specific functionality and peripherals such as GPIO, Timers, ADC,
DAC, PWM, SPI, I2C, CAN, Bluetooth, and USB.
---
Getting started
---------------
**Test suite**
See the [online documentation](https://docs.micropython.org/) for API
references and information about using MicroPython and information about how
it is implemented.
Located in [`ports/sh/examples`](ports/sh/examples).
We use [GitHub Discussions](https://github.com/micropython/micropython/discussions)
as our forum, and [Discord](https://discord.gg/RB8HZSAExQ) for chat. These
are great places to ask questions and advice from the community or to discuss your
MicroPython-based projects.
* **fx-CG**: Whether the program successfully runs on PythonExtra on
models of the fx-CG family. This is typically tested on a Graph 90+E but
should include the fx-CG 10/20/50.
* **G-III**: Whether the program successfully runs on G-III models.
This does **not** include older models like the fx-9860G II.
* **Raw speedup**: Speedup from using PythonExtra instead of the official
Python app, without changing the code (as a ratio of execution times).
* **Full speedup**: Seedup from using PythonExtra-provided modules for
rendering and input (usually `gint`), after changing the program's code.
For bugs and feature requests, please [raise an issue](https://github.com/micropython/micropython/issues/new/choose)
and follow the templates there.
| Program | fx-CG | G-III | Raw speedup | Full speedup |
| ------- | ----- | ----- | ----------- | ------------ |
| Chute tridimensionnelle | Yes | Yes | x1.36 | x2.26 ⁽¹⁾ |
| Bad Apple | Meh⁽²⁾ | - | TODO | TODO |
| Island of the Dead Kings | TODO | TODO | TODO | TODO |
| Synchro-Donjon (AI mode) | Yes | TODO | x1.82 | - |
| Flappy Bird | Yes | Yes | x1.04 | x2.35 |
For information about the [MicroPython pyboard](https://store.micropython.org/pyb-features),
the officially supported board from the
[original Kickstarter campaign](https://www.kickstarter.com/projects/214379695/micro-python-python-for-microcontrollers),
see the [schematics and pinouts](http://github.com/micropython/pyboard) and
[documentation](https://docs.micropython.org/en/latest/pyboard/quickref.html).
⁽¹⁾ After upgrading to full-screen 396x224 instead of the original 120x80. (!)
Contributing
------------
⁽²⁾ Bad Apple requires unloading modules to not run out of memory, and I
haven't been able to consistently do that. See the `unload-modules` branch.
MicroPython is an open-source project and welcomes contributions. To be
productive, please be sure to follow the
[Contributors' Guidelines](https://github.com/micropython/micropython/wiki/ContributorGuidelines)
and the [Code Conventions](https://github.com/micropython/micropython/blob/master/CODECONVENTIONS.md).
Note that MicroPython is licenced under the MIT license, and all contributions
should follow this license.
---
About this repository
---------------------
**Basic benchmarks**
This repository contains the following components:
- [py/](py/) -- the core Python implementation, including compiler, runtime, and
core library.
- [mpy-cross/](mpy-cross/) -- the MicroPython cross-compiler which is used to turn scripts
into precompiled bytecode.
- [ports/](ports/) -- platform-specific code for the various ports and architectures that MicroPython runs on.
- [lib/](lib/) -- submodules for external dependencies.
- [tests/](tests/) -- test framework and test scripts.
- [docs/](docs/) -- user documentation in Sphinx reStructuredText format. This is used to generate the [online documentation](http://docs.micropython.org).
- [extmod/](extmod/) -- additional (non-core) modules implemented in C.
- [tools/](tools/) -- various tools, including the pyboard.py module.
- [examples/](examples/) -- a few example Python scripts.
PythonExtra is slightly faster than the official Python app, probably due to
optimization during compilation of the VM. The tests below show the effect on
basic Python operations.
"make" is used to build the components, or "gmake" on BSD-based systems.
You will also need bash, gcc, and Python 3.3+ available as the command `python3`
(if your system only has Python 2.7 then invoke make with the additional option
`PYTHON=python2`). Some ports (rp2 and esp32) additionally use CMake.
| Test | Program | Official Python (fx-CG 50) | PythonExtra (fx-CG 50) |
| ---- | ------- | -------------------------- | ---------------------- |
| VM speed | `pe_loop.py` (1 million `pass`) | ~12 seconds | 8.9 seconds |
| Shell output | `pe_print.py` (print 100000 integers) | ~22 seconds | 11.3 seconds |
| Large integers | `pe_fact.py` (compute 250!, 500 times) | ~15 seconds | 8.6 seconds |
Supported platforms & architectures
-----------------------------------
---
MicroPython runs on a wide range of microcontrollers, as well as on Unix-like
(including Linux, BSD, macOS, WSL) and Windows systems.
**TODO list**
Microcontroller targets can be as small as 256kiB flash + 16kiB RAM, although
devices with at least 512kiB flash + 128kiB RAM allow a much more
full-featured experience.
Bugs to fix:
- Fix not world switching during filesystem accesses (very unstable)
- Fix current working directory not changing during a module import (for
relative imports)
- Fix casioplot not stopping on the last `show_screen()`
The [Unix](ports/unix) and [Windows](ports/windows) ports allow both
development and testing of MicroPython itself, as well as providing
lightweight alternative to CPython on these platforms (in particular on
embedded Linux systems).
Python features:
- Compare features with existing implementations and other brands
- Get filesystem access (open etc) with the POSIX interface
- Get a decent amount of RAM not just the fixed 32 kiB that's hardcoded so far
The ["minimal"](ports/minimal) port provides an example of a very basic
MicroPython port and can be compiled as both a standalone Linux binary as
well as for ARM Cortex M4. Start with this if you want to port MicroPython to
another microcontroller. Additionally the ["bare-arm"](ports/bare-arm) port
is an example of the absolute minimum configuration, and is used to keep
track of the code size of the core runtime and VM.
UI:
- Add an option for fixed-width font which also sets $COLUMNS properly so that
MicroPython paginates (requires better getenv/setenv support in fxlibc)
- Use [unicode-fonts](/Lephenixnoir/unicode-fonts) to provide Unicode support
* Extend it with a fixed-width uf8x9 which maybe changes some glyphs (like
`i` and `l`; the usual fixed-width unambiguous styles)
* Try and provide a font smaller than 5x7 for more compact shell on mono
- A decent keymap that can input all relevant characters into the shell
- Features that would match MicroPython's readline:
* Multi-line input (figure out how to store it); also, auto-indent
* History (use `MP_STATE_PORT(readline_hist)` with `readline_push_history()`
for a start); also, zsh-style search
* Autocompletion (use `mp_repl_autocomplete()` which should hook just fine)
In addition, the following ports are provided in this repository:
- [cc3200](ports/cc3200) -- Texas Instruments CC3200 (including PyCom WiPy).
- [esp32](ports/esp32) -- Espressif ESP32 SoC (including ESP32S2, ESP32S3, ESP32C3).
- [esp8266](ports/esp8266) -- Espressif ESP8266 SoC.
- [mimxrt](ports/mimxrt) -- NXP m.iMX RT (including Teensy 4.x).
- [nrf](ports/nrf) -- Nordic Semiconductor nRF51 and nRF52.
- [pic16bit](ports/pic16bit) -- Microchip PIC 16-bit.
- [powerpc](ports/powerpc) -- IBM PowerPC (including Microwatt)
- [qemu-arm](ports/qemu-arm) -- QEMU-based emulated target, for testing)
- [renesas-ra](ports/renesas-ra) -- Renesas RA family.
- [rp2](ports/rp2) -- Raspberry Pi RP2040 (including Pico and Pico W).
- [samd](ports/samd) -- Microchip (formerly Atmel) SAMD21 and SAMD51.
- [stm32](ports/stm32) -- STMicroelectronics STM32 family (including F0, F4, F7, G0, G4, H7, L0, L4, WB)
- [teensy](ports/teensy) -- Teensy 3.x.
- [webassembly](ports/webassembly) -- Emscripten port targeting browsers and NodeJS.
- [zephyr](ports/zephyr) -- Zephyr RTOS.
The MicroPython cross-compiler, mpy-cross
-----------------------------------------
Most ports require the [MicroPython cross-compiler](mpy-cross) to be built
first. This program, called mpy-cross, is used to pre-compile Python scripts
to .mpy files which can then be included (frozen) into the
firmware/executable for a port. To build mpy-cross use:
$ cd mpy-cross
$ make
External dependencies
---------------------
The core MicroPython VM and runtime has no external dependencies, but a given
port might depend on third-party drivers or vendor HALs. This repository
includes [several submodules](lib/) linking to these external dependencies.
Before compiling a given port, use
$ cd ports/name
$ make submodules
to ensure that all required submodules are initialised.
Future wishes:
- Build for fx-9860G II (requires manual filesystem support)
- Lephe's secret ideas (complete previous list to unlock)

View File

@ -19,58 +19,56 @@ import os
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
sys.path.insert(0, os.path.abspath('.'))
sys.path.insert(0, os.path.abspath("."))
# The MICROPY_VERSION env var should be "vX.Y.Z" (or unset).
micropy_version = os.getenv('MICROPY_VERSION') or 'latest'
micropy_all_versions = (os.getenv('MICROPY_ALL_VERSIONS') or 'latest').split(',')
url_pattern = '%s/en/%%s' % (os.getenv('MICROPY_URL_PREFIX') or '/',)
micropy_version = os.getenv("MICROPY_VERSION") or "latest"
micropy_all_versions = (os.getenv("MICROPY_ALL_VERSIONS") or "latest").split(",")
url_pattern = "%s/en/%%s" % (os.getenv("MICROPY_URL_PREFIX") or "/",)
# The members of the html_context dict are available inside topindex.html
html_context = {
'cur_version':micropy_version,
'all_versions':[
(ver, url_pattern % ver) for ver in micropy_all_versions
"cur_version": micropy_version,
"all_versions": [(ver, url_pattern % ver) for ver in micropy_all_versions],
"downloads": [
("PDF", url_pattern % micropy_version + "/micropython-docs.pdf"),
],
'downloads':[
('PDF', url_pattern % micropy_version + '/micropython-docs.pdf'),
],
'is_release': micropy_version != 'latest',
"is_release": micropy_version != "latest",
}
# -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'
# needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.doctest',
'sphinx.ext.intersphinx',
'sphinx.ext.todo',
'sphinx.ext.coverage',
'sphinxcontrib.jquery',
"sphinx.ext.autodoc",
"sphinx.ext.doctest",
"sphinx.ext.intersphinx",
"sphinx.ext.todo",
"sphinx.ext.coverage",
"sphinxcontrib.jquery",
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['templates']
templates_path = ["templates"]
# The suffix of source filenames.
source_suffix = '.rst'
source_suffix = ".rst"
# The encoding of source files.
#source_encoding = 'utf-8-sig'
# source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
master_doc = "index"
# General information about the project.
project = 'MicroPython'
copyright = '- The MicroPython Documentation is Copyright © 2014-2023, Damien P. George, Paul Sokolovsky, and contributors'
project = "MicroPython"
copyright = "- The MicroPython Documentation is Copyright © 2014-2023, Damien P. George, Paul Sokolovsky, and contributors"
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
@ -82,41 +80,41 @@ version = release = micropy_version
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None
# language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = ['build', '.venv']
exclude_patterns = ["build", ".venv"]
# The reST default role (used for this markup: `text`) to use for all
# documents.
default_role = 'any'
default_role = "any"
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
pygments_style = "sphinx"
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# modindex_common_prefix = []
# If true, keep warnings as "system message" paragraphs in the built documents.
#keep_warnings = False
# keep_warnings = False
# Global include files. Sphinx docs suggest using rst_epilog in preference
# of rst_prolog, so we follow. Absolute paths below mean "from the base
@ -128,144 +126,148 @@ rst_epilog = """
# -- Options for HTML output ----------------------------------------------
# on_rtd is whether we are on readthedocs.org
on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
on_rtd = os.environ.get("READTHEDOCS", None) == "True"
if not on_rtd: # only import and set the theme if we're building docs locally
try:
import sphinx_rtd_theme
html_theme = 'sphinx_rtd_theme'
html_theme_path = [sphinx_rtd_theme.get_html_theme_path(), '.']
html_theme = "sphinx_rtd_theme"
html_theme_path = [sphinx_rtd_theme.get_html_theme_path(), "."]
except:
html_theme = 'default'
html_theme_path = ['.']
html_theme = "default"
html_theme_path = ["."]
else:
html_theme_path = ['.']
html_theme_path = ["."]
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}
# html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
# html_theme_path = ['.']
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = '../../logo/trans-logo.png'
# html_logo = '../../logo/trans-logo.png'
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
html_favicon = 'static/favicon.ico'
html_favicon = "static/favicon.ico"
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['static']
html_static_path = ["static"]
# Add a custom CSS file for HTML generation
html_css_files = [
'custom.css',
"custom.css",
]
# Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied
# directly to the root of the documentation.
#html_extra_path = []
# html_extra_path = []
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
html_last_updated_fmt = '%d %b %Y'
html_last_updated_fmt = "%d %b %Y"
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
html_additional_pages = {"index": "topindex.html"}
# If false, no module index is generated.
#html_domain_indices = True
# html_domain_indices = True
# If false, no index is generated.
#html_use_index = True
# html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True
# html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True
# html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None
# html_file_suffix = None
# Output file base name for HTML help builder.
htmlhelp_basename = 'MicroPythondoc'
htmlhelp_basename = "MicroPythondoc"
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#'preamble': '',
# Include 3 levels of headers in PDF ToC
'preamble': r'\setcounter{tocdepth}{2}',
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#'preamble': '',
# Include 3 levels of headers in PDF ToC
"preamble": r"\setcounter{tocdepth}{2}",
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, 'MicroPython.tex', 'MicroPython Documentation',
'Damien P. George, Paul Sokolovsky, and contributors', 'manual'),
(
master_doc,
"MicroPython.tex",
"MicroPython Documentation",
"Damien P. George, Paul Sokolovsky, and contributors",
"manual",
),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# latex_use_parts = False
# If true, show page references after internal links.
#latex_show_pagerefs = False
# latex_show_pagerefs = False
# If true, show URL addresses after external links.
#latex_show_urls = False
# latex_show_urls = False
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# latex_appendices = []
# If false, no module index is generated.
#latex_domain_indices = True
# latex_domain_indices = True
# Enable better Unicode support so that `make latexpdf` doesn't fail
latex_engine = "xelatex"
@ -275,12 +277,17 @@ latex_engine = "xelatex"
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
('index', 'micropython', 'MicroPython Documentation',
['Damien P. George, Paul Sokolovsky, and contributors'], 1),
(
"index",
"micropython",
"MicroPython Documentation",
["Damien P. George, Paul Sokolovsky, and contributors"],
1,
),
]
# If true, show URL addresses after external links.
#man_show_urls = False
# man_show_urls = False
# -- Options for Texinfo output -------------------------------------------
@ -289,23 +296,29 @@ man_pages = [
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'MicroPython', 'MicroPython Documentation',
'Damien P. George, Paul Sokolovsky, and contributors', 'MicroPython', 'One line description of project.',
'Miscellaneous'),
(
master_doc,
"MicroPython",
"MicroPython Documentation",
"Damien P. George, Paul Sokolovsky, and contributors",
"MicroPython",
"One line description of project.",
"Miscellaneous",
),
]
# Documents to append as an appendix to all manuals.
#texinfo_appendices = []
# texinfo_appendices = []
# If false, no module index is generated.
#texinfo_domain_indices = True
# texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'
# texinfo_show_urls = 'footnote'
# If true, do not generate a @detailmenu in the "Top" node's menu.
#texinfo_no_detailmenu = False
# texinfo_no_detailmenu = False
# Example configuration for intersphinx: refer to the Python standard library.
intersphinx_mapping = {'python': ('https://docs.python.org/3.5', None)}
intersphinx_mapping = {"python": ("https://docs.python.org/3.5", None)}

View File

@ -141,7 +141,7 @@ These are working configurations for LAN interfaces of popular boards::
# Olimex ESP32-GATEWAY: power controlled by Pin(5)
# Olimex ESP32 PoE and ESP32-PoE ISO: power controlled by Pin(12)
lan = network.LAN(mdc=machine.Pin(23), mdio=machine.Pin(18), power=machine.Pin(5),
lan = network.LAN(mdc=machine.Pin(23), mdio=machine.Pin(18), power=machine.Pin(5),
phy_type=network.PHY_LAN8720, phy_addr=0,
ref_clk=machine.Pin(17), ref_clk_mode=machine.Pin.OUT)
@ -330,6 +330,19 @@ possible at the same frequency.
See more examples in the :ref:`esp32_pwm` tutorial.
DAC (digital to analog conversion)
----------------------------------
On the ESP32, DAC functionality is available on pins 25, 26.
On the ESP32S2, DAC functionality is available on pins 17, 18.
Use the DAC::
from machine import DAC, Pin
dac = DAC(Pin(25)) # create an DAC object acting on a pin
dac.write(128) # set a raw analog value in the range 0-255, 50% now
ADC (analog to digital conversion)
----------------------------------

View File

@ -201,10 +201,12 @@ class Lock
TCP stream connections
----------------------
.. function:: open_connection(host, port)
.. function:: open_connection(host, port, ssl=None)
Open a TCP connection to the given *host* and *port*. The *host* address will be
resolved using `socket.getaddrinfo`, which is currently a blocking call.
If *ssl* is a `ssl.SSLContext` object, this context is used to create the transport;
if *ssl* is ``True``, a default context is used.
Returns a pair of streams: a reader and a writer stream.
Will raise a socket-specific ``OSError`` if the host could not be resolved or if
@ -212,12 +214,14 @@ TCP stream connections
This is a coroutine.
.. function:: start_server(callback, host, port, backlog=5)
.. function:: start_server(callback, host, port, backlog=5, ssl=None)
Start a TCP server on the given *host* and *port*. The *callback* will be
called with incoming, accepted connections, and be passed 2 arguments: reader
and writer streams for the connection.
If *ssl* is a `ssl.SSLContext` object, this context is used to create the transport.
Returns a `Server` object.
This is a coroutine.

View File

@ -62,12 +62,35 @@ Functions
.. function:: flash_erase(sector_no)
.. function:: osdebug(level)
.. function:: osdebug(uart_no)
Turn esp os debugging messages on or off.
.. note:: This is the ESP8266 form of this function.
The *level* parameter sets the threshold for the log messages for all esp components.
The log levels are defined as constants:
Change the level of OS serial debug log messages. On boot,
OS serial debug log messages are disabled.
``uart_no`` is the number of the UART peripheral which should receive
OS-level output, or ``None`` to disable OS serial debug log messages.
.. function:: osdebug(uart_no, [level])
:no-index:
.. note:: This is the ESP32 form of this function.
Change the level of OS serial debug log messages. On boot, OS
serial debug log messages are limited to Error output only.
The behaviour of this function depends on the arguments passed to it. The
following combinations are supported:
``osdebug(None)`` restores the default OS debug log message level
(``LOG_ERROR``).
``osdebug(0)`` enables all available OS debug log messages (in the
default build configuration this is ``LOG_INFO``).
``osdebug(0, level)`` sets the OS debug log message level to the
specified value. The log levels are defined as constants:
* ``LOG_NONE`` -- No log output
* ``LOG_ERROR`` -- Critical errors, software module can not recover on its own
@ -77,6 +100,15 @@ Functions
* ``LOG_VERBOSE`` -- Bigger chunks of debugging information, or frequent messages
which can potentially flood the output
.. note:: ``LOG_DEBUG`` and ``LOG_VERBOSE`` are not compiled into the
MicroPython binary by default, to save size. A custom build with a
modified "``sdkconfig``" source file is needed to see any output
at these log levels.
.. note:: Log output on ESP32 is automatically suspended in "Raw REPL" mode,
to prevent communications issues. This means OS level logging is never
seen when using ``mpremote run`` and similar tools.
.. function:: set_native_code_location(start, length)
**Note**: ESP8266 only

View File

@ -193,7 +193,7 @@ numbers specified in ``write_pulses`` are multiplied by the resolution to
define the pulses.
``clock_div`` is an 8-bit divider (0-255) and each pulse can be defined by
multiplying the resolution by a 15-bit (0-32,768) number. There are eight
multiplying the resolution by a 15-bit (1-``PULSE_MAX``) number. There are eight
channels (0-7) and each can have a different clock divider.
So, in the example above, the 80MHz clock is divided by 8. Thus the
@ -226,7 +226,7 @@ For more details see Espressif's `ESP-IDF RMT documentation.
``100``) and the output level to apply the carrier to (a boolean as per
*idle_level*).
.. method:: RMT.source_freq()
.. classmethod:: RMT.source_freq()
Returns the source clock frequency. Currently the source clock is not
configurable so this will always return 80MHz.
@ -264,10 +264,10 @@ For more details see Espressif's `ESP-IDF RMT documentation.
**Mode 3:** *duration* and *data* are lists or tuples of equal length,
specifying individual durations and the output level for each.
Durations are in integer units of the channel resolution (as described
above), between 1 and 32767 units. Output levels are any value that can
be converted to a boolean, with ``True`` representing high voltage and
``False`` representing low.
Durations are in integer units of the channel resolution (as
described above), between 1 and ``PULSE_MAX`` units. Output levels
are any value that can be converted to a boolean, with ``True``
representing high voltage and ``False`` representing low.
If transmission of an earlier sequence is in progress then this method will
block until that transmission is complete before beginning the new sequence.
@ -290,6 +290,13 @@ For more details see Espressif's `ESP-IDF RMT documentation.
Passing in no argument will not change the channel. This function returns
the current channel number.
Constants
---------
.. data:: RMT.PULSE_MAX
Maximum integer that can be set for a pulse duration.
Ultra-Low-Power co-processor
----------------------------

View File

@ -86,16 +86,6 @@ Functions
Classes
-------
.. class:: FileIO(...)
This is type of a file open in binary mode, e.g. using ``open(name, "rb")``.
You should not instantiate this class directly.
.. class:: TextIOWrapper(...)
This is type of a file open in text mode, e.g. using ``open(name, "rt")``.
You should not instantiate this class directly.
.. class:: StringIO([string])
.. class:: BytesIO([string])

View File

@ -39,9 +39,9 @@ Methods
Configure the ADC peripheral. *bits* will set the resolution of the
conversion process.
.. method:: ADCBlock.connect(channel)
ADCBlock.connect(source)
ADCBlock.connect(channel, source)
.. method:: ADCBlock.connect(channel, *, ...)
ADCBlock.connect(source, *, ...)
ADCBlock.connect(channel, source, *, ...)
Connect up a channel on the ADC peripheral so it is ready for sampling,
and return an :ref:`ADC <machine.ADC>` object that represents that connection.
@ -56,3 +56,6 @@ Methods
If both *channel* and *source* are given then they are connected together
and made ready for sampling.
Any additional keyword arguments are used to configure the returned ADC object,
via its :meth:`init <machine.ADC.init>` method.

View File

@ -39,6 +39,33 @@ class SSLContext
Create a new SSLContext instance. The *protocol* argument must be one of the ``PROTOCOL_*``
constants.
.. method:: SSLContext.load_cert_chain(certfile, keyfile)
Load a private key and the corresponding certificate. The *certfile* is a string
with the file path of the certificate. The *keyfile* is a string with the file path
of the private key.
.. admonition:: Difference to CPython
:class: attention
MicroPython extension: *certfile* and *keyfile* can be bytes objects instead of
strings, in which case they are interpreted as the actual certificate/key data.
.. method:: SSLContext.load_verify_locations(cafile=None, cadata=None)
Load the CA certificate chain that will validate the peer's certificate.
*cafile* is the file path of the CA certificates. *cadata* is a bytes object
containing the CA certificates. Only one of these arguments should be provided.
.. method:: SSLContext.get_ciphers()
Get a list of enabled ciphers, returned as a list of strings.
.. method:: SSLContext.set_ciphers(ciphers)
Set the available ciphers for sockets created with this context. *ciphers* should be
a list of strings in the `IANA cipher suite format <https://wiki.mozilla.org/Security/Cipher_Suites>`_ .
.. method:: SSLContext.wrap_socket(sock, *, server_side=False, do_handshake_on_connect=True, server_hostname=None)
Takes a `stream` *sock* (usually socket.socket instance of ``SOCK_STREAM`` type),
@ -77,6 +104,12 @@ class SSLContext
Set or get the behaviour for verification of peer certificates. Must be one of the
``CERT_*`` constants.
.. note::
``ssl.CERT_REQUIRED`` requires the device's date/time to be properly set, e.g. using
`mpremote rtc --set <mpremote_command_rtc>` or ``ntptime``, and ``server_hostname``
must be specified when on the client side.
Exceptions
----------

View File

@ -28,7 +28,7 @@ MIMXRT1060-EVK Debug USB D0/D1 D7/D6 D8/D9
MIMXRT1064-EVK Debug USB D0/D1 D7/D6 D8/D9
MIMXRT1170-EVK Debug USB D0/D1 D12/D11 D10/D13
Adafruit Metro M7 - D0/D1 D7/D3 A1/A0
Olimex RT1010Py - RxD/TxD D5/D6 -
Olimex RT1010Py - RxD/TxD D7/D8 D5/D6
Seeed ARCH MIX - J3_19/J3_20 J4_16/J4_17 J4_06/J4_07
================= =========== =========== =========== ===========

View File

@ -92,9 +92,7 @@ Use the :ref:`machine.Pin <machine.Pin>` class::
Available Pins follow the ranges and labelling of the respective board, like:
- 0-33 for Teensy 4.0,
- 0-21 for the MIMXRT10xx-EVK board, or 'D0-Dxx', or 'A0-Ann',
- 0-14 for the Olimex RT1010Py board, or 'D0'-'Dxx' and 'A0'-'Ann'
- 'D0-Dxx', or 'A0-Ann' for Teensy 4.0, MIMXRT10xx-EVK ns Olimex board,
- 'J3_xx', 'J4_xx', 'J5_xx' for the Seeed ARCH MIX board,
or the pin names of the Pin.board or Pin.cpu classes.
@ -106,9 +104,9 @@ Notes:
* At the MIMXRT1010_EVK, pins D4, D5 and D9 of the Arduino connector are by
default not connected to the MCU. For details refer to the schematics.
* At the MIMXRT1170_EVK board, the inner rows of the Arduino connectors are assigned as follows:
- D16 - D23: J9, odd pin numbers; D17 is by default not connected.
- D24 - D27: J26, odd pin numbers; J63-J66 have to be closed to enable these pins.
- D29 - D36: J25, odd pin numbers; D29 and D30 are by default not connected.
- 'D16' - 'D23': J9, odd pin numbers; 'D17' is by default not connected.
- 'D24' - 'D27': J26, odd pin numbers; J63-J66 have to be closed to enable these pins.
- 'D29' - 'D36': J25, odd pin numbers; 'D29' and 'D30' are by default not connected.
There's a higher-level abstraction :ref:`machine.Signal <machine.Signal>`
which can be used to invert a pin. Useful for illuminating active-low LEDs
@ -146,22 +144,22 @@ handling signal groups. ::
from machine import Pin, PWM
# create PWM object from a pin and set the frequency and duty cycle
pwm2 = PWM(Pin(2), freq=2000, duty_u16=32768)
pwm2 = PWM(Pin('D2'), freq=2000, duty_u16=32768)
pwm2.freq() # get the current frequency
pwm2.freq(1000) # set/change the frequency
pwm2.duty_u16() # get the current duty cycle, range 0-65535
pwm2.duty_u16(200) # set the duty cycle, range 0-65535
pwm2.deinit() # turn off PWM on the pin
# create a complementary signal pair on Pin 2 and 3
pwm2 = PWM((2, 3), freq=2000, duty_ns=20000)
pwm2 = PWM(('D2', 'D3'), freq=2000, duty_ns=20000)
# Create a group of four synchronized signals.
# Start with Pin(4) at submodule 0, which creates the sync pulse.
pwm4 = PWM(Pin(4), freq=1000, align=PWM.HEAD)
# Pins 5, 6, and 9 are pins at the same module
pwm5 = PWM(Pin(5), freq=1000, duty_u16=10000, align=PWM.HEAD, sync=True)
pwm6 = PWM(Pin(6), freq=1000, duty_u16=20000, align=PWM.HEAD, sync=True)
pwm9 = PWM(Pin(9), freq=1000, duty_u16=30000, align=PWM.HEAD, sync=True)
# Start with Pin('D4') at submodule 0, which creates the sync pulse.
pwm4 = PWM(Pin('D4'), freq=1000, align=PWM.HEAD)
# Pins D5, D6, and D9 are pins at the same module
pwm5 = PWM(Pin('D5'), freq=1000, duty_u16=10000, align=PWM.HEAD, sync=True)
pwm6 = PWM(Pin('D6', freq=1000, duty_u16=20000, align=PWM.HEAD, sync=True)
pwm9 = PWM(Pin('D9'), freq=1000, duty_u16=30000, align=PWM.HEAD, sync=True)
pwm3 # show the PWM objects properties
@ -256,7 +254,7 @@ Use the :ref:`machine.ADC <machine.ADC>` class::
from machine import ADC
adc = ADC(Pin(32)) # create ADC object on ADC pin
adc = ADC(Pin('A2')) # create ADC object on ADC pin
adc.read_u16() # read value, 0-65536 across voltage range 0.0v - 3.3v
The resolution of the ADC is 12 bit with 10 to 11 bit accuracy, irrespective of the
@ -274,7 +272,7 @@ Software SPI (using bit-banging) works on all pins, and is accessed via the
# construct a SoftSPI bus on the given pins
# polarity is the idle state of SCK
# phase=0 means sample on the first edge of SCK, phase=1 means the second
spi = SoftSPI(baudrate=100000, polarity=1, phase=0, sck=Pin(0), mosi=Pin(2), miso=Pin(4))
spi = SoftSPI(baudrate=100000, polarity=1, phase=0, sck=Pin('D0'), mosi=Pin('D2'), miso=Pin('D4'))
spi.init(baudrate=200000) # set the baudrate
@ -303,7 +301,7 @@ rates (up to 30Mhz). Hardware SPI is accessed via the
from machine import SPI, Pin
spi = SPI(0, 10000000)
cs_pin = Pin(6, Pin.OUT, value=1)
cs_pin = Pin('D6', Pin.OUT, value=1)
cs_pin(0)
spi.write('Hello World')
cs_pin(1)
@ -331,7 +329,7 @@ accessed via the :ref:`machine.SoftI2C <machine.SoftI2C>` class::
from machine import Pin, SoftI2C
i2c = SoftI2C(scl=Pin(5), sda=Pin(4), freq=100000)
i2c = SoftI2C(scl=Pin('D5'), sda=Pin('D4'), freq=100000)
i2c.scan() # scan for devices
@ -365,7 +363,7 @@ See :ref:`machine.I2S <machine.I2S>`. Example using a Teensy 4.1 board with a si
external Codec like UDA1334.::
from machine import I2S, Pin
i2s = I2S(2, sck=Pin(26), ws=Pin(27), sd=Pin(7),
i2s = I2S(2, sck=Pin('D26'), ws=Pin('D27'), sd=Pin('D7'),
mode=I2S.TX, bts=16,format=I2S.STEREO,
rate=44100,ibuf=40000)
i2s.write(buf) # write buffer of audio samples to I2S device
@ -397,7 +395,7 @@ Example using the Teensy audio shield::
from machine import I2C, I2S, Pin
from sgtl5000 import CODEC
i2s = I2S(1, sck=Pin(21), ws=Pin(20), sd=Pin(7), mck=Pin(23),
i2s = I2S(1, sck=Pin('D21'), ws=Pin('D20'), sd=Pin('D7'), mck=Pin('D23'),
mode=I2S.TX, bits=16,rate=44100,format=I2S.STEREO,
ibuf=40000,
)
@ -475,7 +473,7 @@ The OneWire driver is implemented in software and works on all pins::
from machine import Pin
import onewire
ow = onewire.OneWire(Pin(12)) # create a OneWire bus on GPIO12
ow = onewire.OneWire(Pin('D12')) # create a OneWire bus on GPIO12
ow.scan() # return a list of devices on the bus
ow.reset() # reset the bus
ow.readbyte() # read a byte
@ -505,12 +503,12 @@ The DHT driver is implemented in software and works on all pins::
import dht
import machine
d = dht.DHT11(machine.Pin(4))
d = dht.DHT11(machine.Pin('D4'))
d.measure()
d.temperature() # eg. 23 (°C)
d.humidity() # eg. 41 (% RH)
d = dht.DHT22(machine.Pin(4))
d = dht.DHT22(machine.Pin('D4'))
d.measure()
d.temperature() # eg. 23.6 (°C)
d.humidity() # eg. 41.3 (% RH)

View File

@ -1,9 +1,10 @@
import os
# Directory that the project lives in, aka ../..
SITE_ROOT = '/'.join(os.path.dirname(__file__).split('/')[0:-2])
SITE_ROOT = "/".join(os.path.dirname(__file__).split("/")[0:-2])
TEMPLATE_DIRS = (
"%s/templates/" % SITE_ROOT, # Your custom template directory, before the RTD one to override it.
"%s/readthedocs/templates/" % SITE_ROOT, # Default RTD template dir
"%s/templates/"
% SITE_ROOT, # Your custom template directory, before the RTD one to override it.
"%s/readthedocs/templates/" % SITE_ROOT, # Default RTD template dir
)

View File

@ -31,3 +31,4 @@ implementation and the best practices to use them.
asm_thumb2_index.rst
filesystem.rst
pyboard.py.rst
micropython2_migration.rst

View File

@ -0,0 +1,74 @@
.. _micropython2_migration:
MicroPython 2.0 Migration Guide
===============================
MicroPython 2.0 is the (currently in development, not yet available) next major
release of MicroPython.
After maintaining API compatibility for almost a decade with the ``1.x`` series, in
order to unblock some project-wide improvements MicroPython 2.0 will introduce a
small number of breaking API changes that will require some programs to be
updated. This guide explains how to update your Python code to accommodate these
changes.
This document is a work-in-progress. As more work is done on MicroPython 2.0,
more items will be added to the lists below.
**Note:** There are currently no MicroPython 2.0 firmware builds available for
download. You can build it yourself by enabling the ``MICROPY_PREVIEW_VERSION_2``
config option. As it gets closer to being ready for release, builds will be
provided for both ``1.x.y`` and ``2.0.0-preview``.
Hardware and peripherals
------------------------
Overview
~~~~~~~~
The goal is to improve consistency in the :mod:`machine` APIs across different
ports, making it easier to write code, documentation, and tutorials that work on
any supported microcontroller.
This means that some ports' APIs need to change to match other ports.
Changes
~~~~~~~
*None yet*
OS & filesystem
---------------
Overview
~~~~~~~~
The primary goal is to support the ability to execute :term:`.mpy files <.mpy
file>` directly from the filesystem without first copying them into RAM. This
improves code deployment time and reduces memory overhead and fragmentation.
Additionally, a further goal is to support a more flexible way of configuring
partitions, filesystem types, and options like USB mass storage.
Changes
~~~~~~~
*None yet*
CPython compatibility
---------------------
Overview
~~~~~~~~
The goal is to improve compatibility with CPython by removing MicroPython
extensions from CPython APIs. In most cases this means moving existing
MicroPython-specific functions or classes to new modules.
This makes it easier to write code that works on both CPython and MicroPython,
which is useful for development and testing.
Changes
~~~~~~~
*None yet*

View File

@ -86,7 +86,8 @@ and .mpy version.
=================== ============
MicroPython release .mpy version
=================== ============
v1.20 and up 6.1
v1.22.0 and up 6.2
v1.20 - v1.21.0 6.1
v1.19.x 6
v1.12 - v1.18 5
v1.11 4
@ -101,6 +102,7 @@ MicroPython repository at which the .mpy version was changed.
=================== ========================================
.mpy version change Git commit
=================== ========================================
6.1 to 6.2 6967ff3c581a66f73e9f3d78975f47528db39980
6 to 6.1 d94141e1473aebae0d3c63aeaa8397651ad6fa01
5 to 6 f2040bfc7ee033e48acef9f289790f3b4e6b74e5
4 to 5 5716c5cf65e9b2cb46c2906f40302401bdd27517

View File

@ -17,44 +17,53 @@ Adafruit ItsyBitsy M0 Express pin assignment table
=== ==== ============ ==== ==== ====== ====== ====== ======
Pin GPIO Pin name IRQ ADC Serial Serial TCC/TC TCC/TC
=== ==== ============ ==== ==== ====== ====== ====== ======
0 PA11 D0 11 19 0/3 2/3 1/1 0/3
1 PA10 D1 10 18 0/2 2/2 1/0 0/2
2 PA14 D2 14 - 2/2 4/2 3/0 0/4
3 PA09 D3 9 17 0/1 2/1 0/1 1/3
4 PA08 D4 - 16 0/0 2/0 0/0 1/2
5 PA15 D5 15 - 2/3 4/3 3/1 0/5
7 PA21 D7 5 - 5/3 3/3 7/1 0/7
9 PA07 D9 7 7 - 0/3 1/1 -
10 PA18 D10 2 - 1/2 3/2 3/0 0/2
11 PA16 D11 0 - 1/0 3/0 2/0 0/6
12 PA19 D12 3 - 1/3 3/3 3/1 0/3
13 PA17 D13 1 - 1/1 3/1 2/1 0/7
14 PA02 A0 2 0 - - - -
15 PB08 A1 8 2 - 4/0 4/0 -
16 PB09 A2 9 3 - 4/1 4/1 -
17 PA04 A3 4 4 - 0/0 0/0 -
18 PA05 A4 5 5 - 0/1 0/1 -
19 PB02 A5 2 - - 5/0 6/0 -
20 PA22 SDA 6 - 3/0 5/0 4/0 0/4
21 PA23 SCL 7 - 3/1 5/1 4/1 0/5
22 PB10 MOSI 10 - - 4/2 5/0 0/4
23 PA12 MISO 12 - 2/0 4/0 2/0 0/6
24 PB11 SCK 11 - - 4/3 5/1 0/5
25 PA00 DOTSTAR_CLK 0 - - 1/0 2/0 -
26 PA01 DOTSTAR_DATA 1 - - 1/1 2/1 -
27 PB22 FLASH_MOSI 6 - - 5/2 7/0 -
28 PB03 FLASH_MISO 3 - - 5/1 6/1 -
29 PB23 FLASH_SCK 7 - - 5/3 7/1 -
2 PA02 A0 2 0 - - - -
40 PB08 A1 8 2 - 4/0 4/0 -
41 PB09 A2 9 3 - 4/1 4/1 -
4 PA04 A3 4 4 - 0/0 0/0 -
5 PA05 A4 5 5 - 0/1 0/1 -
34 PB02 A5 2 10 - 5/0 6/0 -
11 PA11 D0 11 19 0/3 2/3 1/1 0/3
10 PA10 D1 10 18 0/2 2/2 1/0 0/2
14 PA14 D2 14 - 2/2 4/2 3/0 0/4
9 PA09 D3 9 17 0/1 2/1 0/1 1/3
8 PA08 D4 - 16 0/0 2/0 0/0 1/2
15 PA15 D5 15 - 2/3 4/3 3/1 0/5
21 PA21 D7 5 - 5/3 3/3 7/1 0/7
7 PA07 D9 7 7 - 0/3 1/1 -
18 PA18 D10 2 - 1/2 3/2 3/0 0/2
16 PA16 D11 0 - 1/0 3/0 2/0 0/6
19 PA19 D12 3 - 1/3 3/3 3/1 0/3
17 PA17 D13 1 - 1/1 3/1 2/1 0/7
0 PA00 DOTSTAR_CLK 0 - - 1/0 2/0 -
1 PA01 DOTSTAR_DATA 1 - - 1/1 2/1 -
27 PA27 FLASH_CS 15 - - - - -
35 PB03 FLASH_MISO 3 11 - 5/1 6/1 -
54 PB22 FLASH_MOSI 6 - - 5/2 7/0 -
55 PB23 FLASH_SCK 7 - - 5/3 7/1 -
12 PA12 MISO 12 - 2/0 4/0 2/0 0/6
42 PB10 MOSI 10 - - 4/2 5/0 0/4
43 PB11 SCK 11 - - 4/3 5/1 0/5
23 PA23 SCL 7 - 3/1 5/1 4/1 0/5
22 PA22 SDA 6 - 3/0 5/0 4/0 0/4
30 PA30 SWCLK 10 - - 1/2 1/0 -
31 PA31 SWDIO 11 - - 1/3 1/1 -
24 PA24 USB_DM 12 - 3/2 5/2 5/0 1/2
25 PA25 USB_DP 13 - 3/3 5/3 5/1 1/3
3 PA03 3 1 - - - -
6 PA06 6 6 - 0/2 1/0 -
13 PA13 13 - 2/1 4/1 2/0 0/7
20 PA20 4 - 5/2 3/2 7/0 0/4
28 PA28 8 - - - - -
=== ==== ============ ==== ==== ====== ====== ====== ======
Description of the columns:
- *Pin* - The number that is expected at ``machine.Pin(n)``, if the pin is given
as a number. This is NOT the GPIO number, but the board pin number, as
given in the board specific definition file.
- *GPIO* - The GPIO number.
- *Pin Name* - The name of a Pin which is expected argument to ``machine.Pin("name")``.
as a number.
- *GPIO* - The GPIO name, which can be used as argument to ``machine.Pin("name")``.
- *Pin Name* - The boards name, which can be used as argument to ``machine.Pin("name")``.
- *IRQ* - The IRQ number assigned to that GPIO, used internally by ``Pin.irq()``. When
using ``Pin.irq()``, different pins must use different IRQs
- *ADC* - The ADC channel assigned to the pin. When using ADC, different pins must
@ -183,10 +192,9 @@ Pin GPIO Pin name IRQ ADC ADC Serial Serial TC PWM PWM
Description of the columns:
- *Pin* - The number that is expected at ``machine.Pin(n)``, if the pin is given
as a number. This is NOT the GPIO number, but the board pin number, as
given in the board specific definition file.
- *GPIO* - The GPIO number.
- *Pin Name* The name of a Pin which is expected argument to ``machine.Pin("name")``.
as a number.
- *GPIO* - The GPIO name, which can be used as argument to ``machine.Pin("name")``.
- *Pin Name* - The boards name, which can be used as argument to ``machine.Pin("name")``.
- *IRQ* - The IRQ number assigned to that GPIO, used internally by ``Pin.irq()``. When
using ``Pin.irq()``, different pins must use different IRQs
- *ADC* - The ADC0/1 channel assigned to the pin. When using ADC, different pins must
@ -862,7 +870,7 @@ Adafruit ItsyBitsy M4 Express :ref:`samd51_pinout_table`.
The default devices at the board are:
- UART 1 at pins PB23/PB22, labelled RXD/TXD
- UART 2 at pins PA13/PA12, labelled RXD/TXD
- I2C 5 at pins PA22/PA23, labelled SDA/SCL
- SPI 4 at pins PB12/PB11/PB13, labelled MOSI, MISO and SCK
- DAC output on pins PA02 and PA05, labelled A0 and A4
@ -876,36 +884,36 @@ The tables shown above were created with small a Python script running on the ta
from machine import Pin
import os
def print_entry(e, txt):
def print_item(e, txt):
print(txt, end=": ")
if e == 255:
print(" - ", end="")
else:
print("%d/%d" % (e >> 4, e & 0x0f), end="")
def print_pininfo(pin, info):
print("%3d" % pin, end=" ")
print("P%c%02d" % ("ABCD"[pin // 32], pin % 32), end="")
print(" %12s" % info[0], end="")
def print_pininfo(pin_id, name, info):
print("%3d" % pin_id, end=" ")
print("%4s %12s" % (info[0], name), end="")
print(" IRQ:%2s" % (info[1] if info[1] != 255 else "-"), end="")
print(" ADC0:%2s" % (info[2] if info[2] != 255 else "-"), end="")
if len(info) == 7:
print_entry(info[3], " Serial1")
print_entry(info[4], " Serial2")
print_entry(info[5], " PWM1" if (info[5] >> 4) < 3 else " TC")
print_entry(info[6], " PWM2")
print_item(info[3], " Serial1")
print_item(info[4], " Serial2")
print_item(info[5], " PWM1" if (info[5] >> 4) < 3 else " TC")
print_item(info[6], " PWM2")
else:
print(" ADC1:%2s" % (info[3] if info[3] != 255 else "-"), end="")
print_entry(info[4], " Serial1")
print_entry(info[5], " Serial2")
print_entry(info[6], " TC")
print_entry(info[7], " PWM1")
print_entry(info[8], " PWM2")
print_item(info[4], " Serial1")
print_item(info[5], " Serial2")
print_item(info[6], " TC")
print_item(info[7], " PWM1")
print_item(info[8], " PWM2")
print()
def tblkey(i):
name = i[1][0]
if name != "-":
name = i[1]
if name != "":
if len(name) < 3:
return " " + name
else:
@ -913,17 +921,25 @@ The tables shown above were created with small a Python script running on the ta
else:
return "zzzzzzz%03d" % i[0]
def table(num = 127):
def table(num=127, sort=True):
pintbl = []
inv_bd = {v: k for k, v in Pin.board.__dict__.items()}
for i in range(num):
try:
pintbl.append((i, pininfo(i)))
p = Pin(i)
pi = pininfo(p)
if p in inv_bd.keys():
name = inv_bd[p]
else:
name = ""
pintbl.append((i, name, pininfo(i)))
except:
pass
# print("not defined")
pintbl.sort(key=tblkey)
if sort:
pintbl.sort(key=tblkey)
for item in pintbl:
print_pininfo(item[0], item[1])
print_pininfo(item[0], item[1], item[2])
table()

View File

@ -0,0 +1,120 @@
# Using Numworks' modules `kandinsky`, `ion` and `time` with PythonExtra
PythonExtra offers the possibility of using certain Numworks modules in order to make the scripts of this machine compatible as is on Casio fx-CG50 (no support on the fx9860G due to insufficient memory and lack of color screen ).
This is a Work in Progress (WIP) and the support is subject to extensive testing at this stage. The port concerns the Numworks `kandinsky`, `ion` and `time` modules which are machine specific and are now supported via this implementation. The `math`, `cmath`, `random` modules being identical between the `Numworks` version and the `builtins` modules of MicroPython, they are therefore not part of this implementation but are perfectly usable without modification in the scripts.
Note: the `turtle` and `matplotlib.pyplot` modules are not included in this implementation. It is possible to use the `turtle`, `matplotlib` and `casioplot` modules from Casio Education which are perfectly functional and provided as an example in `ports/sh/examples`.
## `kandinsky`
The `kandinsky` module provides support for graphics primitives via high-performance `gint` routines. All the functions of this module are available:
- `color(r,g,b)`: Generates the value of the color r,g,b. You can also simply use a tuple to define a color: (r,g,b).
- `get_pixel(x,y)`: Returns the color of the pixel at x,y coordinates as a tuple (r,g,b).
- `set_pixel(x,y,color)`: Lights the pixel x,y of the color color.
- `draw_string(text,x,y,[color1],[color2])`: Displays the text at x,y coordinates. The arguments color1 (text color) and color2 (text background color) are optional.
- `fill_rect(x,y,width,height,color)`: Fills a rectangle of width width and height height with the color color at the point of x and y coordinates.
The module also offers a certain number of colors explicitly named and accessible by a character string. The following values can be used instead of the color parameters of the `kandinsky` functions:
- "red", "r"
- "green", "g"
- "blue", "b"
- "black", "k"
- "white", "w"
- "yellow", "y"
- "pink"
- "magenta"
- "grey", "gray"
- "purple"
- "orange"
- "cyan"
- "brown"
The following functions are additions to take advantage of the wide screen of the fxCG and are therefore an extension of the `Kandinsky` module. They are therefore by definition not compatible with Python Numwork. These functions can be recognized by their names which all begin with `CGEXT_`:
- `CGEXT_Enable_Wide_Screen()`: Enables the fxCG wide screen, no settings are necessary. The x-coordinates of the physical screen can be negative to encroach on the left white stripe and greater than 319 pixels to encroach on the right white stripe;
- `CGEXT_Disable_Wide_Screen()`: Cancels the activation of the fxCG extended screen, no settings are necessary. The x coordinates of the physical screen will be constrained between 0 and 320 pixels. Beyond that, the route will not be carried out.
- `CGEXT_Is_Wide_Screen_Enabled()`: Returns `True` if the extended screen is active and `False` otherwise.
- `CGEXT_Set_Margin_Color( color )` : Paints the margin of the `Numworks` screen on fxCG with the specified color.
Note 1: after having made a plot in the extended area, it must be active to allow its deletion (typically via a call to the `fill_rect()` function with the appropriate parameters).
Note 2: In non-extended mode (by default when initializing the `Kandinsky` module) the screen coordinates go from (0,0) to (319,221) centered on the fxCG screen. In extended mode, the screen coordinates range from (-38,-1) to (358,223).
## `ion`
The `ion` module gives access to the `keydown(k)` function which returns True if the key k placed as an argument is pressed and False otherwise.
The “conversion” of the keys between the Numworks machine and Casio fxCG50 is done according to the following mapping:
| Numworks | Casio fxCG50 | Numworks Key # |
|----------|--------------|---------------------|
| KEY_LEFT | KEY_LEFT | 0 |
| KEY_UP | KEY_UP | 1 |
| KEY_DOWN | KEY_DOWN | 2 |
| KEY_RIGHT | KEY_RIGHT | 2 |
| KEY_OK | KEY_F1 | 4 |
| KEY_BACK | KEY_EXIT | 5 |
| KEY_HOME | KEY_MENU | 6 |
| KEY_ONOFF | KEY_ACON | 7 |
| ... | ... | ... |
| KEY_SHIFT | KEY_SHIFT | 12 |
| KEY_ALPHA | KEY_ALPHA | 13 |
| KEY_XNT | KEY_XOT | 14 |
| KEY_VAR | KEY_VARS | 15 |
| KEY_TOOLBOX | KEY_OPTN | 16 |
| KEY_BACKSPACE | KEY_DEL | 17 |
| KEY_EXP | KEY_EXP | 17 |
| KEY_LN | KEY_LN | 19 |
| KEY_LOG | KEY_LOG | 20 |
| KEY_IMAGINARY | KEY_F2 | 21 |
| KEY_COMMA | KEY_COMMA | 22 |
| KEY_POWER | KEY_POWER | 23 |
| KEY_SINE | KEY_SIN | 24 |
| KEY_COSINE | KEY_COS | 25 |
| KEY_TANGENT | KEY_TAN | 26 |
| KEY_PI | KEY_F3 | 27 |
| KEY_SQRT | KEY_F4 | 28 |
| KEY_SQUARE | KEY_SQUARE | 29 |
| KEY_SEVEN | KEY_7 | 30 |
| KEY_EIGHT | KEY_8 | 31 |
| KEY_NINE | KEY_9 | 32 |
| KEY_LEFTPARENTHESIS | KEY_LEFTP | 33 |
| KEY_RIGHTPARENTHESIS | KEY_RIGHTP | 34 |
| ... | ... | ... |
| KEY_FOUR | KEY_4 | 36 |
| KEY_FIVE | KEY_5 | 37 |
| KEY_SIX | KEY_6 | 38 |
| KEY_MULTIPLICATION | KEY_MUL | 39 |
| KEY_DIVISION | KEY_DIV | 40 |
| ... | ... | ... |
| KEY_ONE | KEY_1 | 42 |
| KEY_TWO | KEY_2 | 43 |
| KEY_THREE | KEY_3 | 44 |
| KEY_PLUS | KEY_ADD | 45 |
| KEY_MINUS | KEY_SUB | 46 |
| ... | ... | ... |
| KEY_ZERO | KEY_0 | 48 |
| KEY_DOT | KEY_DOT | 49 |
| KEY_EE | KEY_F5 | 50 |
| KEY_ANS | KEY_NEG | 51 |
| KEY_EXE | KEY_EXE | 52 |
## `time`
The `time` module gives access to two functions:
- `monotonic()`: Returns the clock value at the time the function is called.
- `sleep(t)`: Suspends execution for t seconds.

View File

@ -0,0 +1,120 @@
# Utilisation des modules `kandinsky`, `ion` et `time` de l'implémentation Python `Numworks`
PythonExtra offre la possibilité d'utiliser certains modules de la Numworks afin de rendre les scripts de cette machine compatible en l'état sur Casio fx-CG50 (pas de support sur la fx9860G pour cause de mémoire insuffisante et d'abence d'écran couleur).
Il s'agit d'un Work in Progress (WIP) et le support est sujet à tests approfondis à ce stade. Le port concerne les modules `kandinsky`, `ion` et `time` de la Numworks qui sont spécifiques à la machine et sont désormais supportés via cette implémentation. Les modules `math`, `cmath`, `random` étant identiques entre la version `Numworks` et les modules `builtins` de MicroPython, ils ne font donc pas partie de cette implémentation mais sont parfaitement utilisables sans modification dans les scripts.
Note : les modules `turtle` et `matplotlib.pyplot` ne sont pas repris dans cette implémentation. Il est possible d'utiliser les modules `turtle`, `matplotlib` et `casioplot` de Casio Education qui sont parfaitement fonctionnels et fournis en example dans `ports/sh/examples`.
## `kandinsky`
Le module `kandinsky` offre le support des primitives graphiques via les routines hautes performance de `gint`. Toutes les fonctions de ce module sont disponibles :
- `color(r,g,b)` : Génère la valeur de la couleur r,g,b. Vous pouvez aussi simplement utiliser un tuple pour définir une couleur : (r,g,b).
- `get_pixel(x,y)` : Renvoie la couleur du pixel aux coordonnées x,y sous forme de tuple (r,g,b).
- `set_pixel(x,y,color)` : Allume le pixel x,y de la couleur color.
- `draw_string(text,x,y,[color1],[color2])` : Affiche le texte text aux coordonnées x,y. Les arguments color1 (couleur du texte) et color2 (couleur de lʼarrière plan du texte) sont optionnels.
- `fill_rect(x,y,width,height,color)` : Remplit un rectangle de largeur width et de hauteur height avec la couleur color au point de coordonnées x et y.
Le module offre de plus un certain nombre de couleurs explicitement nommées et accessibles par une chaine de caractères. Les valeurs suivantes sont utilisables en lieu et place des paramètres de couleur des fonctions de `kandinsky` :
- "red", "r"
- "green", "g"
- "blue", "b"
- "black", "k"
- "white", "w"
- "yellow", "y"
- "pink"
- "magenta"
- "grey", "gray"
- "purple"
- "orange"
- "cyan"
- "brown"
Les fonctions suivantes sont des ajouts pour tirer partie de l'écran large de la fxCG et qui sont donc une extension du module `Kandinsky`. Elles ne sont donc par définition pas compatible avec le Python Numwork. Ces fonctions sont reconnaisables à leurs appellations qui commencent toutes par `CGEXT_` :
- `CGEXT_Enable_Wide_Screen()` : Active l'écran étendu de la fxCG, aucun paramètre n'est nécessaire. Les coordonnées x de l'écran physique peuvent être négatives pour empiéter sur la bande blanche de gauche et supérieures à 319 pixels pour empièter sur la bande blanche de droite;
- `CGEXT_Disable_Wide_Screen()` : Annule l'activation de l'écran étendu de la fxCG, aucun paramètre n'est nécessaire. Les coordonnées x de l'écran physique seront contraintes entre 0 et 320 pixels. Au-delà, le tracé ne sera pas effectué.
- `CGEXT_Is_Wide_Screen_Enabled()` : Retourne `True` si l'écran étendu est actif et `False` dans le cas contraire.
- `CGEXT_Set_Margin_Color( color )` : Trace les marge de la fxCG50 (pourtours de l'écran `Numworks`) de la couleur passée en argument.
Note 1 : après avoir réalisé un tracé dans la zone étendue, il faut que celle-ci soit active pour permettre son effacement (typiquement via un appel à la fonction `fill_rect()` avec les paramètres adéquats).
Note 2 : En mode non étendu (par défaut à l'initialisation du module `Kandinsky`) les coordonnées de l'écran vont de (0,0) à (319,221) centré sur l'écran de la fxCG. En mode étendu, les coordonnées de l'écran vont de (-38,-1) à (358,223).
## `ion`
Le module `ion` donne accès à la fonction `keydown(k)` qui renvoie True si la touche k placée en argument est appuyée et False sinon.
La "conversion" des touches entre la machine Numworks et Casio fxCG50 se fait selon le mapping suivant :
| Numworks | Casio fxCG50 | Numworks Key # |
|----------|--------------|---------------------|
| KEY_LEFT | KEY_LEFT | 0 |
| KEY_UP | KEY_UP | 1 |
| KEY_DOWN | KEY_DOWN | 2 |
| KEY_RIGHT | KEY_RIGHT | 2 |
| KEY_OK | KEY_F1 | 4 |
| KEY_BACK | KEY_EXIT | 5 |
| KEY_HOME | KEY_MENU | 6 |
| KEY_ONOFF | KEY_ACON | 7 |
| ... | ... | ... |
| KEY_SHIFT | KEY_SHIFT | 12 |
| KEY_ALPHA | KEY_ALPHA | 13 |
| KEY_XNT | KEY_XOT | 14 |
| KEY_VAR | KEY_VARS | 15 |
| KEY_TOOLBOX | KEY_OPTN | 16 |
| KEY_BACKSPACE | KEY_DEL | 17 |
| KEY_EXP | KEY_EXP | 17 |
| KEY_LN | KEY_LN | 19 |
| KEY_LOG | KEY_LOG | 20 |
| KEY_IMAGINARY | KEY_F2 | 21 |
| KEY_COMMA | KEY_COMMA | 22 |
| KEY_POWER | KEY_POWER | 23 |
| KEY_SINE | KEY_SIN | 24 |
| KEY_COSINE | KEY_COS | 25 |
| KEY_TANGENT | KEY_TAN | 26 |
| KEY_PI | KEY_F3 | 27 |
| KEY_SQRT | KEY_F4 | 28 |
| KEY_SQUARE | KEY_SQUARE | 29 |
| KEY_SEVEN | KEY_7 | 30 |
| KEY_EIGHT | KEY_8 | 31 |
| KEY_NINE | KEY_9 | 32 |
| KEY_LEFTPARENTHESIS | KEY_LEFTP | 33 |
| KEY_RIGHTPARENTHESIS | KEY_RIGHTP | 34 |
| ... | ... | ... |
| KEY_FOUR | KEY_4 | 36 |
| KEY_FIVE | KEY_5 | 37 |
| KEY_SIX | KEY_6 | 38 |
| KEY_MULTIPLICATION | KEY_MUL | 39 |
| KEY_DIVISION | KEY_DIV | 40 |
| ... | ... | ... |
| KEY_ONE | KEY_1 | 42 |
| KEY_TWO | KEY_2 | 43 |
| KEY_THREE | KEY_3 | 44 |
| KEY_PLUS | KEY_ADD | 45 |
| KEY_MINUS | KEY_SUB | 46 |
| ... | ... | ... |
| KEY_ZERO | KEY_0 | 48 |
| KEY_DOT | KEY_DOT | 49 |
| KEY_EE | KEY_F5 | 50 |
| KEY_ANS | KEY_NEG | 51 |
| KEY_EXE | KEY_EXE | 52 |
## `time`
Le module `time` donne accès à deux fonctions :
- `monotonic()` : Renvoie la valeur de lʼhorloge au moment où la fonction est appelée.
- `sleep(t)` : Suspend lʼexécution pendant t secondes.

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@ -0,0 +1,53 @@
# `casioplot`: CASIO's official I/O module
`casioplot` is a drawing library provided by CASIO as support for the official `turtle` and `matplotlib` modules. It was [announced in February 2020](https://www.planet-casio.com/Fr/forums/topic16154-1-modules-graphiques-python-en-avril-matplotlib-et-turtle.html) and [released in April](https://www.planet-casio.com/Fr/forums/topic16243-1-rendu-graphique-en-python-partie-1-decouverte-de-matplotlib-et-turtle.html). The module is notably available on G-III and fx-CG models with the same API. As of March 2024, `casioplot` is the only custom module in CASIO's official port of MicroPython. PythonExtra also provides the module for source compatibility.
```py
import casioplot
# or
from casioplot import *
```
**Contents**
- [Rendering functions](#rendering-functions)
- [Considerations for rendering](#considerations-for-rendering)
- [Differences with the official `casioplot` module](#differences-with-the-official-casioplot-module)
## Rendering functions
```py
show_screen() -> None
clear_screen() -> None
set_pixel(x: int, y: int, ?color: (int, int, int)) -> None
get_pixel(x: int, y: int) -> (int, int, int)
draw_string(x: int, y: int, text: str, ?color: (int, int, int), ?size: str) -> None
```
The rendering area is of size 128x64 on G-III and 384x216 on fx-CG. While the G-III supports only two colors (black and white), the fx-CG supports 65536 colors (16-bit RGB565). Still, the color format is _always_ (r,g,b) triplets with 0 ≤ r,g,b ≤ 255. This helps compatibility between models and with PC, at a performance cost. Calculators process these colors by _approximating_ them to the closest color they can represent.
Like the gint module, `casioplot` functions draw to an internal buffer called the VRAM, and the module only pushes that to the screen when explicitly asked to or at the end of the program.
`show_screen()` pushes the VRAM to screen after something has been drawn.
`clear_screen()` fills the VRAM in white.
`set_pixel()` changes the color of the pixel at (x,y) into the provided `color` encoded as an (r,g,b) triplet (black if not provided). Building triplets is a bit slow so don't write something like `set_pixel(x, y, (0,0,0))` in a loop, store the triplet in a variable and use that instead.
`get_pixel()` returns the color of the pixel at (x,y) in VRAM as an (r,g,b) triplet. Because VRAM stores colors in the same format as the display, which typically doesn't support all 16 million colors, `get_pixel()` immediately after `set_pixel()`usually returns an _approximation_ of the original color. Because it allocates a triplet, this function is also excruciatingly slow to call in a loop, to the point of creating GC-driven lag spikes that in some situations make it completely unusable.
`draw_string()` draws text. (x,y) is the location of the top-left corner of the rendered string. The text color is optional; if specified it should be an (r,g,b) triplet, otherwise it is black. The font size can be either of the strings `"small"`, `"medium"` or `"large"` and defaults to medium. On the G-III, the font sizes `"small"` and `"medium"` are identical, but on the fx-CG all three fonts are different. Any `'\n'` in the string is replaced with spaces when drawing.
TODO: Example
## Considerations for rendering
_Text mode._ `casioplot` automatically switches PythonExtra into graphics mode when imported. Programs that want to render graphics frames after a `print()` should `show_screen()` _before_ rendering the first frame since `print()` switches to text mode.
_Performance._ Writing to VRAM is the main reason why rendering in `casioplot` is sometimes much faster than in Basic. Basic pushes the rendered data to the display after every call, which is slow. Unfortunately, `casioplot` ends up losing for complex drawing tasks for which Basic has complex functions (like DrawStat) while `casioplot` just has single pixels. In this case, functions from the [gint module](modgint-en.md) can be of help.
## Differences with the official `casioplot` module
- PythonExtra's implementation doesn't automatically show the screen when the program finishes executing.
- The fonts for `draw_string()` are not identical on the G-III port.
- The fonts for `draw_string()` currently only support ASCII.
- The drawable space on fx-CG is at the top left section of the screen.

View File

@ -0,0 +1,53 @@
# `casioplot` : Module officiel d'I/O de CASIO
`casioplot` est une bibliothèque de dessin fournie par CASIO pour supporter les modules officiels `turtle` et `matplotlib`. Le module a été [annoncé en Février 2020](https://www.planet-casio.com/Fr/forums/topic16154-1-modules-graphiques-python-en-avril-matplotlib-et-turtle.html) et [publié en Avril](https://www.planet-casio.com/Fr/forums/topic16243-1-rendu-graphique-en-python-partie-1-decouverte-de-matplotlib-et-turtle.html). Le module est disponible sur Graph 35+E II et Graph 90+E avec la même API. C'est le seul module personnalisé dans le port MicroPython de CASIO (à date de Mars 2024). PythonExtra fournit le module par compatibilité pour les scripts officiels.
```py
import casioplot
# or
from casioplot import *
```
**Sommaire**
- [Fonctions de dessin](#fonctions-de-dessin)
- [Considérations spéciales pour le rendu](#considérations-spéciales-pour-le-rendu)
- [Différences avec le module `casioplot` officiel](#différences-avec-le-module-casioplot-officiel)
## Fonctions de dessin
```py
show_screen() -> None
clear_screen() -> None
set_pixel(x: int, y: int, ?color: (int, int, int)) -> None
get_pixel(x: int, y: int) -> (int, int, int)
draw_string(x: int, y: int, text: str, ?color: (int, int, int), ?size: str) -> None
```
La zone de dessin est de 128x64 pixels sur Graph 35+E II et 384x216 pixels sur la Graph 90+E. La Graph 35+E II ne supporte que deux couleurs (noir et blanc) tandis que la Graph 90+E peut afficher 65536 couleurs (RGB565 16 bits). Cependant, le format de couleurs est _quand même_ des triplets (r,g,b) avec 0 ≤ r,g,b ≤ 255. Ce choix maintient la compabilité entre les modèles et avec le PC, en échange d'un coût en performance. Les calculatrices approximent ces couleurs en les remplaçant par la couleur la plus proche qu'elles peuvent afficher.
Comme le module gint, `casioplot` dessine systématiquement dans un buffer interne qu'on appelle la VRAM, et n'affiche le résultat à l'écran que quand on lui demande explicitement, ou à la fin de l'exécution.
`show_screen()` affiche à l'écran les contenus de la VRAM après un dessin.
`clear_screen()` remplit la VRAM en blanc.
`set_pixel()` remplace la couleur du pixel à la position (x,y) par `color`, qui doit être un triplet (r,g,b) si fournie, et sera noir si absente. Construire des triplets est un peu lent donc il vaut mieux éviter d'écrire des appels comme `set_pixel(x, y, (0,0,0))` dans des boucles ; il est plus performant de stocker le triplet dans une variable et d'utiliser la variable.
`get_pixel()` renvoie la couleur du pixel à la position (x,y) de la VRAM sous la forme d'un triplet (r,g,b). Comme la VRAM stocke les couleurs au même format que l'écran, qui ne supporte généralement pas 16 millions de couleurs, appeler `get_pixel()` juste après `set_pixel()` renvoie une _approximation_ de la couleur originale. Comme cette fonction alloue un triplet, elle est atrocement lente à appeler en boucle, au point où elle peut créer du lag simplement par sa pression sur le GC, ce qui la rend parfois inutilisable.
`draw_string()` affiche du texte. (x,y) est la position du coin haut-gauche du rectangle dans lequel le texte est dessiné. La couleur est optionnelle ; si elle est spécifiée il faut que ce soit un triplet (r,g,b), sinon c'est noir. La taille peut être l'une des trois chaînes `"small"`, `"medium"` ou `"large"` ; la valeur par défaut est `"medium"`. Sur la Graph 35+E II, les polices `"small"` et `"medium"` sont identiques, tandis que sur la Graph 90+E les trois polices sont différentes. Tout `'\n'` dans la chaîne est remplacé par un espace avant d'afficher.
TODO: Exemple
## Considérations spéciales pour le rendu
_Mode texte._ `casioplot` passe automatiquement PythonExtra en mode graphique à l'import. Les programmes qui veulent faire du dessin graphique après un `print()` doivent appeler `show_screen()` _avant_ de commencer à dessiner le premier frame parce que `print()` repasse en mode texte.
_Performance._ Le fait que les fonctions de dessin écrivent silencieusement dans la VRAM est la principale raison pour laquelle `casioplot` est parfois beaucoup plus rapide que le dessin en Basic. PRGM réaffiche la VRAM à l'écran après chaque appel d'une fonction de dessin, ce qui est lent. Malheureusement, `casioplot` redevient plus lent que le Basic pour les dessins complexes pour lesquels il y a des fonctions spécialisées en Basic (comme `DrawStat`), puisque `casioplot` ne peut dessiner qu'un pixel à la fois. Dans ces situations, il vaut mieux utiliser les fonctions de dessin du [module gint](modgint-fr.md).
## Différences avec le module `casioplot` officiel
- L'implémentation PythonExtra du module n'affiche pas automatiquement l'écran à la fin du programme.
- Les polices pour `draw_string()` diffèrent des polices officielles sur Graph 35+E II.
- Les polices pour `draw_string()` ne supportent actuellement que les caractères ASCII.
- Les zone de dessin sur Graph 90+E est en haut à gauche de l'écran.

433
docs/sh/modgint-en.md Normal file
View File

@ -0,0 +1,433 @@
# `gint`: Wrapper for the gint library
PythonExtra is developed with the [fxSDK](https://gitea.planet-casio.com/Lephenixnoir/fxsdk) and uses the [gint kernel](https://gitea.planet-casio.com/Lephenixnoir/gint) as a runtime. The Python module `gint` provides access to gint's internal functions for rendering, keyboard, and more. Since gint has many versatile functions with good performance, it is beneficial to use it instead of e.g. `casioplot` or `turtle`.
The `gint` module tries to match its API with the original API of the C library, which is why few functions use keyword arguments or overloading. There are a few differences documented at the end of this document. For details not described in this document, one can refer to [gint's header files](https://gitea.planet-casio.com/Lephenixnoir/gint/src/branch/master/include/gint) which are always applicable unless this document explicitly says otherwise.
All constants, functions, etc. discussed here are in the `gint` module.
```py
import gint
# or:
from gint import *
```
**Contents**
- [Keyboard input](#keyboard-input)
- [Drawing and rendering](#drawing-and-rendering)
- [Differences with gint's C API](#differences-with-gints-c-api)
## Keyboard input
Reference headers: [`<gint/keyboard.h>`](https://gitea.planet-casio.com/Lephenixnoir/gint/src/branch/master/include/gint/keyboard.h) and [`<gint/keycodes.h>`](https://gitea.planet-casio.com/Lephenixnoir/gint/src/branch/master/include/gint/keycodes.h).
The module provides integer constants to refer to keyboard keys, with the following names:
| | | | | | |
|------------|------------|------------|------------|------------|-------------|
|`KEY_F1` |`KEY_F2` |`KEY_F3` |`KEY_F4` |`KEY_F5` |`KEY_F6` |
|`KEY_SHIFT` |`KEY_OPTN` |`KEY_VARS` |`KEY_MENU` |`KEY_LEFT` |`KEY_UP` |
|`KEY_ALPHA` |`KEY_SQUARE`|`KEY_POWER` |`KEY_EXIT` |`KEY_DOWN` |`KEY_RIGHT` |
|`KEY_XOT` |`KEY_LOG` |`KEY_LN` |`KEY_SIN` |`KEY_COS` |`KEY_TAN` |
|`KEY_FRAC` |`KEY_FD` |`KEY_LEFTP` |`KEY_RIGHTP`|`KEY_COMMA` |`KEY_ARROW` |
|`KEY_7` |`KEY_8` |`KEY_9` |`KEY_DEL` |`KEY_ACON` | |
|`KEY_4` |`KEY_5` |`KEY_6` |`KEY_MUL` |`KEY_DIV` | |
|`KEY_1` |`KEY_2` |`KEY_3` |`KEY_ADD` |`KEY_SUB` | |
|`KEY_0` |`KEY_DOT` |`KEY_EXP` |`KEY_NEG` |`KEY_EXE` | |
### Keyboard events
```
key_event:
.time -> int
.mod -> bool
.shift -> bool
.alpha -> bool
.type -> KEYEV_NONE | KEYEV_DOWN | KEYEV_UP | KEYEV_HOLD
.key -> KEY_*
```
gint communicates information about keyboard activity through _events_. Events indicate when a key (`.key` field) is pressed, repeated or released (`.type` field equal to `KEYEV_DOWN`, `KEYEV_HOLD` and `KEYEV_UP` respectively), when (`.time` field), and whether modifiers (SHIFT, `.shift` field, and ALPHA, `.alpha` field) where active at that time.
(The `.mod` field isn't very interesting, and the `KEYEV_NONE` value for the `.type` field is discussed later with `pollevent()`.)
The functions `getkey()`, `getkey_opt()`, `pollevent()` and `waitevent()` all return events.
### Waiting for a key press
```py
getkey() -> key_event
getkey_opt(opts: GETKEY_*, timeout_ms: int | None) -> key_event
```
The function `getkey()` pauses the program until a key is pressed or repeated, and returns the associated event (which is always of type `KEYEV_DOWN` or `KEYEV_HOLD`). By default, only arrow keys are repeated, once after 400 ms, then every 40 ms.
A few things can happen while `getkey()` is waiting. The user can press SHIFT or ALPHA which will trigger modifiers and affect the `.shift` and `.alpha` fields of the returned event. The user can also go to the main menu by pressing MENU or turn the calculator off with SHIFT+AC/ON.
_Example._ In a selection menu with N possible items, one could navigate with the up and down arrow keys, jump to the top or bottom with SHIFT up and SHIFT down, and validate with EXE.
```py
ev = getkey()
if ev.key == KEY_EXE:
pass # Validate
elif ev.key == KEY_UP and ev.shift:
pos = 0 # Jump to top
elif ev.key == KEY_DOWN and ev.shift:
pos = N-1 # Jump to bottom
elif ev.key == KEY_UP and pos > 0:
pos -= 1 # Move one place up
elif ev.key == KEY_DOWN and pos < N-1:
pos += 1 # Move one place down
```
The function `getkey_opt()` generalizes `getkey()` and provides more options to customize its behavior. The `opts` parameter accepts a combination (sum) of options from the table below, and the parameter `timeout_ms`, when not `None`, specifies how long `getkey_opt()` should wait before returning a `KEYEV_NONE` event if nothing happens. The delay is specified in milliseconds but the actual resolution is about 7-8 ms.
| Option | `getkey()` | Description |
|------------------------|------------|--------------------------------------------------|
| `GETKEY_MOD_SHIFT` | Yes | SHIFT is a modifier key |
| `GETKEY_MOD_ALPHA` | Yes | ALPHA is a modifier key |
| `GETKEY_BACKLIGHT` | Yes | SHIFT+OPTN toggles display backlight |
| `GETKEY_MENU` | Yes | MENU brings up the calculator's main menu |
| `GETKEY_REP_ARROWS` | Yes | Repeats arrow keys when held |
| `GETKEY_REP_ALL` | No | Repeats all keys when held |
| `GETKEY_REP_PROFILE` | Yes* | Enable custom repeat delays |
| `GETKEY_FEATURES` | Yes* | Enable custom global shortcuts |
| `GETKEY_MENU_DUPDATE` | Yes | Update display after return to menu (fx-CG) |
| `GETKEY_MENU_EVENT` | No | Send a `KEYEV_OSMENU` event after return to menu |
| `GETKEY_POWEROFF` | Yes | SHIFT+AC/ON turns the calculator off |
`getkey()` is equivalent to `getkey_opt(opts, None)` where `opts` is the sum of all options that have "Yes" in the `getkey()` column above.
The two options `GETKEY_REP_PROFILE` and `GETKEY_FEATURES` are only useful when configured through other functions that are not yet available in PythonExtra.
### Reading keyboard events in real time
```py
pollevent() -> key_event
waitevent() -> key_event
clearevents() -> None
```
gint records keyboard activity in the background while the program is running. Events are placed in a queue until the program reads them. This is how `getkey()` learns about keyboard activity, for example.
The `pollevent()` function provides direct access to events. `pollevent()` returns the oldest event that hasn't yet been read by the program. If there are no events waiting to be read, `pollevent()` returns a "fake" event with type `KEYEV_NONE` to indicate that the queue is empty.
Since `pollevent()` returns instantly, it can be used to read keyboard activity without pausing the program.
_Example._ A game loop could, at every frame, read all pending events to determine when the player pressed the SHIFT key (in this example the "action" key) to perform an action.
```py
# Render game...
while True:
ev = pollevent()
if ev.type == KEYEV_NONE:
break # We're done reading events
if ev.type == KEYEV_DOWN and ev.key == KEY_SHIFT:
pass # The SHIFT key was just pressed!
# Implicitly ignores other keys
# Simulate game...
```
The `waitevent()` function operates similarly, but if there are no pending events it waits for something to happen before returning. It is used quite rarely because in waiting situations one usually uses `getkey()` instead.
The function `clearevents()` reads and ignores all events, i.e. it "throws away" all the information about recent keyboard activity. It is useful to know the immediate state of the keyboard with `keydown()'` (see below). `clearevents()` is equivalent to the following definition:
```py
def clearevents():
ev = pollevent()
while ev.type != KEYEV_NONE:
ev = pollevent()
```
### Reading the immediate state of the keyboard
```py
keydown(key: int) -> bool
keydown_all(*keys: [int]) -> bool
keydown_any(*keys: [int]) -> bool
```
After events have been read and the event queue is empty, one can query the immediate state of keys with the `keydown()` function. `keydown(k)` returns `True` if key `k` is currently pressed, `False` otherwise. This function only works **after events have been read**, which is usually done either with `pollevent()` or with `clearevents()`.
_Example._ A game loop could check the state of the left/right keys at every frame to move the player.
```py
while True:
ev = pollevent()
# ... same thing as the pollevent() example
if keydown(KEY_LEFT):
player_x -= 1
if keydown(KEY_RIGHT):
player_x += 1
```
`keydown_all()` takes a series of keys as parameters and returns `True` if they are all pressed. `keydown_any()` is similar and returns `True` if at least one of the listed keys is pressed.
### Quickly querying key state changes
```py
cleareventflips() -> None
keypressed(key: int) -> bool
keyreleased(key: int) -> bool
```
`keydown()` only tells whether keys are pressed at a given time; it cannot be used to check when keys change from the released state to the pressed state or the other way around. To do this, one must either read individual events (which can be annoying), remember which keys were pressed at the previous frame, or use the functions described below.
`keypressed(k)` and `keyreleased(k)` indicate whether key `k` was pressed/released since the last call to `cleareventflips()`. As previously, here "pressed/released" means "as indicated by keyboard events read" not as a real-time state change.
_Example._ A game loop could test both the immediate state of some keys and state changes for other keys by using immediate functions after `cleareventflips()` followed by `clearevents()`.
```py
# Render game...
cleareventflips()
clearevents()
if keypressed(KEY_SHIFT):
pass # Action !
if keydown(KEY_LEFT):
player_x -= 1
if keydown(KEY_RIGHT):
player_x += 1
# Simulate game...
```
### Miscellaneous keyboard functions
```py
keycode_function(key: int) -> int
keycode_digit(key: int) -> int
```
`keycode_function(k)` returns the F-key number of `k` (i.e. 1 for `KEY_F1`, 2 for `KEY_F2`, etc.) and -1 for other keys.
`keycode_digit(k)` returns the digit associated with `k` (i.e. 0 for `KEY_0`, 1 for `KEY_1`, etc.) and -1 for other keys.
## Drawing and rendering
Reference headers: [`<gint/display.h>`](https://gitea.planet-casio.com/Lephenixnoir/gint/src/branch/master/include/gint/display.h), and for some details [`<gint/display-fx.h>`](https://gitea.planet-casio.com/Lephenixnoir/gint/src/branch/master/include/gint/display-fx.h) and [`<gint/display-cg.h>`](https://gitea.planet-casio.com/Lephenixnoir/gint/src/branch/master/include/gint/display-cg.h).
### Color manipulation
```py
C_WHITE: int # White
C_BLACK: int # Black
C_LIGHT: int # Light gray (on B&W: gray engine)
C_DARK: int # Dark gray (on B&W: gray engine)
C_NONE: int # Transparent
C_INVERT: int # Function: inverse
# Black-and-white (B&W) models only:
C_LIGHTEN: int # Function: lighten (gray engine)
C_DARKEN: int # Function: darken (gray engine)
# fx-CG models only:
C_RED: int # Pure red
C_GREEN: int # Pure green
C_BLUE: int # Pure blue
C_RGB(r: int, g: int, b: int) -> int
```
Colors are all integers (manipulating `(r,g,b)` tuples is excruciatingly slow and requires memory allocations all over the place). A few default colors are provided.
On the fx-CG series, the `C_RGB()` function can be used to create colors from three components ranging from 0 to 31.
TODO: Explain the gray engine.
### Basic rendering functions
```py
DWIDTH: int
DHEIGHT: int
dupdate() -> None
dclear(color: int) -> None
dpixel(x: int, y: int, color: int) -> None
dgetpixel(x: int, y: int) -> int
```
The integers `DWIDTH` and `DHEIGHT` indicate the screen's dimensions. The screen is 128x64 on black-and-white models (like the G-III) and 396x224 on the fx-CG series (the full screen is available).
All rendering functions draw to an internal image called the "VRAM"; rendering calls are thus not immediate visible on the screen. For the result to be visible one must call the `dupdate()` function, which transfers the contents of the VRAM to the real display. Usually, this is done after rendering everything we need on one frame instead of after each drawing function call.
In PythonExtra, `dupdate()` also indicates a "switch to graphics mode". Due to certain optimizations any call to `print()` is considered a "switch to text mode", and while in text mode the shell might redraw at any time. In order to draw after using text mode, one must call `dupdate()` to force a switch to graphics mode before starting rendering. Otherwise the shell and program might render at the same time and produce incoherent results.
`dclear()` fills the screen with a uniform color.
`dpixel()` changes a pixel's color. Coordinates, as in every other drawing function, are (x,y) where `x` is in the range 0 to DWIDTH-1 inclusive (0 being left) and `y` is in the range 0 to DHEIGHT-1 inclusive (0 being top).
`dgetpixel()` returns the color of a pixel. Note that `dgetpixel()` reads from VRAM, not from the display.
_Example ([`ex_draw1.py`](../../ports/sh/examples/ex_draw1.py))._
```py
from gint import *
dclear(C_WHITE)
for y in range(10):
for x in range(10):
if (x^y) & 1:
dpixel(x, y, C_BLACK)
dupdate()
```
![](images/modgint-draw1-cg.png) ![](images/modgint-draw1-fx.png)
### Geometric shape rendering functions
```py
drect(x1: int, y1: int, x2: int, y2: int, color: int) -> None
drect_border(x1: int, y1: int, x2: int, y2: int, fill_color: int,
border_width: int, border_color: int) -> None
dline(x1: int, y1: int, x2: int, y2: int, color: int) -> None
dhline(y: int, color: int) -> None
dvline(x: int, color: int) -> None
dcircle(x: int, y: int, radius: int, fill_color: int,
border_color: int) -> None
dellipse(x1: int, y1: int, x2: int, y2: int, fill_color: int,
border_color: int) -> None
```
`drect()` draws a flat rectangle spanning from (x1, y1) to (x2, y2) (both inclusive). The order of points does not matter, i.e. x1 ≥ x2 and y1 ≥ y2 are both allowed.
`drect_border()` is similar but also draws a border. The border is located _inside_ the rectangle.
`dline()` draws a straight line from (x1, y1) to (x2, y2). The shortcut functions `dhline()` and `dvline()` draw a full horizontal and vertical line across the screen respectively.
`dcircle()` draws a circle defined by its center and radius using the Bresenham algorithm. The colors for the circle's interior and its edge can be specified separately, including as `C_NONE` (transparent). By construction, `dcircle()` can only draw circles of odd diameter; for even diameters, use `dellipse()`.
`dellipse()` draws an ellipse defined by its bounding box. Both (x1, y1) and (x2, y2) are included in the bounding box. To render an ellipse from its center coordinates (x,y) and semi-major/minor axes a/b, use `dellipse(x-a, y-b, x+a, y+b, fill_color, border_color)`.
_Exemple ([`ex_draw2.py`](../../ports/sh/examples/ex_draw2.py))._
![](images/modgint-draw2-cg.png) ![](images/modgint-draw2-fx.png)
_Example ([`ex_circle.py`](../../ports/sh/examples/ex_circle.py))._
![](images/modgint-circle-cg.png) ![](images/modgint-circle-fx.png)
### Image rendering functions
```py
dimage(x: int, y: int, img: image) -> None
dsubimage(x: int, y: int, img: image, left: int, top: int, width: int, height: int) -> None
```
**On black-and-white models**
```py
image:
.profile -> IMAGE_MONO | ...
.width -> int
.height -> int
.data -> buffer-like
# Constructor
image(profile: IMAGE_*, width: int, height: int, data: buffer-like) -> image
```
Images on black-and-white models have either 2 or 4 colors (when the gray engine is enabled). Each image has a `.profile` field indicating the image format (the name "profile" comes from old gint versions), two fields `.width` and `.height` specifying its size, and a `.data` field providing direct access to pixel data.
The table below lists the four available formats.
| Format | Colors | Layers | Name in fxconv |
|--------------------|---------------------------------|--------|----------------|
| `IMAGE_MONO` | Black/white (2) | 1 | `mono` |
| `IMAGE_MONO_ALPHA` | Black/white, transparent (3) | 2 | `mono_alpha` |
| `IMAGE_GRAY` | Shades of gray (4) | 2 | `gray` |
| `IMAGE_GRAY_ALPHA` | Shades of gray, transparent (5) | 3 | `gray_alpha` |
The raw storage format for data is a bit complicated. The image is stored in row-major order; each line is represented left-to-right by a series of words each covering 32 pixels. Each word contains one bit per pixel (as a 4-byte integer) for each layer.
The easiest way to obtain an image is to generate the associated code with the fxconv tool from the [fxSDK](https://gitea.planet-casio.com/Lephenixnoir/fxsdk). The options `--bopti-image-fx --fx` specify a conversion for black-and-white models and the metadata `profile:mono` selects the encoding. The table above lists the value of `profile:` to use for each desired format. For instance for [`fx_image_7seg.py`](../../ports/sh/examples/fx_image_7seg.png) :
![](../../ports/sh/examples/fx_image_7seg.png)
```bash
% fxconv --bopti-image fx_image_7seg.png -o 7seg.py --fx profile:mono name:seg --py
```
```py
import gint
seg = gint.image(0, 79, 12, b'|\x00||\x00|||||\x00\x00\xba\x02::\x82\xb8\xb8:\xba\xba\x00\x00\xc6\x06\x06\x06\xc6\xc0\xc0\x06\xc6\xc6\x00\x00\xc6\x06\x06\x06\xc6\xc0\xc0\x06\xc6\xc6\x00\x00\x82\x02\x02\x02\x82\x80\x80\x02\x82\x82\x00\x00\x00\x00|||||\x00||\x00\x00\x82\x02\xb8:::\xba\x02\xba:\x00\x00\xc6\x06\xc0\x06\x06\x06\xc6\x06\xc6\x06\x00\x00\xc6\x06\xc0\x06\x06\x06\xc6\x06\xc6\x06\x00\x00\xc6\x06\xc0\x06\x06\x06\xc6\x06\xc6\x06\x00\x00\xba\x02\xb8:\x02:\xba\x02\xba:\x00\x00|\x00||\x00||\x00||\x00\x00')
```
The option `--py-compact` generates much shorter code (less `\x`), however the resulting file can generally not be read or modified by a text editor. The only easy option to use that file is to send it to the calculator and import it as-is. (It can also by manipulated by a program if needed.)
`dimage()` renders an image, positioned so that the top-left corner of the image is located at (x, y).
`dsubimage()` renders a sub-rectangle of an image. The rectangle starts at position (left, top) within the image and is of size `width` by `height`. It is positioned so that the (left, top) pixel is drawn at (x, y) on the screen.
_Example ([`fx_image.py`](../../ports/sh/examples/fx_image.py))._
![](images/modgint-image-fx.png)
**On color models**
```py
image:
.format -> IMAGE_RGB565 | ...
.flags -> int
.color_count -> int
.width -> int
.height -> int
.stride -> int
.data -> buffer-like
.palette -> buffer-like
# Constructor
image(format: IMAGE_*, color_count: int, width: int, height: int, stride: int, data: buffer-like, palette: buffer-like) -> image
# Format-specific constructors
image_rgb565(width: int, height: int, data: buffer-like) -> image
image_rgb565a(width: int, height: int, data: buffer-like) -> image
image_p8_rgb565(width: int, height: int, data: buffer-like, palette: buffer-like) -> image
image_p8_rgb565a(width: int, height: int, data: buffer-like, palette: buffer-like) -> image
image_p4_rgb565(width: int, height: int, data: buffer-like, palette: buffer-like) -> image
image_p4_rgb565a(width: int, height: int, data: buffer-like, palette: buffer-like) -> image
```
Images on color models are available in multiple formats as indicated by the `.format` field; the possible values are listed below. Formats differ in the number of colors, the presence of a transparent color, and the presence of a palette. Of course, the less colors the smaller the memory footprint of the image, so in general it is very beneficial to use the smallest format in which an image fits.
| Format | Colors | Palette | Name in fxconv |
|--------------------|---------------------|-------------|----------------|
| `IMAGE_RGB565` | 65536 | No | `rgb565` |
| `IMAGE_RGB565A` | 65535 + transparent | No | `rgb565a` |
| `IMAGE_P8_RGB565` | 256 | Yes (1-256) | `p8_rgb565` |
| `IMAGE_P8_RGB565A` | 255 + transparent | Yes (1-256) | `p8_rgb565a` |
| `IMAGE_P4_RGB565` | 16 | Yes (16) | `p4_rgb565` |
| `IMAGE_P4_RGB565A` | 15 + transparent | Yes (16) | `p4_rgb565a` |
The `.color_count` field indicates the number of colors in the palette, when there is one. For P8 formats this number varies between 1 and 256, and for P4 formats it is always equal to 16. The `.width` and `.height` fields indicate the image's size. Finally, the `.data` and `.palette` fields provide direct access to the raw data for the image's pixels and color palette.
(The `.flags` field has details of memory management that shouldn't be important to Python scripts. The `.stride` fields indicates the distance in bytes between rows of pixels in `.data` and should similarly be of rare use.)
The functions `dimage()` and `dsubimage()` work the same way as for black-and-white models; please see above.
As for black-and-white models, images can be converted into a Python format with fxconv. For instance with [`cg_image_puzzle.png`](../../ports/sh/examples/cg_image_puzzle.png) (full encoding elided):
![](../../ports/sh/examples/cg_image_puzzle.png)
```bash
% fxconv --bopti-image cg_image_puzzle.png -o puzzle.py --cg profile:p4_rgb565 name:puzzle --py
```
```py
import gint
puzzle = gint.image(6, 16, 64, 32, 32,
b'\xbb\xbb\xbb\xbb\xbb ... \xdd\xdd\xdd\xdd\xdd\xdd\xdd',
b'\xff\xff\xcfW\x86\xd8\xbe|\xceP\xe5\x8a\x963f9u\x9c}\xa8\x9dxD\xfa\x83\xceLNZ\xcci\xa7')
```
The option `--py-compact` is recommended to reduce code size; please see details in the black-and-white section above.
_Exemple ([`cg_image.py`](../../ports/sh/examples/cg_image.py))._
![](images/modgint-image-cg.png)
## Differences with gint's C API
- `dsubimage()` doesn't have its final parameter `int flags`. The flags are only minor optimizations and could be removed in future gint versions.
- Image constructors`image()` and `image_<format>()` don't exist in the C API.
- Asynchronous volatile-flag-based timeouts are replaced with synchronous millisecond delays (integer value or `None`).
TODO: There are more.

434
docs/sh/modgint-fr.md Normal file
View File

@ -0,0 +1,434 @@
# `gint`: Module d'accès aux fonctionnalités de gint
PythonExtra est écrit à l'aide du [fxSDK](https://gitea.planet-casio.com/Lephenixnoir/fxsdk) et utilise [gint](https://gitea.planet-casio.com/Lephenixnoir/gint) pour exécuter l'add-in. Le module Python `gint` permet d'accéder aux fonctions internes de gint en Python pour le dessin, le clavier, etc. Comme gint possède beaucoup de fonctions utiles avec de bonnes performances, il est intéressant de s'en servir au lieu d'utiliser e.g. `casioplot` ou `turtle`.
Le module `gint` essaie de garder en Python la même API que dans la version originale de la bibliothèque en C, c'est pourquoi peu de fonctions utilisent des arguments nommés ou autres fonctions surchargées. Il y a quelques différences, documentées à la fin de cette page. En cas de doute, la documentation fournie par les [fichiers d'en-tête de gint](https://gitea.planet-casio.com/Lephenixnoir/gint/src/branch/master/include/gint) (les `.h`) est tout à fait applicable pour comprendre les comportements que cette page n'explique pas.
Tous les noms de constantes, fonctions, etc. discutés dans cet article sont dans le module `gint`.
```py
import gint
# ou:
from gint import *
```
**Sommaire**
- [Saisie au clavier](#saisie-au-clavier)
- [Dessin à l'écran](#dessin-à-lécran)
- [Différences avec l'API C de gint](#différences-avec-lapi-c-de-gint)
## Saisie au clavier
Les en-têtes de référence sont [`<gint/keyboard.h>`](https://gitea.planet-casio.com/Lephenixnoir/gint/src/branch/master/include/gint/keyboard.h) et [`<gint/keycodes.h>`](https://gitea.planet-casio.com/Lephenixnoir/gint/src/branch/master/include/gint/keycodes.h).
### Noms des touches
Le module fournit des constantes entières désignant toutes les touches du clavier. Les noms sont les suivants :
| | | | | | |
|------------|------------|------------|------------|------------|-------------|
|`KEY_F1` |`KEY_F2` |`KEY_F3` |`KEY_F4` |`KEY_F5` |`KEY_F6` |
|`KEY_SHIFT` |`KEY_OPTN` |`KEY_VARS` |`KEY_MENU` |`KEY_LEFT` |`KEY_UP` |
|`KEY_ALPHA` |`KEY_SQUARE`|`KEY_POWER` |`KEY_EXIT` |`KEY_DOWN` |`KEY_RIGHT` |
|`KEY_XOT` |`KEY_LOG` |`KEY_LN` |`KEY_SIN` |`KEY_COS` |`KEY_TAN` |
|`KEY_FRAC` |`KEY_FD` |`KEY_LEFTP` |`KEY_RIGHTP`|`KEY_COMMA` |`KEY_ARROW` |
|`KEY_7` |`KEY_8` |`KEY_9` |`KEY_DEL` |`KEY_ACON` | |
|`KEY_4` |`KEY_5` |`KEY_6` |`KEY_MUL` |`KEY_DIV` | |
|`KEY_1` |`KEY_2` |`KEY_3` |`KEY_ADD` |`KEY_SUB` | |
|`KEY_0` |`KEY_DOT` |`KEY_EXP` |`KEY_NEG` |`KEY_EXE` | |
### Événements clavier
```
key_event:
.time -> int
.mod -> bool
.shift -> bool
.alpha -> bool
.type -> KEYEV_NONE | KEYEV_DOWN | KEYEV_UP | KEYEV_HOLD
.key -> KEY_*
```
gint communique les informations sur ce qu'il se passe au clavier via des _événements_. Les événements indiquent quand une touche (champ `.key`) a été pressée, maintenue, ou relâchée (champ `.type` égal à `KEYEV_DOWN`, `KEYEV_HOLD` et `KEYEV_UP` respectivement), quand (champ `.time`) et si des modifieurs (SHIFT ou ALPHA, champs `.shift` et `.alpha`) étaient actifs à ce moment-là.
(Le champ `.mod` n'est pas très intéressant, et la valeur `KEYEV_NONE` de `.type` est discutée dans `pollevent()`.)
Les fonctions `getkey()`, `getekey_opt()`, `pollevent()` et `waitevent()` renvoient toutes des événements.
### Saisie d'une touche avec attente
```py
getkey() -> key_event
getkey_opt(opts: GETKEY_*, timeout_ms: int | None) -> key_event
```
La fonction `getkey()` met le programme en pause jusqu'à ce qu'une touche soit pressée ou répétée, et renvoie l'événement associé (qui est forcément de type `KEYEV_DOWN` ou `KEYEV_HOLD`). Par défaut, les seules touches qui sont répétées sont les touches directionnelles, une première fois après 400 ms, et ensuite toutes les 40 ms.
Pas mal de choses peuvent se produire pendant l'exécution de `getkey()`. L'utilisateur peut appuyer sur SHIFT ou ALPHA, ce qui affecte les champs `.shift` et `.alpha` de l'événement renvoyé. L'utilisateur peut également se rendre au menu principal avec MENU et éteindre la calculatrice avec SHIFT+AC/ON.
_Exemple._ Dans un menu de sélection de N éléments, on pourrait naviguer avec les touches haut et bas, sauter directement au début ou à la fin avec SHIFT haut et SHIFT bas, et valider avec EXE.
```py
ev = getkey()
if ev.key == KEY_EXE:
pass # Valider
elif ev.key == KEY_UP and ev.shift:
pos = 0 # Revenir au début
elif ev.key == KEY_DOWN and ev.shift:
pos = N-1 # Aller à la fin
elif ev.key == KEY_UP and pos > 0:
pos -= 1 # Monter d'une position
elif ev.key == KEY_DOWN and pos < N-1:
pos += 1 # Descendre d'une position
```
La fonction `getkey_opt()` est une généralisation de `getkey()` qui donne accès à plus d'options pour personnaliser le comportement de la fonction. Le paramètre `opts` accepte une combinaison d'options dans le tableau ci-dessous, et le paramètre `timeout_ms`, quand il n'est pas `None`, spécifie au bout de combien de temps la fonction doit s'arrêter et renvoyer un événement de type `KEYEV_NONE` s'il n'y a aucune activité sur le clavier. Le délai est exprimé en millisecondes mais la précision réelle est de l'ordre de 7-8 ms.
| Option | `getkey()` | Description |
|------------------------|------------|------------------------------------------------------------|
| `GETKEY_MOD_SHIFT` | Oui | La touche SHIFT est un modifieur |
| `GETKEY_MOD_ALPHA` | Oui | La touche ALPHA est un modifieur |
| `GETKEY_BACKLIGHT` | Oui | SHIFT+OPTN allume/éteint le rétroéclairage |
| `GETKEY_MENU` | Oui | MENU retourne au menu principal de la calculatrice |
| `GETKEY_REP_ARROWS` | Oui | Répète les touches directionnelles si maintenues |
| `GETKEY_REP_ALL` | Non | Répète toutes les touches si maintenues |
| `GETKEY_REP_PROFILE` | Oui* | Personnalisation des durées de répétition |
| `GETKEY_FEATURES` | Oui* | Personnalisation des raccourcis claviers globaux |
| `GETKEY_MENU_DUPDATE` | Oui | Rafraîchit l'écran après un retour au menu (Prizm/G90) |
| `GETKEY_MENU_EVENT` | Non | Envoie un événement `KEYEV_OSMENU` après un retour au menu |
| `GETKEY_POWEROFF` | Oui | SHIFT+AC/ON éteint la calculatrice |
`getkey()` est équivalent à `getkey_opt(opts, None)``opts` est la somme de toutes les options marquées "Oui" dans la colonne `getkey()` ci-dessus.
Les deux options `GETKEY_REP_PROFILE` et `GETKEY_FEATURES` ne sont utiles qu'au travers de fonctions de configuration qui ne sont pour l'instant pas disponibles dans PythonExtra.
### Lecture des événements en temps réel
```py
pollevent() -> key_event
waitevent() -> key_event
clearevents() -> None
```
gint enregistre l'activité du clavier en tâche de fond pendant que le programme s'exécute. Les événements sont mis dans une file d'attente jusqu'à ce que le programme les lise. C'est comme ça par exemple que `getkey()` détermine quoi renvoyer.
Il est possible d'accéder aux événements directement à l'aide de la fonction `pollevent()`. `pollevent()` renvoie l'événement le plus ancien qui n'a pas encore été lu par le programme. Si le programme a lu tous les événements et qu'il n'y a plus rien en attente, `pollevent()` renvoie un "faux" évenement de type `KEYEV_NONE` pour indiquer qu'il n'y a plus rien à lire.
Comme `pollevent()` retourne instanténement, on peut s'en servir pour lire l'activité du clavier sans mettre le programme en pause.
_Exemple._ Une boucle de jeu pourrait, à chaque frame, lire tous les événements en attente pour déterminer quand le joueur appuie sur la touche SHIFT ("action" dans cet exemple) pour déclencher une action.
```py
# Dessiner le jeu...
while True:
ev = pollevent()
if ev.type == KEYEV_NONE:
break # Fin de la lecture des événements
if ev.type == KEYEV_DOWN and ev.key == KEY_SHIFT:
pass # La touche SHIFT vient d'être pressée !
# Ignore implicitement les autres touches
# Simuler le jeu...
```
La fonction `waitevent()` est similaire, mais si tous les événements ont été lus elle attend qu'un événement se produise avant de retourner. Elle est plus rarement utilisée parce qu'en général quand on veut attendre on utilise `getkey()`.
La fonction `clearevents()` lit et ignore tous les événements, i.e. elle "jette" toutes les informations sur ce qu'il s'est passé au clavier. Elle est utile pour connaître l'état instantané du clavier avec `keydown()` (voir ci-dessous). `clearevents()` est équivalente à la définition suivante :
```py
def clearevents():
ev = pollevent()
while ev.type != KEYEV_NONE:
ev = pollevent()
```
### Lecture de l'état instantané du clavier
```py
keydown(key: int) -> bool
keydown_all(*keys: [int]) -> bool
keydown_any(*keys: [int]) -> bool
```
Une fois les événements lus, on peut tester individuellement si les touches sont pressées ou pas à l'aide de la fonction `keydown()`. `keydown(k)` renvoie `True` si la touche `k` est pressée, `False` sinon. Cette fonction ne marche **que si les événements ont été lus**, ce qu'on fait souvent soit avec `pollevent()` soit avec `clearevents()`.
_Exemple._ Une boucle de jeu pourrait tester si les touches gauche/droite sont pressées à chaque frame pour déplacer le joueur.
```py
while True:
ev = pollevent()
# ... comme dans l'exemple pollevent()
if keydown(KEY_LEFT):
player_x -= 1
if keydown(KEY_RIGHT):
player_x += 1
```
La fonction `keydown_all()` prent une série de touches en paramètre et renvoie `True` si elles sout toutes pressées. `keydown_any()` est similaire et renvoie `True` si au moins une des touches listées est pressée.
### Lecture rapide des changements de position des touches
```py
cleareventflips() -> None
keypressed(key: int) -> bool
keyreleased(key: int) -> bool
```
`keydown()` indique uniquement l'état instantané des touches. Elle ne permet pas de déterminer à quel moment une touche passe de l'état relâché à l'état pressé ou l'inverse. Pour ça, il faut soit utiliser les événements (ce qui est un peu lourd), soit se souvenir de quelles touches étaient pressées à "l'instant" précédent, soit utiliser les fonctions ci-dessous.
Les fonctions `keypressed(k)` et `keyreleased(k)` indiquent si la touche a été pressée/relâchée depuis le dernier appel à `cleareventflips()`. Attention la notion de "pressée/relâchée" ici n'est pas le temps réel mais la lecture des événements.
_Exemple._ Une boucle de jeu peut tester à la fois l'état immédiat et les changements d'état des touches en utilisant les fonctions instantanée après `cleareventflips()` suivi de `clearevents()`.
```py
# Dessiner le jeu...
cleareventflips()
clearevents()
if keypressed(KEY_SHIFT):
pass # Action !
if keydown(KEY_LEFT):
player_x -= 1
if keydown(KEY_RIGHT):
player_x += 1
# Simuler le jeu...
```
### Fonctions diverses concernant le clavier
```py
keycode_function(key: int) -> int
keycode_digit(key: int) -> int
```
`keycode_function(k)` renvoie le numéro de F-touche de `k` (i.e. 1 pour `KEY_F1`, 2 pour `KEY_F2`, etc.) et -1 pour les autres touches.
`keycode_digit(k)` renvoie le chiffre associé à `k` (i.e. 0 pour `KEY_0`, 1 pour `KEY_1`, etc.) et -1 pour les autres touches.
## Dessin à l'écran
Les en-têtes de référence sont [`<gint/display.h>`](https://gitea.planet-casio.com/Lephenixnoir/gint/src/branch/master/include/gint/display.h), et pour certains détails techniques [`<gint/display-fx.h>`](https://gitea.planet-casio.com/Lephenixnoir/gint/src/branch/master/include/gint/display-fx.h) et [`<gint/display-cg.h>`](https://gitea.planet-casio.com/Lephenixnoir/gint/src/branch/master/include/gint/display-cg.h).
### Manipulation de couleurs
```py
C_WHITE: int # Blanc
C_BLACK: int # Noir
C_LIGHT: int # Gris clair (sur mono: moteur de gris)
C_DARK: int # Gris foncé (sur mono: moteur de gris)
C_NONE: int # Transparent
C_INVERT: int # Inverseur de couleur
# Graph mono uniquement :
C_LIGHTEN: int # Éclaircisseur de couleur (moteur de gris)
C_DARKEN: int # Assombrisseur de couleur (moteur de gris)
# Graph 90+E uniquement :
C_RED: int # Rouge pur
C_GREEN: int # Vert pur
C_BLUE: int # Bleu pur
C_RGB(r: int, g: int, b: int) -> int
```
Les couleurs sont toutes des nombres entiers (manipuler des tuples `(r,g,b)` est atrocement lent par comparaison et requiert des allocations mémoire dans tous les sens). Une poignée de couleurs est fournie par défaut.
Sur Graph 90+E, la fonction `C_RGB()` peut être utilisée pour créer des couleurs à partir de trois composantes de valeur 0 à 31.
TODO: Expliquer le moteur de gris.
### Fonctions de dessin basiques
```py
DWIDTH: int
DHEIGHT: int
dupdate() -> None
dclear(color: int) -> None
dpixel(x: int, y: int, color: int) -> None
dgetpixel(x: int, y: int) -> int
```
Les entiers `DWIDTH` et `DHEIGHT` indiquent la taille de l'écran. C'est 128x64 sur les Graph mono (type Graph 35+E II), 396x224 sur la Prizm et Graph 90+E (le plein écran est disponible).
Toutes les fonctions de dessin opèrent sur une image interne appellée "VRAM" ; l'effet du dessin n'est donc pas visible immédiatement à l'écran. Pour que le dessin se voie il faut appeler la fonction `dupdate()` qui transfère les contenus de la VRAM à l'écran réel. Généralement, on fait ça après avoir affiché tout ce dont on a besoin et pas après chaque appel de fonction de dessin.
Dans PythonExtra, la fonction `dupdate()` indique aussi implicitement qu'on « passe en mode graphique ». À cause de certaines optimisations tout appel à `print()` est considéré comme un « passage en mode texte » et pendant qu'on est en mode texte le shell peut redessiner à tout moment. Si on veut dessiner après avoir utilisé le mode texte, il faut appeler `dupdate()` pour forcer un passage en mode graphique avant de commencer à dessiner. Sinon le dessin du shell pourrait interférer avec le dessin du programme.
La fonction `dclear()` remplit l'écran d'une couleur unie.
La fonction `dpixel()` modifie la couleur d'un pixel. Les coordonnées, comme pour toutes les fonctions de dessin, sont (x,y) où `x` varie entre 0 et DWIDTH-1 inclus (0 étant à gauche), et `y` varie entre 0 et DHEIGHT-1 inclus (0 étant en haut).
La fonction `dgetpixel()` renvoie la couleur d'un pixel. Attention, `dgetpixel()` lit dans la VRAM, pas sur l'écran.
_Exemple ([`ex_draw1.py`](../../ports/sh/examples/ex_draw1.py))._
```py
from gint import *
dclear(C_WHITE)
for y in range(10):
for x in range(10):
if (x^y) & 1:
dpixel(x, y, C_BLACK)
dupdate()
```
![](images/modgint-draw1-cg.png) ![](images/modgint-draw1-fx.png)
### Fonctions de dessin de formes géométriques
```py
drect(x1: int, y1: int, x2: int, y2: int, color: int) -> None
drect_border(x1: int, y1: int, x2: int, y2: int, fill_color: int,
border_width: int, border_color: int) -> None
dline(x1: int, y1: int, x2: int, y2: int, color: int) -> None
dhline(y: int, color: int) -> None
dvline(x: int, color: int) -> None
dcircle(x: int, y: int, radius: int, fill_color: int,
border_color: int) -> None
dellipse(x1: int, y1: int, x2: int, y2: int, fill_color: int,
border_color: int) -> None
```
`drect()` dessine un rectangle plein allant de (x1, y1) à (x2, y2) (tous les deux inclus). L'ordre des points ne compte pas, i.e. x1 ≥ x2 ou y1 ≥ y2 est autorisé.
`drect_border()` est similaire mais dessine une bordure de largeur `border_width` et de couleur `border_color`. La bordure est dessinée _à l'intérieur_ du rectangle.
`dline()` dessine une ligne droite entre les points (x1, y1) et (x2, y2). Les raccourcis `dhline()` et `dvline()` dessinent respectivement une ligne horizontale et verticale à travers tout l'écran.
`dcircle()` dessine un cercle défini par son centre et rayon avec l'algorithme de Bresenham. La couleur de l'intérieur et du bord peuvent être spécifiées séparément, y compris avec `C_NONE` (transparente). Par construction, `dcircle()` ne peut construire que des cercles de diamètre impair ; pour les diamètres plus fin, utilisez `dellipse()`.
`dellipse()` dessine une ellipse définie par son rectangle englobant. Les points (x1, y1) et (x2, y2) sont tous les deux inclus dans le rectangle. Pour dessiner une ellipse à partir de son centre (x, y) et de ses demi-grand/petit axes a/b, utilisez `dellipse(x-a, y-b, x+a, y+b, fill_color, border_color)`.
_Exemple ([`ex_draw2.py`](../../ports/sh/examples/ex_draw2.py))._
![](images/modgint-draw2-cg.png) ![](images/modgint-draw2-fx.png)
_Exemple ([`ex_circle.py`](../../ports/sh/examples/ex_circle.py))._
![](images/modgint-circle-cg.png) ![](images/modgint-circle-fx.png)
### Fonctions de dessin d'images
```py
dimage(x: int, y: int, img: image) -> None
dsubimage(x: int, y: int, img: image, left: int, top: int, width: int, height: int) -> None
```
**Sur Graph mono**
```py
image:
.profile -> IMAGE_MONO | ...
.width -> int
.height -> int
.data -> buffer-like
# Constructeur
image(profile: IMAGE_*, width: int, height: int, data: buffer-like) -> image
```
Les images sur Graph mono sont en noir-et-blanc ou 4 couleurs (quand le moteur de gris est utilisé). Chaque image a un champ `.profile` indiquant le format d'image (le nom "profile" est hérité d'anciennes versions de gint), deux champs `.width` et `.height` indiquant sa taille, et un champ `.data` donnant accès aux données brutes.
Les quatre formats disponibles sont les suivants.
| Format | Couleurs | Calques | Nom dans fxconv |
|--------------------|----------------------------------|---------|-----------------|
| `IMAGE_MONO` | Noir/blanc (2) | 1 | `mono` |
| `IMAGE_MONO_ALPHA` | Noir/blanc, transparent (3) | 2 | `mono_alpha` |
| `IMAGE_GRAY` | Niveaux de gris (4) | 2 | `gray` |
| `IMAGE_GRAY_ALPHA` | Niveaux de gris, transparent (5) | 3 | `gray_alpha` |
Le format des données brutes est un peu compliqué. L'image est stockée ligne par ligne de haut en bas ; chaque ligne est représentée de gauche à droite par une série de mots représentant chacun 32 pixels. Chaque mot contient un bit par pixel (sous la forme d'un entier de 4 octets) pour chaque calque.
Le plus simple pour obtenir une image est de générer le code associé avec l'outil fxconv du [fxSDK](https://gitea.planet-casio.com/Lephenixnoir/fxsdk). Les options `--bopti-image-fx --fx` spécifient qu'on convertit une image pour Graph mono et la métadonnée `profile:mono` choisit le format de l'image produite. Le tableau ci-dessus liste la valeur de `profile:` à spécifier pour chaque format. Par exemple pour l'image [`fx_image_7seg.py`](../../ports/sh/examples/fx_image_7seg.png) :
![](../../ports/sh/examples/fx_image_7seg.png)
```bash
% fxconv --bopti-image fx_image_7seg.png -o 7seg.py --fx profile:mono name:seg --py
```
```py
import gint
seg = gint.image(0, 79, 12, b'|\x00||\x00|||||\x00\x00\xba\x02::\x82\xb8\xb8:\xba\xba\x00\x00\xc6\x06\x06\x06\xc6\xc0\xc0\x06\xc6\xc6\x00\x00\xc6\x06\x06\x06\xc6\xc0\xc0\x06\xc6\xc6\x00\x00\x82\x02\x02\x02\x82\x80\x80\x02\x82\x82\x00\x00\x00\x00|||||\x00||\x00\x00\x82\x02\xb8:::\xba\x02\xba:\x00\x00\xc6\x06\xc0\x06\x06\x06\xc6\x06\xc6\x06\x00\x00\xc6\x06\xc0\x06\x06\x06\xc6\x06\xc6\x06\x00\x00\xc6\x06\xc0\x06\x06\x06\xc6\x06\xc6\x06\x00\x00\xba\x02\xb8:\x02:\xba\x02\xba:\x00\x00|\x00||\x00||\x00||\x00\x00')
```
L'option `--py-compact` permet de générer du code beaucoup plus compact (avec moins de `\x`), par contre le fichier obtenu ne peut pas être lu par un éditeur de texte. La seule option simple pour l'utiliser est de l'envoyer sur la calculatrice et l'importer tel quel (on peut aussi le manipuler avec un programme).
La fonction `dimage()` dessine une image à l'écran en positionnant le coin haut gauche de l'image à la position (x, y).
La fonction `dsubimage()` permet de dessiner un sous-rectangle d'une image. Le sous-rectangle commence à la position (left, top) de l'image et s'étend sur une largeur `width` et une hauteur `height`. Le sous-rectangle est dessiné de façon à ce que le pixel (left, top) arrive à la position (x, y) de l'écran.
_Exemple ([`fx_image.py`](../../ports/sh/examples/fx_image.py))._
![](images/modgint-image-fx.png)
**Sur Graph couleur**
```py
image:
.format -> IMAGE_RGB565 | ...
.flags -> int
.color_count -> int
.width -> int
.height -> int
.stride -> int
.data -> buffer-like
.palette -> buffer-like
# Constructeur
image(format: IMAGE_*, color_count: int, width: int, height: int, stride: int, data: buffer-like, palette: buffer-like) -> image
# Constructeurs spécialisés par format
image_rgb565(width: int, height: int, data: buffer-like) -> image
image_rgb565a(width: int, height: int, data: buffer-like) -> image
image_p8_rgb565(width: int, height: int, data: buffer-like, palette: buffer-like) -> image
image_p8_rgb565a(width: int, height: int, data: buffer-like, palette: buffer-like) -> image
image_p4_rgb565(width: int, height: int, data: buffer-like, palette: buffer-like) -> image
image_p4_rgb565a(width: int, height: int, data: buffer-like, palette: buffer-like) -> image
```
Les images sur Graph couleur sont déclinées en différents formats indiqués par le champ `.format`, dont les valeurs possibles sont listées ci-dessous. Les différences sont dans le nombre de couleurs, la présence ou pas de transparence, et la présence ou pas d'une palette de couleurs. Bien sûr, moins il y a de couleurs moins l'image prend de place en mémoire, donc de façon générale il est très bénéfique d'utiliser le plus petit format possible pour chaque image.
| Format | Couleurs | Palette | Nom dans fxconv |
|--------------------|---------------------|-------------|-----------------|
| `IMAGE_RGB565` | 65536 | Non | `rgb565` |
| `IMAGE_RGB565A` | 65535 + transparent | Non | `rgb565a` |
| `IMAGE_P8_RGB565` | 256 | Oui (1-256) | `p8_rgb565` |
| `IMAGE_P8_RGB565A` | 255 + transparent | Oui (1-256) | `p8_rgb565a` |
| `IMAGE_P4_RGB565` | 16 | Oui (16) | `p4_rgb565` |
| `IMAGE_P4_RGB565A` | 15 + transparent | Oui (16) | `p4_rgb565a` |
Le champ `.color_count` indique le nombre de couleurs dans la palette quand il y en a une. Pour les formats P8 ce nombre varie entre 1 et 256, pour les formats P4 il est toujours égal à 16. Les deux champs `.width` et `.height` indiquent la taille de l'image. Enfin, les champs `.data` et `.palette` permettent d'accéder aux données brutes des pixels ainsi que de la palette.
(Le champ `.flags` est un détail de gestion de mémoire qui ne devrait pas importer aux scripts Python. Le champ `.stride` indique combien d'octets séparent chaque ligne de pixels dans `.data` et sera de même rarement utilisé.)
Les fonctions `dimage()` et `dsubimage()` ont le même fonctionnement que pour les Graph mono ; voir ci-dessus.
Comme pour Graph mono les images peuvent être converties avec fxconv. Par exemple pour l'image [`cg_image_puzzle.png`](../../ports/sh/examples/cg_image_puzzle.png) (code abrégé) :
![](../../ports/sh/examples/cg_image_puzzle.png)
```bash
% fxconv --bopti-image cg_image_puzzle.png -o puzzle.py --cg profile:p4_rgb565 name:puzzle --py
```
```py
import gint
puzzle = gint.image(6, 16, 64, 32, 32,
b'\xbb\xbb\xbb\xbb\xbb ... \xdd\xdd\xdd\xdd\xdd\xdd\xdd',
b'\xff\xff\xcfW\x86\xd8\xbe|\xceP\xe5\x8a\x963f9u\x9c}\xa8\x9dxD\xfa\x83\xceLNZ\xcci\xa7')
```
L'option `--py-compact` est recommandée pour réduire la taille du code ; voir les détails dans la section Graph mono.
_Exemple ([`cg_image.py`](../../ports/sh/examples/cg_image.py))._
![](images/modgint-image-cg.png)
## Différences avec l'API C de gint
- `dsubimage()` n'a pas de paramètre `int flags`. Les flags en question ne ont que des optimisations mineures et pourraient disparaître dans une version future de gint.
- Les constructeurs d'image `image()` et `image_<format>()` n'existent pas dans l'API C.
- Les timeouts asynchrones à base d'entiers volatiles sont remplacés par des timeouts synchrones avec des durées optionnelles en millisecondes (entier ou `None`).
TODO : Il y en a d'autres.

View File

@ -49,7 +49,7 @@ extern uint8_t mp_bluetooth_hci_cmd_buf[4 + 256];
#include "uart.h"
// Provided by the port.
extern pyb_uart_obj_t mp_bluetooth_hci_uart_obj;
extern machine_uart_obj_t mp_bluetooth_hci_uart_obj;
STATIC void cywbt_wait_cts_low(void) {
mp_hal_pin_config(CYW43_PIN_BT_CTS, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_UP, 0);
@ -68,7 +68,7 @@ STATIC int cywbt_hci_cmd_raw(size_t len, uint8_t *buf) {
mp_bluetooth_hci_uart_write((void *)buf, len);
for (int c, i = 0; i < 6; ++i) {
while ((c = mp_bluetooth_hci_uart_readchar()) == -1) {
MICROPY_EVENT_POLL_HOOK
mp_event_wait_indefinite();
}
buf[i] = c;
}
@ -88,7 +88,7 @@ STATIC int cywbt_hci_cmd_raw(size_t len, uint8_t *buf) {
int sz = buf[2] - 3;
for (int c, i = 0; i < sz; ++i) {
while ((c = mp_bluetooth_hci_uart_readchar()) == -1) {
MICROPY_EVENT_POLL_HOOK
mp_event_wait_indefinite();
}
buf[i] = c;
}

View File

@ -29,7 +29,7 @@
#include "py/runtime.h"
#include "py/mperrno.h"
#include "py/mphal.h"
#include "extmod/machine_pulse.h"
#include "extmod/modmachine.h"
#include "drivers/dht/dht.h"
// Allow the open-drain-high call to be DHT specific for ports that need it

View File

@ -34,9 +34,7 @@
#include <string.h>
#include "py/runtime.h"
#include "modmachine.h"
#include "extmod/machine_spi.h"
#include "mpconfigboard.h"
#include "extmod/modmachine.h"
#ifdef MICROPY_HW_WIFI_LED
#include "led.h"
#endif

View File

@ -42,9 +42,13 @@
#define NINA_GPIO_MODE (0x50)
#define NINA_GPIO_READ (0x53)
#define NINA_GPIO_READ_ANALOG (0x54)
#define NINA_GPIO_WRITE (0x51)
#define NINA_GPIO_IS_INPUT_ONLY(p) ((p >= 34 && p <= 36) || (p == 39))
#define NINA_GPIO_IS_INPUT_ONLY(p) ((p >= 3 && p <= 6))
#define NINA_GPIO_IS_ADC_CHANNEL(p) ((p >= 3 && p <= 6))
// This maps logical pin ID (0..MICROPY_HW_PIN_EXT_COUNT) to
// physical pins on the Nina module.
static uint8_t pin_map[MICROPY_HW_PIN_EXT_COUNT] = {
27, // LEDR
25, // LEDG
@ -55,10 +59,30 @@ static uint8_t pin_map[MICROPY_HW_PIN_EXT_COUNT] = {
35, // A7
};
// This maps logical pin ID (0..MICROPY_HW_PIN_EXT_COUNT) to
// ADC channel numbers on the Nina module.
static uint8_t adc_map[MICROPY_HW_PIN_EXT_COUNT] = {
-1, // LEDR
-1, // LEDG
-1, // LEDB
6, // A4
3, // A5
0, // A6
7, // A7
};
void machine_pin_ext_init(void) {
nina_init();
}
bool machine_pin_ext_is_adc_channel(const machine_pin_obj_t *self) {
return NINA_GPIO_IS_ADC_CHANNEL(self->id);
}
uint32_t machine_pin_ext_to_adc_channel(const machine_pin_obj_t *self) {
return adc_map[self->id];
}
void machine_pin_ext_set(machine_pin_obj_t *self, bool value) {
if (self->id >= 0 && self->id < MICROPY_HW_PIN_EXT_COUNT) {
uint8_t buf[] = {pin_map[self->id], value};
@ -76,8 +100,14 @@ bool machine_pin_ext_get(machine_pin_obj_t *self) {
return value;
}
uint16_t machine_pin_ext_read_u16(uint32_t channel) {
uint16_t buf = channel;
nina_ioctl(NINA_GPIO_READ_ANALOG, sizeof(buf), (uint8_t *)&buf, 0);
return buf;
}
void machine_pin_ext_config(machine_pin_obj_t *self, int mode, int value) {
if (mode == MACHINE_PIN_MODE_IN) {
if (mode == MACHINE_PIN_MODE_IN || mode == MACHINE_PIN_MODE_ANALOG) {
mode = NINA_GPIO_INPUT;
self->is_output = false;
} else if (mode == MACHINE_PIN_MODE_OUT) {
@ -89,7 +119,7 @@ void machine_pin_ext_config(machine_pin_obj_t *self, int mode, int value) {
if (self->id >= 0 && self->id < MICROPY_HW_PIN_EXT_COUNT) {
uint8_t buf[] = {pin_map[self->id], mode};
if (mode == NINA_GPIO_OUTPUT) {
if (NINA_GPIO_IS_INPUT_ONLY(buf[0])) {
if (NINA_GPIO_IS_INPUT_ONLY(self->id)) {
mp_raise_ValueError("only Pin.IN is supported for this pin");
}
machine_pin_ext_set(self, value);

View File

@ -75,12 +75,13 @@ static int nina_hci_cmd(int ogf, int ocf, size_t param_len, const uint8_t *param
// Receive HCI event packet, initially reading 3 bytes (HCI Event, Event code, Plen).
for (mp_uint_t start = mp_hal_ticks_ms(), size = 3, i = 0; i < size;) {
while (!mp_bluetooth_hci_uart_any()) {
MICROPY_EVENT_POLL_HOOK
mp_uint_t elapsed = mp_hal_ticks_ms() - start;
// Timeout.
if ((mp_hal_ticks_ms() - start) > HCI_COMMAND_TIMEOUT) {
if (elapsed > HCI_COMMAND_TIMEOUT) {
error_printf("timeout waiting for HCI packet\n");
return -1;
}
mp_event_wait_ms(HCI_COMMAND_TIMEOUT - elapsed);
}
buf[i] = mp_bluetooth_hci_uart_readchar();

View File

@ -35,9 +35,7 @@
#include <string.h>
#include "py/runtime.h"
#include "modmachine.h"
#include "extmod/machine_spi.h"
#include "mpconfigboard.h"
#include "extmod/modmachine.h"
#include "nina_bsp.h"
#include "nina_wifi_drv.h"

View File

@ -684,6 +684,14 @@ int nina_ioctl(uint32_t cmd, size_t len, uint8_t *buf, uint32_t iface) {
return -1;
}
break;
case NINA_CMD_GET_ANALOG_READ: {
if (len != 2 || nina_send_command_read_vals(NINA_CMD_GET_ANALOG_READ,
1, ARG_8BITS, NINA_ARGS(ARG_BYTE(buf[0])),
1, ARG_8BITS, NINA_VALS({(uint16_t *)&len, buf})) != 0) {
return -1;
}
break;
}
default:
return 0;
}

View File

@ -36,7 +36,6 @@ mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *a
MP_OBJ_TYPE_SET_SLOT(&mp_type_framebuf, locals_dict, (void*)&framebuf_locals_dict, 2);
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));

View File

@ -1,60 +0,0 @@
# Print a nice list of pins, their current settings, and available afs.
# Requires pins_af.py from ports/stm32/build-PYBV10/ directory.
import pyb
import pins_af
def af():
max_name_width = 0
max_af_width = 0
for pin_entry in pins_af.PINS_AF:
max_name_width = max(max_name_width, len(pin_entry[0]))
for af_entry in pin_entry[1:]:
max_af_width = max(max_af_width, len(af_entry[1]))
for pin_entry in pins_af.PINS_AF:
pin_name = pin_entry[0]
print("%-*s " % (max_name_width, pin_name), end="")
for af_entry in pin_entry[1:]:
print("%2d: %-*s " % (af_entry[0], max_af_width, af_entry[1]), end="")
print("")
def pins():
mode_str = {
pyb.Pin.IN: "IN",
pyb.Pin.OUT_PP: "OUT_PP",
pyb.Pin.OUT_OD: "OUT_OD",
pyb.Pin.AF_PP: "AF_PP",
pyb.Pin.AF_OD: "AF_OD",
pyb.Pin.ANALOG: "ANALOG",
}
pull_str = {pyb.Pin.PULL_NONE: "", pyb.Pin.PULL_UP: "PULL_UP", pyb.Pin.PULL_DOWN: "PULL_DOWN"}
width = [0, 0, 0, 0]
rows = []
for pin_entry in pins_af.PINS_AF:
row = []
pin_name = pin_entry[0]
pin = pyb.Pin(pin_name)
pin_mode = pin.mode()
row.append(pin_name)
row.append(mode_str[pin_mode])
row.append(pull_str[pin.pull()])
if pin_mode == pyb.Pin.AF_PP or pin_mode == pyb.Pin.AF_OD:
pin_af = pin.af()
for af_entry in pin_entry[1:]:
if pin_af == af_entry[0]:
af_str = "%d: %s" % (pin_af, af_entry[1])
break
else:
af_str = "%d" % pin_af
else:
af_str = ""
row.append(af_str)
for col in range(len(width)):
width[col] = max(width[col], len(row[col]))
rows.append(row)
for row in rows:
for col in range(len(width)):
print("%-*s " % (width[col], row[col]), end="")
print("")

View File

@ -1,9 +1,16 @@
extern "C" {
#include <examplemodule.h>
#include <py/objstr.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) {
// The following no-ops are just here to verify the static assertions used in
// the public API all compile with C++.
MP_STATIC_ASSERT_STR_ARRAY_COMPATIBLE;
if (mp_obj_is_type(a_obj, &mp_type_BaseException)) {
}
// 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);

View File

@ -272,9 +272,9 @@ class Loop:
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"])
print(context["message"], file=sys.stderr)
print("future:", context["future"], "coro=", context["future"].coro, file=sys.stderr)
sys.print_exception(context["exception"], sys.stderr)
def call_exception_handler(context):
(Loop._exc_handler or Loop.default_exception_handler)(Loop, context)

View File

@ -13,12 +13,6 @@ class Stream:
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
@ -63,6 +57,8 @@ class Stream:
while True:
yield core._io_queue.queue_read(self.s)
l2 = self.s.readline() # may do multiple reads but won't block
if l2 is None:
continue
l += l2
if not l2 or l[-1] == 10: # \n (check l in case l2 is str)
return l
@ -100,19 +96,29 @@ StreamWriter = Stream
# Create a TCP stream connection to a remote host
#
# async
def open_connection(host, port):
def open_connection(host, port, ssl=None, server_hostname=None):
from errno import EINPROGRESS
import 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
# wrap with SSL, if requested
if ssl:
if ssl is True:
import ssl as _ssl
ssl = _ssl.SSLContext(_ssl.PROTOCOL_TLS_CLIENT)
if not server_hostname:
server_hostname = host
s = ssl.wrap_socket(s, server_hostname=server_hostname, do_handshake_on_connect=False)
s.setblocking(False)
ss = Stream(s)
yield core._io_queue.queue_write(s)
return ss, ss
@ -135,7 +141,7 @@ class Server:
async def wait_closed(self):
await self.task
async def _serve(self, s, cb):
async def _serve(self, s, cb, ssl):
self.state = False
# Accept incoming connections
while True:
@ -156,6 +162,13 @@ class Server:
except:
# Ignore a failed accept
continue
if ssl:
try:
s2 = ssl.wrap_socket(s2, server_side=True, do_handshake_on_connect=False)
except OSError as e:
core.sys.print_exception(e)
s2.close()
continue
s2.setblocking(False)
s2s = Stream(s2, {"peername": addr})
core.create_task(cb(s2s, s2s))
@ -163,7 +176,7 @@ class Server:
# 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):
async def start_server(cb, host, port, backlog=5, ssl=None):
import socket
# Create and bind server socket.
@ -176,7 +189,7 @@ async def start_server(cb, host, port, backlog=5):
# Create and return server object and task.
srv = Server()
srv.task = core.create_task(srv._serve(s, cb))
srv.task = core.create_task(srv._serve(s, cb, ssl))
try:
# Ensure that the _serve task has been scheduled so that it gets to
# handle cancellation.

View File

@ -552,7 +552,7 @@ STATIC void set_random_address(void) {
volatile bool ready = false;
btstack_crypto_random_generate(&sm_crypto_random_request, static_addr, 6, &btstack_static_address_ready, (void *)&ready);
while (!ready) {
MICROPY_EVENT_POLL_HOOK
mp_event_wait_indefinite();
}
#endif // MICROPY_BLUETOOTH_USE_MP_HAL_GET_MAC_STATIC_ADDRESS
@ -574,7 +574,7 @@ STATIC void set_random_address(void) {
break;
}
MICROPY_EVENT_POLL_HOOK
mp_event_wait_indefinite();
}
DEBUG_printf("set_random_address: Address loaded by controller\n");
}
@ -654,7 +654,7 @@ int mp_bluetooth_init(void) {
// Either the HCI event will set state to ACTIVE, or the timeout will set it to TIMEOUT.
mp_bluetooth_btstack_port_start();
while (mp_bluetooth_btstack_state == MP_BLUETOOTH_BTSTACK_STATE_STARTING) {
MICROPY_EVENT_POLL_HOOK
mp_event_wait_indefinite();
}
btstack_run_loop_remove_timer(&btstack_init_deinit_timeout);
@ -727,7 +727,7 @@ void mp_bluetooth_deinit(void) {
// either timeout or clean shutdown.
mp_bluetooth_btstack_port_deinit();
while (mp_bluetooth_btstack_state == MP_BLUETOOTH_BTSTACK_STATE_ACTIVE) {
MICROPY_EVENT_POLL_HOOK
mp_event_wait_indefinite();
}
btstack_run_loop_remove_timer(&btstack_init_deinit_timeout);

View File

@ -7,16 +7,22 @@ set(MICROPY_SOURCE_EXTMOD
${MICROPY_DIR}/shared/libc/abort_.c
${MICROPY_DIR}/shared/libc/printf.c
${MICROPY_EXTMOD_DIR}/btstack/modbluetooth_btstack.c
${MICROPY_EXTMOD_DIR}/machine_adc.c
${MICROPY_EXTMOD_DIR}/machine_adc_block.c
${MICROPY_EXTMOD_DIR}/machine_bitstream.c
${MICROPY_EXTMOD_DIR}/machine_i2c.c
${MICROPY_EXTMOD_DIR}/machine_i2s.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}/machine_uart.c
${MICROPY_EXTMOD_DIR}/machine_wdt.c
${MICROPY_EXTMOD_DIR}/modbluetooth.c
${MICROPY_EXTMOD_DIR}/modframebuf.c
${MICROPY_EXTMOD_DIR}/modlwip.c
${MICROPY_EXTMOD_DIR}/modmachine.c
${MICROPY_EXTMOD_DIR}/modnetwork.c
${MICROPY_EXTMOD_DIR}/modonewire.c
${MICROPY_EXTMOD_DIR}/modasyncio.c
@ -56,6 +62,41 @@ set(MICROPY_SOURCE_EXTMOD
${MICROPY_EXTMOD_DIR}/nimble/modbluetooth_nimble.c
)
# Single-precision libm math library.
set(MICROPY_SOURCE_LIB_LIBM
${MICROPY_DIR}/lib/libm/acoshf.c
${MICROPY_DIR}/lib/libm/asinfacosf.c
${MICROPY_DIR}/lib/libm/asinhf.c
${MICROPY_DIR}/lib/libm/atan2f.c
${MICROPY_DIR}/lib/libm/atanf.c
${MICROPY_DIR}/lib/libm/atanhf.c
${MICROPY_DIR}/lib/libm/ef_rem_pio2.c
${MICROPY_DIR}/lib/libm/erf_lgamma.c
${MICROPY_DIR}/lib/libm/fmodf.c
${MICROPY_DIR}/lib/libm/kf_cos.c
${MICROPY_DIR}/lib/libm/kf_rem_pio2.c
${MICROPY_DIR}/lib/libm/kf_sin.c
${MICROPY_DIR}/lib/libm/kf_tan.c
${MICROPY_DIR}/lib/libm/log1pf.c
${MICROPY_DIR}/lib/libm/math.c
${MICROPY_DIR}/lib/libm/nearbyintf.c
${MICROPY_DIR}/lib/libm/roundf.c
${MICROPY_DIR}/lib/libm/sf_cos.c
${MICROPY_DIR}/lib/libm/sf_erf.c
${MICROPY_DIR}/lib/libm/sf_frexp.c
${MICROPY_DIR}/lib/libm/sf_ldexp.c
${MICROPY_DIR}/lib/libm/sf_modf.c
${MICROPY_DIR}/lib/libm/sf_sin.c
${MICROPY_DIR}/lib/libm/sf_tan.c
${MICROPY_DIR}/lib/libm/wf_lgamma.c
${MICROPY_DIR}/lib/libm/wf_tgamma.c
)
# Choose only one of these sqrt implementations, software or hardware.
set(MICROPY_SOURCE_LIB_LIBM_SQRT_SW ${MICROPY_DIR}/lib/libm/ef_sqrt.c)
set(MICROPY_SOURCE_LIB_LIBM_SQRT_HW ${MICROPY_DIR}/lib/libm/thumb_vfp_sqrtf.c)
# Library for btree module and associated code
if(MICROPY_PY_BTREE)

View File

@ -2,8 +2,11 @@
# and provides rules to build 3rd-party components for extmod modules.
SRC_EXTMOD_C += \
extmod/machine_adc.c \
extmod/machine_adc_block.c \
extmod/machine_bitstream.c \
extmod/machine_i2c.c \
extmod/machine_i2s.c \
extmod/machine_mem.c \
extmod/machine_pinbase.c \
extmod/machine_pulse.c \
@ -11,6 +14,8 @@ SRC_EXTMOD_C += \
extmod/machine_signal.c \
extmod/machine_spi.c \
extmod/machine_timer.c \
extmod/machine_uart.c \
extmod/machine_wdt.c \
extmod/modasyncio.c \
extmod/modbinascii.c \
extmod/modbluetooth.c \
@ -22,6 +27,7 @@ SRC_EXTMOD_C += \
extmod/modheapq.c \
extmod/modjson.c \
extmod/modlwip.c \
extmod/modmachine.c \
extmod/modnetwork.c \
extmod/modonewire.c \
extmod/modos.c \
@ -64,6 +70,96 @@ SRC_QSTR += $(SRC_EXTMOD_C)
CFLAGS += $(CFLAGS_EXTMOD) $(CFLAGS_THIRDPARTY)
LDFLAGS += $(LDFLAGS_EXTMOD) $(LDFLAGS_THIRDPARTY)
################################################################################
# libm/libm_dbl math library
# Single-precision math library.
SRC_LIB_LIBM_C += $(addprefix lib/libm/,\
acoshf.c \
asinfacosf.c \
asinhf.c \
atan2f.c \
atanf.c \
atanhf.c \
ef_rem_pio2.c \
erf_lgamma.c \
fmodf.c \
kf_cos.c \
kf_rem_pio2.c \
kf_sin.c \
kf_tan.c \
log1pf.c \
math.c \
nearbyintf.c \
roundf.c \
sf_cos.c \
sf_erf.c \
sf_frexp.c \
sf_ldexp.c \
sf_modf.c \
sf_sin.c \
sf_tan.c \
wf_lgamma.c \
wf_tgamma.c \
)
# Choose only one of these sqrt implementations, software or hardware.
SRC_LIB_LIBM_SQRT_SW_C += lib/libm/ef_sqrt.c
SRC_LIB_LIBM_SQRT_HW_C += lib/libm/thumb_vfp_sqrtf.c
# Double-precision math library.
SRC_LIB_LIBM_DBL_C += $(addprefix lib/libm_dbl/,\
__cos.c \
__expo2.c \
__fpclassify.c \
__rem_pio2.c \
__rem_pio2_large.c \
__signbit.c \
__sin.c \
__tan.c \
acos.c \
acosh.c \
asin.c \
asinh.c \
atan.c \
atan2.c \
atanh.c \
ceil.c \
cos.c \
cosh.c \
copysign.c \
erf.c \
exp.c \
expm1.c \
floor.c \
fmod.c \
frexp.c \
ldexp.c \
lgamma.c \
log.c \
log10.c \
log1p.c \
modf.c \
nearbyint.c \
pow.c \
rint.c \
round.c \
scalbn.c \
sin.c \
sinh.c \
tan.c \
tanh.c \
tgamma.c \
trunc.c \
)
# Choose only one of these sqrt implementations, software or hardware.
SRC_LIB_LIBM_DBL_SQRT_SW_C += lib/libm_dbl/sqrt.c
SRC_LIB_LIBM_DBL_SQRT_HW_C += lib/libm_dbl/thumb_vfp_sqrt.c
# Too many warnings in libm_dbl, disable for now.
$(BUILD)/lib/libm_dbl/%.o: CFLAGS += -Wno-double-promotion -Wno-float-conversion
################################################################################
# VFS FAT FS
@ -102,7 +198,7 @@ SRC_THIRDPARTY_C += $(addprefix $(LITTLEFS_DIR)/,\
lfs2_util.c \
)
$(BUILD)/$(LITTLEFS_DIR)/lfs2.o: CFLAGS += -Wno-missing-field-initializers
$(BUILD)/$(LITTLEFS_DIR)/lfs2.o: CFLAGS += -Wno-shadow
endif
################################################################################
@ -262,6 +358,9 @@ SRC_THIRDPARTY_C += $(addprefix $(LWIP_DIR)/,\
core/ipv6/nd6.c \
netif/ethernet.c \
)
ifeq ($(MICROPY_PY_LWIP_LOOPBACK),1)
CFLAGS_EXTMOD += -DLWIP_NETIF_LOOPBACK=1
endif
ifeq ($(MICROPY_PY_LWIP_SLIP),1)
CFLAGS_EXTMOD += -DMICROPY_PY_LWIP_SLIP=1
SRC_THIRDPARTY_C += $(LWIP_DIR)/netif/slipif.c

183
extmod/machine_adc.c Normal file
View File

@ -0,0 +1,183 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2023 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"
#if MICROPY_PY_MACHINE_ADC
#include "extmod/modmachine.h"
// The port must provide implementations of these low-level ADC functions.
STATIC void mp_machine_adc_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind);
STATIC mp_obj_t mp_machine_adc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args);
STATIC mp_int_t mp_machine_adc_read_u16(machine_adc_obj_t *self);
#if MICROPY_PY_MACHINE_ADC_INIT
STATIC void mp_machine_adc_init_helper(machine_adc_obj_t *self, size_t n_pos_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
#endif
#if MICROPY_PY_MACHINE_ADC_DEINIT
STATIC void mp_machine_adc_deinit(machine_adc_obj_t *self);
#endif
#if MICROPY_PY_MACHINE_ADC_BLOCK
STATIC mp_obj_t mp_machine_adc_block(machine_adc_obj_t *self);
#endif
#if MICROPY_PY_MACHINE_ADC_READ_UV
STATIC mp_int_t mp_machine_adc_read_uv(machine_adc_obj_t *self);
#endif
#if MICROPY_PY_MACHINE_ADC_ATTEN_WIDTH
STATIC void mp_machine_adc_atten_set(machine_adc_obj_t *self, mp_int_t atten);
STATIC void mp_machine_adc_width_set(machine_adc_obj_t *self, mp_int_t width);
#endif
#if MICROPY_PY_MACHINE_ADC_READ
STATIC mp_int_t mp_machine_adc_read(machine_adc_obj_t *self);
#endif
// The port provides implementations of the above in this file.
#include MICROPY_PY_MACHINE_ADC_INCLUDEFILE
#if MICROPY_PY_MACHINE_ADC_INIT
// ADC.init(...)
STATIC mp_obj_t machine_adc_init(size_t n_pos_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
machine_adc_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
mp_machine_adc_init_helper(self, n_pos_args - 1, pos_args + 1, kw_args);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_adc_init_obj, 1, machine_adc_init);
#endif
#if MICROPY_PY_MACHINE_ADC_DEINIT
// ADC.deinit()
STATIC mp_obj_t machine_adc_deinit(mp_obj_t self_in) {
machine_adc_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_machine_adc_deinit(self);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_adc_deinit_obj, machine_adc_deinit);
#endif
#if MICROPY_PY_MACHINE_ADC_BLOCK
// ADC.block()
STATIC mp_obj_t machine_adc_block(mp_obj_t self_in) {
machine_adc_obj_t *self = MP_OBJ_TO_PTR(self_in);
return mp_machine_adc_block(self);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_adc_block_obj, machine_adc_block);
#endif
// ADC.read_u16()
STATIC mp_obj_t machine_adc_read_u16(mp_obj_t self_in) {
machine_adc_obj_t *self = MP_OBJ_TO_PTR(self_in);
return MP_OBJ_NEW_SMALL_INT(mp_machine_adc_read_u16(self));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_adc_read_u16_obj, machine_adc_read_u16);
#if MICROPY_PY_MACHINE_ADC_READ_UV
// ADC.read_uv()
STATIC mp_obj_t machine_adc_read_uv(mp_obj_t self_in) {
machine_adc_obj_t *self = MP_OBJ_TO_PTR(self_in);
return MP_OBJ_NEW_SMALL_INT(mp_machine_adc_read_uv(self));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_adc_read_uv_obj, machine_adc_read_uv);
#endif
#if MICROPY_PY_MACHINE_ADC_ATTEN_WIDTH
// ADC.atten(value) -- this is a legacy method.
STATIC mp_obj_t machine_adc_atten(mp_obj_t self_in, mp_obj_t atten_in) {
machine_adc_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_int_t atten = mp_obj_get_int(atten_in);
mp_machine_adc_atten_set(self, atten);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_adc_atten_obj, machine_adc_atten);
// ADC.width(value) -- this is a legacy method.
STATIC mp_obj_t machine_adc_width(mp_obj_t self_in, mp_obj_t width_in) {
machine_adc_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_int_t width = mp_obj_get_int(width_in);
mp_machine_adc_width_set(self, width);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_adc_width_obj, machine_adc_width);
#endif
#if MICROPY_PY_MACHINE_ADC_READ
// ADC.read() -- this is a legacy method.
STATIC mp_obj_t machine_adc_read(mp_obj_t self_in) {
machine_adc_obj_t *self = MP_OBJ_TO_PTR(self_in);
return MP_OBJ_NEW_SMALL_INT(mp_machine_adc_read(self));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_adc_read_obj, machine_adc_read);
#endif
STATIC const mp_rom_map_elem_t machine_adc_locals_dict_table[] = {
#if MICROPY_PY_MACHINE_ADC_INIT
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_adc_init_obj) },
#endif
#if MICROPY_PY_MACHINE_ADC_DEINIT
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_adc_deinit_obj) },
#endif
#if MICROPY_PY_MACHINE_ADC_BLOCK
{ MP_ROM_QSTR(MP_QSTR_block), MP_ROM_PTR(&machine_adc_block_obj) },
#endif
{ MP_ROM_QSTR(MP_QSTR_read_u16), MP_ROM_PTR(&machine_adc_read_u16_obj) },
#if MICROPY_PY_MACHINE_ADC_READ_UV
{ MP_ROM_QSTR(MP_QSTR_read_uv), MP_ROM_PTR(&machine_adc_read_uv_obj) },
#endif
// Legacy methods.
#if MICROPY_PY_MACHINE_ADC_ATTEN_WIDTH
{ MP_ROM_QSTR(MP_QSTR_atten), MP_ROM_PTR(&machine_adc_atten_obj) },
{ MP_ROM_QSTR(MP_QSTR_width), MP_ROM_PTR(&machine_adc_width_obj) },
#endif
#if MICROPY_PY_MACHINE_ADC_READ
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&machine_adc_read_obj) },
#endif
// A port must add ADC class constants defining the following macro.
// It can be defined to nothing if there are no constants.
MICROPY_PY_MACHINE_ADC_CLASS_CONSTANTS
};
STATIC MP_DEFINE_CONST_DICT(machine_adc_locals_dict, machine_adc_locals_dict_table);
MP_DEFINE_CONST_OBJ_TYPE(
machine_adc_type,
MP_QSTR_ADC,
MP_TYPE_FLAG_NONE,
make_new, mp_machine_adc_make_new,
print, mp_machine_adc_print,
locals_dict, &machine_adc_locals_dict
);
#endif // MICROPY_PY_MACHINE_ADC

128
extmod/machine_adc_block.c Normal file
View File

@ -0,0 +1,128 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Jonathan Hogg
* Copyright (c) 2023 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"
#if MICROPY_PY_MACHINE_ADC_BLOCK
#include "py/mphal.h"
#include "extmod/modmachine.h"
// The port must provide implementations of these low-level ADCBlock functions.
STATIC void mp_machine_adc_block_print(const mp_print_t *print, machine_adc_block_obj_t *self);
STATIC machine_adc_block_obj_t *mp_machine_adc_block_get(mp_int_t unit);
STATIC void mp_machine_adc_block_bits_set(machine_adc_block_obj_t *self, mp_int_t bits);
STATIC machine_adc_obj_t *mp_machine_adc_block_connect(machine_adc_block_obj_t *self, mp_int_t channel_id, mp_hal_pin_obj_t pin, mp_map_t *kw_args);
// The port provides implementations of the above in this file.
#include MICROPY_PY_MACHINE_ADC_BLOCK_INCLUDEFILE
STATIC void machine_adc_block_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
machine_adc_block_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_machine_adc_block_print(print, self);
}
STATIC void machine_adc_block_init_helper(machine_adc_block_obj_t *self, size_t n_pos_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum {
ARG_bits,
};
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_pos_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
mp_int_t bits = args[ARG_bits].u_int;
mp_machine_adc_block_bits_set(self, bits);
}
STATIC mp_obj_t machine_adc_block_make_new(const mp_obj_type_t *type, size_t n_pos_args, size_t n_kw_args, const mp_obj_t *args) {
mp_arg_check_num(n_pos_args, n_kw_args, 1, MP_OBJ_FUN_ARGS_MAX, true);
mp_int_t unit = mp_obj_get_int(args[0]);
machine_adc_block_obj_t *self = mp_machine_adc_block_get(unit);
if (self == NULL) {
mp_raise_ValueError(MP_ERROR_TEXT("invalid block id"));
}
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw_args, args + n_pos_args);
machine_adc_block_init_helper(self, n_pos_args - 1, args + 1, &kw_args);
return MP_OBJ_FROM_PTR(self);
}
STATIC mp_obj_t machine_adc_block_init(size_t n_pos_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
machine_adc_block_obj_t *self = pos_args[0];
machine_adc_block_init_helper(self, n_pos_args - 1, pos_args + 1, kw_args);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_adc_block_init_obj, 1, machine_adc_block_init);
STATIC mp_obj_t machine_adc_block_connect(size_t n_pos_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
machine_adc_block_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
mp_int_t channel_id = -1;
mp_hal_pin_obj_t pin = -1;
if (n_pos_args == 2) {
if (mp_obj_is_int(pos_args[1])) {
channel_id = mp_obj_get_int(pos_args[1]);
} else {
pin = mp_hal_get_pin_obj(pos_args[1]);
}
} else if (n_pos_args == 3) {
channel_id = mp_obj_get_int(pos_args[1]);
pin = mp_hal_get_pin_obj(pos_args[2]);
} else {
mp_raise_TypeError(MP_ERROR_TEXT("too many positional args"));
}
machine_adc_obj_t *adc = mp_machine_adc_block_connect(self, channel_id, pin, kw_args);
if (adc == NULL) {
mp_raise_ValueError(MP_ERROR_TEXT("no matching ADC"));
}
return MP_OBJ_FROM_PTR(adc);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_adc_block_connect_obj, 2, machine_adc_block_connect);
STATIC const mp_rom_map_elem_t machine_adc_block_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_adc_block_init_obj) },
{ MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&machine_adc_block_connect_obj) },
};
STATIC MP_DEFINE_CONST_DICT(machine_adc_block_locals_dict, machine_adc_block_locals_dict_table);
MP_DEFINE_CONST_OBJ_TYPE(
machine_adc_block_type,
MP_QSTR_ADCBlock,
MP_TYPE_FLAG_NONE,
make_new, machine_adc_block_make_new,
print, machine_adc_block_print,
locals_dict, &machine_adc_block_locals_dict
);
#endif // MICROPY_PY_MACHINE_ADC_BLOCK

View File

@ -27,7 +27,7 @@
#include "py/runtime.h"
#include "py/mphal.h"
#include "extmod/machine_bitstream.h"
#include "extmod/modmachine.h"
#if MICROPY_PY_MACHINE_BITSTREAM

View File

@ -1,37 +0,0 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Jim Mussared
* Copyright (c) 2021 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_EXTMOD_MACHINE_BITSTREAM_H
#define MICROPY_INCLUDED_EXTMOD_MACHINE_BITSTREAM_H
#include "py/obj.h"
#include "py/mphal.h"
void machine_bitstream_high_low(mp_hal_pin_obj_t pin, uint32_t *timing_ns, const uint8_t *buf, size_t len);
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(machine_bitstream_obj);
#endif // MICROPY_INCLUDED_EXTMOD_MACHINE_BITSTREAM_H

View File

@ -31,7 +31,7 @@
#include "py/mperrno.h"
#include "py/mphal.h"
#include "py/runtime.h"
#include "extmod/machine_i2c.h"
#include "extmod/modmachine.h"
#define SOFT_I2C_DEFAULT_TIMEOUT_US (50000) // 50ms
@ -328,9 +328,10 @@ STATIC mp_obj_t machine_i2c_scan(mp_obj_t self_in) {
if (ret == 0) {
mp_obj_list_append(list, MP_OBJ_NEW_SMALL_INT(addr));
}
#ifdef MICROPY_EVENT_POLL_HOOK
MICROPY_EVENT_POLL_HOOK
#endif
// This scan loop may run for some time, so process any pending events/exceptions,
// or allow the port to run any necessary background tasks. But do it as fast as
// possible, in particular we are not waiting on any events.
mp_event_handle_nowait();
}
return list;
}

View File

@ -1,90 +0,0 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2016 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_EXTMOD_MACHINE_I2C_H
#define MICROPY_INCLUDED_EXTMOD_MACHINE_I2C_H
#include "py/obj.h"
#include "py/mphal.h"
// Temporary support for legacy construction of SoftI2C via I2C type.
#define MP_MACHINE_I2C_CHECK_FOR_LEGACY_SOFTI2C_CONSTRUCTION(n_args, n_kw, all_args) \
do { \
if (n_args == 0 || all_args[0] == MP_OBJ_NEW_SMALL_INT(-1)) { \
mp_print_str(MICROPY_ERROR_PRINTER, "Warning: I2C(-1, ...) is deprecated, use SoftI2C(...) instead\n"); \
if (n_args != 0) { \
--n_args; \
++all_args; \
} \
return MP_OBJ_TYPE_GET_SLOT(&mp_machine_soft_i2c_type, make_new)(&mp_machine_soft_i2c_type, n_args, n_kw, all_args); \
} \
} while (0)
#define MP_MACHINE_I2C_FLAG_READ (0x01) // if not set then it's a write
#define MP_MACHINE_I2C_FLAG_STOP (0x02)
#if MICROPY_PY_MACHINE_I2C_TRANSFER_WRITE1
// If set, the first mp_machine_i2c_buf_t in a transfer is a write.
#define MP_MACHINE_I2C_FLAG_WRITE1 (0x04)
#endif
typedef struct _mp_machine_i2c_buf_t {
size_t len;
uint8_t *buf;
} mp_machine_i2c_buf_t;
// I2C protocol
// - init must be non-NULL
// - start/stop/read/write can be NULL, meaning operation is not supported
// - transfer must be non-NULL
// - transfer_single only needs to be set if transfer=mp_machine_i2c_transfer_adaptor
typedef struct _mp_machine_i2c_p_t {
#if MICROPY_PY_MACHINE_I2C_TRANSFER_WRITE1
bool transfer_supports_write1;
#endif
void (*init)(mp_obj_base_t *obj, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
int (*start)(mp_obj_base_t *obj);
int (*stop)(mp_obj_base_t *obj);
int (*read)(mp_obj_base_t *obj, uint8_t *dest, size_t len, bool nack);
int (*write)(mp_obj_base_t *obj, const uint8_t *src, size_t len);
int (*transfer)(mp_obj_base_t *obj, uint16_t addr, size_t n, mp_machine_i2c_buf_t *bufs, unsigned int flags);
int (*transfer_single)(mp_obj_base_t *obj, uint16_t addr, size_t len, uint8_t *buf, unsigned int flags);
} mp_machine_i2c_p_t;
typedef struct _mp_machine_soft_i2c_obj_t {
mp_obj_base_t base;
uint32_t us_delay;
uint32_t us_timeout;
mp_hal_pin_obj_t scl;
mp_hal_pin_obj_t sda;
} mp_machine_soft_i2c_obj_t;
extern const mp_obj_type_t mp_machine_soft_i2c_type;
extern const mp_obj_dict_t mp_machine_i2c_locals_dict;
int mp_machine_i2c_transfer_adaptor(mp_obj_base_t *self, uint16_t addr, size_t n, mp_machine_i2c_buf_t *bufs, unsigned int flags);
int mp_machine_soft_i2c_transfer(mp_obj_base_t *self, uint16_t addr, size_t n, mp_machine_i2c_buf_t *bufs, unsigned int flags);
#endif // MICROPY_INCLUDED_EXTMOD_MACHINE_I2C_H

698
extmod/machine_i2s.c Normal file
View File

@ -0,0 +1,698 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Mike Teachman
* Copyright (c) 2023 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/stream.h"
#if MICROPY_PY_MACHINE_I2S
#include "extmod/modmachine.h"
// The I2S class has 3 modes of operation:
//
// Mode1: Blocking
// - readinto() and write() methods block until the supplied buffer is filled (read) or emptied (write)
// - this is the default mode of operation
//
// Mode2: Non-Blocking
// - readinto() and write() methods return immediately
// - buffer filling and emptying happens asynchronously to the main MicroPython task
// - a callback function is called when the supplied buffer has been filled (read) or emptied (write)
// - non-blocking mode is enabled when a callback is set with the irq() method
// - implementation of asynchronous background operations is port specific
//
// Mode3: Asyncio
// - implements the stream protocol
// - asyncio mode is enabled when the ioctl() function is called
// - the state of the internal ring buffer is used to detect that I2S samples can be read or written
//
// The samples contained in the app buffer supplied for the readinto() and write() methods have the following convention:
// Mono: little endian format
// Stereo: little endian format, left channel first
//
// I2S terms:
// "frame": consists of two audio samples (Left audio sample + Right audio sample)
//
// Misc:
// - for Mono configuration:
// - readinto method: samples are gathered from the L channel only
// - write method: every sample is output to both the L and R channels
// - for readinto method the I2S hardware is read using 8-byte frames
// (this is standard for almost all I2S hardware, such as MEMS microphones)
#define NUM_I2S_USER_FORMATS (4)
#define I2S_RX_FRAME_SIZE_IN_BYTES (8)
typedef enum {
MONO,
STEREO
} format_t;
typedef enum {
BLOCKING,
NON_BLOCKING,
ASYNCIO
} io_mode_t;
// Arguments for I2S() constructor and I2S.init().
enum {
ARG_sck,
ARG_ws,
ARG_sd,
#if MICROPY_PY_MACHINE_I2S_MCK
ARG_mck,
#endif
ARG_mode,
ARG_bits,
ARG_format,
ARG_rate,
ARG_ibuf,
};
#if MICROPY_PY_MACHINE_I2S_RING_BUF
typedef struct _ring_buf_t {
uint8_t *buffer;
size_t head;
size_t tail;
size_t size;
} ring_buf_t;
typedef struct _non_blocking_descriptor_t {
mp_buffer_info_t appbuf;
uint32_t index;
bool copy_in_progress;
} non_blocking_descriptor_t;
STATIC void ringbuf_init(ring_buf_t *rbuf, uint8_t *buffer, size_t size);
STATIC bool ringbuf_push(ring_buf_t *rbuf, uint8_t data);
STATIC bool ringbuf_pop(ring_buf_t *rbuf, uint8_t *data);
STATIC size_t ringbuf_available_data(ring_buf_t *rbuf);
STATIC size_t ringbuf_available_space(ring_buf_t *rbuf);
STATIC void fill_appbuf_from_ringbuf_non_blocking(machine_i2s_obj_t *self);
STATIC void copy_appbuf_to_ringbuf_non_blocking(machine_i2s_obj_t *self);
#endif // MICROPY_PY_MACHINE_I2S_RING_BUF
// The port must provide implementations of these low-level I2S functions.
STATIC void mp_machine_i2s_init_helper(machine_i2s_obj_t *self, mp_arg_val_t *args);
STATIC machine_i2s_obj_t *mp_machine_i2s_make_new_instance(mp_int_t i2s_id);
STATIC void mp_machine_i2s_deinit(machine_i2s_obj_t *self);
STATIC void mp_machine_i2s_irq_update(machine_i2s_obj_t *self);
// The port provides implementations of the above in this file.
#include MICROPY_PY_MACHINE_I2S_INCLUDEFILE
#if MICROPY_PY_MACHINE_I2S_RING_BUF
// Ring Buffer
// Thread safe when used with these constraints:
// - Single Producer, Single Consumer
// - Sequential atomic operations
// One byte of capacity is used to detect buffer empty/full
STATIC void ringbuf_init(ring_buf_t *rbuf, uint8_t *buffer, size_t size) {
rbuf->buffer = buffer;
rbuf->size = size;
rbuf->head = 0;
rbuf->tail = 0;
}
STATIC bool ringbuf_push(ring_buf_t *rbuf, uint8_t data) {
size_t next_tail = (rbuf->tail + 1) % rbuf->size;
if (next_tail != rbuf->head) {
rbuf->buffer[rbuf->tail] = data;
rbuf->tail = next_tail;
return true;
}
// full
return false;
}
STATIC bool ringbuf_pop(ring_buf_t *rbuf, uint8_t *data) {
if (rbuf->head == rbuf->tail) {
// empty
return false;
}
*data = rbuf->buffer[rbuf->head];
rbuf->head = (rbuf->head + 1) % rbuf->size;
return true;
}
STATIC bool ringbuf_is_empty(ring_buf_t *rbuf) {
return rbuf->head == rbuf->tail;
}
STATIC bool ringbuf_is_full(ring_buf_t *rbuf) {
return ((rbuf->tail + 1) % rbuf->size) == rbuf->head;
}
STATIC size_t ringbuf_available_data(ring_buf_t *rbuf) {
return (rbuf->tail - rbuf->head + rbuf->size) % rbuf->size;
}
STATIC size_t ringbuf_available_space(ring_buf_t *rbuf) {
return rbuf->size - ringbuf_available_data(rbuf) - 1;
}
STATIC uint32_t fill_appbuf_from_ringbuf(machine_i2s_obj_t *self, mp_buffer_info_t *appbuf) {
// copy audio samples from the ring buffer to the app buffer
// loop, copying samples until the app buffer is filled
// For asyncio mode, the loop will make an early exit if the ring buffer becomes empty
// Example:
// a MicroPython I2S object is configured for 16-bit mono (2 bytes per audio sample).
// For every frame coming from the ring buffer (8 bytes), 2 bytes are "cherry picked" and
// copied to the supplied app buffer.
// Thus, for every 1 byte copied to the app buffer, 4 bytes are read from the ring buffer.
// If a 8kB app buffer is supplied, 32kB of audio samples is read from the ring buffer.
uint32_t num_bytes_copied_to_appbuf = 0;
uint8_t *app_p = (uint8_t *)appbuf->buf;
uint8_t appbuf_sample_size_in_bytes = (self->bits == 16? 2 : 4) * (self->format == STEREO ? 2: 1);
uint32_t num_bytes_needed_from_ringbuf = appbuf->len * (I2S_RX_FRAME_SIZE_IN_BYTES / appbuf_sample_size_in_bytes);
uint8_t discard_byte;
while (num_bytes_needed_from_ringbuf) {
uint8_t f_index = get_frame_mapping_index(self->bits, self->format);
for (uint8_t i = 0; i < I2S_RX_FRAME_SIZE_IN_BYTES; i++) {
int8_t r_to_a_mapping = i2s_frame_map[f_index][i];
if (r_to_a_mapping != -1) {
if (self->io_mode == BLOCKING) {
// poll the ringbuf until a sample becomes available, copy into appbuf using the mapping transform
while (ringbuf_pop(&self->ring_buffer, app_p + r_to_a_mapping) == false) {
;
}
num_bytes_copied_to_appbuf++;
} else if (self->io_mode == ASYNCIO) {
if (ringbuf_pop(&self->ring_buffer, app_p + r_to_a_mapping) == false) {
// ring buffer is empty, exit
goto exit;
} else {
num_bytes_copied_to_appbuf++;
}
} else {
return 0; // should never get here (non-blocking mode does not use this function)
}
} else { // r_a_mapping == -1
// discard unused byte from ring buffer
if (self->io_mode == BLOCKING) {
// poll the ringbuf until a sample becomes available
while (ringbuf_pop(&self->ring_buffer, &discard_byte) == false) {
;
}
} else if (self->io_mode == ASYNCIO) {
if (ringbuf_pop(&self->ring_buffer, &discard_byte) == false) {
// ring buffer is empty, exit
goto exit;
}
} else {
return 0; // should never get here (non-blocking mode does not use this function)
}
}
num_bytes_needed_from_ringbuf--;
}
app_p += appbuf_sample_size_in_bytes;
}
exit:
return num_bytes_copied_to_appbuf;
}
// function is used in IRQ context
STATIC void fill_appbuf_from_ringbuf_non_blocking(machine_i2s_obj_t *self) {
// attempt to copy a block of audio samples from the ring buffer to the supplied app buffer.
// audio samples will be formatted as part of the copy operation
uint32_t num_bytes_copied_to_appbuf = 0;
uint8_t *app_p = &(((uint8_t *)self->non_blocking_descriptor.appbuf.buf)[self->non_blocking_descriptor.index]);
uint8_t appbuf_sample_size_in_bytes = (self->bits == 16? 2 : 4) * (self->format == STEREO ? 2: 1);
uint32_t num_bytes_remaining_to_copy_to_appbuf = self->non_blocking_descriptor.appbuf.len - self->non_blocking_descriptor.index;
uint32_t num_bytes_remaining_to_copy_from_ring_buffer = num_bytes_remaining_to_copy_to_appbuf *
(I2S_RX_FRAME_SIZE_IN_BYTES / appbuf_sample_size_in_bytes);
uint32_t num_bytes_needed_from_ringbuf = MIN(SIZEOF_NON_BLOCKING_COPY_IN_BYTES, num_bytes_remaining_to_copy_from_ring_buffer);
uint8_t discard_byte;
if (ringbuf_available_data(&self->ring_buffer) >= num_bytes_needed_from_ringbuf) {
while (num_bytes_needed_from_ringbuf) {
uint8_t f_index = get_frame_mapping_index(self->bits, self->format);
for (uint8_t i = 0; i < I2S_RX_FRAME_SIZE_IN_BYTES; i++) {
int8_t r_to_a_mapping = i2s_frame_map[f_index][i];
if (r_to_a_mapping != -1) {
ringbuf_pop(&self->ring_buffer, app_p + r_to_a_mapping);
num_bytes_copied_to_appbuf++;
} else { // r_a_mapping == -1
// discard unused byte from ring buffer
ringbuf_pop(&self->ring_buffer, &discard_byte);
}
num_bytes_needed_from_ringbuf--;
}
app_p += appbuf_sample_size_in_bytes;
}
self->non_blocking_descriptor.index += num_bytes_copied_to_appbuf;
if (self->non_blocking_descriptor.index >= self->non_blocking_descriptor.appbuf.len) {
self->non_blocking_descriptor.copy_in_progress = false;
mp_sched_schedule(self->callback_for_non_blocking, MP_OBJ_FROM_PTR(self));
}
}
}
STATIC uint32_t copy_appbuf_to_ringbuf(machine_i2s_obj_t *self, mp_buffer_info_t *appbuf) {
// copy audio samples from the app buffer to the ring buffer
// loop, reading samples until the app buffer is emptied
// for asyncio mode, the loop will make an early exit if the ring buffer becomes full
uint32_t a_index = 0;
while (a_index < appbuf->len) {
if (self->io_mode == BLOCKING) {
// copy a byte to the ringbuf when space becomes available
while (ringbuf_push(&self->ring_buffer, ((uint8_t *)appbuf->buf)[a_index]) == false) {
;
}
a_index++;
} else if (self->io_mode == ASYNCIO) {
if (ringbuf_push(&self->ring_buffer, ((uint8_t *)appbuf->buf)[a_index]) == false) {
// ring buffer is full, exit
break;
} else {
a_index++;
}
} else {
return 0; // should never get here (non-blocking mode does not use this function)
}
}
return a_index;
}
// function is used in IRQ context
STATIC void copy_appbuf_to_ringbuf_non_blocking(machine_i2s_obj_t *self) {
// copy audio samples from app buffer into ring buffer
uint32_t num_bytes_remaining_to_copy = self->non_blocking_descriptor.appbuf.len - self->non_blocking_descriptor.index;
uint32_t num_bytes_to_copy = MIN(SIZEOF_NON_BLOCKING_COPY_IN_BYTES, num_bytes_remaining_to_copy);
if (ringbuf_available_space(&self->ring_buffer) >= num_bytes_to_copy) {
for (uint32_t i = 0; i < num_bytes_to_copy; i++) {
ringbuf_push(&self->ring_buffer,
((uint8_t *)self->non_blocking_descriptor.appbuf.buf)[self->non_blocking_descriptor.index + i]);
}
self->non_blocking_descriptor.index += num_bytes_to_copy;
if (self->non_blocking_descriptor.index >= self->non_blocking_descriptor.appbuf.len) {
self->non_blocking_descriptor.copy_in_progress = false;
mp_sched_schedule(self->callback_for_non_blocking, MP_OBJ_FROM_PTR(self));
}
}
}
#endif // MICROPY_PY_MACHINE_I2S_RING_BUF
MP_NOINLINE STATIC void machine_i2s_init_helper(machine_i2s_obj_t *self, size_t n_pos_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_sck, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_ws, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_sd, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
#if MICROPY_PY_MACHINE_I2S_MCK
{ MP_QSTR_mck, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
#endif
{ MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_format, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_rate, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_ibuf, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = -1} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_pos_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
mp_machine_i2s_init_helper(self, args);
}
STATIC void machine_i2s_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
machine_i2s_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_printf(print, "I2S(id=%u,\n"
"sck="MP_HAL_PIN_FMT ",\n"
"ws="MP_HAL_PIN_FMT ",\n"
"sd="MP_HAL_PIN_FMT ",\n"
#if MICROPY_PY_MACHINE_I2S_MCK
"mck="MP_HAL_PIN_FMT ",\n"
#endif
"mode=%u,\n"
"bits=%u, format=%u,\n"
"rate=%d, ibuf=%d)",
self->i2s_id,
mp_hal_pin_name(self->sck),
mp_hal_pin_name(self->ws),
mp_hal_pin_name(self->sd),
#if MICROPY_PY_MACHINE_I2S_MCK
mp_hal_pin_name(self->mck),
#endif
self->mode,
self->bits, self->format,
self->rate, self->ibuf
);
}
STATIC mp_obj_t machine_i2s_make_new(const mp_obj_type_t *type, size_t n_pos_args, size_t n_kw_args, const mp_obj_t *args) {
mp_arg_check_num(n_pos_args, n_kw_args, 1, MP_OBJ_FUN_ARGS_MAX, true);
mp_int_t i2s_id = mp_obj_get_int(args[0]);
machine_i2s_obj_t *self = mp_machine_i2s_make_new_instance(i2s_id);
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw_args, args + n_pos_args);
machine_i2s_init_helper(self, n_pos_args - 1, args + 1, &kw_args);
return MP_OBJ_FROM_PTR(self);
}
// I2S.init(...)
STATIC mp_obj_t machine_i2s_init(size_t n_pos_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
machine_i2s_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
mp_machine_i2s_deinit(self);
machine_i2s_init_helper(self, n_pos_args - 1, pos_args + 1, kw_args);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2s_init_obj, 1, machine_i2s_init);
// I2S.deinit()
STATIC mp_obj_t machine_i2s_deinit(mp_obj_t self_in) {
machine_i2s_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_machine_i2s_deinit(self);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_i2s_deinit_obj, machine_i2s_deinit);
// I2S.irq(handler)
STATIC mp_obj_t machine_i2s_irq(mp_obj_t self_in, mp_obj_t handler) {
machine_i2s_obj_t *self = MP_OBJ_TO_PTR(self_in);
if (handler != mp_const_none && !mp_obj_is_callable(handler)) {
mp_raise_ValueError(MP_ERROR_TEXT("invalid callback"));
}
if (handler != mp_const_none) {
self->io_mode = NON_BLOCKING;
} else {
self->io_mode = BLOCKING;
}
self->callback_for_non_blocking = handler;
mp_machine_i2s_irq_update(self);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_i2s_irq_obj, machine_i2s_irq);
// Shift() is typically used as a volume control.
// shift=1 increases volume by 6dB, shift=-1 decreases volume by 6dB
STATIC mp_obj_t machine_i2s_shift(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_buf, ARG_bits, ARG_shift};
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_buf, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_bits, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_shift, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
};
// parse args
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[ARG_buf].u_obj, &bufinfo, MP_BUFFER_RW);
int16_t *buf_16 = bufinfo.buf;
int32_t *buf_32 = bufinfo.buf;
uint8_t bits = args[ARG_bits].u_int;
int8_t shift = args[ARG_shift].u_int;
uint32_t num_audio_samples;
switch (bits) {
case 16:
num_audio_samples = bufinfo.len / sizeof(uint16_t);
break;
case 32:
num_audio_samples = bufinfo.len / sizeof(uint32_t);
break;
default:
mp_raise_ValueError(MP_ERROR_TEXT("invalid bits"));
break;
}
for (uint32_t i = 0; i < num_audio_samples; i++) {
switch (bits) {
case 16:
if (shift >= 0) {
buf_16[i] = buf_16[i] << shift;
} else {
buf_16[i] = buf_16[i] >> abs(shift);
}
break;
case 32:
if (shift >= 0) {
buf_32[i] = buf_32[i] << shift;
} else {
buf_32[i] = buf_32[i] >> abs(shift);
}
break;
}
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2s_shift_fun_obj, 0, machine_i2s_shift);
STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(machine_i2s_shift_obj, MP_ROM_PTR(&machine_i2s_shift_fun_obj));
STATIC const mp_rom_map_elem_t machine_i2s_locals_dict_table[] = {
// Methods
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_i2s_init_obj) },
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_i2s_deinit_obj) },
{ MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&machine_i2s_irq_obj) },
#if MICROPY_PY_MACHINE_I2S_FINALISER
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&machine_i2s_deinit_obj) },
#endif
// Static method
{ MP_ROM_QSTR(MP_QSTR_shift), MP_ROM_PTR(&machine_i2s_shift_obj) },
// Constants
{ MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_INT(MICROPY_PY_MACHINE_I2S_CONSTANT_RX) },
{ MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_INT(MICROPY_PY_MACHINE_I2S_CONSTANT_TX) },
{ MP_ROM_QSTR(MP_QSTR_STEREO), MP_ROM_INT(STEREO) },
{ MP_ROM_QSTR(MP_QSTR_MONO), MP_ROM_INT(MONO) },
};
MP_DEFINE_CONST_DICT(machine_i2s_locals_dict, machine_i2s_locals_dict_table);
STATIC mp_uint_t machine_i2s_stream_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) {
machine_i2s_obj_t *self = MP_OBJ_TO_PTR(self_in);
if (self->mode != MICROPY_PY_MACHINE_I2S_CONSTANT_RX) {
*errcode = MP_EPERM;
return MP_STREAM_ERROR;
}
uint8_t appbuf_sample_size_in_bytes = (self->bits / 8) * (self->format == STEREO ? 2: 1);
if (size % appbuf_sample_size_in_bytes != 0) {
*errcode = MP_EINVAL;
return MP_STREAM_ERROR;
}
if (size == 0) {
return 0;
}
if (self->io_mode == NON_BLOCKING) {
#if MICROPY_PY_MACHINE_I2S_RING_BUF
self->non_blocking_descriptor.appbuf.buf = (void *)buf_in;
self->non_blocking_descriptor.appbuf.len = size;
self->non_blocking_descriptor.index = 0;
self->non_blocking_descriptor.copy_in_progress = true;
#else
non_blocking_descriptor_t descriptor;
descriptor.appbuf.buf = (void *)buf_in;
descriptor.appbuf.len = size;
descriptor.callback = self->callback_for_non_blocking;
descriptor.direction = I2S_RX_TRANSFER;
// send the descriptor to the task that handles non-blocking mode
xQueueSend(self->non_blocking_mode_queue, &descriptor, 0);
#endif
return size;
} else { // blocking or asyncio mode
mp_buffer_info_t appbuf;
appbuf.buf = (void *)buf_in;
appbuf.len = size;
#if MICROPY_PY_MACHINE_I2S_RING_BUF
uint32_t num_bytes_read = fill_appbuf_from_ringbuf(self, &appbuf);
#else
uint32_t num_bytes_read = fill_appbuf_from_dma(self, &appbuf);
#endif
return num_bytes_read;
}
}
STATIC mp_uint_t machine_i2s_stream_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) {
machine_i2s_obj_t *self = MP_OBJ_TO_PTR(self_in);
if (self->mode != MICROPY_PY_MACHINE_I2S_CONSTANT_TX) {
*errcode = MP_EPERM;
return MP_STREAM_ERROR;
}
if (size == 0) {
return 0;
}
if (self->io_mode == NON_BLOCKING) {
#if MICROPY_PY_MACHINE_I2S_RING_BUF
self->non_blocking_descriptor.appbuf.buf = (void *)buf_in;
self->non_blocking_descriptor.appbuf.len = size;
self->non_blocking_descriptor.index = 0;
self->non_blocking_descriptor.copy_in_progress = true;
#else
non_blocking_descriptor_t descriptor;
descriptor.appbuf.buf = (void *)buf_in;
descriptor.appbuf.len = size;
descriptor.callback = self->callback_for_non_blocking;
descriptor.direction = I2S_TX_TRANSFER;
// send the descriptor to the task that handles non-blocking mode
xQueueSend(self->non_blocking_mode_queue, &descriptor, 0);
#endif
return size;
} else { // blocking or asyncio mode
mp_buffer_info_t appbuf;
appbuf.buf = (void *)buf_in;
appbuf.len = size;
#if MICROPY_PY_MACHINE_I2S_RING_BUF
uint32_t num_bytes_written = copy_appbuf_to_ringbuf(self, &appbuf);
#else
uint32_t num_bytes_written = copy_appbuf_to_dma(self, &appbuf);
#endif
return num_bytes_written;
}
}
STATIC mp_uint_t machine_i2s_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) {
machine_i2s_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_uint_t ret;
uintptr_t flags = arg;
self->io_mode = ASYNCIO; // a call to ioctl() is an indication that asyncio is being used
if (request == MP_STREAM_POLL) {
ret = 0;
if (flags & MP_STREAM_POLL_RD) {
if (self->mode != MICROPY_PY_MACHINE_I2S_CONSTANT_RX) {
*errcode = MP_EPERM;
return MP_STREAM_ERROR;
}
#if MICROPY_PY_MACHINE_I2S_RING_BUF
if (!ringbuf_is_empty(&self->ring_buffer)) {
ret |= MP_STREAM_POLL_RD;
}
#else
// check event queue to determine if a DMA buffer has been filled
// (which is an indication that at least one DMA buffer is available to be read)
// note: timeout = 0 so the call is non-blocking
i2s_event_t i2s_event;
if (xQueueReceive(self->i2s_event_queue, &i2s_event, 0)) {
if (i2s_event.type == I2S_EVENT_RX_DONE) {
// getting here means that at least one DMA buffer is now full
// indicating that audio samples can be read from the I2S object
ret |= MP_STREAM_POLL_RD;
}
}
#endif
}
if (flags & MP_STREAM_POLL_WR) {
if (self->mode != MICROPY_PY_MACHINE_I2S_CONSTANT_TX) {
*errcode = MP_EPERM;
return MP_STREAM_ERROR;
}
#if MICROPY_PY_MACHINE_I2S_RING_BUF
if (!ringbuf_is_full(&self->ring_buffer)) {
ret |= MP_STREAM_POLL_WR;
}
#else
// check event queue to determine if a DMA buffer has been emptied
// (which is an indication that at least one DMA buffer is available to be written)
// note: timeout = 0 so the call is non-blocking
i2s_event_t i2s_event;
if (xQueueReceive(self->i2s_event_queue, &i2s_event, 0)) {
if (i2s_event.type == I2S_EVENT_TX_DONE) {
// getting here means that at least one DMA buffer is now empty
// indicating that audio samples can be written to the I2S object
ret |= MP_STREAM_POLL_WR;
}
}
#endif
}
} else {
*errcode = MP_EINVAL;
ret = MP_STREAM_ERROR;
}
return ret;
}
STATIC const mp_stream_p_t i2s_stream_p = {
.read = machine_i2s_stream_read,
.write = machine_i2s_stream_write,
.ioctl = machine_i2s_ioctl,
.is_text = false,
};
MP_DEFINE_CONST_OBJ_TYPE(
machine_i2s_type,
MP_QSTR_I2S,
MP_TYPE_FLAG_ITER_IS_STREAM,
make_new, machine_i2s_make_new,
print, machine_i2s_print,
protocol, &i2s_stream_p,
locals_dict, &machine_i2s_locals_dict
);
#endif // MICROPY_PY_MACHINE_I2S

View File

@ -25,7 +25,7 @@
*/
#include "py/runtime.h"
#include "extmod/machine_mem.h"
#include "extmod/modmachine.h"
#if MICROPY_PY_MACHINE

View File

@ -1,49 +0,0 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2015 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_EXTMOD_MACHINE_MEM_H
#define MICROPY_INCLUDED_EXTMOD_MACHINE_MEM_H
#include "py/obj.h"
typedef struct _machine_mem_obj_t {
mp_obj_base_t base;
unsigned elem_size; // in bytes
} machine_mem_obj_t;
extern const mp_obj_type_t machine_mem_type;
extern const machine_mem_obj_t machine_mem8_obj;
extern const machine_mem_obj_t machine_mem16_obj;
extern const machine_mem_obj_t machine_mem32_obj;
#if defined(MICROPY_MACHINE_MEM_GET_READ_ADDR)
uintptr_t MICROPY_MACHINE_MEM_GET_READ_ADDR(mp_obj_t addr_o, uint align);
#endif
#if defined(MICROPY_MACHINE_MEM_GET_WRITE_ADDR)
uintptr_t MICROPY_MACHINE_MEM_GET_WRITE_ADDR(mp_obj_t addr_o, uint align);
#endif
#endif // MICROPY_INCLUDED_EXTMOD_MACHINE_MEM_H

View File

@ -24,13 +24,12 @@
* THE SOFTWARE.
*/
#include "py/mpconfig.h"
#if MICROPY_PY_MACHINE
#include "py/obj.h"
#include "py/runtime.h"
#if MICROPY_PY_MACHINE_PIN_BASE
#include "extmod/modmachine.h"
#include "extmod/virtpin.h"
#include "extmod/machine_pinbase.h"
// PinBase class
@ -85,4 +84,4 @@ MP_DEFINE_CONST_OBJ_TYPE(
protocol, &pinbase_pin_p
);
#endif // MICROPY_PY_MACHINE
#endif // MICROPY_PY_MACHINE_PIN_BASE

View File

@ -1,33 +0,0 @@
/*
* 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_MACHINE_PINBASE_H
#define MICROPY_INCLUDED_EXTMOD_MACHINE_PINBASE_H
#include "py/obj.h"
extern const mp_obj_type_t machine_pinbase_type;
#endif // MICROPY_INCLUDED_EXTMOD_MACHINE_PINBASE_H

View File

@ -26,7 +26,7 @@
#include "py/runtime.h"
#include "py/mperrno.h"
#include "extmod/machine_pulse.h"
#include "extmod/modmachine.h"
#if MICROPY_PY_MACHINE_PULSE

View File

@ -28,11 +28,26 @@
#if MICROPY_PY_MACHINE_PWM
#include "extmod/machine_pwm.h"
#include "extmod/modmachine.h"
#ifdef MICROPY_PY_MACHINE_PWM_INCLUDEFILE
#include MICROPY_PY_MACHINE_PWM_INCLUDEFILE
// The port must provide implementations of these low-level PWM functions.
STATIC void mp_machine_pwm_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind);
STATIC mp_obj_t mp_machine_pwm_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args);
STATIC void mp_machine_pwm_init_helper(machine_pwm_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
STATIC void mp_machine_pwm_deinit(machine_pwm_obj_t *self);
STATIC mp_obj_t mp_machine_pwm_freq_get(machine_pwm_obj_t *self);
STATIC void mp_machine_pwm_freq_set(machine_pwm_obj_t *self, mp_int_t freq);
#if MICROPY_PY_MACHINE_PWM_DUTY
STATIC mp_obj_t mp_machine_pwm_duty_get(machine_pwm_obj_t *self);
STATIC void mp_machine_pwm_duty_set(machine_pwm_obj_t *self, mp_int_t duty);
#endif
STATIC mp_obj_t mp_machine_pwm_duty_get_u16(machine_pwm_obj_t *self);
STATIC void mp_machine_pwm_duty_set_u16(machine_pwm_obj_t *self, mp_int_t duty_u16);
STATIC mp_obj_t mp_machine_pwm_duty_get_ns(machine_pwm_obj_t *self);
STATIC void mp_machine_pwm_duty_set_ns(machine_pwm_obj_t *self, mp_int_t duty_ns);
// The port provides implementations of the above in this file.
#include MICROPY_PY_MACHINE_PWM_INCLUDEFILE
STATIC mp_obj_t machine_pwm_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
mp_machine_pwm_init_helper(args[0], n_args - 1, args + 1, kw_args);

View File

@ -1,55 +0,0 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2021 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_EXTMOD_MACHINE_PWM_H
#define MICROPY_INCLUDED_EXTMOD_MACHINE_PWM_H
#include "py/obj.h"
// A port must provide this type, but it's otherwise opaque.
typedef struct _machine_pwm_obj_t machine_pwm_obj_t;
// This PWM class is implemented by machine_pwm.c.
extern const mp_obj_type_t machine_pwm_type;
// A port must provide implementations of these low-level PWM functions, either as global
// linker symbols, or included directly if MICROPY_PY_MACHINE_PWM_INCLUDEFILE is defined.
#ifndef MICROPY_PY_MACHINE_PWM_INCLUDEFILE
void mp_machine_pwm_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind);
mp_obj_t mp_machine_pwm_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args);
void mp_machine_pwm_init_helper(machine_pwm_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
void mp_machine_pwm_deinit(machine_pwm_obj_t *self);
mp_obj_t mp_machine_pwm_freq_get(machine_pwm_obj_t *self);
void mp_machine_pwm_freq_set(machine_pwm_obj_t *self, mp_int_t freq);
mp_obj_t mp_machine_pwm_duty_get(machine_pwm_obj_t *self);
void mp_machine_pwm_duty_set(machine_pwm_obj_t *self, mp_int_t duty);
mp_obj_t mp_machine_pwm_duty_get_u16(machine_pwm_obj_t *self);
void mp_machine_pwm_duty_set_u16(machine_pwm_obj_t *self, mp_int_t duty_u16);
mp_obj_t mp_machine_pwm_duty_get_ns(machine_pwm_obj_t *self);
void mp_machine_pwm_duty_set_ns(machine_pwm_obj_t *self, mp_int_t duty_ns);
#endif
#endif // MICROPY_INCLUDED_EXTMOD_MACHINE_PWM_H

View File

@ -29,10 +29,9 @@
#include <string.h>
#include "py/obj.h"
#include "py/runtime.h"
#include "extmod/modmachine.h"
#include "extmod/virtpin.h"
#include "extmod/machine_signal.h"
// Signal class

View File

@ -31,7 +31,7 @@
#if MICROPY_PY_MACHINE_SPI || MICROPY_PY_MACHINE_SOFTSPI
#include "extmod/machine_spi.h"
#include "extmod/modmachine.h"
// if a port didn't define MSB/LSB constants then provide them
#ifndef MICROPY_PY_MACHINE_SPI_MSB

View File

@ -1,69 +0,0 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2016 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_EXTMOD_MACHINE_SPI_H
#define MICROPY_INCLUDED_EXTMOD_MACHINE_SPI_H
#include "py/obj.h"
#include "py/mphal.h"
#include "drivers/bus/spi.h"
// Temporary support for legacy construction of SoftSPI via SPI type.
#define MP_MACHINE_SPI_CHECK_FOR_LEGACY_SOFTSPI_CONSTRUCTION(n_args, n_kw, all_args) \
do { \
if (n_args == 0 || all_args[0] == MP_OBJ_NEW_SMALL_INT(-1)) { \
mp_print_str(MICROPY_ERROR_PRINTER, "Warning: SPI(-1, ...) is deprecated, use SoftSPI(...) instead\n"); \
if (n_args != 0) { \
--n_args; \
++all_args; \
} \
return MP_OBJ_TYPE_GET_SLOT(&mp_machine_soft_spi_type, make_new)(&mp_machine_soft_spi_type, n_args, n_kw, all_args); \
} \
} while (0)
// SPI protocol
typedef struct _mp_machine_spi_p_t {
void (*init)(mp_obj_base_t *obj, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
void (*deinit)(mp_obj_base_t *obj); // can be NULL
void (*transfer)(mp_obj_base_t *obj, size_t len, const uint8_t *src, uint8_t *dest);
} mp_machine_spi_p_t;
typedef struct _mp_machine_soft_spi_obj_t {
mp_obj_base_t base;
mp_soft_spi_obj_t spi;
} mp_machine_soft_spi_obj_t;
extern const mp_machine_spi_p_t mp_machine_soft_spi_p;
extern const mp_obj_type_t mp_machine_soft_spi_type;
extern const mp_obj_dict_t mp_machine_spi_locals_dict;
mp_obj_t mp_machine_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args);
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_spi_read_obj);
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_spi_readinto_obj);
MP_DECLARE_CONST_FUN_OBJ_2(mp_machine_spi_write_obj);
MP_DECLARE_CONST_FUN_OBJ_3(mp_machine_spi_write_readinto_obj);
#endif // MICROPY_INCLUDED_EXTMOD_MACHINE_SPI_H

187
extmod/machine_uart.c Normal file
View File

@ -0,0 +1,187 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2023 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/stream.h"
#if MICROPY_PY_MACHINE_UART
#include "extmod/modmachine.h"
#include "shared/runtime/mpirq.h"
// The port must provide implementations of these low-level UART functions.
STATIC void mp_machine_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind);
STATIC void mp_machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
STATIC mp_obj_t mp_machine_uart_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args);
STATIC void mp_machine_uart_deinit(machine_uart_obj_t *self);
STATIC mp_int_t mp_machine_uart_any(machine_uart_obj_t *self);
STATIC bool mp_machine_uart_txdone(machine_uart_obj_t *self);
#if MICROPY_PY_MACHINE_UART_SENDBREAK
STATIC void mp_machine_uart_sendbreak(machine_uart_obj_t *self);
#endif
#if MICROPY_PY_MACHINE_UART_READCHAR_WRITECHAR
STATIC mp_int_t mp_machine_uart_readchar(machine_uart_obj_t *self);
STATIC void mp_machine_uart_writechar(machine_uart_obj_t *self, uint16_t data);
#endif
#if MICROPY_PY_MACHINE_UART_IRQ
STATIC mp_irq_obj_t *mp_machine_uart_irq(machine_uart_obj_t *self, bool any_args, mp_arg_val_t *args);
#endif
STATIC mp_uint_t mp_machine_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode);
STATIC mp_uint_t mp_machine_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode);
STATIC mp_uint_t mp_machine_uart_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode);
// The port provides implementations of the above in this file.
#include MICROPY_PY_MACHINE_UART_INCLUDEFILE
// UART.init(...)
STATIC mp_obj_t machine_uart_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
mp_machine_uart_init_helper(MP_OBJ_TO_PTR(args[0]), n_args - 1, args + 1, kw_args);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_KW(machine_uart_init_obj, 1, machine_uart_init);
// UART.deinit()
STATIC mp_obj_t machine_uart_deinit(mp_obj_t self_in) {
machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_machine_uart_deinit(self);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_deinit_obj, machine_uart_deinit);
// UART.any()
STATIC mp_obj_t machine_uart_any(mp_obj_t self_in) {
machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
return MP_OBJ_NEW_SMALL_INT(mp_machine_uart_any(self));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_any_obj, machine_uart_any);
// UART.txdone()
STATIC mp_obj_t machine_uart_txdone(mp_obj_t self_in) {
machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
return mp_obj_new_bool(mp_machine_uart_txdone(self));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_txdone_obj, machine_uart_txdone);
#if MICROPY_PY_MACHINE_UART_SENDBREAK
// UART.sendbreak()
STATIC mp_obj_t machine_uart_sendbreak(mp_obj_t self_in) {
machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_machine_uart_sendbreak(self);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_sendbreak_obj, machine_uart_sendbreak);
#endif
#if MICROPY_PY_MACHINE_UART_READCHAR_WRITECHAR
// UART.readchar()
STATIC mp_obj_t machine_uart_readchar(mp_obj_t self_in) {
machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
return MP_OBJ_NEW_SMALL_INT(mp_machine_uart_readchar(self));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_readchar_obj, machine_uart_readchar);
// UART.writechar(char)
STATIC mp_obj_t machine_uart_writechar(mp_obj_t self_in, mp_obj_t char_in) {
machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_machine_uart_writechar(self, mp_obj_get_int(char_in));
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_uart_writechar_obj, machine_uart_writechar);
#endif
#if MICROPY_PY_MACHINE_UART_IRQ
// UART.irq(handler, trigger, hard)
STATIC mp_obj_t machine_uart_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
mp_arg_val_t args[MP_IRQ_ARG_INIT_NUM_ARGS];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_IRQ_ARG_INIT_NUM_ARGS, mp_irq_init_args, args);
machine_uart_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
bool any_args = n_args > 1 || kw_args->used != 0;
return MP_OBJ_FROM_PTR(mp_machine_uart_irq(self, any_args, args));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_uart_irq_obj, 1, machine_uart_irq);
#endif
STATIC const mp_rom_map_elem_t machine_uart_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_uart_init_obj) },
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_uart_deinit_obj) },
{ MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&mp_stream_flush_obj) },
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
{ MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) },
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
{ MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&machine_uart_any_obj) },
{ MP_ROM_QSTR(MP_QSTR_txdone), MP_ROM_PTR(&machine_uart_txdone_obj) },
#if MICROPY_PY_MACHINE_UART_SENDBREAK
{ MP_ROM_QSTR(MP_QSTR_sendbreak), MP_ROM_PTR(&machine_uart_sendbreak_obj) },
#endif
#if MICROPY_PY_MACHINE_UART_READCHAR_WRITECHAR
{ MP_ROM_QSTR(MP_QSTR_readchar), MP_ROM_PTR(&machine_uart_readchar_obj) },
{ MP_ROM_QSTR(MP_QSTR_writechar), MP_ROM_PTR(&machine_uart_writechar_obj) },
#endif
#if MICROPY_PY_MACHINE_UART_IRQ
{ MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&machine_uart_irq_obj) },
#endif
// A port must add UART class constants defining the following macro.
// It can be defined to nothing if there are no constants.
MICROPY_PY_MACHINE_UART_CLASS_CONSTANTS
};
STATIC MP_DEFINE_CONST_DICT(machine_uart_locals_dict, machine_uart_locals_dict_table);
STATIC const mp_stream_p_t uart_stream_p = {
.read = mp_machine_uart_read,
.write = mp_machine_uart_write,
.ioctl = mp_machine_uart_ioctl,
.is_text = false,
};
MP_DEFINE_CONST_OBJ_TYPE(
machine_uart_type,
MP_QSTR_UART,
MP_TYPE_FLAG_ITER_IS_STREAM,
make_new, mp_machine_uart_make_new,
print, mp_machine_uart_print,
protocol, &uart_stream_p,
locals_dict, &machine_uart_locals_dict
);
#endif // MICROPY_PY_MACHINE_UART

95
extmod/machine_wdt.c Normal file
View File

@ -0,0 +1,95 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2020-2023 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"
#if MICROPY_PY_MACHINE_WDT
#include "extmod/modmachine.h"
// The port must provide implementations of these low-level WDT functions.
STATIC machine_wdt_obj_t *mp_machine_wdt_make_new_instance(mp_int_t id, mp_int_t timeout_ms);
STATIC void mp_machine_wdt_feed(machine_wdt_obj_t *self);
#if MICROPY_PY_MACHINE_WDT_TIMEOUT_MS
STATIC void mp_machine_wdt_timeout_ms_set(machine_wdt_obj_t *self_in, mp_int_t timeout_ms);
#endif
// The port provides implementations of the above in this file.
#include MICROPY_PY_MACHINE_WDT_INCLUDEFILE
STATIC mp_obj_t machine_wdt_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
enum { ARG_id, ARG_timeout };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_id, MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_timeout, MP_ARG_INT, {.u_int = 5000} },
};
// Parse the arguments.
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
// Create WDT instance.
machine_wdt_obj_t *self = mp_machine_wdt_make_new_instance(args[ARG_id].u_int, args[ARG_timeout].u_int);
return MP_OBJ_FROM_PTR(self);
}
// WDT.feed()
STATIC mp_obj_t machine_wdt_feed(mp_obj_t self_in) {
machine_wdt_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_machine_wdt_feed(self);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_wdt_feed_obj, machine_wdt_feed);
#if MICROPY_PY_MACHINE_WDT_TIMEOUT_MS
// WDT.timeout_ms(timeout)
STATIC mp_obj_t machine_wdt_timeout_ms(mp_obj_t self_in, mp_obj_t timeout_in) {
machine_wdt_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_int_t timeout_ms = mp_obj_get_int(timeout_in);
mp_machine_wdt_timeout_ms_set(self, timeout_ms);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_wdt_timeout_ms_obj, machine_wdt_timeout_ms);
#endif
STATIC const mp_rom_map_elem_t machine_wdt_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_feed), MP_ROM_PTR(&machine_wdt_feed_obj) },
#if MICROPY_PY_MACHINE_WDT_TIMEOUT_MS
{ MP_ROM_QSTR(MP_QSTR_timeout_ms), MP_ROM_PTR(&machine_wdt_timeout_ms_obj) },
#endif
};
STATIC MP_DEFINE_CONST_DICT(machine_wdt_locals_dict, machine_wdt_locals_dict_table);
MP_DEFINE_CONST_OBJ_TYPE(
machine_wdt_type,
MP_QSTR_WDT,
MP_TYPE_FLAG_NONE,
make_new, machine_wdt_make_new,
locals_dict, &machine_wdt_locals_dict
);
#endif // MICROPY_PY_MACHINE_WDT

View File

@ -31,6 +31,8 @@
// #define MBEDTLS_DEBUG_C
// Set mbedtls configuration.
#define MBEDTLS_HAVE_TIME
#define MBEDTLS_HAVE_TIME_DATE
#define MBEDTLS_DEPRECATED_REMOVED
#define MBEDTLS_AES_ROM_TABLES
#define MBEDTLS_CIPHER_MODE_CBC

View File

@ -39,10 +39,12 @@ bool mp_os_dupterm_is_builtin_stream(mp_const_obj_t stream);
void mp_os_dupterm_stream_detached_attached(mp_obj_t stream_detached, mp_obj_t stream_attached);
uintptr_t mp_os_dupterm_poll(uintptr_t poll_flags);
int mp_os_dupterm_rx_chr(void);
void mp_os_dupterm_tx_strn(const char *str, size_t len);
int mp_os_dupterm_tx_strn(const char *str, size_t len);
void mp_os_deactivate(size_t dupterm_idx, const char *msg, mp_obj_t exc);
#else
#define mp_os_dupterm_tx_strn(s, l)
static inline int mp_os_dupterm_tx_strn(const char *s, size_t l) {
return -1;
}
#endif
#endif // MICROPY_INCLUDED_EXTMOD_MISC_H

View File

@ -1276,6 +1276,7 @@ STATIC mp_obj_t invoke_irq_handler(uint16_t event,
mp_stack_set_top(&ts + 1); // need to include ts in root-pointer scan
mp_stack_set_limit(MICROPY_PY_BLUETOOTH_SYNC_EVENT_STACK_SIZE - 1024);
ts.gc_lock_depth = 0;
ts.nlr_jump_callback_top = NULL;
ts.mp_pending_exception = MP_OBJ_NULL;
mp_locals_set(mp_state_ctx.thread.dict_locals); // set from the outer context
mp_globals_set(mp_state_ctx.thread.dict_globals); // set from the outer context

View File

@ -273,42 +273,59 @@ STATIC void fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w, int h, u
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_in) {
mp_arg_check_num(n_args, n_kw, 4, 5, false);
mp_obj_framebuf_t *o = mp_obj_malloc(mp_obj_framebuf_t, type);
o->buf_obj = args_in[0];
mp_int_t width = mp_obj_get_int(args_in[1]);
mp_int_t height = mp_obj_get_int(args_in[2]);
mp_int_t format = mp_obj_get_int(args_in[3]);
mp_int_t stride = n_args >= 5 ? mp_obj_get_int(args_in[4]) : width;
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args_in[0], &bufinfo, MP_BUFFER_WRITE);
o->buf = bufinfo.buf;
o->width = mp_obj_get_int(args_in[1]);
o->height = mp_obj_get_int(args_in[2]);
o->format = mp_obj_get_int(args_in[3]);
if (n_args >= 5) {
o->stride = mp_obj_get_int(args_in[4]);
} else {
o->stride = o->width;
if (width < 1 || height < 1 || width > 0xffff || height > 0xffff || stride > 0xffff || stride < width) {
mp_raise_ValueError(NULL);
}
switch (o->format) {
size_t height_required = height;
size_t bpp = 1;
switch (format) {
case FRAMEBUF_MVLSB:
case FRAMEBUF_RGB565:
height_required = (height + 7) & ~7;
break;
case FRAMEBUF_MHLSB:
case FRAMEBUF_MHMSB:
o->stride = (o->stride + 7) & ~7;
stride = (stride + 7) & ~7;
break;
case FRAMEBUF_GS2_HMSB:
o->stride = (o->stride + 3) & ~3;
stride = (stride + 3) & ~3;
bpp = 2;
break;
case FRAMEBUF_GS4_HMSB:
o->stride = (o->stride + 1) & ~1;
stride = (stride + 1) & ~1;
bpp = 4;
break;
case FRAMEBUF_GS8:
bpp = 8;
break;
case FRAMEBUF_RGB565:
bpp = 16;
break;
default:
mp_raise_ValueError(MP_ERROR_TEXT("invalid format"));
}
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args_in[0], &bufinfo, MP_BUFFER_WRITE);
if (height_required * stride * bpp / 8 > bufinfo.len) {
mp_raise_ValueError(NULL);
}
mp_obj_framebuf_t *o = mp_obj_malloc(mp_obj_framebuf_t, type);
o->buf_obj = args_in[0];
o->buf = bufinfo.buf;
o->width = width;
o->height = height;
o->format = format;
o->stride = stride;
return MP_OBJ_FROM_PTR(o);
}
@ -319,12 +336,8 @@ STATIC void framebuf_args(const mp_obj_t *args_in, mp_int_t *args_out, int n) {
}
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 = MP_OBJ_TO_PTR(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;
return mp_get_buffer(self->buf_obj, bufinfo, flags) ? 0 : 1;
}
STATIC mp_obj_t framebuf_fill(mp_obj_t self_in, mp_obj_t col_in) {
@ -851,28 +864,15 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE(
);
#endif
// this factory function is provided for backwards compatibility with old FrameBuffer1 class
#if !MICROPY_ENABLE_DYNRUNTIME
// This factory function is provided for backwards compatibility with the old
// FrameBuffer1 class which did not support a format argument.
STATIC mp_obj_t legacy_framebuffer1(size_t n_args, const mp_obj_t *args_in) {
mp_obj_framebuf_t *o = mp_obj_malloc(mp_obj_framebuf_t, (mp_obj_type_t *)&mp_type_framebuf);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args_in[0], &bufinfo, MP_BUFFER_WRITE);
o->buf = bufinfo.buf;
o->width = mp_obj_get_int(args_in[1]);
o->height = mp_obj_get_int(args_in[2]);
o->format = FRAMEBUF_MVLSB;
if (n_args >= 4) {
o->stride = mp_obj_get_int(args_in[3]);
} else {
o->stride = o->width;
}
return MP_OBJ_FROM_PTR(o);
mp_obj_t args[] = {args_in[0], args_in[1], args_in[2], MP_OBJ_NEW_SMALL_INT(FRAMEBUF_MVLSB), n_args >= 4 ? args_in[3] : args_in[1] };
return framebuf_make_new(&mp_type_framebuf, 5, 0, args);
}
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) },

View File

@ -297,7 +297,7 @@ STATIC mp_obj_t hashlib_md5_digest(mp_obj_t self_in) {
#if MICROPY_SSL_MBEDTLS
#if MBEDTLS_VERSION_NUMBER < 0x02070000
#if MBEDTLS_VERSION_NUMBER < 0x02070000 || MBEDTLS_VERSION_NUMBER >= 0x03000000
#define mbedtls_md5_starts_ret mbedtls_md5_starts
#define mbedtls_md5_update_ret mbedtls_md5_update
#define mbedtls_md5_finish_ret mbedtls_md5_finish

View File

@ -318,11 +318,7 @@ typedef struct _lwip_socket_obj_t {
} lwip_socket_obj_t;
static inline void poll_sockets(void) {
#ifdef MICROPY_EVENT_POLL_HOOK
MICROPY_EVENT_POLL_HOOK;
#else
mp_hal_delay_ms(1);
#endif
mp_event_wait_ms(1);
}
STATIC struct tcp_pcb *volatile *lwip_socket_incoming_array(lwip_socket_obj_t *socket) {

242
extmod/modmachine.c Normal file
View File

@ -0,0 +1,242 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2023 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"
#if MICROPY_PY_MACHINE
#include "extmod/modmachine.h"
#include "shared/runtime/pyexec.h"
#if MICROPY_PY_MACHINE_DHT_READINTO
#include "drivers/dht/dht.h"
#endif
// The port must provide implementations of these low-level machine functions.
STATIC void mp_machine_idle(void);
#if MICROPY_PY_MACHINE_BOOTLOADER
NORETURN void mp_machine_bootloader(size_t n_args, const mp_obj_t *args);
#endif
#if MICROPY_PY_MACHINE_BARE_METAL_FUNCS
STATIC mp_obj_t mp_machine_unique_id(void);
NORETURN STATIC void mp_machine_reset(void);
STATIC mp_int_t mp_machine_reset_cause(void);
STATIC mp_obj_t mp_machine_get_freq(void);
STATIC void mp_machine_set_freq(size_t n_args, const mp_obj_t *args);
STATIC void mp_machine_lightsleep(size_t n_args, const mp_obj_t *args);
NORETURN STATIC void mp_machine_deepsleep(size_t n_args, const mp_obj_t *args);
#endif
// The port can provide additional machine-module implementation in this file.
#ifdef MICROPY_PY_MACHINE_INCLUDEFILE
#include MICROPY_PY_MACHINE_INCLUDEFILE
#endif
STATIC mp_obj_t machine_soft_reset(void) {
pyexec_system_exit = PYEXEC_FORCED_EXIT;
mp_raise_type(&mp_type_SystemExit);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_soft_reset_obj, machine_soft_reset);
#if MICROPY_PY_MACHINE_BOOTLOADER
NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args) {
mp_machine_bootloader(n_args, args);
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_bootloader_obj, 0, 1, machine_bootloader);
#endif
STATIC mp_obj_t machine_idle(void) {
mp_machine_idle();
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_idle_obj, machine_idle);
#if MICROPY_PY_MACHINE_BARE_METAL_FUNCS
STATIC mp_obj_t machine_unique_id(void) {
return mp_machine_unique_id();
}
MP_DEFINE_CONST_FUN_OBJ_0(machine_unique_id_obj, machine_unique_id);
NORETURN STATIC mp_obj_t machine_reset(void) {
mp_machine_reset();
}
MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_obj, machine_reset);
STATIC mp_obj_t machine_reset_cause(void) {
return MP_OBJ_NEW_SMALL_INT(mp_machine_reset_cause());
}
MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_cause_obj, machine_reset_cause);
STATIC mp_obj_t machine_freq(size_t n_args, const mp_obj_t *args) {
if (n_args == 0) {
return mp_machine_get_freq();
} else {
mp_machine_set_freq(n_args, args);
return mp_const_none;
}
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_freq_obj, 0, 1, machine_freq);
STATIC mp_obj_t machine_lightsleep(size_t n_args, const mp_obj_t *args) {
mp_machine_lightsleep(n_args, args);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_lightsleep_obj, 0, 1, machine_lightsleep);
NORETURN STATIC mp_obj_t machine_deepsleep(size_t n_args, const mp_obj_t *args) {
mp_machine_deepsleep(n_args, args);
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_deepsleep_obj, 0, 1, machine_deepsleep);
#endif
#if MICROPY_PY_MACHINE_DISABLE_IRQ_ENABLE_IRQ
STATIC mp_obj_t machine_disable_irq(void) {
uint32_t state = MICROPY_BEGIN_ATOMIC_SECTION();
return mp_obj_new_int(state);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_disable_irq_obj, machine_disable_irq);
STATIC mp_obj_t machine_enable_irq(mp_obj_t state_in) {
uint32_t state = mp_obj_get_int(state_in);
MICROPY_END_ATOMIC_SECTION(state);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_enable_irq_obj, machine_enable_irq);
#endif
STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_machine) },
// Memory access objects.
{ MP_ROM_QSTR(MP_QSTR_mem8), MP_ROM_PTR(&machine_mem8_obj) },
{ MP_ROM_QSTR(MP_QSTR_mem16), MP_ROM_PTR(&machine_mem16_obj) },
{ MP_ROM_QSTR(MP_QSTR_mem32), MP_ROM_PTR(&machine_mem32_obj) },
// Miscellaneous functions.
#if MICROPY_PY_MACHINE_BARE_METAL_FUNCS
{ MP_ROM_QSTR(MP_QSTR_unique_id), MP_ROM_PTR(&machine_unique_id_obj) },
#endif
// Reset related functions.
{ MP_ROM_QSTR(MP_QSTR_soft_reset), MP_ROM_PTR(&machine_soft_reset_obj) },
#if MICROPY_PY_MACHINE_BOOTLOADER
{ MP_ROM_QSTR(MP_QSTR_bootloader), MP_ROM_PTR(&machine_bootloader_obj) },
#endif
#if MICROPY_PY_MACHINE_BARE_METAL_FUNCS
{ MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&machine_reset_obj) },
{ MP_ROM_QSTR(MP_QSTR_reset_cause), MP_ROM_PTR(&machine_reset_cause_obj) },
#endif
// Power related functions.
{ MP_ROM_QSTR(MP_QSTR_idle), MP_ROM_PTR(&machine_idle_obj) },
#if MICROPY_PY_MACHINE_BARE_METAL_FUNCS
{ MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&machine_freq_obj) },
{ MP_ROM_QSTR(MP_QSTR_lightsleep), MP_ROM_PTR(&machine_lightsleep_obj) },
{ MP_ROM_QSTR(MP_QSTR_deepsleep), MP_ROM_PTR(&machine_deepsleep_obj) },
#endif
// Interrupt related functions.
#if MICROPY_PY_MACHINE_DISABLE_IRQ_ENABLE_IRQ
{ MP_ROM_QSTR(MP_QSTR_disable_irq), MP_ROM_PTR(&machine_disable_irq_obj) },
{ MP_ROM_QSTR(MP_QSTR_enable_irq), MP_ROM_PTR(&machine_enable_irq_obj) },
#endif
// Functions for bit protocols.
#if MICROPY_PY_MACHINE_BITSTREAM
{ MP_ROM_QSTR(MP_QSTR_bitstream), MP_ROM_PTR(&machine_bitstream_obj) },
#endif
#if MICROPY_PY_MACHINE_DHT_READINTO
{ MP_ROM_QSTR(MP_QSTR_dht_readinto), MP_ROM_PTR(&dht_readinto_obj) },
#endif
#if MICROPY_PY_MACHINE_PULSE
{ MP_ROM_QSTR(MP_QSTR_time_pulse_us), MP_ROM_PTR(&machine_time_pulse_us_obj) },
#endif
// Classes for PinBase and Signal.
#if MICROPY_PY_MACHINE_PIN_BASE
{ MP_ROM_QSTR(MP_QSTR_PinBase), MP_ROM_PTR(&machine_pinbase_type) },
#endif
{ MP_ROM_QSTR(MP_QSTR_Signal), MP_ROM_PTR(&machine_signal_type) },
// Classes for software bus protocols.
#if MICROPY_PY_MACHINE_SOFTI2C
{ MP_ROM_QSTR(MP_QSTR_SoftI2C), MP_ROM_PTR(&mp_machine_soft_i2c_type) },
#endif
#if MICROPY_PY_MACHINE_SOFTSPI
{ MP_ROM_QSTR(MP_QSTR_SoftSPI), MP_ROM_PTR(&mp_machine_soft_spi_type) },
#endif
// Classes for hardware peripherals.
#if MICROPY_PY_MACHINE_ADC
{ MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&machine_adc_type) },
#endif
#if MICROPY_PY_MACHINE_ADC_BLOCK
{ MP_ROM_QSTR(MP_QSTR_ADCBlock), MP_ROM_PTR(&machine_adc_block_type) },
#endif
#if MICROPY_PY_MACHINE_DAC
{ MP_ROM_QSTR(MP_QSTR_DAC), MP_ROM_PTR(&machine_dac_type) },
#endif
#if MICROPY_PY_MACHINE_I2C
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) },
#endif
#if MICROPY_PY_MACHINE_I2S
{ MP_ROM_QSTR(MP_QSTR_I2S), MP_ROM_PTR(&machine_i2s_type) },
#endif
#if MICROPY_PY_MACHINE_PWM
{ MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&machine_pwm_type) },
#endif
#if MICROPY_PY_MACHINE_SPI
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_spi_type) },
#endif
#if MICROPY_PY_MACHINE_UART
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&machine_uart_type) },
#endif
#if MICROPY_PY_MACHINE_WDT
{ MP_ROM_QSTR(MP_QSTR_WDT), MP_ROM_PTR(&machine_wdt_type) },
#endif
// A port can add extra entries to the module by defining the following macro.
#ifdef MICROPY_PY_MACHINE_EXTRA_GLOBALS
MICROPY_PY_MACHINE_EXTRA_GLOBALS
#endif
};
STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table);
const mp_obj_module_t mp_module_machine = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t *)&machine_module_globals,
};
MP_REGISTER_EXTENSIBLE_MODULE(MP_QSTR_machine, mp_module_machine);
#endif // MICROPY_PY_MACHINE

269
extmod/modmachine.h Normal file
View File

@ -0,0 +1,269 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2023 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_MODMACHINE_H
#define MICROPY_INCLUDED_EXTMOD_MODMACHINE_H
#include "py/mphal.h"
#include "py/obj.h"
#if MICROPY_PY_MACHINE
#include "drivers/bus/spi.h"
// Whether to enable the ADC.init() method.
// Requires a port to implement mp_machine_adc_init_helper().
#ifndef MICROPY_PY_MACHINE_ADC_INIT
#define MICROPY_PY_MACHINE_ADC_INIT (0)
#endif
// Whether to enable the ADC.deinit() method.
// Requires a port to implement mp_machine_adc_deinit().
#ifndef MICROPY_PY_MACHINE_ADC_DEINIT
#define MICROPY_PY_MACHINE_ADC_DEINIT (0)
#endif
// Whether to enable the ADC.block() method.
// Requires a port to implement mp_machine_adc_block().
#ifndef MICROPY_PY_MACHINE_ADC_BLOCK
#define MICROPY_PY_MACHINE_ADC_BLOCK (0)
#endif
// Whether to enable the ADC.read_uv() method.
// Requires a port to implement mp_machine_adc_read_uv().
#ifndef MICROPY_PY_MACHINE_ADC_READ_UV
#define MICROPY_PY_MACHINE_ADC_READ_UV (0)
#endif
// Whether to enable the ADC.atten() and ADC.width() methods.
// Note: these are legacy and should not be used on new ports.
#ifndef MICROPY_PY_MACHINE_ADC_ATTEN_WIDTH
#define MICROPY_PY_MACHINE_ADC_ATTEN_WIDTH (0)
#endif
// Whether to enable the ADC.read() method.
// Note: this is legacy and should not be used on new ports.
#ifndef MICROPY_PY_MACHINE_ADC_READ
#define MICROPY_PY_MACHINE_ADC_READ (0)
#endif
// Whether to enable the UART.sendbreak() method.
// Requires a port to implement mp_machine_uart_sendbreak().
#ifndef MICROPY_PY_MACHINE_UART_SENDBREAK
#define MICROPY_PY_MACHINE_UART_SENDBREAK (0)
#endif
// Whether to enable the UART.readchar() and UART.writechar() methods.
// Requires a port to implement mp_machine_uart_readchar() and mp_machine_uart_writechar().
#ifndef MICROPY_PY_MACHINE_UART_READCHAR_WRITECHAR
#define MICROPY_PY_MACHINE_UART_READCHAR_WRITECHAR (0)
#endif
// Whether to enable the UART.irq() method.
// Requires a port to implement mp_machine_uart_irq().
#ifndef MICROPY_PY_MACHINE_UART_IRQ
#define MICROPY_PY_MACHINE_UART_IRQ (0)
#endif
// Temporary support for legacy construction of SoftI2C via I2C type.
#define MP_MACHINE_I2C_CHECK_FOR_LEGACY_SOFTI2C_CONSTRUCTION(n_args, n_kw, all_args) \
do { \
if (n_args == 0 || all_args[0] == MP_OBJ_NEW_SMALL_INT(-1)) { \
mp_print_str(MICROPY_ERROR_PRINTER, "Warning: I2C(-1, ...) is deprecated, use SoftI2C(...) instead\n"); \
if (n_args != 0) { \
--n_args; \
++all_args; \
} \
return MP_OBJ_TYPE_GET_SLOT(&mp_machine_soft_i2c_type, make_new)(&mp_machine_soft_i2c_type, n_args, n_kw, all_args); \
} \
} while (0)
// Temporary support for legacy construction of SoftSPI via SPI type.
#define MP_MACHINE_SPI_CHECK_FOR_LEGACY_SOFTSPI_CONSTRUCTION(n_args, n_kw, all_args) \
do { \
if (n_args == 0 || all_args[0] == MP_OBJ_NEW_SMALL_INT(-1)) { \
mp_print_str(MICROPY_ERROR_PRINTER, "Warning: SPI(-1, ...) is deprecated, use SoftSPI(...) instead\n"); \
if (n_args != 0) { \
--n_args; \
++all_args; \
} \
return MP_OBJ_TYPE_GET_SLOT(&mp_machine_soft_spi_type, make_new)(&mp_machine_soft_spi_type, n_args, n_kw, all_args); \
} \
} while (0)
#if MICROPY_PY_MACHINE_I2C || MICROPY_PY_MACHINE_SOFTI2C
#define MP_MACHINE_I2C_FLAG_READ (0x01) // if not set then it's a write
#define MP_MACHINE_I2C_FLAG_STOP (0x02)
#if MICROPY_PY_MACHINE_I2C_TRANSFER_WRITE1
// If set, the first mp_machine_i2c_buf_t in a transfer is a write.
#define MP_MACHINE_I2C_FLAG_WRITE1 (0x04)
#endif
#endif
// A port must provide these types, but they are otherwise opaque.
typedef struct _machine_adc_obj_t machine_adc_obj_t;
typedef struct _machine_adc_block_obj_t machine_adc_block_obj_t;
typedef struct _machine_i2s_obj_t machine_i2s_obj_t;
typedef struct _machine_pwm_obj_t machine_pwm_obj_t;
typedef struct _machine_uart_obj_t machine_uart_obj_t;
typedef struct _machine_wdt_obj_t machine_wdt_obj_t;
typedef struct _machine_mem_obj_t {
mp_obj_base_t base;
unsigned elem_size; // in bytes
} machine_mem_obj_t;
#if MICROPY_PY_MACHINE_I2C || MICROPY_PY_MACHINE_SOFTI2C
typedef struct _mp_machine_i2c_buf_t {
size_t len;
uint8_t *buf;
} mp_machine_i2c_buf_t;
// I2C protocol:
// - init must be non-NULL
// - start/stop/read/write can be NULL, meaning operation is not supported
// - transfer must be non-NULL
// - transfer_single only needs to be set if transfer=mp_machine_i2c_transfer_adaptor
typedef struct _mp_machine_i2c_p_t {
#if MICROPY_PY_MACHINE_I2C_TRANSFER_WRITE1
bool transfer_supports_write1;
#endif
void (*init)(mp_obj_base_t *obj, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
int (*start)(mp_obj_base_t *obj);
int (*stop)(mp_obj_base_t *obj);
int (*read)(mp_obj_base_t *obj, uint8_t *dest, size_t len, bool nack);
int (*write)(mp_obj_base_t *obj, const uint8_t *src, size_t len);
int (*transfer)(mp_obj_base_t *obj, uint16_t addr, size_t n, mp_machine_i2c_buf_t *bufs, unsigned int flags);
int (*transfer_single)(mp_obj_base_t *obj, uint16_t addr, size_t len, uint8_t *buf, unsigned int flags);
} mp_machine_i2c_p_t;
// SoftI2C object.
typedef struct _mp_machine_soft_i2c_obj_t {
mp_obj_base_t base;
uint32_t us_delay;
uint32_t us_timeout;
mp_hal_pin_obj_t scl;
mp_hal_pin_obj_t sda;
} mp_machine_soft_i2c_obj_t;
#endif
#if MICROPY_PY_MACHINE_SPI || MICROPY_PY_MACHINE_SOFTSPI
// SPI protocol.
typedef struct _mp_machine_spi_p_t {
void (*init)(mp_obj_base_t *obj, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
void (*deinit)(mp_obj_base_t *obj); // can be NULL
void (*transfer)(mp_obj_base_t *obj, size_t len, const uint8_t *src, uint8_t *dest);
} mp_machine_spi_p_t;
// SoftSPI object.
typedef struct _mp_machine_soft_spi_obj_t {
mp_obj_base_t base;
mp_soft_spi_obj_t spi;
} mp_machine_soft_spi_obj_t;
#endif
// Objects for machine.mem8, machine.mem16 and machine.mem32.
extern const machine_mem_obj_t machine_mem8_obj;
extern const machine_mem_obj_t machine_mem16_obj;
extern const machine_mem_obj_t machine_mem32_obj;
// These classes correspond to machine.Type entries in the machine module.
// Their Python bindings are implemented in extmod, and their implementation
// is provided by a port.
extern const mp_obj_type_t machine_adc_type;
extern const mp_obj_type_t machine_adc_block_type;
extern const mp_obj_type_t machine_i2c_type;
extern const mp_obj_type_t machine_i2s_type;
extern const mp_obj_type_t machine_mem_type;
extern const mp_obj_type_t machine_pin_type;
extern const mp_obj_type_t machine_pinbase_type;
extern const mp_obj_type_t machine_pwm_type;
extern const mp_obj_type_t machine_rtc_type;
extern const mp_obj_type_t machine_signal_type;
extern const mp_obj_type_t machine_spi_type;
extern const mp_obj_type_t machine_timer_type;
extern const mp_obj_type_t machine_uart_type;
extern const mp_obj_type_t machine_wdt_type;
#if MICROPY_PY_MACHINE_SOFTI2C
extern const mp_obj_type_t mp_machine_soft_i2c_type;
#endif
#if MICROPY_PY_MACHINE_I2C || MICROPY_PY_MACHINE_SOFTI2C
extern const mp_obj_dict_t mp_machine_i2c_locals_dict;
#endif
#if MICROPY_PY_MACHINE_SOFTSPI
extern const mp_obj_type_t mp_machine_soft_spi_type;
extern const mp_machine_spi_p_t mp_machine_soft_spi_p;
#endif
#if MICROPY_PY_MACHINE_SPI || MICROPY_PY_MACHINE_SOFTSPI
extern const mp_obj_dict_t mp_machine_spi_locals_dict;
#endif
#if defined(MICROPY_MACHINE_MEM_GET_READ_ADDR)
uintptr_t MICROPY_MACHINE_MEM_GET_READ_ADDR(mp_obj_t addr_o, uint align);
#endif
#if defined(MICROPY_MACHINE_MEM_GET_WRITE_ADDR)
uintptr_t MICROPY_MACHINE_MEM_GET_WRITE_ADDR(mp_obj_t addr_o, uint align);
#endif
NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args);
void machine_bitstream_high_low(mp_hal_pin_obj_t pin, uint32_t *timing_ns, const uint8_t *buf, size_t len);
mp_uint_t machine_time_pulse_us(mp_hal_pin_obj_t pin, int pulse_level, mp_uint_t timeout_us);
MP_DECLARE_CONST_FUN_OBJ_0(machine_unique_id_obj);
MP_DECLARE_CONST_FUN_OBJ_0(machine_reset_obj);
MP_DECLARE_CONST_FUN_OBJ_0(machine_reset_cause_obj);
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(machine_freq_obj);
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(machine_lightsleep_obj);
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(machine_deepsleep_obj);
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(machine_bootloader_obj);
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(machine_bitstream_obj);
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(machine_time_pulse_us_obj);
#if MICROPY_PY_MACHINE_I2C
int mp_machine_i2c_transfer_adaptor(mp_obj_base_t *self, uint16_t addr, size_t n, mp_machine_i2c_buf_t *bufs, unsigned int flags);
int mp_machine_soft_i2c_transfer(mp_obj_base_t *self, uint16_t addr, size_t n, mp_machine_i2c_buf_t *bufs, unsigned int flags);
#endif
#if MICROPY_PY_MACHINE_SPI
mp_obj_t mp_machine_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args);
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_spi_read_obj);
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_spi_readinto_obj);
MP_DECLARE_CONST_FUN_OBJ_2(mp_machine_spi_write_obj);
MP_DECLARE_CONST_FUN_OBJ_3(mp_machine_spi_write_readinto_obj);
#endif
#endif // MICROPY_PY_MACHINE
#endif // MICROPY_INCLUDED_EXTMOD_MODMACHINE_H

View File

@ -65,6 +65,15 @@ void mod_network_init(void) {
}
void mod_network_deinit(void) {
#if !MICROPY_PY_LWIP
for (mp_uint_t i = 0; i < MP_STATE_PORT(mod_network_nic_list).len; i++) {
mp_obj_t nic = MP_STATE_PORT(mod_network_nic_list).items[i];
const mod_network_nic_protocol_t *nic_protocol = MP_OBJ_TYPE_GET_SLOT(mp_obj_get_type(nic), protocol);
if (nic_protocol->deinit) {
nic_protocol->deinit();
}
}
#endif
}
void mod_network_register_nic(mp_obj_t nic) {

View File

@ -80,6 +80,7 @@ struct _mod_network_socket_obj_t;
typedef struct _mod_network_nic_protocol_t {
// API for non-socket operations
int (*gethostbyname)(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *ip_out);
void (*deinit)(void);
// API for socket operations; return -1 on error
int (*socket)(struct _mod_network_socket_obj_t *socket, int *_errno);

View File

@ -38,11 +38,11 @@
#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_READ1 (6)
#define TIMING_READ2 (9)
#define TIMING_READ3 (55)
#define TIMING_WRITE1 (6)
#define TIMING_WRITE2 (54)
#define TIMING_WRITE3 (10)
STATIC int onewire_bus_reset(mp_hal_pin_obj_t pin) {

View File

@ -24,6 +24,7 @@
* THE SOFTWARE.
*/
#include "py/mphal.h"
#include "py/objstr.h"
#include "py/runtime.h"
@ -48,6 +49,13 @@
#include "extmod/vfs_posix.h"
#endif
#if MICROPY_MBFS
#if MICROPY_VFS
#error "MICROPY_MBFS requires MICROPY_VFS to be disabled"
#endif
#include "ports/nrf/modules/os/microbitfs.h"
#endif
#if MICROPY_PY_OS_UNAME
#include "genhdr/mpversion.h"
#endif
@ -121,6 +129,21 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_os_uname_obj, mp_os_uname);
#endif
#if MICROPY_PY_OS_DUPTERM_NOTIFY
STATIC mp_obj_t mp_os_dupterm_notify(mp_obj_t obj_in) {
(void)obj_in;
for (;;) {
int c = mp_os_dupterm_rx_chr();
if (c < 0) {
break;
}
ringbuf_put(&stdin_ringbuf, c);
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_os_dupterm_notify_obj, mp_os_dupterm_notify);
#endif
STATIC const mp_rom_map_elem_t os_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_os) },
@ -187,6 +210,14 @@ STATIC const mp_rom_map_elem_t os_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_VfsPosix), MP_ROM_PTR(&mp_type_vfs_posix) },
#endif
#endif
#if MICROPY_MBFS
// For special micro:bit filesystem only.
{ MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&os_mbfs_listdir_obj) },
{ MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&os_mbfs_ilistdir_obj) },
{ MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&os_mbfs_stat_obj) },
{ MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&os_mbfs_remove_obj) },
#endif
};
STATIC MP_DEFINE_CONST_DICT(os_module_globals, os_module_globals_table);

View File

@ -207,12 +207,12 @@ STATIC mp_obj_t re_exec(bool is_anchored, uint n_args, const mp_obj_t *args) {
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;
mp_obj_match_t *match = m_new_obj_var(mp_obj_match_t, char *, caps_num);
mp_obj_match_t *match = m_new_obj_var(mp_obj_match_t, caps, char *, caps_num);
// cast is a workaround for a bug in msvc: it treats const char** as a const pointer instead of a pointer to pointer to const char
memset((char *)match->caps, 0, caps_num * sizeof(char *));
int res = re1_5_recursiveloopprog(&self->re, &subj, match->caps, caps_num, is_anchored);
if (res == 0) {
m_del_var(mp_obj_match_t, char *, caps_num, match);
m_del_var(mp_obj_match_t, caps, char *, caps_num, match);
return mp_const_none;
}

View File

@ -41,6 +41,7 @@
#if MICROPY_PY_SELECT_POSIX_OPTIMISATIONS
#include <string.h>
#include <poll.h>
#if !((MP_STREAM_POLL_RD) == (POLLIN) && \
@ -142,14 +143,47 @@ STATIC void poll_obj_set_revents(poll_obj_t *poll_obj, mp_uint_t revents) {
}
}
// How much (in pollfds) to grow the allocation for poll_set->pollfds by.
#define POLL_SET_ALLOC_INCREMENT (4)
STATIC struct pollfd *poll_set_add_fd(poll_set_t *poll_set, int fd) {
struct pollfd *free_slot = NULL;
if (poll_set->used == poll_set->max_used) {
// No free slots below max_used, so expand max_used (and possibly allocate).
if (poll_set->max_used >= poll_set->alloc) {
poll_set->pollfds = m_renew(struct pollfd, poll_set->pollfds, poll_set->alloc, poll_set->alloc + 4);
poll_set->alloc += 4;
size_t new_alloc = poll_set->alloc + POLL_SET_ALLOC_INCREMENT;
// Try to grow in-place.
struct pollfd *new_fds = m_renew_maybe(struct pollfd, poll_set->pollfds, poll_set->alloc, new_alloc, false);
if (!new_fds) {
// Failed to grow in-place. Do a new allocation and copy over the pollfd values.
new_fds = m_new(struct pollfd, new_alloc);
memcpy(new_fds, poll_set->pollfds, sizeof(struct pollfd) * poll_set->alloc);
// Update existing poll_obj_t to update their pollfd field to
// point to the same offset inside the new allocation.
for (mp_uint_t i = 0; i < poll_set->map.alloc; ++i) {
if (!mp_map_slot_is_filled(&poll_set->map, i)) {
continue;
}
poll_obj_t *poll_obj = MP_OBJ_TO_PTR(poll_set->map.table[i].value);
if (!poll_obj) {
// This is the one we're currently adding,
// poll_set_add_obj doesn't assign elem->value until
// afterwards.
continue;
}
poll_obj->pollfd = new_fds + (poll_obj->pollfd - poll_set->pollfds);
}
// Delete the old allocation.
m_del(struct pollfd, poll_set->pollfds, poll_set->alloc);
}
poll_set->pollfds = new_fds;
poll_set->alloc = new_alloc;
}
free_slot = &poll_set->pollfds[poll_set->max_used++];
} else {
@ -306,6 +340,7 @@ STATIC mp_uint_t poll_set_poll_once(poll_set_t *poll_set, size_t *rwx_num) {
STATIC mp_uint_t poll_set_poll_until_ready_or_timeout(poll_set_t *poll_set, size_t *rwx_num, mp_uint_t timeout) {
mp_uint_t start_ticks = mp_hal_ticks_ms();
bool has_timeout = timeout != (mp_uint_t)-1;
#if MICROPY_PY_SELECT_POSIX_OPTIMISATIONS
@ -350,12 +385,12 @@ STATIC mp_uint_t poll_set_poll_until_ready_or_timeout(poll_set_t *poll_set, size
}
// Return if an object is ready, or if the timeout expired.
if (n_ready > 0 || (timeout != (mp_uint_t)-1 && mp_hal_ticks_ms() - start_ticks >= timeout)) {
if (n_ready > 0 || (has_timeout && mp_hal_ticks_ms() - start_ticks >= timeout)) {
return n_ready;
}
// This would be MICROPY_EVENT_POLL_HOOK but the call to poll() above already includes a delay.
mp_handle_pending(true);
// This would be mp_event_wait_ms() but the call to poll() above already includes a delay.
mp_event_handle_nowait();
}
#else
@ -363,10 +398,15 @@ STATIC mp_uint_t poll_set_poll_until_ready_or_timeout(poll_set_t *poll_set, size
for (;;) {
// poll the objects
mp_uint_t n_ready = poll_set_poll_once(poll_set, rwx_num);
if (n_ready > 0 || (timeout != (mp_uint_t)-1 && mp_hal_ticks_ms() - start_ticks >= timeout)) {
uint32_t elapsed = mp_hal_ticks_ms() - start_ticks;
if (n_ready > 0 || (has_timeout && elapsed >= timeout)) {
return n_ready;
}
MICROPY_EVENT_POLL_HOOK
if (has_timeout) {
mp_event_wait_ms(timeout - elapsed);
} else {
mp_event_wait_indefinite();
}
}
#endif

View File

@ -36,6 +36,8 @@
#include "py/runtime.h"
#include "py/stream.h"
#include "py/objstr.h"
#include "py/reader.h"
#include "extmod/vfs.h"
// mbedtls_time_t
#include "mbedtls/platform.h"
@ -46,6 +48,11 @@
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/debug.h"
#include "mbedtls/error.h"
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
#include "mbedtls/build_info.h"
#else
#include "mbedtls/version.h"
#endif
#define MP_STREAM_POLL_RDWR (MP_STREAM_POLL_RD | MP_STREAM_POLL_WR)
@ -59,6 +66,7 @@ typedef struct _mp_obj_ssl_context_t {
mbedtls_x509_crt cert;
mbedtls_pk_context pkey;
int authmode;
int *ciphersuites;
} mp_obj_ssl_context_t;
// This corresponds to an SSLSocket object.
@ -75,12 +83,32 @@ typedef struct _mp_obj_ssl_socket_t {
STATIC const mp_obj_type_t ssl_context_type;
STATIC const mp_obj_type_t ssl_socket_type;
STATIC const MP_DEFINE_STR_OBJ(mbedtls_version_obj, MBEDTLS_VERSION_STRING_FULL);
STATIC mp_obj_t ssl_socket_make_new(mp_obj_ssl_context_t *ssl_context, mp_obj_t sock,
bool server_side, bool do_handshake_on_connect, mp_obj_t server_hostname);
/******************************************************************************/
// Helper functions.
STATIC mp_obj_t read_file(mp_obj_t self_in) {
// file = open(args[0], "rb")
mp_obj_t f_args[2] = {
self_in,
MP_OBJ_NEW_QSTR(MP_QSTR_rb),
};
mp_obj_t file = mp_vfs_open(2, &f_args[0], (mp_map_t *)&mp_const_empty_map);
// data = file.read()
mp_obj_t dest[2];
mp_load_method(file, MP_QSTR_read, dest);
mp_obj_t data = mp_call_method_n_kw(0, 0, dest);
// file.close()
mp_stream_close(file);
return data;
}
#ifdef MBEDTLS_DEBUG_C
STATIC void mbedtls_debug(void *ctx, int level, const char *file, int line, const char *str) {
(void)ctx;
@ -138,6 +166,46 @@ STATIC NORETURN void mbedtls_raise_error(int err) {
#endif
}
STATIC void ssl_check_async_handshake_failure(mp_obj_ssl_socket_t *sslsock, int *errcode) {
if (
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
(*errcode < 0) && (mbedtls_ssl_is_handshake_over(&sslsock->ssl) == 0) && (*errcode != MBEDTLS_ERR_SSL_CONN_EOF)
#else
(*errcode < 0) && (*errcode != MBEDTLS_ERR_SSL_CONN_EOF)
#endif
) {
// Asynchronous handshake is done by mbdetls_ssl_read/write. If the return code is
// MBEDTLS_ERR_XX (i.e < 0) and the handshake is not done due to a handshake failure,
// then notify peer with proper error code and raise local error with mbedtls_raise_error.
if (*errcode == MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE) {
// Check if TLSv1.3 and use proper alert for this case (to be implemented)
// uint8_t alert = MBEDTLS_SSL_ALERT_MSG_CERT_REQUIRED; tlsv1.3
// uint8_t alert = MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE; tlsv1.2
mbedtls_ssl_send_alert_message(&sslsock->ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);
}
if (*errcode == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) {
// The certificate may have been rejected for several reasons.
char xcbuf[256];
uint32_t flags = mbedtls_ssl_get_verify_result(&sslsock->ssl);
int ret = mbedtls_x509_crt_verify_info(xcbuf, sizeof(xcbuf), "\n", flags);
// The length of the string written (not including the terminated nul byte),
// or a negative err code.
if (ret > 0) {
sslsock->sock = MP_OBJ_NULL;
mbedtls_ssl_free(&sslsock->ssl);
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("%s"), xcbuf);
}
}
sslsock->sock = MP_OBJ_NULL;
mbedtls_ssl_free(&sslsock->ssl);
mbedtls_raise_error(*errcode);
}
}
/******************************************************************************/
// SSLContext type.
@ -162,6 +230,7 @@ STATIC mp_obj_t ssl_context_make_new(const mp_obj_type_t *type_in, size_t n_args
mbedtls_x509_crt_init(&self->cacert);
mbedtls_x509_crt_init(&self->cert);
mbedtls_pk_init(&self->pkey);
self->ciphersuites = NULL;
#ifdef MBEDTLS_DEBUG_C
// Debug level (0-4) 1=warning, 2=info, 3=debug, 4=verbose
@ -236,6 +305,52 @@ STATIC mp_obj_t ssl_context___del__(mp_obj_t self_in) {
STATIC MP_DEFINE_CONST_FUN_OBJ_1(ssl_context___del___obj, ssl_context___del__);
#endif
// SSLContext.get_ciphers()
STATIC mp_obj_t ssl_context_get_ciphers(mp_obj_t self_in) {
mp_obj_t list = mp_obj_new_list(0, NULL);
for (const int *cipher_list = mbedtls_ssl_list_ciphersuites(); *cipher_list; ++cipher_list) {
const char *cipher_name = mbedtls_ssl_get_ciphersuite_name(*cipher_list);
mp_obj_list_append(list, MP_OBJ_FROM_PTR(mp_obj_new_str(cipher_name, strlen(cipher_name))));
cipher_list++;
if (!*cipher_list) {
break;
}
}
return list;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(ssl_context_get_ciphers_obj, ssl_context_get_ciphers);
// SSLContext.set_ciphers(ciphersuite)
STATIC mp_obj_t ssl_context_set_ciphers(mp_obj_t self_in, mp_obj_t ciphersuite) {
mp_obj_ssl_context_t *ssl_context = MP_OBJ_TO_PTR(self_in);
// Check that ciphersuite is a list or tuple.
size_t len = 0;
mp_obj_t *ciphers;
mp_obj_get_array(ciphersuite, &len, &ciphers);
if (len == 0) {
mbedtls_raise_error(MBEDTLS_ERR_SSL_BAD_CONFIG);
}
// Parse list of ciphers.
ssl_context->ciphersuites = m_new(int, len + 1);
for (size_t i = 0; i < len; ++i) {
const char *ciphername = mp_obj_str_get_str(ciphers[i]);
const int id = mbedtls_ssl_get_ciphersuite_id(ciphername);
if (id == 0) {
mbedtls_raise_error(MBEDTLS_ERR_SSL_BAD_CONFIG);
}
ssl_context->ciphersuites[i] = id;
}
ssl_context->ciphersuites[len] = 0;
// Configure ciphersuite.
mbedtls_ssl_conf_ciphersuites(&ssl_context->conf, (const int *)ssl_context->ciphersuites);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(ssl_context_set_ciphers_obj, ssl_context_set_ciphers);
STATIC void ssl_context_load_key(mp_obj_ssl_context_t *self, mp_obj_t key_obj, mp_obj_t cert_obj) {
size_t key_len;
const byte *key = (const byte *)mp_obj_str_get_data(key_obj, &key_len);
@ -264,6 +379,30 @@ STATIC void ssl_context_load_key(mp_obj_ssl_context_t *self, mp_obj_t key_obj, m
}
}
// SSLContext.load_cert_chain(certfile, keyfile)
STATIC mp_obj_t ssl_context_load_cert_chain(mp_obj_t self_in, mp_obj_t certfile, mp_obj_t keyfile) {
mp_obj_ssl_context_t *self = MP_OBJ_TO_PTR(self_in);
mp_obj_t pkey;
mp_obj_t cert;
if (certfile != mp_const_none) {
// check if key is a string/path
if (!(mp_obj_is_type(keyfile, &mp_type_bytes))) {
pkey = read_file(keyfile);
} else {
pkey = keyfile;
}
// check if cert is a string/path
if (!(mp_obj_is_type(certfile, &mp_type_bytes))) {
cert = read_file(certfile);
} else {
cert = certfile;
}
ssl_context_load_key(self, pkey, cert);
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(ssl_context_load_cert_chain_obj, ssl_context_load_cert_chain);
STATIC void ssl_context_load_cadata(mp_obj_ssl_context_t *self, mp_obj_t cadata_obj) {
size_t cacert_len;
const byte *cacert = (const byte *)mp_obj_str_get_data(cadata_obj, &cacert_len);
@ -276,6 +415,30 @@ STATIC void ssl_context_load_cadata(mp_obj_ssl_context_t *self, mp_obj_t cadata_
mbedtls_ssl_conf_ca_chain(&self->conf, &self->cacert, NULL);
}
// SSLContext.load_verify_locations(cafile=None, *, cadata=None)
STATIC mp_obj_t ssl_context_load_verify_locations(size_t n_args, const mp_obj_t *pos_args,
mp_map_t *kw_args) {
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_cafile, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
{ MP_QSTR_cadata, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
};
mp_obj_ssl_context_t *self = MP_OBJ_TO_PTR(pos_args[0]);
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
// cafile
if (args[0].u_obj != mp_const_none) {
ssl_context_load_cadata(self, read_file(args[0].u_obj));
}
// cadata
if (args[1].u_obj != mp_const_none) {
ssl_context_load_cadata(self, args[1].u_obj);
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(ssl_context_load_verify_locations_obj, 1, ssl_context_load_verify_locations);
STATIC mp_obj_t ssl_context_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_server_side, ARG_do_handshake_on_connect, ARG_server_hostname };
static const mp_arg_t allowed_args[] = {
@ -300,6 +463,10 @@ STATIC const mp_rom_map_elem_t ssl_context_locals_dict_table[] = {
#if MICROPY_PY_SSL_FINALISER
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&ssl_context___del___obj) },
#endif
{ MP_ROM_QSTR(MP_QSTR_get_ciphers), MP_ROM_PTR(&ssl_context_get_ciphers_obj)},
{ MP_ROM_QSTR(MP_QSTR_set_ciphers), MP_ROM_PTR(&ssl_context_set_ciphers_obj)},
{ MP_ROM_QSTR(MP_QSTR_load_cert_chain), MP_ROM_PTR(&ssl_context_load_cert_chain_obj)},
{ MP_ROM_QSTR(MP_QSTR_load_verify_locations), MP_ROM_PTR(&ssl_context_load_verify_locations_obj)},
{ MP_ROM_QSTR(MP_QSTR_wrap_socket), MP_ROM_PTR(&ssl_context_wrap_socket_obj) },
};
STATIC MP_DEFINE_CONST_DICT(ssl_context_locals_dict, ssl_context_locals_dict_table);
@ -369,6 +536,8 @@ STATIC mp_obj_t ssl_socket_make_new(mp_obj_ssl_context_t *ssl_context, mp_obj_t
o->last_error = 0;
int ret;
uint32_t flags = 0;
mbedtls_ssl_init(&o->ssl);
ret = mbedtls_ssl_setup(&o->ssl, &ssl_context->conf);
@ -382,6 +551,11 @@ STATIC mp_obj_t ssl_socket_make_new(mp_obj_ssl_context_t *ssl_context, mp_obj_t
if (ret != 0) {
goto cleanup;
}
} else if (ssl_context->authmode == MBEDTLS_SSL_VERIFY_REQUIRED && server_side == false) {
o->sock = MP_OBJ_NULL;
mbedtls_ssl_free(&o->ssl);
mp_raise_ValueError(MP_ERROR_TEXT("CERT_REQUIRED requires server_hostname"));
}
mbedtls_ssl_set_bio(&o->ssl, &o->sock, _mbedtls_ssl_send, _mbedtls_ssl_recv, NULL);
@ -391,20 +565,34 @@ STATIC mp_obj_t ssl_socket_make_new(mp_obj_ssl_context_t *ssl_context, mp_obj_t
if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
goto cleanup;
}
#ifdef MICROPY_EVENT_POLL_HOOK
MICROPY_EVENT_POLL_HOOK
#endif
mp_event_wait_ms(1);
}
}
return MP_OBJ_FROM_PTR(o);
cleanup:
if (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) {
flags = mbedtls_ssl_get_verify_result(&o->ssl);
}
o->sock = MP_OBJ_NULL;
mbedtls_ssl_free(&o->ssl);
if (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) {
char xcbuf[256];
int ret_info = mbedtls_x509_crt_verify_info(xcbuf, sizeof(xcbuf), "\n", flags);
// The length of the string written (not including the terminated nul byte),
// or a negative err code.
if (ret_info > 0) {
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("%s"), xcbuf);
}
}
mbedtls_raise_error(ret);
}
#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
STATIC mp_obj_t mod_ssl_getpeercert(mp_obj_t o_in, mp_obj_t binary_form) {
mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in);
if (!mp_obj_is_true(binary_form)) {
@ -417,6 +605,18 @@ STATIC mp_obj_t mod_ssl_getpeercert(mp_obj_t o_in, mp_obj_t binary_form) {
return mp_obj_new_bytes(peer_cert->raw.p, peer_cert->raw.len);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_ssl_getpeercert_obj, mod_ssl_getpeercert);
#endif
STATIC mp_obj_t mod_ssl_cipher(mp_obj_t o_in) {
mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in);
const char *cipher_suite = mbedtls_ssl_get_ciphersuite(&o->ssl);
const char *tls_version = mbedtls_ssl_get_version(&o->ssl);
mp_obj_t tuple[2] = {mp_obj_new_str(cipher_suite, strlen(cipher_suite)),
mp_obj_new_str(tls_version, strlen(tls_version))};
return mp_obj_new_tuple(2, tuple);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ssl_cipher_obj, mod_ssl_cipher);
STATIC mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {
mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in);
@ -454,6 +654,7 @@ STATIC mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errc
} else {
o->last_error = ret;
}
ssl_check_async_handshake_failure(o, &ret);
*errcode = ret;
return MP_STREAM_ERROR;
}
@ -482,6 +683,7 @@ STATIC mp_uint_t socket_write(mp_obj_t o_in, const void *buf, mp_uint_t size, in
} else {
o->last_error = ret;
}
ssl_check_async_handshake_failure(o, &ret);
*errcode = ret;
return MP_STREAM_ERROR;
}
@ -566,7 +768,10 @@ STATIC const mp_rom_map_elem_t ssl_socket_locals_dict_table[] = {
#if MICROPY_UNIX_COVERAGE
{ MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&mp_stream_ioctl_obj) },
#endif
#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
{ MP_ROM_QSTR(MP_QSTR_getpeercert), MP_ROM_PTR(&mod_ssl_getpeercert_obj) },
#endif
{ MP_ROM_QSTR(MP_QSTR_cipher), MP_ROM_PTR(&mod_ssl_cipher_obj) },
};
STATIC MP_DEFINE_CONST_DICT(ssl_socket_locals_dict, ssl_socket_locals_dict_table);
@ -647,6 +852,7 @@ STATIC const mp_rom_map_elem_t mp_module_ssl_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_SSLContext), MP_ROM_PTR(&ssl_context_type) },
// Constants.
{ MP_ROM_QSTR(MP_QSTR_MBEDTLS_VERSION), MP_ROM_PTR(&mbedtls_version_obj)},
{ MP_ROM_QSTR(MP_QSTR_PROTOCOL_TLS_CLIENT), MP_ROM_INT(MBEDTLS_SSL_IS_CLIENT) },
{ MP_ROM_QSTR(MP_QSTR_PROTOCOL_TLS_SERVER), MP_ROM_INT(MBEDTLS_SSL_IS_SERVER) },
{ MP_ROM_QSTR(MP_QSTR_CERT_NONE), MP_ROM_INT(MBEDTLS_SSL_VERIFY_NONE) },

View File

@ -96,7 +96,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 = mp_obj_malloc(mp_obj_uctypes_struct_t, type);
o->addr = (void *)(uintptr_t)mp_obj_int_get_truncated(args[0]);
o->addr = (void *)(uintptr_t)mp_obj_get_int_truncated(args[0]);
o->desc = args[1];
o->flags = LAYOUT_NATIVE;
if (n_args == 3) {

View File

@ -222,8 +222,13 @@ STATIC mp_obj_t network_cyw43_scan(size_t n_args, const mp_obj_t *pos_args, mp_m
// Wait for scan to finish, with a 10s timeout
uint32_t start = mp_hal_ticks_ms();
while (cyw43_wifi_scan_active(self->cyw) && mp_hal_ticks_ms() - start < 10000) {
MICROPY_EVENT_POLL_HOOK
const uint32_t TIMEOUT = 10000;
while (cyw43_wifi_scan_active(self->cyw)) {
uint32_t elapsed = mp_hal_ticks_ms() - start;
if (elapsed >= TIMEOUT) {
break;
}
mp_event_wait_ms(TIMEOUT - elapsed);
}
return res;

View File

@ -42,6 +42,7 @@
#include "py/misc.h"
#include "py/mperrno.h"
#include "shared/netutils/netutils.h"
#include "shared/runtime/softtimer.h"
#include "extmod/modnetwork.h"
#include "modmachine.h"
@ -50,6 +51,7 @@
typedef struct _nina_obj_t {
mp_obj_base_t base;
bool active;
bool poll_enable;
uint32_t itf;
mp_uint_t security;
char ssid[NINA_MAX_SSID_LEN + 1];
@ -71,6 +73,7 @@ typedef struct _nina_obj_t {
#define SO_ERROR (0x1007)
#define SO_TYPE (0x1008)
#define SO_NO_CHECK (0x100a)
#define NINAW10_POLL_INTERVAL (100)
#define is_nonblocking_error(errno) ((errno) == MP_EAGAIN || (errno) == MP_EWOULDBLOCK || (errno) == MP_EINPROGRESS)
@ -78,28 +81,56 @@ typedef struct _nina_obj_t {
static uint16_t bind_port = BIND_PORT_RANGE_MIN;
const mp_obj_type_t mod_network_nic_type_nina;
static nina_obj_t network_nina_wl_sta = {{(mp_obj_type_t *)&mod_network_nic_type_nina}, false, MOD_NETWORK_STA_IF};
static nina_obj_t network_nina_wl_ap = {{(mp_obj_type_t *)&mod_network_nic_type_nina}, false, MOD_NETWORK_AP_IF};
static mp_sched_node_t mp_wifi_sockpoll_node;
static mp_sched_node_t mp_wifi_connpoll_node;
static nina_obj_t network_nina_wl_sta = {{(mp_obj_type_t *)&mod_network_nic_type_nina}, false, false, MOD_NETWORK_STA_IF};
static nina_obj_t network_nina_wl_ap = {{(mp_obj_type_t *)&mod_network_nic_type_nina}, false, false, MOD_NETWORK_AP_IF};
static mp_sched_node_t mp_wifi_poll_node;
static soft_timer_entry_t mp_wifi_poll_timer;
STATIC void network_ninaw10_deinit(void);
STATIC bool network_ninaw10_poll_list_is_empty(void) {
return MP_STATE_PORT(mp_wifi_poll_list) == NULL ||
MP_STATE_PORT(mp_wifi_poll_list)->len == 0;
}
STATIC void network_ninaw10_poll_list_insert(mp_obj_t socket) {
if (MP_STATE_PORT(mp_wifi_poll_list) == NULL) {
MP_STATE_PORT(mp_wifi_poll_list) = mp_obj_new_list(0, NULL);
}
mp_obj_list_append(MP_STATE_PORT(mp_wifi_poll_list), socket);
}
STATIC void network_ninaw10_poll_list_remove(mp_obj_t socket) {
if (MP_STATE_PORT(mp_wifi_poll_list) == NULL) {
return;
}
mp_obj_list_remove(MP_STATE_PORT(mp_wifi_poll_list), socket);
if (MP_STATE_PORT(mp_wifi_poll_list)->len == 0) {
MP_STATE_PORT(mp_wifi_poll_list) = NULL;
}
}
STATIC void network_ninaw10_poll_sockets(mp_sched_node_t *node) {
(void)node;
for (mp_uint_t i = 0; i < MP_STATE_PORT(mp_wifi_sockpoll_list)->len; i++) {
mod_network_socket_obj_t *socket = MP_STATE_PORT(mp_wifi_sockpoll_list)->items[i];
for (mp_uint_t i = 0; MP_STATE_PORT(mp_wifi_poll_list) && i < MP_STATE_PORT(mp_wifi_poll_list)->len;) {
mod_network_socket_obj_t *socket = MP_STATE_PORT(mp_wifi_poll_list)->items[i];
uint8_t flags = 0;
if (socket->callback == MP_OBJ_NULL || nina_socket_poll(socket->fileno, &flags) < 0) {
// remove from poll list on error.
// Remove socket from poll list on error.
socket->callback = MP_OBJ_NULL;
mp_obj_list_remove(MP_STATE_PORT(mp_wifi_sockpoll_list), socket);
} else if (flags) {
mp_call_function_1(socket->callback, MP_OBJ_FROM_PTR(socket));
if (flags & SOCKET_POLL_ERR) {
// remove from poll list on error.
socket->callback = MP_OBJ_NULL;
mp_obj_list_remove(MP_STATE_PORT(mp_wifi_sockpoll_list), socket);
}
network_ninaw10_poll_list_remove(socket);
// Check the same index on the next iteration.
continue;
}
if (flags & SOCKET_POLL_RD) {
mp_call_function_1(socket->callback, MP_OBJ_FROM_PTR(socket));
}
i++;
debug_printf("poll_sockets(%d) -> flags %d\n", socket->fileno, flags);
}
if (!network_ninaw10_poll_list_is_empty()) {
// Reschedule the sockets polling code.
soft_timer_reinsert(&mp_wifi_poll_timer, NINAW10_POLL_INTERVAL);
}
}
@ -109,10 +140,8 @@ STATIC void network_ninaw10_poll_connect(mp_sched_node_t *node) {
int status = nina_connection_status();
if (status == NINA_STATUS_CONNECTED) {
// Connected to AP, nothing else to do.
return;
}
if (status != NINA_STATUS_NO_SSID_AVAIL) {
self->poll_enable = false;
} else if (status != NINA_STATUS_NO_SSID_AVAIL) {
// If not connected, and no connection in progress, the connection attempt has failed.
// Read the ESP failure reason, reconnect and reschedule the connection polling code.
int reason = nina_connection_reason();
@ -121,7 +150,7 @@ STATIC void network_ninaw10_poll_connect(mp_sched_node_t *node) {
reason == NINA_ESP_REASON_NOT_AUTHED ||
reason == NINA_ESP_REASON_4WAY_HANDSHAKE_TIMEOUT ||
reason >= NINA_ESP_REASON_BEACON_TIMEOUT) {
debug_printf(&mp_plat_print, "poll_connect() status: %d reason %d\n", status, reason);
debug_printf("poll_connect() status: %d reason %d\n", status, reason);
if (nina_connect(self->ssid, self->security, self->key, 0) != 0) {
mp_raise_msg_varg(&mp_type_OSError,
MP_ERROR_TEXT("could not connect to ssid=%s, sec=%d, key=%s\n"),
@ -129,21 +158,23 @@ STATIC void network_ninaw10_poll_connect(mp_sched_node_t *node) {
}
} else {
// Will not attempt to reconnect if there's another error code set.
return;
self->poll_enable = false;
}
}
// Reschedule the connection polling code.
mp_sched_schedule_node(&mp_wifi_connpoll_node, network_ninaw10_poll_connect);
// Reinsert the timer to schedule the polling code.
soft_timer_reinsert(&mp_wifi_poll_timer, NINAW10_POLL_INTERVAL);
}
STATIC mp_obj_t network_ninaw10_timer_callback(mp_obj_t none_in) {
if (MP_STATE_PORT(mp_wifi_sockpoll_list) != MP_OBJ_NULL && MP_STATE_PORT(mp_wifi_sockpoll_list)->len) {
mp_sched_schedule_node(&mp_wifi_sockpoll_node, network_ninaw10_poll_sockets);
STATIC void network_ninaw10_timer_callback(soft_timer_entry_t *self) {
debug_printf("timer_callback() poll status STA: %d AP: %d SOCKETS: %d\n",
network_nina_wl_sta.poll_enable, network_nina_wl_ap.poll_enable, !network_ninaw10_poll_list_is_empty());
if (network_nina_wl_sta.poll_enable) {
mp_sched_schedule_node(&mp_wifi_poll_node, network_ninaw10_poll_connect);
} else if (!network_ninaw10_poll_list_is_empty()) {
mp_sched_schedule_node(&mp_wifi_poll_node, network_ninaw10_poll_sockets);
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_ninaw10_timer_callback_obj, network_ninaw10_timer_callback);
STATIC mp_obj_t network_ninaw10_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);
@ -162,6 +193,7 @@ STATIC mp_obj_t network_ninaw10_active(size_t n_args, const mp_obj_t *args) {
nina_obj_t *self = MP_OBJ_TO_PTR(args[0]);
if (n_args == 2) {
bool active = mp_obj_is_true(args[1]);
network_ninaw10_deinit();
if (active) {
int error = 0;
if ((error = nina_init()) != 0) {
@ -190,19 +222,9 @@ STATIC mp_obj_t network_ninaw10_active(size_t n_args, const mp_obj_t *args) {
NINA_FW_VER_MIN_MAJOR, NINA_FW_VER_MIN_MINOR, NINA_FW_VER_MIN_PATCH, semver[NINA_FW_VER_MAJOR_OFFS] - 48,
semver[NINA_FW_VER_MINOR_OFFS] - 48, semver[NINA_FW_VER_PATCH_OFFS] - 48);
}
MP_STATE_PORT(mp_wifi_sockpoll_list) = mp_obj_new_list(0, NULL);
if (MP_STATE_PORT(mp_wifi_timer) == MP_OBJ_NULL) {
// Start sockets poll timer
mp_obj_t timer_args[] = {
MP_OBJ_NEW_QSTR(MP_QSTR_freq), MP_OBJ_NEW_SMALL_INT(10),
MP_OBJ_NEW_QSTR(MP_QSTR_callback), MP_OBJ_FROM_PTR(&network_ninaw10_timer_callback_obj),
};
MP_STATE_PORT(mp_wifi_timer) = MP_OBJ_TYPE_GET_SLOT(&machine_timer_type, make_new)((mp_obj_t)&machine_timer_type, 0, 2, timer_args);
}
soft_timer_static_init(&mp_wifi_poll_timer, SOFT_TIMER_MODE_ONE_SHOT, 0, network_ninaw10_timer_callback);
} else {
nina_deinit();
MP_STATE_PORT(mp_wifi_timer) = MP_OBJ_NULL;
MP_STATE_PORT(mp_wifi_sockpoll_list) = MP_OBJ_NULL;
}
self->active = active;
return mp_const_none;
@ -283,7 +305,8 @@ STATIC mp_obj_t network_ninaw10_connect(mp_uint_t n_args, const mp_obj_t *pos_ar
self->security = security;
strncpy(self->key, key, NINA_MAX_WPA_LEN);
strncpy(self->ssid, ssid, NINA_MAX_SSID_LEN);
mp_sched_schedule_node(&mp_wifi_connpoll_node, network_ninaw10_poll_connect);
self->poll_enable = true;
soft_timer_reinsert(&mp_wifi_poll_timer, NINAW10_POLL_INTERVAL);
} else {
mp_uint_t channel = args[ARG_channel].u_int;
@ -428,7 +451,11 @@ STATIC mp_obj_t network_ninaw10_ioctl(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj_
nina_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_buffer_info_t buf;
mp_get_buffer_raise(buf_in, &buf, MP_BUFFER_READ | MP_BUFFER_WRITE);
nina_ioctl(mp_obj_get_int(cmd_in), buf.len, buf.buf, self->itf);
int ret = nina_ioctl(mp_obj_get_int(cmd_in), buf.len, buf.buf, self->itf);
if (ret != 0) {
mp_raise_msg_varg(&mp_type_OSError,
MP_ERROR_TEXT("ioctl %d failed %d"), mp_obj_get_int(cmd_in), ret);
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(network_ninaw10_ioctl_obj, network_ninaw10_ioctl);
@ -447,7 +474,7 @@ STATIC int network_ninaw10_socket_poll(mod_network_socket_obj_t *socket, uint32_
}
mp_uint_t start = mp_hal_ticks_ms();
for (; !(flags & rwf); mp_hal_delay_ms(5)) {
if (nina_socket_poll(socket->fileno, &flags) < 0 || (flags & SOCKET_POLL_ERR)) {
if (nina_socket_poll(socket->fileno, &flags) < 0) {
nina_socket_errno(_errno);
debug_printf("socket_poll(%d) -> errno %d flags %d\n", socket->fileno, *_errno, flags);
return -1;
@ -529,10 +556,8 @@ STATIC int network_ninaw10_socket_socket(mod_network_socket_obj_t *socket, int *
STATIC void network_ninaw10_socket_close(mod_network_socket_obj_t *socket) {
debug_printf("socket_close(%d)\n", socket->fileno);
if (socket->callback != MP_OBJ_NULL) {
mp_sched_lock();
socket->callback = MP_OBJ_NULL;
mp_obj_list_remove(MP_STATE_PORT(mp_wifi_sockpoll_list), socket);
mp_sched_unlock();
network_ninaw10_poll_list_remove(socket);
}
if (socket->fileno >= 0) {
nina_socket_close(socket->fileno);
@ -740,7 +765,8 @@ STATIC int network_ninaw10_socket_setsockopt(mod_network_socket_obj_t *socket, m
mp_sched_lock();
socket->callback = (void *)optval;
if (socket->callback != MP_OBJ_NULL) {
mp_obj_list_append(MP_STATE_PORT(mp_wifi_sockpoll_list), socket);
network_ninaw10_poll_list_insert(socket);
soft_timer_reinsert(&mp_wifi_poll_timer, NINAW10_POLL_INTERVAL);
}
mp_sched_unlock();
return 0;
@ -804,6 +830,14 @@ STATIC int network_ninaw10_socket_ioctl(mod_network_socket_obj_t *socket, mp_uin
return ret;
}
STATIC void network_ninaw10_deinit(void) {
// On soft-reboot, gc_sweep_all is called and all open sockets are closed
// and collected. Make sure that the driver is not keeping any references
// to collected sockets in the poll list.
soft_timer_remove(&mp_wifi_poll_timer);
MP_STATE_PORT(mp_wifi_poll_list) = NULL;
}
STATIC const mp_rom_map_elem_t nina_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_active), MP_ROM_PTR(&network_ninaw10_active_obj) },
{ MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&network_ninaw10_scan_obj) },
@ -827,6 +861,7 @@ STATIC MP_DEFINE_CONST_DICT(nina_locals_dict, nina_locals_dict_table);
STATIC const mod_network_nic_protocol_t mod_network_nic_protocol_nina = {
.gethostbyname = network_ninaw10_gethostbyname,
.deinit = network_ninaw10_deinit,
.socket = network_ninaw10_socket_socket,
.close = network_ninaw10_socket_close,
.bind = network_ninaw10_socket_bind,
@ -852,7 +887,6 @@ MP_DEFINE_CONST_OBJ_TYPE(
);
MP_REGISTER_ROOT_POINTER(struct _machine_spi_obj_t *mp_wifi_spi);
MP_REGISTER_ROOT_POINTER(struct _machine_timer_obj_t *mp_wifi_timer);
MP_REGISTER_ROOT_POINTER(struct _mp_obj_list_t *mp_wifi_sockpoll_list);
MP_REGISTER_ROOT_POINTER(struct _mp_obj_list_t *mp_wifi_poll_list);
#endif // #if MICROPY_PY_BLUETOOTH && MICROPY_PY_NETWORK_NINAW10

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