diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 8caf56d268..af62072c89 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -15,6 +15,10 @@ jobs: steps: - uses: actions/checkout@v1 - uses: actions/setup-python@v1 + - name: Install deps + run: sudo apt-get update && sudo apt-get install -y gettext + - name: Populate selected submodules + run: git submodule update --init extmod/ulab - name: set PY run: echo >>$GITHUB_ENV PY="$(python -c 'import hashlib, sys;print(hashlib.sha256(sys.version.encode()+sys.executable.encode()).hexdigest())')" - uses: actions/cache@v1 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 322f37da46..82d89eaa3e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,3 +11,10 @@ repos: exclude: '^(tests/.*\.exp|tests/cmdline/.*|tests/.*/data/.*|ports/esp32s2/esp-idf-config/.*|ports/esp32s2/boards/.*/sdkconfig)' - id: trailing-whitespace exclude: '^(tests/.*\.exp|tests/cmdline/.*|tests/.*/data/.*)' +- repo: local + hooks: + - id: translations + name: Check Translations + entry: sh -c "make translate" + language: system + always_run: true diff --git a/Makefile b/Makefile index a1807c308f..adb206d7bc 100644 --- a/Makefile +++ b/Makefile @@ -222,7 +222,7 @@ pseudoxml: all-source: locale/circuitpython.pot: all-source - find $(TRANSLATE_SOURCES) -type d \( $(TRANSLATE_SOURCES_EXC) \) -prune -o -type f \( -iname "*.c" -o -iname "*.h" \) -print | (LC_ALL=C sort) | xgettext -f- -L C -s --add-location=file --keyword=translate -o circuitpython.pot -p locale + find $(TRANSLATE_SOURCES) -type d \( $(TRANSLATE_SOURCES_EXC) \) -prune -o -type f \( -iname "*.c" -o -iname "*.h" \) -print | (LC_ALL=C sort) | xgettext -f- -L C -s --add-location=file --keyword=translate -o - | sed -e '/"POT-Creation-Date: /d' > $@ # Historically, `make translate` updated the .pot file and ran msgmerge. # However, this was a frequent source of merge conflicts. Weblate can perform diff --git a/conf.py b/conf.py index 1a90b617b8..590e5bc2c5 100644 --- a/conf.py +++ b/conf.py @@ -276,7 +276,7 @@ html_static_path = ['docs/static'] # 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 = ["docs/robots.txt"] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. diff --git a/docs/robots.txt b/docs/robots.txt new file mode 100644 index 0000000000..ad3189d42c --- /dev/null +++ b/docs/robots.txt @@ -0,0 +1,6 @@ +User-agent: * +Allow: /*/latest/ +Allow: /en/latest/ # Fallback for bots that don't understand wildcards +Allow: /*/6.0.x/ +Allow: /en/6.0.x/ # Fallback for bots that don't understand wildcards +Disallow: / diff --git a/extmod/ulab b/extmod/ulab index c4b06e419f..d62d07ea0b 160000 --- a/extmod/ulab +++ b/extmod/ulab @@ -1 +1 @@ -Subproject commit c4b06e419f3d515478b05bb8ce03ebdb29cddec4 +Subproject commit d62d07ea0b9597535428ebe6012da6b0d6608bf9 diff --git a/lib/tinyusb b/lib/tinyusb index 218b80e63a..cfcffe94ce 160000 --- a/lib/tinyusb +++ b/lib/tinyusb @@ -1 +1 @@ -Subproject commit 218b80e63ab6ff87c1851e403f08b3d716d68f5e +Subproject commit cfcffe94ce62f5ef1fb5aef4641924d64dc4b1c0 diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index dc5396b8e7..5a8c607632 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -8,7 +8,6 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-01-11 14:24+0530\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -276,6 +275,10 @@ msgstr "" msgid "3-arg pow() not supported" msgstr "" +#: shared-module/msgpack/__init__.c +msgid "64 bit types" +msgstr "" + #: ports/atmel-samd/common-hal/countio/Counter.c #: ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.c msgid "A hardware interrupt channel is already in use" @@ -2426,6 +2429,10 @@ msgstr "" msgid "circle can only be registered in one parent" msgstr "" +#: shared-bindings/msgpack/ExtType.c +msgid "code outside range 0~127" +msgstr "" + #: shared-bindings/displayio/Palette.c msgid "color buffer must be 3 bytes (RGB) or 4 bytes (RGB + pad byte)" msgstr "" @@ -2510,6 +2517,10 @@ msgstr "" msgid "default 'except' must be last" msgstr "" +#: shared-bindings/msgpack/__init__.c +msgid "default is not a function" +msgstr "" + #: shared-bindings/audiobusio/PDMIn.c msgid "" "destination buffer must be a bytearray or array of type 'B' for bit_depth = 8" @@ -2609,6 +2620,10 @@ msgstr "" msgid "expecting key:value for dict" msgstr "" +#: shared-bindings/msgpack/__init__.c +msgid "ext_hook is not a function" +msgstr "" + #: py/argcheck.c msgid "extra keyword arguments given" msgstr "" @@ -3141,6 +3156,10 @@ msgstr "" msgid "no binding for nonlocal found" msgstr "" +#: shared-module/msgpack/__init__.c +msgid "no default packer" +msgstr "" + #: py/builtinimport.c msgid "no module named '%q'" msgstr "" @@ -3474,6 +3493,10 @@ msgstr "" msgid "shape must be a tuple" msgstr "" +#: shared-module/msgpack/__init__.c +msgid "short read" +msgstr "" + #: py/objstr.c msgid "sign not allowed in string format specifier" msgstr "" diff --git a/locale/de_DE.po b/locale/de_DE.po index 0dd7119993..a1d0726433 100644 --- a/locale/de_DE.po +++ b/locale/de_DE.po @@ -6,20 +6,22 @@ msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 12:55-0600\n" -"PO-Revision-Date: 2020-11-26 03:11+0000\n" -"Last-Translator: Daniel Bravo Darriba \n" +"PO-Revision-Date: 2021-01-07 18:01+0000\n" +"Last-Translator: Dennis Schweer \n" "Language: de_DE\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 4.4-dev\n" +"X-Generator: Weblate 4.4.1-dev\n" #: main.c msgid "" "\n" "Code done running.\n" msgstr "" +"\n" +"Programm wird ausgeführt.\n" #: main.c msgid "" @@ -129,7 +131,7 @@ msgstr "'%q' Objekt unterstützt '%q' nicht" #: py/obj.c msgid "'%q' object does not support item assignment" -msgstr "" +msgstr "'%q' Objekt unterschützt keine Elementzuweisung" #: py/obj.c msgid "'%q' object does not support item deletion" @@ -141,7 +143,7 @@ msgstr "'%q' Objekt hat kein Attribut '%q'" #: py/runtime.c msgid "'%q' object is not an iterator" -msgstr "" +msgstr "'%q' Objekt ist kein Iterator" #: py/objtype.c py/runtime.c msgid "'%q' object is not callable" @@ -235,7 +237,7 @@ msgstr "'continue' außerhalb einer Schleife" #: py/objgenerator.c msgid "'coroutine' object is not an iterator" -msgstr "" +msgstr "'coroutine' Objekt ist kein Iterator" #: py/compile.c msgid "'data' requires at least 2 arguments" @@ -307,7 +309,7 @@ msgstr "Alle I2C-Peripheriegeräte sind in Benutzung" #: ports/esp32s2/common-hal/frequencyio/FrequencyIn.c #: ports/esp32s2/common-hal/rotaryio/IncrementalEncoder.c msgid "All PCNT units in use" -msgstr "" +msgstr "Alle PCNT Einheiten sind in Benutzung" #: ports/atmel-samd/common-hal/canio/Listener.c #: ports/esp32s2/common-hal/canio/Listener.c @@ -710,7 +712,7 @@ msgstr "Konnte Kamera nicht initialisieren" #: ports/cxd56/common-hal/gnss/GNSS.c msgid "Could not initialize GNSS" -msgstr "" +msgstr "GNSS konnte nicht initialisiert werden" #: ports/cxd56/common-hal/sdioio/SDCard.c msgid "Could not initialize SDCard" @@ -837,7 +839,7 @@ msgstr "Die EZB arbeitet jeweils nur mit 16 Bytes" #: ports/esp32s2/common-hal/busio/SPI.c ports/esp32s2/common-hal/canio/CAN.c msgid "ESP-IDF memory allocation failed" -msgstr "" +msgstr "ESP-IDF Speicherallozierung fehlgeschlagen" #: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c #: ports/atmel-samd/common-hal/ps2io/Ps2.c @@ -903,7 +905,7 @@ msgstr "FFT ist nur für ndarrays definiert" #: extmod/ulab/code/fft/fft.c msgid "FFT is implemented for linear arrays only" -msgstr "" +msgstr "FFT ist nur für lineare Arrays implementiert" #: ports/esp32s2/common-hal/socketpool/Socket.c msgid "Failed SSL handshake" @@ -934,7 +936,7 @@ msgstr "Konnte keine RX Buffer mit %d allozieren" #: ports/esp32s2/common-hal/wifi/__init__.c msgid "Failed to allocate Wifi memory" -msgstr "" +msgstr "Zuweisung des Wifi Speichers ist fehlgeschlagen" #: ports/esp32s2/common-hal/wifi/ScannedNetworks.c msgid "Failed to allocate wifi scan memory" @@ -950,7 +952,7 @@ msgstr "Verbindung nicht erfolgreich: timeout" #: ports/esp32s2/common-hal/wifi/__init__.c msgid "Failed to init wifi" -msgstr "" +msgstr "Wifi Initialisierung ist fehlgeschlagen" #: shared-module/audiomp3/MP3Decoder.c msgid "Failed to parse MP3 file" @@ -1037,7 +1039,7 @@ msgstr "I2SOut nicht verfügbar" #: ports/esp32s2/common-hal/alarm/pin/__init__.c msgid "IOs 0, 2 & 4 do not support internal pullup in sleep" -msgstr "" +msgstr "IOs 0, 2 & 4 unterstützen keinen internen Pull up im sleep-Modus" #: shared-bindings/aesio/aes.c #, c-format @@ -1058,7 +1060,7 @@ msgstr "Inkorrekte Puffergröße" #: ports/esp32s2/common-hal/watchdog/WatchDogTimer.c msgid "Initialization failed due to lack of memory" -msgstr "" +msgstr "Initialisierung aufgrund von Speichermangel fehlgeschlagen" #: ports/atmel-samd/common-hal/pulseio/PulseIn.c msgid "Input taking too long" @@ -3858,7 +3860,7 @@ msgstr "nicht unterstütztes Formatzeichen '%c' (0x%x) bei Index %d" #: py/runtime.c msgid "unsupported type for %q: '%q'" -msgstr "" +msgstr "nicht unterstützer Typ für %q: '%q'" #: py/runtime.c msgid "unsupported type for operator" @@ -3866,7 +3868,7 @@ msgstr "nicht unterstützter Typ für Operator" #: py/runtime.c msgid "unsupported types for %q: '%q', '%q'" -msgstr "" +msgstr "nicht unterstützte Typen für %q: '%q', '%q'" #: py/objint.c #, c-format @@ -3911,7 +3913,7 @@ msgstr "" #: extmod/ulab/code/vector/vectorise.c msgid "wrong input type" -msgstr "" +msgstr "falscher Eingabetyp" #: extmod/ulab/code/ulab_create.c py/objstr.c msgid "wrong number of arguments" @@ -3927,7 +3929,7 @@ msgstr "falscher Operandentyp" #: extmod/ulab/code/vector/vectorise.c msgid "wrong output type" -msgstr "" +msgstr "Falscher Ausgabetyp" #: shared-module/displayio/Shape.c msgid "x value out of bounds" diff --git a/locale/fr.po b/locale/fr.po index 187ee6f92d..e898631ea9 100644 --- a/locale/fr.po +++ b/locale/fr.po @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: 0.1\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 12:55-0600\n" -"PO-Revision-Date: 2021-01-01 04:29+0000\n" +"PO-Revision-Date: 2021-01-07 01:29+0000\n" "Last-Translator: Hugo Dahl \n" "Language: fr\n" "MIME-Version: 1.0\n" @@ -2595,7 +2595,7 @@ msgstr "les données doivent être de longueur égale" #: extmod/ulab/code/ndarray.c msgid "data type not understood" -msgstr "" +msgstr "le type de donnée n'est pas reconnu" #: py/parsenum.c msgid "decimal numbers not supported" @@ -2913,7 +2913,7 @@ msgstr "les formes d'entrée et de sortie ne sont pas compatibles" #: extmod/ulab/code/ulab_create.c msgid "input argument must be an integer, a tuple, or a list" -msgstr "" +msgstr "Paramètre entrant doit être un chiffre entier, un tuple, ou une liste" #: extmod/ulab/code/fft/fft.c msgid "input array length must be power of 2" @@ -3161,7 +3161,7 @@ msgstr "maxiter devrait être > 0" #: extmod/ulab/code/numerical/numerical.c msgid "median argument must be an ndarray" -msgstr "" +msgstr "Paramètre pour median doit être un ndarray" #: py/runtime.c #, c-format @@ -3745,7 +3745,7 @@ msgstr "trop d'arguments fournis avec ce format" #: extmod/ulab/code/ulab_create.c msgid "too many dimensions" -msgstr "" +msgstr "Trop de dimensions" #: extmod/ulab/code/ndarray.c msgid "too many indices" @@ -3758,7 +3758,7 @@ msgstr "trop de valeur à dégrouper (%d attendues)" #: extmod/ulab/code/approx/approx.c msgid "trapz is defined for 1D arrays" -msgstr "" +msgstr "trapz est défini pour tableaux à une dimension" #: extmod/ulab/code/approx/approx.c msgid "trapz is defined for 1D arrays of equal length" diff --git a/ports/atmel-samd/boards/bdmicro_vina_d21/mpconfigboard.mk b/ports/atmel-samd/boards/bdmicro_vina_d21/mpconfigboard.mk index a0d9a779f8..cff5a32d1c 100644 --- a/ports/atmel-samd/boards/bdmicro_vina_d21/mpconfigboard.mk +++ b/ports/atmel-samd/boards/bdmicro_vina_d21/mpconfigboard.mk @@ -14,6 +14,7 @@ LONGINT_IMPL = MPZ CIRCUITPY_BITBANGIO = 0 CIRCUITPY_COUNTIO = 0 CIRCUITPY_I2CPERIPHERAL = 0 +CIRCUITPY_MSGPACK = 0 CIRCUITPY_VECTORIO = 0 CIRCUITPY_BUSDEVICE = 0 diff --git a/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk b/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk index 13ec9e861c..505f5c145d 100644 --- a/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk @@ -15,6 +15,7 @@ LONGINT_IMPL = MPZ CIRCUITPY_DISPLAYIO = 0 CIRCUITPY_FREQUENCYIO = 0 CIRCUITPY_I2CPERIPHERAL = 0 +CIRCUITPY_MSGPACK = 0 MICROPY_PY_ASYNC_AWAIT = 0 SUPEROPT_GC = 0 diff --git a/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.mk b/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.mk index 7aa45eb39e..c3be33134c 100644 --- a/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.mk +++ b/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.mk @@ -16,6 +16,7 @@ CIRCUITPY_BITBANGIO = 0 CIRCUITPY_DISPLAYIO = 0 CIRCUITPY_FREQUENCYIO = 0 CIRCUITPY_I2CPERIPHERAL = 0 +CIRCUITPY_MSGPACK = 0 CIRCUITPY_PIXELBUF = 1 CIRCUITPY_ROTARYIO = 0 CIRCUITPY_RTC = 0 diff --git a/ports/atmel-samd/boards/circuitplayground_express_displayio/mpconfigboard.mk b/ports/atmel-samd/boards/circuitplayground_express_displayio/mpconfigboard.mk index 3a43093a98..51e9b05af2 100644 --- a/ports/atmel-samd/boards/circuitplayground_express_displayio/mpconfigboard.mk +++ b/ports/atmel-samd/boards/circuitplayground_express_displayio/mpconfigboard.mk @@ -16,6 +16,7 @@ CIRCUITPY_BITBANGIO = 0 CIRCUITPY_COUNTIO = 0 CIRCUITPY_FREQUENCYIO = 0 CIRCUITPY_I2CPERIPHERAL = 0 +CIRCUITPY_MSGPACK = 0 CIRCUITPY_PIXELBUF = 0 CIRCUITPY_ROTARYIO = 0 CIRCUITPY_RTC = 0 diff --git a/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk index 2fe085567a..d1a6fc7ae5 100644 --- a/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk @@ -15,6 +15,7 @@ CIRCUITPY_BITBANGIO = 0 CIRCUITPY_FREQUENCYIO = 0 CIRCUITPY_COUNTIO = 0 CIRCUITPY_I2CPERIPHERAL = 0 +CIRCUITPY_MSGPACK = 0 CIRCUITPY_VECTORIO = 0 CIRCUITPY_BUSDEVICE = 0 diff --git a/ports/atmel-samd/boards/feather_m0_express_crickit/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_express_crickit/mpconfigboard.mk index 5624144e88..f06163b84a 100644 --- a/ports/atmel-samd/boards/feather_m0_express_crickit/mpconfigboard.mk +++ b/ports/atmel-samd/boards/feather_m0_express_crickit/mpconfigboard.mk @@ -18,6 +18,7 @@ CIRCUITPY_FREQUENCYIO = 0 CIRCUITPY_I2CPERIPHERAL = 0 CIRCUITPY_GAMEPAD = 0 CFLAGS_INLINE_LIMIT = 50 +CIRCUITPY_MSGPACK = 0 # Include these Python libraries in firmware. FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_BusDevice diff --git a/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk index c2d692f9b7..3078544fcb 100644 --- a/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk +++ b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk @@ -15,6 +15,7 @@ CIRCUITPY_BITBANGIO = 0 CIRCUITPY_FREQUENCYIO = 0 CIRCUITPY_COUNTIO = 0 CIRCUITPY_I2CPERIPHERAL = 0 +CIRCUITPY_MSGPACK = 0 # supersized, not ultra-supersized CIRCUITPY_VECTORIO = 0 CIRCUITPY_BUSDEVICE = 0 diff --git a/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk b/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk index c35854758c..03f633e6d8 100644 --- a/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk @@ -14,6 +14,7 @@ LONGINT_IMPL = MPZ CIRCUITPY_BITBANGIO = 0 CIRCUITPY_COUNTIO = 0 CIRCUITPY_I2CPERIPHERAL = 0 +CIRCUITPY_MSGPACK = 0 CIRCUITPY_VECTORIO = 0 CIRCUITPY_BUSDEVICE = 0 diff --git a/ports/atmel-samd/boards/qtpy_m0_haxpress/mpconfigboard.mk b/ports/atmel-samd/boards/qtpy_m0_haxpress/mpconfigboard.mk index a63f142742..8773c5771d 100644 --- a/ports/atmel-samd/boards/qtpy_m0_haxpress/mpconfigboard.mk +++ b/ports/atmel-samd/boards/qtpy_m0_haxpress/mpconfigboard.mk @@ -17,6 +17,7 @@ CIRCUITPY_BITBANGIO = 0 CIRCUITPY_COUNTIO = 0 CIRCUITPY_FREQUENCYIO = 0 CIRCUITPY_I2CPERIPHERAL = 0 +CIRCUITPY_MSGPACK = 0 SUPEROPT_GC = 0 diff --git a/ports/atmel-samd/boards/snekboard/mpconfigboard.mk b/ports/atmel-samd/boards/snekboard/mpconfigboard.mk index 67e5b2312d..889490450f 100644 --- a/ports/atmel-samd/boards/snekboard/mpconfigboard.mk +++ b/ports/atmel-samd/boards/snekboard/mpconfigboard.mk @@ -14,6 +14,7 @@ LONGINT_IMPL = MPZ CIRCUITPY_BITBANGIO = 0 CIRCUITPY_GAMEPAD = 0 CIRCUITPY_I2CPERIPHERAL = 0 +CIRCUITPY_MSGPACK = 0 CIRCUITPY_VECTORIO = 0 CIRCUITPY_BUSDEVICE = 0 diff --git a/ports/atmel-samd/boards/sparkfun_redboard_turbo/mpconfigboard.mk b/ports/atmel-samd/boards/sparkfun_redboard_turbo/mpconfigboard.mk index 590c4795fb..5b7f93328d 100755 --- a/ports/atmel-samd/boards/sparkfun_redboard_turbo/mpconfigboard.mk +++ b/ports/atmel-samd/boards/sparkfun_redboard_turbo/mpconfigboard.mk @@ -15,6 +15,7 @@ CIRCUITPY_BITBANGIO = 0 CIRCUITPY_COUNTIO = 0 CIRCUITPY_GAMEPAD = 0 CIRCUITPY_I2CPERIPHERAL = 0 +CIRCUITPY_MSGPACK = 0 CIRCUITPY_VECTORIO = 0 CIRCUITPY_BUSDEVICE = 0 diff --git a/ports/atmel-samd/boards/stackrduino_m0_pro/mpconfigboard.mk b/ports/atmel-samd/boards/stackrduino_m0_pro/mpconfigboard.mk index 704d265141..734be2d145 100644 --- a/ports/atmel-samd/boards/stackrduino_m0_pro/mpconfigboard.mk +++ b/ports/atmel-samd/boards/stackrduino_m0_pro/mpconfigboard.mk @@ -16,6 +16,7 @@ CIRCUITPY_BITBANGIO = 0 CIRCUITPY_FREQUENCYIO = 0 CIRCUITPY_COUNTIO = 0 CIRCUITPY_I2CPERIPHERAL = 0 +CIRCUITPY_MSGPACK = 0 CIRCUITPY_VECTORIO = 0 CIRCUITPY_BUSDEVICE = 0 diff --git a/ports/atmel-samd/common-hal/pwmio/PWMOut.c b/ports/atmel-samd/common-hal/pwmio/PWMOut.c index 2e538ccdc3..b5142c21e1 100644 --- a/ports/atmel-samd/common-hal/pwmio/PWMOut.c +++ b/ports/atmel-samd/common-hal/pwmio/PWMOut.c @@ -44,6 +44,7 @@ # define _TCC_SIZE(unused, n) TCC ## n ## _SIZE, # define TCC_SIZES { REPEAT_MACRO(_TCC_SIZE, 0, TCC_INST_NUM) } +static const uint8_t tcc_sizes[TCC_INST_NUM] = TCC_SIZES; static uint32_t tcc_periods[TCC_INST_NUM]; static uint32_t tc_periods[TC_INST_NUM]; @@ -233,8 +234,7 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t* self, resolution = 16; } else { // TCC resolution varies so look it up. - const uint8_t _tcc_sizes[TCC_INST_NUM] = TCC_SIZES; - resolution = _tcc_sizes[timer->index]; + resolution = tcc_sizes[timer->index]; } // First determine the divisor that gets us the highest resolution. uint32_t system_clock = common_hal_mcu_processor_get_frequency(); @@ -421,7 +421,8 @@ void common_hal_pwmio_pwmout_set_frequency(pwmio_pwmout_obj_t* self, if (t->is_tc) { resolution = 16; } else { - resolution = 24; + // TCC resolution varies so look it up. + resolution = tcc_sizes[t->index]; } uint32_t system_clock = common_hal_mcu_processor_get_frequency(); uint32_t new_top; diff --git a/ports/atmel-samd/supervisor/port.c b/ports/atmel-samd/supervisor/port.c index b9977fdc46..02b9e38743 100644 --- a/ports/atmel-samd/supervisor/port.c +++ b/ports/atmel-samd/supervisor/port.c @@ -429,7 +429,9 @@ uint32_t port_get_saved_word(void) { // TODO: Move this to an RTC backup register so we can preserve it when only the BACKUP power domain // is enabled. static volatile uint64_t overflowed_ticks = 0; +#ifdef SAMD21 static volatile bool _ticks_enabled = false; +#endif static uint32_t _get_count(uint64_t* overflow_count) { #ifdef SAM_D5X_E5X @@ -537,9 +539,11 @@ void port_disable_tick(void) { // they'll wake us up earlier. If we don't, we'll mess up ticks by overwriting // the next RTC wake up time. void port_interrupt_after_ticks(uint32_t ticks) { + #ifdef SAMD21 if (_ticks_enabled) { return; } + #endif _port_interrupt_after_ticks(ticks); } diff --git a/ports/cxd56/boards/spresense/mpconfigboard.mk b/ports/cxd56/boards/spresense/mpconfigboard.mk index 7b8ac6ff63..80c6e4b692 100644 --- a/ports/cxd56/boards/spresense/mpconfigboard.mk +++ b/ports/cxd56/boards/spresense/mpconfigboard.mk @@ -4,3 +4,5 @@ USB_PRODUCT = "Spresense" USB_MANUFACTURER = "Sony" INTERNAL_FLASH_FILESYSTEM = 1 + +CIRCUITPY_MSGPACK = 0 diff --git a/ports/esp32s2/boards/unexpectedmaker_feathers2/board.c b/ports/esp32s2/boards/unexpectedmaker_feathers2/board.c index d8fd3a0a2b..ac08190a5b 100644 --- a/ports/esp32s2/boards/unexpectedmaker_feathers2/board.c +++ b/ports/esp32s2/boards/unexpectedmaker_feathers2/board.c @@ -27,6 +27,8 @@ #include "supervisor/board.h" #include "mpconfigboard.h" #include "shared-bindings/microcontroller/Pin.h" +#include "components/driver/include/driver/gpio.h" +#include "components/soc/include/hal/gpio_hal.h" void board_init(void) { // USB @@ -47,6 +49,12 @@ void board_init(void) { common_hal_never_reset_pin(&pin_GPIO30); common_hal_never_reset_pin(&pin_GPIO31); common_hal_never_reset_pin(&pin_GPIO32); + + + // Add LDO2 to never reset list, set to output and enable + common_hal_never_reset_pin(&pin_GPIO21); + gpio_set_direction(pin_GPIO21.number, GPIO_MODE_DEF_OUTPUT); + gpio_set_level(pin_GPIO21.number, true); } bool board_requests_safe_mode(void) { diff --git a/ports/esp32s2/boards/unexpectedmaker_feathers2/mpconfigboard.h b/ports/esp32s2/boards/unexpectedmaker_feathers2/mpconfigboard.h index e100ac118e..6b1a0c4aa5 100644 --- a/ports/esp32s2/boards/unexpectedmaker_feathers2/mpconfigboard.h +++ b/ports/esp32s2/boards/unexpectedmaker_feathers2/mpconfigboard.h @@ -34,8 +34,8 @@ #define AUTORESET_DELAY_MS 500 -// #define MICROPY_HW_APA102_MOSI (&pin_GPIO40) -// #define MICROPY_HW_APA102_SCK (&pin_GPIO45) +#define MICROPY_HW_APA102_MOSI (&pin_GPIO40) +#define MICROPY_HW_APA102_SCK (&pin_GPIO45) #define DEFAULT_I2C_BUS_SCL (&pin_GPIO9) #define DEFAULT_I2C_BUS_SDA (&pin_GPIO8) diff --git a/ports/esp32s2/common-hal/microcontroller/Pin.c b/ports/esp32s2/common-hal/microcontroller/Pin.c index fca89ce8ec..6889720e84 100644 --- a/ports/esp32s2/common-hal/microcontroller/Pin.c +++ b/ports/esp32s2/common-hal/microcontroller/Pin.c @@ -37,13 +37,14 @@ #ifdef MICROPY_HW_NEOPIXEL bool neopixel_in_use; #endif +#ifdef MICROPY_HW_APA102_MOSI +bool apa102_sck_in_use; +bool apa102_mosi_in_use; +#endif STATIC uint32_t never_reset_pins[2]; STATIC uint32_t in_use[2]; -bool apa102_mosi_in_use; -bool apa102_sck_in_use; - STATIC void floating_gpio_reset(gpio_num_t pin_number) { // This is the same as gpio_reset_pin(), but without the pullup. // Note that gpio_config resets the iomatrix to GPIO_FUNC as well. @@ -86,6 +87,20 @@ void reset_pin_number(gpio_num_t pin_number) { return; } #endif + #ifdef MICROPY_HW_APA102_MOSI + if (pin_number == MICROPY_HW_APA102_MOSI->number || + pin_number == MICROPY_HW_APA102_SCK->number) { + apa102_mosi_in_use = apa102_mosi_in_use && pin_number != MICROPY_HW_APA102_MOSI->number; + apa102_sck_in_use = apa102_sck_in_use && pin_number != MICROPY_HW_APA102_SCK->number; + if (!apa102_sck_in_use && !apa102_mosi_in_use) { + rgb_led_status_init(); + } + return; + } + #endif + + + } void common_hal_reset_pin(const mcu_pin_obj_t* pin) { @@ -110,6 +125,11 @@ void reset_all_pins(void) { #ifdef MICROPY_HW_NEOPIXEL neopixel_in_use = false; #endif + #ifdef MICROPY_HW_APA102_MOSI + apa102_sck_in_use = false; + apa102_mosi_in_use = false; + #endif + } void claim_pin(const mcu_pin_obj_t* pin) { @@ -119,6 +139,15 @@ void claim_pin(const mcu_pin_obj_t* pin) { neopixel_in_use = true; } #endif + #ifdef MICROPY_HW_APA102_MOSI + if (pin == MICROPY_HW_APA102_MOSI) { + apa102_mosi_in_use = true; + } + if (pin == MICROPY_HW_APA102_SCK) { + apa102_sck_in_use = true; + } + #endif + } void common_hal_mcu_pin_claim(const mcu_pin_obj_t* pin) { @@ -131,10 +160,18 @@ bool pin_number_is_free(gpio_num_t pin_number) { return !neopixel_in_use; } #endif + #ifdef MICROPY_HW_APA102_MOSI + if (pin_number == MICROPY_HW_APA102_MOSI->number) { + return !apa102_mosi_in_use; + } + if (pin_number == MICROPY_HW_APA102_SCK->number) { + return !apa102_sck_in_use; + } + #endif uint8_t offset = pin_number / 32; uint32_t mask = 1 << (pin_number % 32); - return (never_reset_pins[offset] & mask) == 0 && (in_use[offset] & mask) == 0; + return (in_use[offset] & mask) == 0; } bool common_hal_mcu_pin_is_free(const mcu_pin_obj_t *pin) { diff --git a/ports/esp32s2/common-hal/microcontroller/Pin.h b/ports/esp32s2/common-hal/microcontroller/Pin.h index f6c0087031..65f57a82d4 100644 --- a/ports/esp32s2/common-hal/microcontroller/Pin.h +++ b/ports/esp32s2/common-hal/microcontroller/Pin.h @@ -31,8 +31,10 @@ #include "peripherals/pins.h" -extern bool apa102_mosi_in_use; +#ifdef MICROPY_HW_APA102_MOSI extern bool apa102_sck_in_use; +extern bool apa102_mosi_in_use; +#endif #ifdef MICROPY_HW_NEOPIXEL extern bool neopixel_in_use; diff --git a/ports/esp32s2/common-hal/socketpool/Socket.c b/ports/esp32s2/common-hal/socketpool/Socket.c index 32c5fc72f2..5e943f8fd0 100644 --- a/ports/esp32s2/common-hal/socketpool/Socket.c +++ b/ports/esp32s2/common-hal/socketpool/Socket.c @@ -178,7 +178,7 @@ mp_uint_t common_hal_socketpool_socket_recvfrom_into(socketpool_socket_obj_t* se struct sockaddr_in source_addr; socklen_t socklen = sizeof(source_addr); - int bytes_received = lwip_recvfrom(self->num, buf, len - 1, 0, (struct sockaddr *)&source_addr, &socklen); + int bytes_received = lwip_recvfrom(self->num, buf, len, 0, (struct sockaddr *)&source_addr, &socklen); memcpy((void *)ip, (void*)&source_addr.sin_addr.s_addr, sizeof source_addr.sin_addr.s_addr); *port = source_addr.sin_port; @@ -186,10 +186,9 @@ mp_uint_t common_hal_socketpool_socket_recvfrom_into(socketpool_socket_obj_t* se if (bytes_received < 0) { mp_raise_BrokenPipeError(); return 0; - } else { - buf[bytes_received] = 0; // Null-terminate whatever we received - return bytes_received; } + + return bytes_received; } void common_hal_socketpool_socket_close(socketpool_socket_obj_t* self) { diff --git a/ports/esp32s2/common-hal/wifi/Network.c b/ports/esp32s2/common-hal/wifi/Network.c index 2674df0651..b6eb6bb433 100644 --- a/ports/esp32s2/common-hal/wifi/Network.c +++ b/ports/esp32s2/common-hal/wifi/Network.c @@ -54,3 +54,37 @@ mp_obj_t common_hal_wifi_network_get_country(wifi_network_obj_t *self) { // 2 instead of strlen(cstr) as this gives us only the country-code return mp_obj_new_str(cstr, 2); } + +mp_obj_t common_hal_wifi_network_get_authmode(wifi_network_obj_t *self) { + const char* authmode = ""; + switch (self->record.authmode) { + case WIFI_AUTH_OPEN: + authmode = "OPEN"; + break; + case WIFI_AUTH_WEP: + authmode = "WEP"; + break; + case WIFI_AUTH_WPA_PSK: + authmode = "WPA_PSK"; + break; + case WIFI_AUTH_WPA2_PSK: + authmode = "WPA2_PSK"; + break; + case WIFI_AUTH_WPA_WPA2_PSK: + authmode = "WPA_WPA2_PSK"; + break; + case WIFI_AUTH_WPA2_ENTERPRISE: + authmode = "WPA2_ENTERPRISE"; + break; + case WIFI_AUTH_WPA3_PSK: + authmode = "WPA3_PSK"; + break; + case WIFI_AUTH_WPA2_WPA3_PSK: + authmode = "WPA2_WPA3_PSK"; + break; + default: + authmode = "UNKNOWN"; + break; + } + return mp_obj_new_str(authmode, strlen(authmode)); +} diff --git a/ports/esp32s2/mpconfigport.h b/ports/esp32s2/mpconfigport.h index db7393d8ef..9c0fd9da3e 100644 --- a/ports/esp32s2/mpconfigport.h +++ b/ports/esp32s2/mpconfigport.h @@ -32,6 +32,7 @@ #define MICROPY_PY_UJSON (1) #define MICROPY_USE_INTERNAL_PRINTF (0) +#define MICROPY_PY_SYS_PLATFORM "Espressif ESP32-S2" #include "py/circuitpy_mpconfig.h" diff --git a/ports/nrf/boards/pca10100/mpconfigboard.mk b/ports/nrf/boards/pca10100/mpconfigboard.mk index 86ba654548..76d15e6081 100644 --- a/ports/nrf/boards/pca10100/mpconfigboard.mk +++ b/ports/nrf/boards/pca10100/mpconfigboard.mk @@ -15,6 +15,7 @@ CIRCUITPY_DISPLAYIO = 0 CIRCUITPY_FRAMEBUFFERIO = 0 CIRCUITPY_FREQUENCYIO = 0 CIRCUITPY_I2CPERIPHERAL = 0 +CIRCUITPY_MSGPACK = 0 CIRCUITPY_NEOPIXEL_WRITE = 0 CIRCUITPY_NVM = 0 CIRCUITPY_PIXELBUF = 0 diff --git a/ports/nrf/boards/simmel/mpconfigboard.mk b/ports/nrf/boards/simmel/mpconfigboard.mk index dd6b1fbfdf..4eb6c98c7e 100644 --- a/ports/nrf/boards/simmel/mpconfigboard.mk +++ b/ports/nrf/boards/simmel/mpconfigboard.mk @@ -16,6 +16,7 @@ CIRCUITPY_AUDIOMP3 = 0 CIRCUITPY_BUSIO = 1 CIRCUITPY_DISPLAYIO = 0 CIRCUITPY_FRAMEBUFFERIO = 0 +CIRCUITPY_MSGPACK = 0 CIRCUITPY_GAMEPAD = 0 CIRCUITPY_NEOPIXEL_WRITE = 0 CIRCUITPY_NVM = 0 diff --git a/ports/nrf/common-hal/_bleio/Adapter.c b/ports/nrf/common-hal/_bleio/Adapter.c index 53a40f9a67..10794c16a8 100644 --- a/ports/nrf/common-hal/_bleio/Adapter.c +++ b/ports/nrf/common-hal/_bleio/Adapter.c @@ -469,7 +469,7 @@ mp_obj_t common_hal_bleio_adapter_start_scan(bleio_adapter_obj_t *self, uint8_t* ble_drv_add_event_handler(scan_on_ble_evt, self->scan_results); - uint32_t nrf_timeout = SEC_TO_UNITS(timeout, UNIT_10_MS); + uint32_t nrf_timeout = SEC_TO_UNITS(timeout, UNIT_10_MS) + 0.5f; if (nrf_timeout > UINT16_MAX) { // 0xffff / 100 mp_raise_ValueError(translate("timeout must be < 655.35 secs")); @@ -479,15 +479,15 @@ mp_obj_t common_hal_bleio_adapter_start_scan(bleio_adapter_obj_t *self, uint8_t* mp_raise_ValueError(translate("non-zero timeout must be > 0.01")); } - if (nrf_timeout) { + if (nrf_timeout == 0) { nrf_timeout = BLE_GAP_SCAN_TIMEOUT_UNLIMITED; } ble_gap_scan_params_t scan_params = { .extended = extended, - .interval = SEC_TO_UNITS(interval, UNIT_0_625_MS), + .interval = SEC_TO_UNITS(interval, UNIT_0_625_MS) + 0.5f, .timeout = nrf_timeout, - .window = SEC_TO_UNITS(window, UNIT_0_625_MS), + .window = SEC_TO_UNITS(window, UNIT_0_625_MS) + 0.5f, .scan_phys = BLE_GAP_PHY_1MBPS, .active = active }; @@ -553,7 +553,7 @@ mp_obj_t common_hal_bleio_adapter_connect(bleio_adapter_obj_t *self, bleio_addre .window = MSEC_TO_UNITS(100, UNIT_0_625_MS), .scan_phys = BLE_GAP_PHY_1MBPS, // timeout of 0 means no timeout - .timeout = SEC_TO_UNITS(timeout, UNIT_10_MS), + .timeout = SEC_TO_UNITS(timeout, UNIT_10_MS) + 0.5f, }; ble_gap_conn_params_t conn_params = { @@ -696,7 +696,7 @@ uint32_t _common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, } ble_gap_adv_params_t adv_params = { - .interval = SEC_TO_UNITS(interval, UNIT_0_625_MS), + .interval = SEC_TO_UNITS(interval, UNIT_0_625_MS) + 0.5f, .properties.type = adv_type, .duration = SEC_TO_UNITS(timeout, UNIT_10_MS), .filter_policy = BLE_GAP_ADV_FP_ANY, diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index d6d192a957..21bd5b9658 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -58,6 +58,14 @@ BASE_CFLAGS = \ # -H +# Set a global CIRCUITPY_DEBUG flag. +# Don't just call it "DEBUG": too many libraries use plain DEBUG. +ifneq ($(DEBUG),) +CFLAGS += -DCIRCUITPY_DEBUG=$(DEBUG) +else +CFLAGS += -DCIRCUITPY_DEBUG=0 +endif + ### # Handle frozen modules. @@ -292,6 +300,9 @@ endif ifeq ($(CIRCUITPY_PEW),1) SRC_PATTERNS += _pew/% endif +ifeq ($(CIRCUITPY_MSGPACK),1) +SRC_PATTERNS += msgpack/% +endif # All possible sources are listed here, and are filtered by SRC_PATTERNS in SRC_COMMON_HAL SRC_COMMON_HAL_ALL = \ @@ -412,6 +423,8 @@ $(filter $(SRC_PATTERNS), \ math/__init__.c \ microcontroller/ResetReason.c \ microcontroller/RunMode.c \ + msgpack/__init__.c \ + msgpack/ExtType.c \ supervisor/RunReason.c \ ) @@ -481,6 +494,7 @@ SRC_SHARED_MODULE_ALL = \ memorymonitor/AllocationAlarm.c \ memorymonitor/AllocationSize.c \ network/__init__.c \ + msgpack/__init__.c \ os/__init__.c \ random/__init__.c \ rgbmatrix/RGBMatrix.c \ diff --git a/py/circuitpy_mpconfig.h b/py/circuitpy_mpconfig.h index 08c92a77ef..a3411b7adb 100644 --- a/py/circuitpy_mpconfig.h +++ b/py/circuitpy_mpconfig.h @@ -774,6 +774,13 @@ extern const struct _mp_obj_module_t wifi_module; #define WIFI_MODULE #endif +#if CIRCUITPY_MSGPACK +extern const struct _mp_obj_module_t msgpack_module; +#define MSGPACK_MODULE { MP_ROM_QSTR(MP_QSTR_msgpack), MP_ROM_PTR(&msgpack_module) }, +#else +#define MSGPACK_MODULE +#endif + // Define certain native modules with weak links so they can be replaced with Python // implementations. This list may grow over time. #define MICROPY_PORT_BUILTIN_MODULE_WEAK_LINKS \ @@ -830,6 +837,7 @@ extern const struct _mp_obj_module_t wifi_module; _EVE_MODULE \ MEMORYMONITOR_MODULE \ MICROCONTROLLER_MODULE \ + MSGPACK_MODULE \ NEOPIXEL_WRITE_MODULE \ NETWORK_MODULE \ SOCKET_MODULE \ diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk index e588c41e0d..a01da29569 100644 --- a/py/circuitpy_mpconfig.mk +++ b/py/circuitpy_mpconfig.mk @@ -308,3 +308,6 @@ CFLAGS += -DCIRCUITPY_WIFI=$(CIRCUITPY_WIFI) # Enabled micropython.native decorator (experimental) CIRCUITPY_ENABLE_MPY_NATIVE ?= 0 CFLAGS += -DCIRCUITPY_ENABLE_MPY_NATIVE=$(CIRCUITPY_ENABLE_MPY_NATIVE) + +CIRCUITPY_MSGPACK ?= $(CIRCUITPY_FULL_BUILD) +CFLAGS += -DCIRCUITPY_MSGPACK=$(CIRCUITPY_MSGPACK) diff --git a/shared-bindings/_bleio/Adapter.c b/shared-bindings/_bleio/Adapter.c index 7d7076aab6..81277fd701 100644 --- a/shared-bindings/_bleio/Adapter.c +++ b/shared-bindings/_bleio/Adapter.c @@ -33,8 +33,8 @@ #include "shared-bindings/_bleio/Address.h" #include "shared-bindings/_bleio/Adapter.h" -#define ADV_INTERVAL_MIN (0.02001f) -#define ADV_INTERVAL_MIN_STRING "0.02001" +#define ADV_INTERVAL_MIN (0.02f) +#define ADV_INTERVAL_MIN_STRING "0.02" #define ADV_INTERVAL_MAX (10.24f) #define ADV_INTERVAL_MAX_STRING "10.24" // 20ms is recommended by Apple @@ -204,7 +204,7 @@ const mp_obj_property_t bleio_adapter_name_obj = { //| :param ~_typing.ReadableBuffer scan_response: scan response data packet bytes. ``None`` if no scan response is needed. //| :param bool connectable: If `True` then other devices are allowed to connect to this peripheral. //| :param bool anonymous: If `True` then this device's MAC address is randomized before advertising. -//| :param int timeout: If set, we will only advertise for this many seconds. +//| :param int timeout: If set, we will only advertise for this many seconds. Zero means no timeout. //| :param float interval: advertising interval, in seconds""" //| ... //| @@ -237,7 +237,7 @@ STATIC mp_obj_t bleio_adapter_start_advertising(mp_uint_t n_args, const mp_obj_t args[ARG_interval].u_obj = mp_obj_new_float(ADV_INTERVAL_DEFAULT); } - const mp_float_t interval = mp_obj_float_get(args[ARG_interval].u_obj); + const mp_float_t interval = mp_obj_get_float(args[ARG_interval].u_obj); if (interval < ADV_INTERVAL_MIN || interval > ADV_INTERVAL_MAX) { mp_raise_ValueError_varg(translate("interval must be in range %s-%s"), ADV_INTERVAL_MIN_STRING, ADV_INTERVAL_MAX_STRING); @@ -279,7 +279,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_adapter_stop_advertising_obj, bleio_adapt //| ignored. Format is one byte for length (n) and n bytes of prefix and can be repeated. //| :param int buffer_size: the maximum number of advertising bytes to buffer. //| :param bool extended: When True, support extended advertising packets. Increasing buffer_size is recommended when this is set. -//| :param float timeout: the scan timeout in seconds. If None, will scan until `stop_scan` is called. +//| :param float timeout: the scan timeout in seconds. If None or zero, will scan until `stop_scan` is called. //| :param float interval: the interval (in seconds) between the start of two consecutive scan windows //| Must be in the range 0.0025 - 40.959375 seconds. //| :param float window: the duration (in seconds) to scan a single BLE channel. @@ -320,7 +320,7 @@ STATIC mp_obj_t bleio_adapter_start_scan(size_t n_args, const mp_obj_t *pos_args args[ARG_window].u_obj = mp_obj_new_float(WINDOW_DEFAULT); } - const mp_float_t interval = mp_obj_float_get(args[ARG_interval].u_obj); + const mp_float_t interval = mp_obj_get_float(args[ARG_interval].u_obj); if (interval < INTERVAL_MIN || interval > INTERVAL_MAX) { mp_raise_ValueError_varg(translate("interval must be in range %s-%s"), INTERVAL_MIN_STRING, INTERVAL_MAX_STRING); } @@ -332,7 +332,7 @@ STATIC mp_obj_t bleio_adapter_start_scan(size_t n_args, const mp_obj_t *pos_args } #pragma GCC diagnostic pop - const mp_float_t window = mp_obj_float_get(args[ARG_window].u_obj); + const mp_float_t window = mp_obj_get_float(args[ARG_window].u_obj); if (window > interval) { mp_raise_ValueError(translate("window must be <= interval")); } diff --git a/shared-bindings/_pixelbuf/__init__.c b/shared-bindings/_pixelbuf/__init__.c index c61acc939f..fdd02509c8 100644 --- a/shared-bindings/_pixelbuf/__init__.c +++ b/shared-bindings/_pixelbuf/__init__.c @@ -51,7 +51,7 @@ //| STATIC mp_obj_t pixelbuf_colorwheel(mp_obj_t n) { - return MP_OBJ_NEW_SMALL_INT(colorwheel(MP_OBJ_IS_SMALL_INT(n) ? MP_OBJ_SMALL_INT_VALUE(n) : mp_obj_float_get(n))); + return MP_OBJ_NEW_SMALL_INT(colorwheel(MP_OBJ_IS_SMALL_INT(n) ? MP_OBJ_SMALL_INT_VALUE(n) : mp_obj_get_float(n))); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pixelbuf_colorwheel_obj, pixelbuf_colorwheel); diff --git a/shared-bindings/alarm/SleepMemory.c b/shared-bindings/alarm/SleepMemory.c index bec0b76658..aed24827ad 100644 --- a/shared-bindings/alarm/SleepMemory.c +++ b/shared-bindings/alarm/SleepMemory.c @@ -53,6 +53,25 @@ //| """Not used. Access the sole instance through `alarm.sleep_memory`.""" //| ... //| +//| def __bool__(self) -> bool: +//| """``sleep_memory`` is ``True`` if its length is greater than zero. +//| This is an easy way to check for its existence. +//| """ +//| ... +//| +//| def __len__(self) -> int: +//| """Return the length. This is used by (`len`)""" +//| ... +//| +STATIC mp_obj_t alarm_sleep_memory_unary_op(mp_unary_op_t op, mp_obj_t self_in) { + alarm_sleep_memory_obj_t *self = MP_OBJ_TO_PTR(self_in); + uint16_t len = common_hal_alarm_sleep_memory_get_length(self); + switch (op) { + case MP_UNARY_OP_BOOL: return mp_obj_new_bool(len != 0); + case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT(len); + default: return MP_OBJ_NULL; // op not supported + } +} STATIC const mp_rom_map_elem_t alarm_sleep_memory_locals_dict_table[] = { }; @@ -154,6 +173,7 @@ const mp_obj_type_t alarm_sleep_memory_type = { { &mp_type_type }, .name = MP_QSTR_SleepMemory, .subscr = alarm_sleep_memory_subscr, + .unary_op = alarm_sleep_memory_unary_op, .print = NULL, .locals_dict = (mp_obj_t)&alarm_sleep_memory_locals_dict, }; diff --git a/shared-bindings/msgpack/ExtType.c b/shared-bindings/msgpack/ExtType.c new file mode 100644 index 0000000000..e9ddd32bce --- /dev/null +++ b/shared-bindings/msgpack/ExtType.c @@ -0,0 +1,126 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Bernhard Boser + * + * 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/smallint.h" +#include "py/objproperty.h" +#include "shared-bindings/msgpack/ExtType.h" + +//| class ExtType: +//| """ExtType represents ext type in msgpack.""" +//| def __init__(self, code: int, data: bytes) -> None: +//| """Constructor +//| :param int code: type code in range 0~127. +//| :param bytes data: representation.""" +//| +STATIC mp_obj_t mod_msgpack_exttype_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + mod_msgpack_extype_obj_t *self = m_new_obj(mod_msgpack_extype_obj_t); + self->base.type = &mod_msgpack_exttype_type; + enum { ARG_code, ARG_data }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_code, MP_ARG_INT | MP_ARG_REQUIRED }, + { MP_QSTR_data, MP_ARG_OBJ | MP_ARG_REQUIRED }, + }; + 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); + + int code = args[ARG_code].u_int; + if (code < 0 || code > 127) { + mp_raise_AttributeError(translate("code outside range 0~127")); + } + self->code = code; + + mp_obj_t data = args[ARG_data].u_obj; + self->data = data; + return MP_OBJ_FROM_PTR(self); +} + + +//| code: int +//| """The type code, in range 0~127.""" +//| ... +//| +STATIC mp_obj_t mod_msgpack_exttype_get_code(mp_obj_t self_in) { + mod_msgpack_extype_obj_t *self = MP_OBJ_TO_PTR(self_in); + return MP_OBJ_NEW_SMALL_INT(self->code); +} +MP_DEFINE_CONST_FUN_OBJ_1(mod_msgpack_exttype_get_code_obj, mod_msgpack_exttype_get_code); + +STATIC mp_obj_t mod_msgpack_exttype_set_code(mp_obj_t self_in, mp_obj_t code_in) { + mod_msgpack_extype_obj_t *self = MP_OBJ_TO_PTR(self_in); + int code = mp_obj_get_int(code_in); + if (code < 0 || code > 127) { + mp_raise_AttributeError(translate("code outside range 0~127")); + } + self->code = code; + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(mod_msgpack_exttype_set_code_obj, mod_msgpack_exttype_set_code); + +const mp_obj_property_t mod_msgpack_exttype_code_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&mod_msgpack_exttype_get_code_obj, + (mp_obj_t)&mod_msgpack_exttype_set_code_obj, + (mp_obj_t)&mp_const_none_obj}, +}; + +//| data: bytes +//| """Data.""" +//| ... +//| +STATIC mp_obj_t mod_msgpack_exttype_get_data(mp_obj_t self_in) { + mod_msgpack_extype_obj_t *self = MP_OBJ_TO_PTR(self_in); + return self->data; +} +MP_DEFINE_CONST_FUN_OBJ_1(mod_msgpack_exttype_get_data_obj, mod_msgpack_exttype_get_data); + +STATIC mp_obj_t mod_msgpack_exttype_set_data(mp_obj_t self_in, mp_obj_t data_in) { + mod_msgpack_extype_obj_t *self = MP_OBJ_TO_PTR(self_in); + self->data = data_in; + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(mod_msgpack_exttype_set_data_obj, mod_msgpack_exttype_set_data); + +const mp_obj_property_t mod_msgpack_exttype_data_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&mod_msgpack_exttype_get_data_obj, + (mp_obj_t)&mod_msgpack_exttype_set_data_obj, + (mp_obj_t)&mp_const_none_obj}, +}; + +STATIC mp_rom_map_elem_t mod_msgpack_exttype_locals_dict_table[] = { + // Properties + { MP_ROM_QSTR(MP_QSTR_code), MP_ROM_PTR(&mod_msgpack_exttype_code_obj) }, + { MP_ROM_QSTR(MP_QSTR_data), MP_ROM_PTR(&mod_msgpack_exttype_data_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(mod_msgpack_exttype_locals_dict, mod_msgpack_exttype_locals_dict_table); + +const mp_obj_type_t mod_msgpack_exttype_type = { + { &mp_type_type }, + .name = MP_QSTR_ExtType, + .make_new = mod_msgpack_exttype_make_new, + .locals_dict = (mp_obj_dict_t*)&mod_msgpack_exttype_locals_dict, +}; diff --git a/shared-bindings/msgpack/ExtType.h b/shared-bindings/msgpack/ExtType.h new file mode 100644 index 0000000000..64173b2213 --- /dev/null +++ b/shared-bindings/msgpack/ExtType.h @@ -0,0 +1,40 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Bernhard Boser + * + * 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_SHARED_BINDINGS_MSGPACK_EXTTYPE___INIT___H +#define MICROPY_INCLUDED_SHARED_BINDINGS_MSGPACK_EXTTYPE___INIT___H + +#include "py/obj.h" + +typedef struct { + mp_obj_base_t base; + int32_t code; + mp_obj_t data; +} mod_msgpack_extype_obj_t; + +extern const mp_obj_type_t mod_msgpack_exttype_type; + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_MSGPACK_EXTTYPE___INIT___H diff --git a/shared-bindings/msgpack/__init__.c b/shared-bindings/msgpack/__init__.c new file mode 100644 index 0000000000..f5c47bb218 --- /dev/null +++ b/shared-bindings/msgpack/__init__.c @@ -0,0 +1,162 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Bernhard Boser + * + * 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 +#include "py/obj.h" +#include "py/runtime.h" +#include "shared-bindings/msgpack/__init__.h" +#include "shared-module/msgpack/__init__.h" +#include "shared-bindings/msgpack/ExtType.h" + +#define MP_OBJ_IS_METH(o) (MP_OBJ_IS_OBJ(o) && (((mp_obj_base_t*)MP_OBJ_TO_PTR(o))->type->name == MP_QSTR_bound_method)) + +//| """Pack object in msgpack format +//| +//| The msgpack format is similar to json, except that the encoded data is binary. +//| See https://msgpack.org for details. The module implements a subset of the cpython +//| module msgpack-python. +//| +//| Not implemented: 64-bit int, uint, float. +//| +//| Example 1:: +//| +//| import msgpack +//| from io import BytesIO +//| +//| b = BytesIO() +//| msgpack.pack({'list': [True, False, None, 1, 3.14], 'str': 'blah'}, b) +//| b.seek(0) +//| print(msgpack.unpack(b)) +//| +//| Example 2: handling objects:: +//| +//| from msgpack import pack, unpack, ExtType +//| from io import BytesIO +//| +//| class MyClass: +//| def __init__(self, val): +//| self.value = val +//| def __str__(self): +//| return str(self.value) +//| +//| data = MyClass(b'my_value') +//| +//| def encoder(obj): +//| if isinstance(obj, MyClass): +//| return ExtType(1, obj.value) +//| return f"no encoder for {obj}" +//| +//| def decoder(code, data): +//| if code == 1: +//| return MyClass(data) +//| return f"no decoder for type {code}" +//| +//| buffer = BytesIO() +//| pack(data, buffer, default=encoder) +//| buffer.seek(0) +//| decoded = unpack(buffer, ext_hook=decoder) +//| print(f"{data} -> {buffer.getvalue()} -> {decoded}") +//| +//| """ +//| + +//| def pack(obj: object, buffer: WriteableBuffer, *, default: Union[Callable[[object], None], None] = None) -> None: +//| """Ouput object to buffer in msgpack format. +//| +//| :param object obj: Object to convert to msgpack format. +//| :param ~_typing.WriteableBuffer buffer: buffer to write into +//| :param Optional[~_typing.Callable[[object], None]] default: +//| function called for python objects that do not have +//| a representation in msgpack format. +//| """ +//| ... +//| +STATIC mp_obj_t mod_msgpack_pack(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_obj, ARG_buffer, ARG_default }; + STATIC const mp_arg_t allowed_args[] = { + { MP_QSTR_obj, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_default, MP_ARG_KW_ONLY | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + }; + 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_obj_t handler = args[ARG_default].u_obj; + if (handler != mp_const_none && !MP_OBJ_IS_FUN(handler) && !MP_OBJ_IS_METH(handler)) { + mp_raise_ValueError(translate("default is not a function")); + } + + common_hal_msgpack_pack(args[ARG_obj].u_obj, args[ARG_buffer].u_obj, handler); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(mod_msgpack_pack_obj, 1, mod_msgpack_pack); + + +//| def unpack(buffer: ReadableBuffer, *, ext_hook: Union[Callable[[int, bytes], object], None] = None, use_list: bool=True) -> object: +//| """Unpack and return one object from buffer. +//| +//| :param ~_typing.ReadableBuffer buffer: buffer to read from +//| :param Optional[~_typing.Callable[[int, bytes], object]] ext_hook: function called for objects in +//| msgpack ext format. +//| :param Optional[bool] use_list: return array as list or tuple (use_list=False). +//| +//| :return object: object read from buffer. +//| """ +//| ... +//| +STATIC mp_obj_t mod_msgpack_unpack(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_buffer, ARG_ext_hook, ARG_use_list }; + STATIC const mp_arg_t allowed_args[] = { + { MP_QSTR_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ, }, + { MP_QSTR_ext_hook, MP_ARG_KW_ONLY | MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_use_list, MP_ARG_KW_ONLY | MP_ARG_BOOL, { .u_bool = true } }, + }; + 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_obj_t hook = args[ARG_ext_hook].u_obj; + if (hook != mp_const_none && !MP_OBJ_IS_FUN(hook) && !MP_OBJ_IS_METH(hook)) { + mp_raise_ValueError(translate("ext_hook is not a function")); + } + + return common_hal_msgpack_unpack(args[ARG_buffer].u_obj, hook, args[ARG_use_list].u_bool); +} +MP_DEFINE_CONST_FUN_OBJ_KW(mod_msgpack_unpack_obj, 1, mod_msgpack_unpack); + + +STATIC const mp_rom_map_elem_t msgpack_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_msgpack) }, + { MP_ROM_QSTR(MP_QSTR_ExtType), MP_ROM_PTR(&mod_msgpack_exttype_type) }, + { MP_ROM_QSTR(MP_QSTR_pack), MP_ROM_PTR(&mod_msgpack_pack_obj) }, + { MP_ROM_QSTR(MP_QSTR_unpack), MP_ROM_PTR(&mod_msgpack_unpack_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(msgpack_module_globals, msgpack_module_globals_table); + +const mp_obj_module_t msgpack_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&msgpack_module_globals, +}; diff --git a/shared-bindings/msgpack/__init__.h b/shared-bindings/msgpack/__init__.h new file mode 100644 index 0000000000..a02ead0bd0 --- /dev/null +++ b/shared-bindings/msgpack/__init__.h @@ -0,0 +1,34 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft for Adafruit Industries + * + * 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_SHARED_BINDINGS_MSGPACK___INIT___H +#define MICROPY_INCLUDED_SHARED_BINDINGS_MSGPACK___INIT___H + +#include "py/obj.h" + +// nothing for now + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_MSGPACK___INIT___H diff --git a/shared-bindings/wifi/Network.c b/shared-bindings/wifi/Network.c index 009712ad19..0f3006f2ea 100644 --- a/shared-bindings/wifi/Network.c +++ b/shared-bindings/wifi/Network.c @@ -124,6 +124,21 @@ const mp_obj_property_t wifi_network_country_obj = { (mp_obj_t)&mp_const_none_obj }, }; +//| authmode: str +//| """String id of the authmode""" +//| +STATIC mp_obj_t wifi_network_get_authmode(mp_obj_t self) { + return common_hal_wifi_network_get_authmode(self); + +} +MP_DEFINE_CONST_FUN_OBJ_1(wifi_network_get_authmode_obj, wifi_network_get_authmode); + +const mp_obj_property_t wifi_network_authmode_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&wifi_network_get_authmode_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj }, +}; STATIC const mp_rom_map_elem_t wifi_network_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_ssid), MP_ROM_PTR(&wifi_network_ssid_obj) }, @@ -131,6 +146,7 @@ STATIC const mp_rom_map_elem_t wifi_network_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_rssi), MP_ROM_PTR(&wifi_network_rssi_obj) }, { MP_ROM_QSTR(MP_QSTR_channel), MP_ROM_PTR(&wifi_network_channel_obj) }, { MP_ROM_QSTR(MP_QSTR_country), MP_ROM_PTR(&wifi_network_country_obj) }, + { MP_ROM_QSTR(MP_QSTR_authmode), MP_ROM_PTR(&wifi_network_authmode_obj) }, }; STATIC MP_DEFINE_CONST_DICT(wifi_network_locals_dict, wifi_network_locals_dict_table); diff --git a/shared-bindings/wifi/Network.h b/shared-bindings/wifi/Network.h index e672e3108a..0f07e7b555 100644 --- a/shared-bindings/wifi/Network.h +++ b/shared-bindings/wifi/Network.h @@ -40,5 +40,6 @@ extern mp_obj_t common_hal_wifi_network_get_bssid(wifi_network_obj_t *self); extern mp_obj_t common_hal_wifi_network_get_rssi(wifi_network_obj_t *self); extern mp_obj_t common_hal_wifi_network_get_channel(wifi_network_obj_t *self); extern mp_obj_t common_hal_wifi_network_get_country(wifi_network_obj_t *self); +extern mp_obj_t common_hal_wifi_network_get_authmode(wifi_network_obj_t *self); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_WIFI_NETWORK_H diff --git a/shared-bindings/wifi/Radio.c b/shared-bindings/wifi/Radio.c index 723572a321..63f507067a 100644 --- a/shared-bindings/wifi/Radio.c +++ b/shared-bindings/wifi/Radio.c @@ -295,7 +295,7 @@ const mp_obj_property_t wifi_radio_ipv4_dns_obj = { }; //| ap_info: Optional[Network] -//| """Network object containing BSSID, SSID, channel, country and RSSI when connected to an access point. None otherwise.""" +//| """Network object containing BSSID, SSID, authmode, channel, country and RSSI when connected to an access point. None otherwise.""" //| STATIC mp_obj_t wifi_radio_get_ap_info(mp_obj_t self) { return common_hal_wifi_radio_get_ap_info(self); diff --git a/shared-module/msgpack/__init__.c b/shared-module/msgpack/__init__.c new file mode 100644 index 0000000000..39178d46e1 --- /dev/null +++ b/shared-module/msgpack/__init__.c @@ -0,0 +1,464 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Bernhard Boser + * + * 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 +#include + +#include "py/obj.h" +#include "py/binary.h" +#include "py/objarray.h" +#include "py/objlist.h" +#include "py/objstringio.h" +#include "py/parsenum.h" +#include "py/runtime.h" +#include "py/stream.h" + +#include "supervisor/shared/translate.h" +#include "shared-bindings/msgpack/ExtType.h" + +//////////////////////////////////////////////////////////////// +// stream management + +typedef struct _msgpack_stream_t { + mp_obj_t stream_obj; + mp_uint_t (*read)(mp_obj_t obj, void *buf, mp_uint_t size, int *errcode); + mp_uint_t (*write)(mp_obj_t obj, const void *buf, mp_uint_t size, int *errcode); + int errcode; +} msgpack_stream_t; + +STATIC msgpack_stream_t get_stream(mp_obj_t stream_obj, int flags) { + const mp_stream_p_t *stream_p = mp_get_stream_raise(stream_obj, flags); + msgpack_stream_t s = {stream_obj, stream_p->read, stream_p->write, 0}; + return s; +} + +//////////////////////////////////////////////////////////////// +// readers + +STATIC void read(msgpack_stream_t *s, void *buf, mp_uint_t size) { + if (size == 0) return; + mp_uint_t ret = s->read(s->stream_obj, buf, size, &s->errcode); + if (s->errcode != 0) { + mp_raise_OSError(s->errcode); + } + if (ret == 0) { + mp_raise_msg(&mp_type_EOFError, NULL); + } + if (ret < size) { + mp_raise_ValueError(translate("short read")); + } +} + +STATIC uint8_t read1(msgpack_stream_t *s) { + uint8_t res = 0; + read(s, &res, 1); + return res; +} + +STATIC uint16_t read2(msgpack_stream_t *s) { + uint16_t res = 0; + read(s, &res, 2); + int n = 1; + if (*(char *)&n == 1) res = __builtin_bswap16(res); + return res; +} + +STATIC uint32_t read4(msgpack_stream_t *s) { + uint32_t res = 0; + read(s, &res, 4); + int n = 1; + if (*(char *)&n == 1) res = __builtin_bswap32(res); + return res; +} + +STATIC size_t read_size(msgpack_stream_t *s, uint8_t len_index) { + size_t res = 0; + switch (len_index) { + case 0: res = (size_t)read1(s); break; + case 1: res = (size_t)read2(s); break; + case 2: res = (size_t)read4(s); break; + } + return res; +} + +//////////////////////////////////////////////////////////////// +// writers + +STATIC void write(msgpack_stream_t *s, const void *buf, mp_uint_t size) { + mp_uint_t ret = s->write(s->stream_obj, buf, size, &s->errcode); + if (s->errcode != 0) { + mp_raise_OSError(s->errcode); + } + if (ret == 0) { + mp_raise_msg(&mp_type_EOFError, NULL); + } +} + +STATIC void write1(msgpack_stream_t *s, uint8_t obj) { + write(s, &obj, 1); +} + +STATIC void write2(msgpack_stream_t *s, uint16_t obj) { + int n = 1; + if (*(char *)&n == 1) obj = __builtin_bswap16(obj); + write(s, &obj, 2); +} + +STATIC void write4(msgpack_stream_t *s, uint32_t obj) { + int n = 1; + if (*(char *)&n == 1) obj = __builtin_bswap32(obj); + write(s, &obj, 4); +} + +// compute and write msgpack size code (array structures) +STATIC void write_size(msgpack_stream_t *s, uint8_t code, size_t size) { + if ((uint8_t)size == size) { + write1(s, code); + write1(s, size); + } else if ((uint16_t)size == size) { + write1(s, code+1); + write2(s, size); + } else { + write1(s, code+2); + write4(s, size); + } +} + +//////////////////////////////////////////////////////////////// +// packers + +// This is a helper function to iterate through a dictionary. The state of +// the iteration is held in *cur and should be initialised with zero for the +// first call. Will return NULL when no more elements are available. +STATIC mp_map_elem_t *dict_iter_next(mp_obj_dict_t *dict, size_t *cur) { + size_t max = dict->map.alloc; + mp_map_t *map = &dict->map; + + for (size_t i = *cur; i < max; i++) { + if (MP_MAP_SLOT_IS_FILLED(map, i)) { + *cur = i + 1; + return &(map->table[i]); + } + } + + return NULL; +} + +STATIC void pack_int(msgpack_stream_t *s, int32_t x) { + if (x > -32 && x < 128) { + write1(s, x); + } else if ((int8_t)x == x) { + write1(s, 0xd0); + write1(s, x); + } else if ((int16_t)x == x) { + write1(s, 0xd1); + write2(s, x); + } else { + write1(s, 0xd2); + write4(s, x); + } +} + +STATIC void pack_bin(msgpack_stream_t *s, const uint8_t* data, size_t len) { + write_size(s, 0xc4, len); + if (len > 0) write(s, data, len); +} + +STATIC void pack_ext(msgpack_stream_t *s, int8_t code, const uint8_t* data, size_t len) { + if (len == 1) { + write1(s, 0xd4); + } else if (len == 2) { + write1(s, 0xd5); + } else if (len == 4) { + write1(s, 0xd6); + } else if (len == 8) { + write1(s, 0xd7); + } else if (len == 16) { + write1(s, 0xd8); + } else { + write_size(s, 0xc7, len); + } + write1(s, code); // type byte + if (len > 0) write(s, data, len); +} + +STATIC void pack_str(msgpack_stream_t *s, const char* str, size_t len) { + if (len < 32) { + write1(s, 0b10100000 | (uint8_t)len); + } else { + write_size(s, 0xd9, len); + } + if (len > 0) write(s, str, len); +} + +STATIC void pack_array(msgpack_stream_t *s, size_t len) { + // only writes the header, manually write the objects after calling pack_array! + if (len < 16) { + write1(s, 0b10010000 | (uint8_t)len); + } else if (len < 0x10000) { + write1(s, 0xdc); + write2(s, len); + } else { + write1(s, 0xdd); + write4(s, len); + } +} + +STATIC void pack_dict(msgpack_stream_t *s, size_t len) { + // only writes the header, manually write the objects after calling pack_array! + if (len < 16) { + write1(s, 0b10000000 | (uint8_t)len); + } else if (len < 0x10000) { + write1(s, 0xde); + write2(s, len); + } else { + write1(s, 0xdf); + write4(s, len); + } +} + +STATIC void pack(mp_obj_t obj, msgpack_stream_t *s, mp_obj_t default_handler) { + if (MP_OBJ_IS_SMALL_INT(obj)) { + // int + int32_t x = MP_OBJ_SMALL_INT_VALUE(obj); + pack_int(s, x); + } else if (MP_OBJ_IS_STR(obj)) { + // string + size_t len; + const char *data = mp_obj_str_get_data(obj, &len); + pack_str(s, data, len); + } else if (MP_OBJ_IS_TYPE(obj, &mod_msgpack_exttype_type)) { + mod_msgpack_extype_obj_t *ext = MP_OBJ_TO_PTR(obj); + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(ext->data, &bufinfo, MP_BUFFER_READ); + pack_ext(s, ext->code, bufinfo.buf, bufinfo.len); + } else if (MP_OBJ_IS_TYPE(obj, &mp_type_bytes)) { + // bytes + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(obj, &bufinfo, MP_BUFFER_READ); + pack_bin(s, bufinfo.buf, bufinfo.len); + } else if (MP_OBJ_IS_TYPE(obj, &mp_type_tuple)) { + // tuple + mp_obj_tuple_t *self = MP_OBJ_TO_PTR(obj); + pack_array(s, self->len); + for (size_t i=0; ilen; i++) { + pack(self->items[i], s, default_handler); + } + } else if (MP_OBJ_IS_TYPE(obj, &mp_type_list)) { + // list (layout differs from tuple) + mp_obj_list_t *self = MP_OBJ_TO_PTR(obj); + pack_array(s, self->len); + for (size_t i=0; ilen; i++) { + pack(self->items[i], s, default_handler); + } + } else if (MP_OBJ_IS_TYPE(obj, &mp_type_dict)) { + // dict + mp_obj_dict_t *self = MP_OBJ_TO_PTR(obj); + pack_dict(s, self->map.used); + size_t cur = 0; + mp_map_elem_t *next = NULL; + while ((next = dict_iter_next(self, &cur)) != NULL) { + pack(next->key, s, default_handler); + pack(next->value, s, default_handler); + } + } else if (mp_obj_is_float(obj)) { + union Float { mp_float_t f; uint32_t u; }; + union Float data; + data.f = mp_obj_float_get(obj); + write1(s, 0xca); + write4(s, data.u); + } else if (obj == mp_const_none) { + write1(s, 0xc0); + } else if (obj == mp_const_false) { + write1(s, 0xc2); + } else if (obj == mp_const_true) { + write1(s, 0xc3); + } else { + if (default_handler != mp_const_none) { + // set default_handler to mp_const_none to avoid infinite recursion + // this also precludes some valid outputs + pack(mp_call_function_1(default_handler, obj), s, mp_const_none); + } else { + mp_raise_ValueError(translate("no default packer")); + } + } +} + +//////////////////////////////////////////////////////////////// +// unpacker + +STATIC mp_obj_t unpack(msgpack_stream_t *s, mp_obj_t ext_hook, bool use_list); + +STATIC mp_obj_t unpack_array_elements(msgpack_stream_t *s, size_t size, mp_obj_t ext_hook, bool use_list) { + if (use_list) { + mp_obj_list_t *t = MP_OBJ_TO_PTR(mp_obj_new_list(size, NULL)); + for (size_t i=0; iitems[i] = unpack(s, ext_hook, use_list); + } + return MP_OBJ_FROM_PTR(t); + } else { + mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(size, NULL)); + for (size_t i=0; iitems[i] = unpack(s, ext_hook, use_list); + } + return MP_OBJ_FROM_PTR(t); + } +} + +STATIC mp_obj_t unpack_bytes(msgpack_stream_t *s, size_t size) { + vstr_t vstr; + vstr_init_len(&vstr, size); + byte *p = (byte*)vstr.buf; + read(s, p, size); + return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); +} + +STATIC mp_obj_t unpack_ext(msgpack_stream_t *s, size_t size, mp_obj_t ext_hook) { + int8_t code = read1(s); + mp_obj_t data = unpack_bytes(s, size); + if (ext_hook != mp_const_none) { + return mp_call_function_2(ext_hook, MP_OBJ_NEW_SMALL_INT(code), data); + } else { + mod_msgpack_extype_obj_t *o = m_new_obj(mod_msgpack_extype_obj_t); + o->base.type = &mod_msgpack_exttype_type; + o->code = code; + o->data = data; + return MP_OBJ_FROM_PTR(o); + } +} + +STATIC mp_obj_t unpack(msgpack_stream_t *s, mp_obj_t ext_hook, bool use_list) { + uint8_t code = read1(s); + if (((code & 0b10000000) == 0) || ((code & 0b11100000) == 0b11100000)) { + // int + return MP_OBJ_NEW_SMALL_INT((int8_t)code); + } + if ((code & 0b11100000) == 0b10100000) { + // str + size_t len = code & 0b11111; + // allocate on stack; len < 32 + char str[len]; + read(s, &str, len); + return mp_obj_new_str(str, len); + } + if ((code & 0b11110000) == 0b10010000) { + // array (list / tuple) + return unpack_array_elements(s, code & 0b1111, ext_hook, use_list); + } + if ((code & 0b11110000) == 0b10000000) { + // map (dict) + size_t len = code & 0b1111; + mp_obj_dict_t *d = MP_OBJ_TO_PTR(mp_obj_new_dict(len)); + for (size_t i=0; i