diff options
| author | Scott Shawcroft <scott@tannewt.org> | 2018-11-30 14:40:01 -0800 |
|---|---|---|
| committer | Scott Shawcroft <scott@tannewt.org> | 2018-11-30 14:40:01 -0800 |
| commit | 95e03092630bbad9949c5fe32cd51e7c29bc065b (patch) | |
| tree | 484cb7535142eaabe873bc10552bbfa1b48ab43b | |
| parent | 754d6afd163ae5f295444166863b5d11afd1b2e4 (diff) | |
| parent | ab94344baee1a5d73d3890de16319cab1e2616de (diff) | |
Merge remote-tracking branch 'adafruit/master' into mini_sam
360 files changed, 28636 insertions, 9237 deletions
diff --git a/.gitmodules b/.gitmodules index c0a3446b9..1c1f8eb65 100644 --- a/.gitmodules +++ b/.gitmodules @@ -75,10 +75,10 @@ url = https://github.com/adafruit/Adafruit_CircuitPython_Crickit [submodule "ports/nrf/nrfx"] path = ports/nrf/nrfx - url = https://github.com/NordicSemiconductor/nrfx.git + url = https://github.com/adafruit/nrfx.git [submodule "lib/tinyusb"] path = lib/tinyusb - url = https://github.com/hathach/tinyusb.git + url = https://github.com/tannewt/tinyusb.git branch = develop [submodule "tools/huffman"] path = tools/huffman diff --git a/.travis.yml b/.travis.yml index 1237a6a6b..396e194b7 100755 --- a/.travis.yml +++ b/.travis.yml @@ -1,44 +1,31 @@ sudo: required -dist: trusty +dist: xenial language: c compiler: - gcc git: depth: 1 -# Put a representative board from each port or sub-port near the top -# to determine more quickly whether that port is going to build or not. +# Each item under 'env' is a separate Travis job to execute. +# They run in separate environments, so each one must take the time +# to clone the repository and submodules; to download and install SDKs, +# pip packages, and so forth. By gathering activities together in optimal +# ways, the "run time" and "total time" of the travis jobs can be minimized. +# +# Since at the time of writing Travis generally starts 5 or 6 jobs, the +# builds have been organized into 5 groups of *approximately* equal durations. +# Additionally, the jobs that need extra SDKs are also organized together. +# +# When adding new boards, take a look on the travis CI page +# https://travis-ci.org/adafruit/circuitpython to which build that installs +# that SDK is shortest and add it there. In the case of major re-organizations, +# just try to make the builds "about equal in run time" env: - - TRAVIS_TEST=unix - - TRAVIS_TEST=docs - - TRAVIS_TEST=translations - - TRAVIS_BOARD=feather_huzzah - - TRAVIS_BOARD=circuitplayground_express - - TRAVIS_BOARD=pca10056 - # The rest of the boards, in alphabetical order. - - TRAVIS_BOARD=trinket_m0 - - TRAVIS_BOARD=feather_m4_express - - TRAVIS_BOARD=grandcentral_m4_express - - TRAVIS_BOARD=arduino_zero - - TRAVIS_BOARD=circuitplayground_express_crickit - - TRAVIS_BOARD=feather_m0_adalogger - - TRAVIS_BOARD=feather_m0_basic - - TRAVIS_BOARD=feather_m0_express - - TRAVIS_BOARD=feather_m0_express_crickit - - TRAVIS_BOARD=feather_m0_rfm69 - - TRAVIS_BOARD=feather_m0_rfm9x - - TRAVIS_BOARD=feather_nrf52832 - - TRAVIS_BOARD=feather_nrf52840_express - - TRAVIS_BOARD=feather_radiofruit_zigbee - - TRAVIS_BOARD=gemma_m0 - - TRAVIS_BOARD=hallowing_m0_express - - TRAVIS_BOARD=itsybitsy_m0_express - - TRAVIS_BOARD=itsybitsy_m4_express - - TRAVIS_BOARD=metro_m0_express - - TRAVIS_BOARD=metro_m4_express - - TRAVIS_BOARD=pca10059 - - TRAVIS_BOARD=pirkey_m0 - - TRAVIS_BOARD=trellis_m4_express + - TRAVIS_TESTS="unix docs translations" TRAVIS_BOARDS="feather_huzzah circuitplayground_express pca10056 pca10059 feather_nrf52832 feather_nrf52840_express makerdiary_nrf52840_mdk" TRAVIS_SDK=arm:nrf:esp8266 + - TRAVIS_BOARDS="metro_m0_express metro_m4_express pirkey_m0 trellis_m4_express trinket_m0" TRAVIS_SDK=arm + - TRAVIS_BOARDS="feather_radiofruit_zigbee gemma_m0 hallowing_m0_express itsybitsy_m0_express itsybitsy_m4_express meowmeow" TRAVIS_SDK=arm + - TRAVIS_BOARDS="feather_m0_express_crickit feather_m0_rfm69 feather_m0_rfm9x feather_m4_express arduino_zero arduino_mkr1300" TRAVIS_SDK=arm + - TRAVIS_BOARDS="circuitplayground_express_crickit feather_m0_adalogger feather_m0_basic feather_m0_express catwan_usbstick" TRAVIS_SDK=arm addons: artifacts: @@ -57,21 +44,33 @@ notifications: on_error: always before_script: + # Expand the git tree back to 4.0.0-alpha.1 and then fetch the latest tag. + - LAST_TAG=`git ls-remote --quiet --tags --sort=version:refname | egrep -o "refs/tags/[0-9]+.*\$" | tail -n 1` + - git fetch --shallow-exclude=4.0.0-alpha.1 + - git fetch --depth 1 origin $LAST_TAG:$LAST_TAG + - git describe --dirty --always --tags + - function var_search () { case "$1" in *$2*) true;; *) false;; esac; } - sudo dpkg --add-architecture i386 - - ([[ -z "$TRAVIS_BOARD" || $TRAVIS_BOARD = "feather_huzzah" ]] || (wget https://s3.amazonaws.com/adafruit-circuit-python/gcc-arm-embedded_7-2018q2-1~trusty1_amd64.deb && sudo dpkg -i gcc-arm-embedded*_amd64.deb)) + - (! var_search "${TRAVIS_SDK-}" arm || (wget https://s3.amazonaws.com/adafruit-circuit-python/gcc-arm-embedded_7-2018q2-1~xenial1_amd64.deb && sudo dpkg -i gcc-arm-embedded*_amd64.deb)) # For nrf builds - - ([[ $TRAVIS_BOARD != "feather_nrf52832" && $TRAVIS_BOARD != "feather_nrf52840_express" && $TRAVIS_BOARD != "pca10056" && $TRAVIS_BOARD != "pca10059" ]] || sudo ports/nrf/drivers/bluetooth/download_ble_stack.sh) + - (! var_search "${TRAVIS_SDK-}" nrf || sudo ports/nrf/bluetooth/download_ble_stack.sh) + # For huzzah builds - - if [[ $TRAVIS_BOARD = "feather_huzzah" ]]; then wget https://github.com/jepler/esp-open-sdk/releases/download/2018-06-10/xtensa-lx106-elf-standalone.tar.gz && tar xavf xtensa-lx106-elf-standalone.tar.gz; PATH=$(readlink -f xtensa-lx106-elf/bin):$PATH; fi + - (! var_search "${TRAVIS_SDK-}" esp8266 || (wget https://github.com/jepler/esp-open-sdk/releases/download/2018-06-10/xtensa-lx106-elf-standalone.tar.gz && tar -C .. -xavf xtensa-lx106-elf-standalone.tar.gz)) + - if var_search "${TRAVIS_SDK-}" esp8266 ; then PATH=$(readlink -f ../xtensa-lx106-elf/bin):$PATH; fi + # For coverage testing (upgrade is used to get latest urllib3 version) - - ([[ -z "$TRAVIS_TEST" ]] || sudo apt-get install -y python3-pip) - - ([[ -z "$TRAVIS_TEST" ]] || sudo pip install --upgrade cpp-coveralls) - - ([[ $TRAVIS_TEST != "docs" ]] || sudo pip install 'Sphinx<1.8.0' sphinx-rtd-theme recommonmark) - - ([[ $TRAVIS_TEST != "translations" ]] || sudo pip3 install polib) + - ([[ -z "$TRAVIS_TESTS" ]] || sudo apt-get install -y python3-pip) + - ([[ -z "$TRAVIS_TESTS" ]] || sudo pip install --upgrade cpp-coveralls) + - (! var_search "${TRAVIS_TESTS-}" docs || sudo pip install 'Sphinx<1.8.0' sphinx-rtd-theme recommonmark) + - (! var_search "${TRAVIS_TESTS-}" translations || sudo pip3 install polib) + + # report some good version numbers to the build - gcc --version - - ([[ -z "$TRAVIS_BOARD" || $TRAVIS_BOARD = "feather_huzzah" ]] || arm-none-eabi-gcc --version) + - (! var_search "${TRAVIS_SDK-}" arm || arm-none-eabi-gcc --version) + - (! var_search "${TRAVIS_SDK-}" esp8266 || xtensa-lx106-elf-gcc --version) - python3 --version script: @@ -81,13 +80,11 @@ script: - echo -en 'travis_fold:end:mpy-cross\\r' - echo 'Building Adafruit binaries' && echo -en 'travis_fold:start:adafruit-bins\\r' - - ([[ -z "$TRAVIS_BOARD" ]] || tools/build_adafruit_bins.sh) + - (for board in $TRAVIS_BOARDS; do TRAVIS_BOARD=$board tools/build_adafruit_bins.sh || exit $?; done) - echo -en 'travis_fold:end:adafruit-bins\\r' - echo 'Building unix' && echo -en 'travis_fold:start:unix\\r' - - ([[ $TRAVIS_TEST != "unix" ]] || make -C ports/unix deplibs -j2) - - ([[ $TRAVIS_TEST != "unix" ]] || make -C ports/unix -j2) - - ([[ $TRAVIS_TEST != "unix" ]] || make -C ports/unix coverage -j2) + - (! var_search "${TRAVIS_TESTS-}" unix || (make -C ports/unix deplibs -j2 && make -C ports/unix -j2 && make -C ports/unix coverage -j2)) - echo -en 'travis_fold:end:unix\\r' # run tests without coverage info @@ -96,27 +93,27 @@ script: # run tests with coverage info - echo 'Test all' && echo -en 'travis_fold:start:test_all\\r' - - ([[ $TRAVIS_TEST != "unix" ]] || (cd tests && MICROPY_CPYTHON3=python3.4 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests -j1)) + - (! var_search "${TRAVIS_TESTS-}" unix || (cd tests && MICROPY_CPYTHON3=python3.5 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests -j1)) - echo -en 'travis_fold:end:test_all\\r' - echo 'Test threads' && echo -en 'travis_fold:start:test_threads\\r' - - ([[ $TRAVIS_TEST != "unix" ]] || (cd tests && MICROPY_CPYTHON3=python3.4 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests -j1 -d thread)) + - (! var_search "${TRAVIS_TESTS-}" unix || (cd tests && MICROPY_CPYTHON3=python3.5 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests -j1 -d thread)) - echo -en 'travis_fold:end:test_threads\\r' - echo 'Testing with native' && echo -en 'travis_fold:start:test_native\\r' - - ([[ $TRAVIS_TEST != "unix" ]] || (cd tests && MICROPY_CPYTHON3=python3.4 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests -j1 --emit native)) + - (! var_search "${TRAVIS_TESTS-}" unix || (cd tests && MICROPY_CPYTHON3=python3.5 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests -j1 --emit native)) - echo -en 'travis_fold:end:test_native\\r' - (echo 'Testing with mpy' && echo -en 'travis_fold:start:test_mpy\\r') - - ([[ $TRAVIS_TEST != "unix" ]] || (cd tests && MICROPY_CPYTHON3=python3.4 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests -j1 --via-mpy -d basics float)) + - (! var_search "${TRAVIS_TESTS-}" unix || (cd tests && MICROPY_CPYTHON3=python3.5 MICROPY_MICROPYTHON=../ports/unix/micropython_coverage ./run-tests -j1 --via-mpy -d basics float)) - echo -en 'travis_fold:end:test_mpy\\r' - (echo 'Building docs' && echo -en 'travis_fold:start:build_docs\\r') - - ([[ $TRAVIS_TEST != "docs" ]] || sphinx-build -E -W -b html . _build/html) + - (! var_search "${TRAVIS_TESTS-}" docs || sphinx-build -E -W -b html . _build/html) - echo -en 'travis_fold:end:build_docs\\r' - (echo 'Building translations' && echo -en 'travis_fold:start:build_translations\\r') - - ([[ $TRAVIS_TEST != "translations" ]] || make check-translate) + - (! var_search "${TRAVIS_TESTS-}" translations || make check-translate) - echo -en 'travis_fold:end:build_translations\\r' # run coveralls coverage analysis (try to, even if some builds/tests failed) diff --git a/README.rst b/README.rst index ac74f10d6..138dbfea7 100644 --- a/README.rst +++ b/README.rst @@ -30,13 +30,21 @@ Supported Boards Designed for CircuitPython ~~~~~~~~~~~~~~~~~~~~~~~~~~ +**M0 Boards** + - `Adafruit CircuitPlayground Express <https://www.adafruit.com/product/3333>`__ (`CircuitPython Guide <https://learn.adafruit.com/adafruit-circuit-playground-express/circuitpython-quickstart>`__) - `Adafruit Feather M0 Express <https://www.adafruit.com/product/3403>`__ (`CircuitPython Guide <https://learn.adafruit.com/adafruit-feather-m0-express-designed-for-circuit-python-circuitpython/kattni-circuitpython>`__) -- `Adafruit Metro M0 Express <https://www.adafruit.com/product/3505>`_ (`CircuitPython Guide <https://learn.adafruit.com/adafruit-metro-m0-express-designed-for-circuitpython/circuitpython>`__) - `Adafruit Gemma M0 <https://www.adafruit.com/product/3501>`__ (`CircuitPython Guide <https://learn.adafruit.com/adafruit-gemma-m0/circuitpython>`__) +- `Adafruit Hallowing M0 Express <https://www.adafruit.com/product/3900>`__ (`CircuitPython Guide <https://learn.adafruit.com/adafruit-hallowing/circuitpython>`__) - `Adafruit ItsyBitsy M0 Express <https://www.adafruit.com/product/3727>`_ (`CircuitPython Guide <https://learn.adafruit.com/introducing-itsy-bitsy-m0/circuitpython>`__) +- `Adafruit Metro M0 Express <https://www.adafruit.com/product/3505>`_ (`CircuitPython Guide <https://learn.adafruit.com/adafruit-metro-m0-express-designed-for-circuitpython/circuitpython>`__) - `Adafruit Trinket M0 <https://www.adafruit.com/product/3500>`__ (`CircuitPython Guide <https://learn.adafruit.com/adafruit-trinket-m0-circuitpython-arduino/circuitpython>`__) -- `Adafruit Metro M4 <https://www.adafruit.com/product/3382>`__ (`CircuitPython Guide <https://learn.adafruit.com/adafruit-metro-m4-express-featuring-atsamd51/overview>`__) + +**M4 Boards** + +- `Adafruit Feather M4 Express <https://www.adafruit.com/product/3857>`__ (`CircuitPython Guide <https://learn.adafruit.com/adafruit-feather-m4-express-atsamd51/circuitpython>`__) +- `Adafruit ItsyBitsy M4 Express <https://www.adafruit.com/product/3800>`__ (`CircuitPython Guide <https://learn.adafruit.com/introducing-adafruit-itsybitsy-m4/circuitpython>`__) +- `Adafruit Metro M4 Express <https://www.adafruit.com/product/3382>`__ (`CircuitPython Guide <https://learn.adafruit.com/adafruit-metro-m4-express-featuring-atsamd51/circuitpython>`__) Other ~~~~~ @@ -53,6 +61,13 @@ Other library <https://github.com/adafruit/Adafruit_CircuitPython_SD>`__) - `Arduino Zero <https://www.arduino.cc/en/Main/ArduinoBoardZero>`__ +"Third-party" or "non-Adafruit" boards +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- `Electronic Cats Meow Meow <https://electroniccats.com/gomeow/>`__ +- `Electronic Cats CatWAN USB Stick <https://electroniccats.com/producto/catwan_usb_stick/>`__ + + Download -------- @@ -84,6 +84,7 @@ version = release = '0.0.0' # directories to ignore when looking for source files. exclude_patterns = ["**/build*", ".venv", + ".direnv", "docs/README.md", "drivers", "examples", @@ -114,7 +115,7 @@ exclude_patterns = ["**/build*", "ports/esp8266/modules", "ports/minimal", "ports/nrf/device", - "ports/nrf/drivers", + "ports/nrf/bluetooth", "ports/nrf/modules", "ports/nrf/nrfx", "ports/nrf/peripherals", diff --git a/docs/drivers.rst b/docs/drivers.rst index 284bfc231..119706d33 100644 --- a/docs/drivers.rst +++ b/docs/drivers.rst @@ -67,6 +67,8 @@ These libraries build on top of the low level APIs to simplify common tasks. DC Motor and Servo <https://circuitpython.readthedocs.io/projects/motor/en/latest/> SD Card <https://circuitpython.readthedocs.io/projects/sd/en/latest/> Image Load <https://circuitpython.readthedocs.io/projects/imageload/en/latest/> + miniQR Non-hardware QR code generator <https://circuitpython.readthedocs.io/projects/miniqr/en/latest/> + Slideshow <https://circuitpython.readthedocs.io/projects/slideshow/en/latest/> LED Animation <https://circuitpython.readthedocs.io/projects/led-animation/en/latest/> Blinky @@ -115,16 +117,18 @@ Motion relating sensing including ``acceleration``, ``magnetic``, ``gyro``, and .. toctree:: + ADXL34x 3 Axis Accelerometer <https://circuitpython.readthedocs.io/projects/adxl34x/en/latest/> BNO055 Accelerometer, Magnetometer, Gyroscope and Absolution Orientation <https://circuitpython.readthedocs.io/projects/bno055/en/latest/> FXAS21002C Gyroscope <https://circuitpython.readthedocs.io/projects/fxas21002c/en/latest/> FXOS8700 Accelerometer <https://circuitpython.readthedocs.io/projects/fxos8700/en/latest/> GPS Global Position <https://circuitpython.readthedocs.io/projects/gps/en/latest/> + L3GD20 Gyroscope <https://circuitpython.readthedocs.io/projects/l3gd20/latest/> LIS3DH Accelerometer <https://circuitpython.readthedocs.io/projects/lis3dh/en/latest/> LSM303 Accelerometer and Magnetometer <https://circuitpython.readthedocs.io/projects/lsm303/en/latest/> LSM9DS0 Accelerometer, Magnetometer, Gyroscope and Temperature <https://circuitpython.readthedocs.io/projects/lsm9ds0/en/latest/> LSM9DS1 Accelerometer, Magnetometer, Gyroscope and Temperature <https://circuitpython.readthedocs.io/projects/lsm9ds1/en/latest/> + MLX90390 3 Axis Mangetometer <https://circuitpython.readthedocs.io/projects/mlx90393/en/latest/> MMA8451 3 axis accelerometer <https://circuitpython.readthedocs.io/projects/mma8451/en/latest/> - L3GD20 Gyroscope <https://circuitpython.readthedocs.io/projects/l3gd20/en/latest/> Environmental Sensors ---------------------- @@ -139,13 +143,18 @@ equivalent carbon dioxide (``eco2`` / ``eCO2``), and total volatile organic comp BME280 Temperature, Humidity and Pressure <https://circuitpython.readthedocs.io/projects/bme280/en/latest/> BME680 Temperature, Humidity, Pressure and Gas <https://circuitpython.readthedocs.io/projects/bme680/en/latest/> BMP280 Barometric Pressure and Altitude <https://circuitpython.readthedocs.io/projects/bmp280/en/latest/> + BMP3xx Barometric Pressure and Altimeter <https://circuitpython.readthedocs.io/projects/bmp3xx/en/latest/> CCS811 Air Quality <https://circuitpython.readthedocs.io/projects/ccs811/en/latest/> DHT Temperature and Humidity <https://circuitpython.readthedocs.io/projects/dht/en/latest/> DS18x20 Temperature <https://circuitpython.readthedocs.io/projects/ds18x20/en/latest/> + HTU21D Temperature and Humidity <https://circuitpython.readthedocs.io/projects/htu21d/en/latest/> MAX31865 Thermocouple Amplifier, Temperature <https://circuitpython.readthedocs.io/projects/max31865/en/latest/> MAX31855 Thermocouple Amplifier, Temperature <https://circuitpython.readthedocs.io/projects/max31855/en/latest/> + MAX31856 Thermocouple Amplifier, Temperature <https://circuitpython.readthedocs.io/projects/max31856/en/latest/> MCP9808 Temperature <https://circuitpython.readthedocs.io/projects/mcp9808/en/latest/> + MP115A2 Barometric Pressure, Temperature <https://circuitpython.readthedocs.io/projects/mpl115a2/en/latest/> MPL3115A2 Barometric Pressure, Altitude and Temperature Sensor <https://circuitpython.readthedocs.io/projects/mpl3115a2/en/latest/> + MPRLS Ported Absolute Pressure <https://circuitpython.readthedocs.io/projects/mprls/en/latest/> SGP30 Air Quality <https://circuitpython.readthedocs.io/projects/sgp30/en/latest/> SHT31-D Temperature and Humidity <https://circuitpython.readthedocs.io/projects/sht31d/en/latest/> Si7021 Temperature and Humidity <https://circuitpython.readthedocs.io/projects/si7021/en/latest/> @@ -168,6 +177,7 @@ These sensors detect light related attributes such as ``color``, ``light`` (unit TSL2591 High Dynamic Range Light Sensor <https://circuitpython.readthedocs.io/projects/tsl2591/en/latest/> VCNL4010 Proximity and Light <https://circuitpython.readthedocs.io/projects/vcnl4010/en/latest/> VEML6070 UV Index <https://circuitpython.readthedocs.io/projects/veml6070/en/latest/> + VEML6075 UV Index <https://circuitpython.readthedocs.io/projects/veml6075/en/latest/> Distance Sensors ------------------ @@ -176,9 +186,11 @@ These sensors measure the ``distance`` to another object and may also measure li .. toctree:: + Garmin LIDARLite I2C <https://circuitpython.readthedocs.io/projects/lidarlite/en/latest/> + TFmini IR Time of Flight ~30cm - 12m <https://circuitpython.readthedocs.io/projects/tfmini/en/latest/> VL6180x 5 - 100 mm <https://circuitpython.readthedocs.io/projects/vl6180x/en/latest/> VL53L0x ~30 - 1000 mm <https://circuitpython.readthedocs.io/projects/vl53l0x/en/latest/> - HC-SR04 ultrasonic range sensors <https://circuitpython.readthedocs.io/projects/hcsr04/en/latest/> + HC-SR04 Ultrasonic Range Sensors <https://circuitpython.readthedocs.io/projects/hcsr04/en/latest/> Radio -------- @@ -187,6 +199,7 @@ These chips communicate to other's over radio. .. toctree:: + Adafruit Bluefruit LE SPI Friend <https://circuitpython.readthedocs.io/projects/bluefruitspi/en/latest/> RFM9x LoRa <https://circuitpython.readthedocs.io/projects/rfm9x/en/latest/> RFM69 Packet Radio <https://circuitpython.readthedocs.io/projects/rfm69/en/latest/> PN532 NFC/RFID <https://circuitpython.readthedocs.io/projects/pn532/en/latest/> @@ -217,9 +230,12 @@ Miscellaneous .. toctree:: + CAP1188 8-Key Capacitive Touch <https://circuitpython.readthedocs.io/projects/cap1188/en/latest/> Si4713 Stereo FM Transmitter <https://circuitpython.readthedocs.io/projects/si4713/en/latest/> AMG88xx Grid-Eye IR Camera <https://circuitpython.readthedocs.io/projects/amg88xx/en/latest/> Trellis 4x4 Keypad <https://circuitpython.readthedocs.io/projects/trellis/en/latest/> + NeoTrellis 4x4 Keypad <https://circuitpython.readthedocs.io/projects/neotrellis/en/latest/> + NeoTrellis M4 4x8 Keypad <https://circuitpython.readthedocs.io/projects/trellism4/en/latest/> DRV2605 Haptic Motor Controller <https://circuitpython.readthedocs.io/projects/drv2605/en/latest/> MAX9744 Audio Amplifier <https://circuitpython.readthedocs.io/projects/max9744/en/latest/> Si5351 Clock Generator <https://circuitpython.readthedocs.io/projects/si5351/en/latest/> @@ -229,3 +245,6 @@ Miscellaneous Fingerprint <https://circuitpython.readthedocs.io/projects/fingerprint/en/latest/> STMPE610 Resistive Touchscreen <https://circuitpython.readthedocs.io/projects/stmpe610/en/latest/> Matrix Keypad <https://circuitpython.readthedocs.io/projects/matrixkeypad/en/latest/> + VS1053 Audio Codec <https://circuitpython.readthedocs.io/projects/vs1053/en/latest/> + FRAM Non-Volatile Memory <https://circuitpython.readthedocs.io/projects/fram/en/latest/> + 74HC595 Shift Register <https://circuitpython.readthedocs.io/projects/74hc595/en/latest/> diff --git a/docs/library/usocket.rst b/docs/library/usocket.rst index 2751db6c4..2115085a3 100644 --- a/docs/library/usocket.rst +++ b/docs/library/usocket.rst @@ -138,16 +138,16 @@ Constants Note that you don't need to specify these in a call to `usocket.socket()`, because `SOCK_STREAM` socket type automatically selects `IPPROTO_TCP`, and `SOCK_DGRAM` - `IPPROTO_UDP`. Thus, the only real use of these constants - is as an argument to `setsockopt()`. + is as an argument to `usocket.socket.setsockopt()`. .. data:: usocket.SOL_* - Socket option levels (an argument to `setsockopt()`). The exact + Socket option levels (an argument to `usocket.socket.setsockopt()`). The exact inventory depends on a ``MicroPython port``. .. data:: usocket.SO_* - Socket options (an argument to `setsockopt()`). The exact + Socket options (an argument to `usocket.socket.setsockopt()`). The exact inventory depends on a ``MicroPython port``. Constants specific to WiPy: diff --git a/drivers/wiznet5k/README.md b/drivers/wiznet5k/README.md new file mode 100644 index 000000000..88f25a2b8 --- /dev/null +++ b/drivers/wiznet5k/README.md @@ -0,0 +1,6 @@ +This is the driver for the WIZnet5x00 series of Ethernet controllers. + +Adapted for MicroPython. + +Original source: https://github.com/Wiznet/W5500_EVB/tree/master/ioLibrary +Taken on: 30 August 2014 diff --git a/drivers/wiznet5k/ethernet/socket.c b/drivers/wiznet5k/ethernet/socket.c new file mode 100644 index 000000000..bea98601d --- /dev/null +++ b/drivers/wiznet5k/ethernet/socket.c @@ -0,0 +1,718 @@ +//***************************************************************************** +// +//! \file socket.c +//! \brief SOCKET APIs Implements file. +//! \details SOCKET APIs like as Berkeley Socket APIs. +//! \version 1.0.3 +//! \date 2013/10/21 +//! \par Revision history +//! <2018/10/09> Nick Moore fixes for CircuitPython +//! <2014/05/01> V1.0.3. Refer to M20140501 +//! 1. Implicit type casting -> Explicit type casting. +//! 2. replace 0x01 with PACK_REMAINED in recvfrom() +//! 3. Validation a destination ip in connect() & sendto(): +//! It occurs a fatal error on converting unint32 address if uint8* addr parameter is not aligned by 4byte address. +//! Copy 4 byte addr value into temporary uint32 variable and then compares it. +//! <2013/12/20> V1.0.2 Refer to M20131220 +//! Remove Warning. +//! <2013/11/04> V1.0.1 2nd Release. Refer to "20131104". +//! In sendto(), Add to clear timeout interrupt status (Sn_IR_TIMEOUT) +//! <2013/10/21> 1st Release +//! \author MidnightCow +//! \copyright +//! +//! Copyright (c) 2013, WIZnet Co., LTD. +//! All rights reserved. +//! +//! Redistribution and use in source and binary forms, with or without +//! modification, are permitted provided that the following conditions +//! are met: +//! +//! * Redistributions of source code must retain the above copyright +//! notice, this list of conditions and the following disclaimer. +//! * Redistributions in binary form must reproduce the above copyright +//! notice, this list of conditions and the following disclaimer in the +//! documentation and/or other materials provided with the distribution. +//! * Neither the name of the <ORGANIZATION> nor the names of its +//! contributors may be used to endorse or promote products derived +//! from this software without specific prior written permission. +//! +//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +//! THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + +#include <string.h> + +#include "py/mpthread.h" +#include "socket.h" + +#define SOCK_ANY_PORT_NUM 0xC000; + +static uint16_t sock_any_port = SOCK_ANY_PORT_NUM; +static uint16_t sock_io_mode = 0; +static uint16_t sock_is_sending = 0; +static uint16_t sock_remained_size[_WIZCHIP_SOCK_NUM_] = {0,0,}; +static uint8_t sock_pack_info[_WIZCHIP_SOCK_NUM_] = {0,}; + +#if _WIZCHIP_ == 5200 + static uint16_t sock_next_rd[_WIZCHIP_SOCK_NUM_] ={0,}; +#endif + +#define CHECK_SOCKNUM() \ + do{ \ + if(sn > _WIZCHIP_SOCK_NUM_) return SOCKERR_SOCKNUM; \ + }while(0); \ + +#define CHECK_SOCKMODE(mode) \ + do{ \ + if((getSn_MR(sn) & 0x0F) != mode) return SOCKERR_SOCKMODE; \ + }while(0); \ + +#define CHECK_SOCKINIT() \ + do{ \ + if((getSn_SR(sn) != SOCK_INIT)) return SOCKERR_SOCKINIT; \ + }while(0); \ + +#define CHECK_SOCKDATA() \ + do{ \ + if(len == 0) return SOCKERR_DATALEN; \ + }while(0); \ + +void WIZCHIP_EXPORT(socket_reset)(void) { + sock_any_port = SOCK_ANY_PORT_NUM; + sock_io_mode = 0; + sock_is_sending = 0; + /* + memset(sock_remained_size, 0, _WIZCHIP_SOCK_NUM_ * sizeof(uint16_t)); + memset(sock_pack_info, 0, _WIZCHIP_SOCK_NUM_ * sizeof(uint8_t)); + */ + +#if _WIZCHIP_ == 5200 + memset(sock_next_rd, 0, _WIZCHIP_SOCK_NUM_ * sizeof(uint16_t)); +#endif +} + +int8_t WIZCHIP_EXPORT(socket)(uint8_t sn, uint8_t protocol, uint16_t port, uint8_t flag) +{ + CHECK_SOCKNUM(); + switch(protocol) + { + case Sn_MR_TCP : + case Sn_MR_UDP : + case Sn_MR_MACRAW : + break; + #if ( _WIZCHIP_ < 5200 ) + case Sn_MR_IPRAW : + case Sn_MR_PPPoE : + break; + #endif + default : + return SOCKERR_SOCKMODE; + } + if((flag & 0x06) != 0) return SOCKERR_SOCKFLAG; +#if _WIZCHIP_ == 5200 + if(flag & 0x10) return SOCKERR_SOCKFLAG; +#endif + + if(flag != 0) + { + switch(protocol) + { + case Sn_MR_TCP: + if((flag & (SF_TCP_NODELAY|SF_IO_NONBLOCK))==0) return SOCKERR_SOCKFLAG; + break; + case Sn_MR_UDP: + if(flag & SF_IGMP_VER2) + { + if((flag & SF_MULTI_ENABLE)==0) return SOCKERR_SOCKFLAG; + } + #if _WIZCHIP_ == 5500 + if(flag & SF_UNI_BLOCK) + { + if((flag & SF_MULTI_ENABLE) == 0) return SOCKERR_SOCKFLAG; + } + #endif + break; + default: + break; + } + } + WIZCHIP_EXPORT(close)(sn); + setSn_MR(sn, (protocol | (flag & 0xF0))); + if(!port) + { + port = sock_any_port++; + if(sock_any_port == 0xFFF0) sock_any_port = SOCK_ANY_PORT_NUM; + } + setSn_PORT(sn,port); + setSn_CR(sn,Sn_CR_OPEN); + while(getSn_CR(sn)); + sock_io_mode |= ((flag & SF_IO_NONBLOCK) << sn); + sock_is_sending &= ~(1<<sn); + sock_remained_size[sn] = 0; + sock_pack_info[sn] = 0; + while(getSn_SR(sn) == SOCK_CLOSED); + return (int8_t)sn; +} + +int8_t WIZCHIP_EXPORT(close)(uint8_t sn) +{ + CHECK_SOCKNUM(); + + setSn_CR(sn,Sn_CR_CLOSE); + /* wait to process the command... */ + while( getSn_CR(sn) ); + /* clear all interrupt of the socket. */ + setSn_IR(sn, 0xFF); + sock_is_sending &= ~(1<<sn); + sock_remained_size[sn] = 0; + sock_pack_info[sn] = 0; + while(getSn_SR(sn) != SOCK_CLOSED); + return SOCK_OK; +} + +int8_t WIZCHIP_EXPORT(listen)(uint8_t sn) +{ + CHECK_SOCKNUM(); + CHECK_SOCKMODE(Sn_MR_TCP); + CHECK_SOCKINIT(); + setSn_CR(sn,Sn_CR_LISTEN); + while(getSn_CR(sn)); + while(getSn_SR(sn) != SOCK_LISTEN) + { + if(getSn_CR(sn) == SOCK_CLOSED) + { + WIZCHIP_EXPORT(close)(sn); + return SOCKERR_SOCKCLOSED; + } + } + return SOCK_OK; +} + + +int8_t WIZCHIP_EXPORT(connect)(uint8_t sn, uint8_t * addr, uint16_t port) +{ + CHECK_SOCKNUM(); + CHECK_SOCKMODE(Sn_MR_TCP); + CHECK_SOCKINIT(); + //M20140501 : For avoiding fatal error on memory align mismatched + //if( *((uint32_t*)addr) == 0xFFFFFFFF || *((uint32_t*)addr) == 0) return SOCKERR_IPINVALID; + { + uint32_t taddr; + taddr = ((uint32_t)addr[0] & 0x000000FF); + taddr = (taddr << 8) + ((uint32_t)addr[1] & 0x000000FF); + taddr = (taddr << 8) + ((uint32_t)addr[2] & 0x000000FF); + taddr = (taddr << 8) + ((uint32_t)addr[3] & 0x000000FF); + if (taddr == 0xFFFFFFFF || taddr == 0) return SOCKERR_IPINVALID; + } + // + + if(port == 0) return SOCKERR_PORTZERO; + setSn_DIPR(sn,addr); + setSn_DPORT(sn,port); + #if _WIZCHIP_ == 5200 // for W5200 ARP errata + setSUBR(wizchip_getsubn()); + #endif + setSn_CR(sn,Sn_CR_CONNECT); + while(getSn_CR(sn)); + if(sock_io_mode & (1<<sn)) return SOCK_BUSY; + while(getSn_SR(sn) != SOCK_ESTABLISHED) + { + if (getSn_SR(sn) == SOCK_CLOSED) { + #if _WIZCHIP_ == 5200 // for W5200 ARP errata + setSUBR((uint8_t*)"\x00\x00\x00\x00"); + #endif + return SOCKERR_SOCKCLOSED; + } + if (getSn_IR(sn) & Sn_IR_TIMEOUT) + { + setSn_IR(sn, Sn_IR_TIMEOUT); + #if _WIZCHIP_ == 5200 // for W5200 ARP errata + setSUBR((uint8_t*)"\x00\x00\x00\x00"); + #endif + return SOCKERR_TIMEOUT; + } + MICROPY_THREAD_YIELD(); + } + #if _WIZCHIP_ == 5200 // for W5200 ARP errata + setSUBR((uint8_t*)"\x00\x00\x00\x00"); + #endif + + return SOCK_OK; +} + +int8_t WIZCHIP_EXPORT(disconnect)(uint8_t sn) +{ + CHECK_SOCKNUM(); + CHECK_SOCKMODE(Sn_MR_TCP); + setSn_CR(sn,Sn_CR_DISCON); + /* wait to process the command... */ + while(getSn_CR(sn)); + sock_is_sending &= ~(1<<sn); + if(sock_io_mode & (1<<sn)) return SOCK_BUSY; + while(getSn_SR(sn) != SOCK_CLOSED) + { + if(getSn_IR(sn) & Sn_IR_TIMEOUT) + { + WIZCHIP_EXPORT(close)(sn); + return SOCKERR_TIMEOUT; + } + } + return SOCK_OK; +} + +int32_t WIZCHIP_EXPORT(send)(uint8_t sn, uint8_t * buf, uint16_t len) +{ + uint8_t tmp=0; + uint16_t freesize=0; + + CHECK_SOCKNUM(); + CHECK_SOCKMODE(Sn_MR_TCP); + CHECK_SOCKDATA(); + tmp = getSn_SR(sn); + if(tmp != SOCK_ESTABLISHED && tmp != SOCK_CLOSE_WAIT) return SOCKERR_SOCKSTATUS; + if( sock_is_sending & (1<<sn) ) + { + tmp = getSn_IR(sn); + if(tmp & Sn_IR_SENDOK) + { + setSn_IR(sn, Sn_IR_SENDOK); + #if _WIZCHIP_ == 5200 + if(getSn_TX_RD(sn) != sock_next_rd[sn]) + { + setSn_CR(sn,Sn_CR_SEND); + while(getSn_CR(sn)); + return SOCKERR_BUSY; + } + #endif + sock_is_sending &= ~(1<<sn); + } + else if(tmp & Sn_IR_TIMEOUT) + { + WIZCHIP_EXPORT(close)(sn); + return SOCKERR_TIMEOUT; + } + else return SOCK_BUSY; + } + freesize = getSn_TxMAX(sn); + if (len > freesize) len = freesize; // check size not to exceed MAX size. + while(1) + { + freesize = getSn_TX_FSR(sn); + tmp = getSn_SR(sn); + if ((tmp != SOCK_ESTABLISHED) && (tmp != SOCK_CLOSE_WAIT)) + { + WIZCHIP_EXPORT(close)(sn); + return SOCKERR_SOCKSTATUS; + } + if( (sock_io_mode & (1<<sn)) && (len > freesize) ) return SOCK_BUSY; + if(len <= freesize) break; + MICROPY_THREAD_YIELD(); + } + wiz_send_data(sn, buf, len); + #if _WIZCHIP_ == 5200 + sock_next_rd[sn] = getSn_TX_RD(sn) + len; + #endif + setSn_CR(sn,Sn_CR_SEND); + /* wait to process the command... */ + while(getSn_CR(sn)); + sock_is_sending |= (1 << sn); + return len; +} + + +int32_t WIZCHIP_EXPORT(recv)(uint8_t sn, uint8_t * buf, uint16_t len) +{ + uint8_t tmp = 0; + uint16_t recvsize = 0; + CHECK_SOCKNUM(); + CHECK_SOCKMODE(Sn_MR_TCP); + CHECK_SOCKDATA(); + + recvsize = getSn_RxMAX(sn); + if(recvsize < len) len = recvsize; + while(1) + { + recvsize = getSn_RX_RSR(sn); + tmp = getSn_SR(sn); + if (tmp != SOCK_ESTABLISHED) + { + if(tmp == SOCK_CLOSE_WAIT) + { + if(recvsize != 0) break; + else if(getSn_TX_FSR(sn) == getSn_TxMAX(sn)) + { + // dpgeorge: Getting here seems to be an orderly shutdown of the + // socket, and trying to get POSIX behaviour we return 0 because: + // "If no messages are available to be received and the peer has per‐ + // formed an orderly shutdown, recv() shall return 0". + // TODO this return value clashes with SOCK_BUSY in non-blocking mode. + WIZCHIP_EXPORT(close)(sn); + return 0; + } + } + else + { + WIZCHIP_EXPORT(close)(sn); + return SOCKERR_SOCKSTATUS; + } + } + if((sock_io_mode & (1<<sn)) && (recvsize == 0)) return SOCK_BUSY; + if(recvsize != 0) break; + MICROPY_THREAD_YIELD(); + }; + if(recvsize < len) len = recvsize; + wiz_recv_data(sn, buf, len); + setSn_CR(sn,Sn_CR_RECV); + while(getSn_CR(sn)); + return len; +} + +int32_t WIZCHIP_EXPORT(sendto)(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t port) +{ + uint8_t tmp = 0; + uint16_t freesize = 0; + CHECK_SOCKNUM(); + switch(getSn_MR(sn) & 0x0F) + { + case Sn_MR_UDP: + case Sn_MR_MACRAW: + break; + default: + return SOCKERR_SOCKMODE; + } + CHECK_SOCKDATA(); + //M20140501 : For avoiding fatal error on memory align mismatched + //if(*((uint32_t*)addr) == 0) return SOCKERR_IPINVALID; + if ((addr[0] | addr[1] | addr[2] | addr[3]) == 0) return SOCKERR_IPINVALID; + if(port == 0) return SOCKERR_PORTZERO; + tmp = getSn_SR(sn); + if(tmp != SOCK_MACRAW && tmp != SOCK_UDP) return SOCKERR_SOCKSTATUS; + + setSn_DIPR(sn,addr); + setSn_DPORT(sn,port); + freesize = getSn_TxMAX(sn); + if (len > freesize) len = freesize; // check size not to exceed MAX size. + while(1) + { + freesize = getSn_TX_FSR(sn); + if(getSn_SR(sn) == SOCK_CLOSED) return SOCKERR_SOCKCLOSED; + if( (sock_io_mode & (1<<sn)) && (len > freesize) ) return SOCK_BUSY; + if(len <= freesize) break; + MICROPY_THREAD_YIELD(); + }; + wiz_send_data(sn, buf, len); + + #if _WIZCHIP_ == 5200 // for W5200 ARP errata + setSUBR(wizchip_getsubn()); + #endif + + setSn_CR(sn,Sn_CR_SEND); + /* wait to process the command... */ + while(getSn_CR(sn)); + while(1) + { + tmp = getSn_IR(sn); + if(tmp & Sn_IR_SENDOK) + { + setSn_IR(sn, Sn_IR_SENDOK); + break; + } + //M:20131104 + //else if(tmp & Sn_IR_TIMEOUT) return SOCKERR_TIMEOUT; + else if(tmp & Sn_IR_TIMEOUT) + { + setSn_IR(sn, Sn_IR_TIMEOUT); + #if _WIZCHIP_ == 5200 // for W5200 ARP errata + setSUBR((uint8_t*)"\x00\x00\x00\x00"); + #endif + return SOCKERR_TIMEOUT; + } + //////////// + MICROPY_THREAD_YIELD(); + } + #if _WIZCHIP_ == 5200 // for W5200 ARP errata + setSUBR((uint8_t*)"\x00\x00\x00\x00"); + #endif + return len; +} + + + +int32_t WIZCHIP_EXPORT(recvfrom)(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port) +{ + uint8_t mr; + uint8_t head[8]; + uint16_t pack_len=0; + + CHECK_SOCKNUM(); + //CHECK_SOCKMODE(Sn_MR_UDP); + switch((mr=getSn_MR(sn)) & 0x0F) + { + case Sn_MR_UDP: + case Sn_MR_MACRAW: + break; + #if ( _WIZCHIP_ < 5200 ) + case Sn_MR_IPRAW: + case Sn_MR_PPPoE: + break; + #endif + default: + return SOCKERR_SOCKMODE; + } + CHECK_SOCKDATA(); + if(sock_remained_size[sn] == 0) + { + while(1) + { + pack_len = getSn_RX_RSR(sn); + if(getSn_SR(sn) == SOCK_CLOSED) return SOCKERR_SOCKCLOSED; + if( (sock_io_mode & (1<<sn)) && (pack_len == 0) ) return SOCK_BUSY; + if(pack_len != 0) break; + MICROPY_THREAD_YIELD(); + }; + } + sock_pack_info[sn] = PACK_COMPLETED; + switch (mr & 0x07) + { + case Sn_MR_UDP : + if(sock_remained_size[sn] == 0) + { + wiz_recv_data(sn, head, 8); + setSn_CR(sn,Sn_CR_RECV); + while(getSn_CR(sn)); + // read peer's IP address, port number & packet length + addr[0] = head[0]; + addr[1] = head[1]; + addr[2] = head[2]; + addr[3] = head[3]; + *port = head[4]; + *port = (*port << 8) + head[5]; + sock_remained_size[sn] = head[6]; + sock_remained_size[sn] = (sock_remained_size[sn] << 8) + head[7]; + sock_pack_info[sn] = PACK_FIRST; + } + if(len < sock_remained_size[sn]) pack_len = len; + else pack_len = sock_remained_size[sn]; + // + // Need to packet length check (default 1472) + // + wiz_recv_data(sn, buf, pack_len); // data copy. + break; + case Sn_MR_MACRAW : + if(sock_remained_size[sn] == 0) + { + wiz_recv_data(sn, head, 2); + setSn_CR(sn,Sn_CR_RECV); + while(getSn_CR(sn)); + // read peer's IP address, port number & packet length + sock_remained_size[sn] = head[0]; + sock_remained_size[sn] = (sock_remained_size[sn] <<8) + head[1]; + sock_remained_size[sn] -= 2; // len includes 2 len bytes + if(sock_remained_size[sn] > 1514) + { + WIZCHIP_EXPORT(close)(sn); + return SOCKFATAL_PACKLEN; + } + sock_pack_info[sn] = PACK_FIRST; + } + if(len < sock_remained_size[sn]) pack_len = len; + else pack_len = sock_remained_size[sn]; + wiz_recv_data(sn,buf,pack_len); + break; + #if ( _WIZCHIP_ < 5200 ) + case Sn_MR_IPRAW: + if(sock_remained_size[sn] == 0) + { + wiz_recv_data(sn, head, 6); + setSn_CR(sn,Sn_CR_RECV); + while(getSn_CR(sn)); + addr[0] = head[0]; + addr[1] = head[1]; + addr[2] = head[2]; + addr[3] = head[3]; + sock_remained_size[sn] = head[4]; + sock_remaiend_size[sn] = (sock_remained_size[sn] << 8) + head[5]; + sock_pack_info[sn] = PACK_FIRST; + } + // + // Need to packet length check + // + if(len < sock_remained_size[sn]) pack_len = len; + else pack_len = sock_remained_size[sn]; + wiz_recv_data(sn, buf, pack_len); // data copy. + break; + #endif + default: + wiz_recv_ignore(sn, pack_len); // data copy. + sock_remained_size[sn] = pack_len; + break; + } + setSn_CR(sn,Sn_CR_RECV); + /* wait to process the command... */ + while(getSn_CR(sn)) ; + sock_remained_size[sn] -= pack_len; + //M20140501 : replace 0x01 with PACK_REMAINED + //if(sock_remained_size[sn] != 0) sock_pack_info[sn] |= 0x01; + if(sock_remained_size[sn] != 0) sock_pack_info[sn] |= PACK_REMAINED; + // + return pack_len; +} + + +int8_t WIZCHIP_EXPORT(ctlsocket)(uint8_t sn, ctlsock_type cstype, void* arg) +{ + uint8_t tmp = 0; + CHECK_SOCKNUM(); + switch(cstype) + { + case CS_SET_IOMODE: + tmp = *((uint8_t*)arg); + if(tmp == SOCK_IO_NONBLOCK) sock_io_mode |= (1<<sn); + else if(tmp == SOCK_IO_BLOCK) sock_io_mode &= ~(1<<sn); + else return SOCKERR_ARG; + break; + case CS_GET_IOMODE: + //M20140501 : implict type casting -> explict type casting + //*((uint8_t*)arg) = (sock_io_mode >> sn) & 0x0001; + *((uint8_t*)arg) = (uint8_t)((sock_io_mode >> sn) & 0x0001); + // + break; + case CS_GET_MAXTXBUF: + *((uint16_t*)arg) = getSn_TxMAX(sn); + break; + case CS_GET_MAXRXBUF: + *((uint16_t*)arg) = getSn_RxMAX(sn); + break; + case CS_CLR_INTERRUPT: + if( (*(uint8_t*)arg) > SIK_ALL) return SOCKERR_ARG; + setSn_IR(sn,*(uint8_t*)arg); + break; + case CS_GET_INTERRUPT: + *((uint8_t*)arg) = getSn_IR(sn); + break; + case CS_SET_INTMASK: + if( (*(uint8_t*)arg) > SIK_ALL) return SOCKERR_ARG; + setSn_IMR(sn,*(uint8_t*)arg); + break; + case CS_GET_INTMASK: + *((uint8_t*)arg) = getSn_IMR(sn); + default: + return SOCKERR_ARG; + } + return SOCK_OK; +} + +int8_t WIZCHIP_EXPORT(setsockopt)(uint8_t sn, sockopt_type sotype, void* arg) +{ + // M20131220 : Remove warning + //uint8_t tmp; + CHECK_SOCKNUM(); + switch(sotype) + { + case SO_TTL: + setSn_TTL(sn,*(uint8_t*)arg); + break; + case SO_TOS: + setSn_TOS(sn,*(uint8_t*)arg); + break; + case SO_MSS: + setSn_MSSR(sn,*(uint16_t*)arg); + break; + case SO_DESTIP: + setSn_DIPR(sn, (uint8_t*)arg); + break; + case SO_DESTPORT: + setSn_DPORT(sn, *(uint16_t*)arg); + break; +#if _WIZCHIP_ != 5100 + case SO_KEEPALIVESEND: + CHECK_SOCKMODE(Sn_MR_TCP); + #if _WIZCHIP_ > 5200 + if(getSn_KPALVTR(sn) != 0) return SOCKERR_SOCKOPT; + #endif + setSn_CR(sn,Sn_CR_SEND_KEEP); + while(getSn_CR(sn) != 0) + { + // M20131220 + //if ((tmp = getSn_IR(sn)) & Sn_IR_TIMEOUT) + if (getSn_IR(sn) & Sn_IR_TIMEOUT) + { + setSn_IR(sn, Sn_IR_TIMEOUT); + return SOCKERR_TIMEOUT; + } + } + break; + #if _WIZCHIP_ > 5200 + case SO_KEEPALIVEAUTO: + CHECK_SOCKMODE(Sn_MR_TCP); + setSn_KPALVTR(sn,*(uint8_t*)arg); + break; + #endif +#endif + default: + return SOCKERR_ARG; + } + return SOCK_OK; +} + +int8_t WIZCHIP_EXPORT(getsockopt)(uint8_t sn, sockopt_type sotype, void* arg) +{ + CHECK_SOCKNUM(); + switch(sotype) + { + case SO_FLAG: + *(uint8_t*)arg = getSn_MR(sn) & 0xF0; + break; + case SO_TTL: + *(uint8_t*) arg = getSn_TTL(sn); + break; + case SO_TOS: + *(uint8_t*) arg = getSn_TOS(sn); + break; + case SO_MSS: + *(uint8_t*) arg = getSn_MSSR(sn); + case SO_DESTIP: + getSn_DIPR(sn, (uint8_t*)arg); + break; + case SO_DESTPORT: + *(uint16_t*) arg = getSn_DPORT(sn); + break; + #if _WIZCHIP_ > 5200 + case SO_KEEPALIVEAUTO: + CHECK_SOCKMODE(Sn_MR_TCP); + *(uint16_t*) arg = getSn_KPALVTR(sn); + break; + #endif + case SO_SENDBUF: + *(uint16_t*) arg = getSn_TX_FSR(sn); + case SO_RECVBUF: + *(uint16_t*) arg = getSn_RX_RSR(sn); + case SO_STATUS: + *(uint8_t*) arg = getSn_SR(sn); + break; + case SO_REMAINSIZE: + if(getSn_MR(sn) == Sn_MR_TCP) + *(uint16_t*)arg = getSn_RX_RSR(sn); + else + *(uint16_t*)arg = sock_remained_size[sn]; + break; + case SO_PACKINFO: + CHECK_SOCKMODE(Sn_MR_TCP); + *(uint8_t*)arg = sock_pack_info[sn]; + break; + default: + return SOCKERR_SOCKOPT; + } + return SOCK_OK; +} diff --git a/drivers/wiznet5k/ethernet/socket.h b/drivers/wiznet5k/ethernet/socket.h new file mode 100644 index 000000000..2f03a34eb --- /dev/null +++ b/drivers/wiznet5k/ethernet/socket.h @@ -0,0 +1,472 @@ +//***************************************************************************** +// +//! \file socket.h +//! \brief SOCKET APIs Header file. +//! \details SOCKET APIs like as berkeley socket api. +//! \version 1.0.2 +//! \date 2013/10/21 +//! \par Revision history +//! <2014/05/01> V1.0.2. Refer to M20140501 +//! 1. Modify the comment : SO_REMAINED -> PACK_REMAINED +//! 2. Add the comment as zero byte udp data reception in getsockopt(). +//! <2013/10/21> 1st Release +//! \author MidnightCow +//! \copyright +//! +//! Copyright (c) 2013, WIZnet Co., LTD. +//! All rights reserved. +//! +//! Redistribution and use in source and binary forms, with or without +//! modification, are permitted provided that the following conditions +//! are met: +//! +//! * Redistributions of source code must retain the above copyright +//! notice, this list of conditions and the following disclaimer. +//! * Redistributions in binary form must reproduce the above copyright +//! notice, this list of conditions and the following disclaimer in the +//! documentation and/or other materials provided with the distribution. +//! * Neither the name of the <ORGANIZATION> nor the names of its +//! contributors may be used to endorse or promote products derived +//! from this software without specific prior written permission. +//! +//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +//! THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** +/** + * @defgroup WIZnet_socket_APIs 1. WIZnet socket APIs + * @brief WIZnet socket APIs are based on Berkeley socket APIs, thus it has much similar name and interface. + * But there is a little bit of difference. + * @details + * <b> Comparison between WIZnet and Berkeley SOCKET APIs </b> + * <table> + * <tr> <td><b>API</b></td> <td><b>WIZnet</b></td> <td><b>Berkeley</b></td> </tr> + * <tr> <td>socket()</td> <td>O</td> <td>O</td> </tr> + * <tr> <td><b>bind()</b></td> <td>X</td> <td>O</td> </tr> + * <tr> <td><b>listen()</b></td> <td>O</td> <td>O</td> </tr> + * <tr> <td><b>connect()</b></td> <td>O</td> <td>O</td> </tr> + * <tr> <td><b>accept()</b></td> <td>X</td> <td>O</td> </tr> + * <tr> <td><b>recv()</b></td> <td>O</td> <td>O</td> </tr> + * <tr> <td><b>send()</b></td> <td>O</td> <td>O</td> </tr> + * <tr> <td><b>recvfrom()</b></td> <td>O</td> <td>O</td> </tr> + * <tr> <td><b>sendto()</b></td> <td>O</td> <td>O</td> </tr> + * <tr> <td><b>closesocket()</b></td> <td>O<br>close() & disconnect()</td> <td>O</td> </tr> + * </table> + * There are @b bind() and @b accept() functions in @b Berkeley SOCKET API but, + * not in @b WIZnet SOCKET API. Because socket() of WIZnet is not only creating a SOCKET but also binding a local port number, + * and listen() of WIZnet is not only listening to connection request from client but also accepting the connection request. \n + * When you program "TCP SERVER" with Berkeley SOCKET API, you can use only one listen port. + * When the listen SOCKET accepts a connection request from a client, it keeps listening. + * After accepting the connection request, a new SOCKET is created and the new SOCKET is used in communication with the client. \n + * Following figure shows network flow diagram by Berkeley SOCKET API. + * @image html Berkeley_SOCKET.jpg "<Berkeley SOCKET API>" + * But, When you program "TCP SERVER" with WIZnet SOCKET API, you can use as many as 8 listen SOCKET with same port number. \n + * Because there's no accept() in WIZnet SOCKET APIs, when the listen SOCKET accepts a connection request from a client, + * it is changed in order to communicate with the client. + * And the changed SOCKET is not listening any more and is dedicated for communicating with the client. \n + * If there're many listen SOCKET with same listen port number and a client requests a connection, + * the SOCKET which has the smallest SOCKET number accepts the request and is changed as communication SOCKET. \n + * Following figure shows network flow diagram by WIZnet SOCKET API. + * @image html WIZnet_SOCKET.jpg "<WIZnet SOCKET API>" + */ +#ifndef _WIZCHIP_SOCKET_H_ +#define _WIZCHIP_SOCKET_H_ + +// use this macro for exported names to avoid name clashes +#define WIZCHIP_EXPORT(name) wizchip_ ## name + +#include "wizchip_conf.h" + +#define SOCKET uint8_t ///< SOCKET type define for legacy driver + +#define SOCK_OK 1 ///< Result is OK about socket process. +#define SOCK_BUSY 0 ///< Socket is busy on processing the operation. Valid only Non-block IO Mode. +#define SOCK_FATAL -1000 ///< Result is fatal error about socket process. + +#define SOCK_ERROR 0 +#define SOCKERR_SOCKNUM (SOCK_ERROR - 1) ///< Invalid socket number +#define SOCKERR_SOCKOPT (SOCK_ERROR - 2) ///< Invalid socket option +#define SOCKERR_SOCKINIT (SOCK_ERROR - 3) ///< Socket is not initialized +#define SOCKERR_SOCKCLOSED (SOCK_ERROR - 4) ///< Socket unexpectedly closed. +#define SOCKERR_SOCKMODE (SOCK_ERROR - 5) ///< Invalid socket mode for socket operation. +#define SOCKERR_SOCKFLAG (SOCK_ERROR - 6) ///< Invalid socket flag +#define SOCKERR_SOCKSTATUS (SOCK_ERROR - 7) ///< Invalid socket status for socket operation. +#define SOCKERR_ARG (SOCK_ERROR - 10) ///< Invalid argument. +#define SOCKERR_PORTZERO (SOCK_ERROR - 11) ///< Port number is zero +#define SOCKERR_IPINVALID (SOCK_ERROR - 12) ///< Invalid IP address +#define SOCKERR_TIMEOUT (SOCK_ERROR - 13) ///< Timeout occurred +#define SOCKERR_DATALEN (SOCK_ERROR - 14) ///< Data length is zero or greater than buffer max size. +#define SOCKERR_BUFFER (SOCK_ERROR - 15) ///< Socket buffer is not enough for data communication. + +#define SOCKFATAL_PACKLEN (SOCK_FATAL - 1) ///< Invalid packet length. Fatal Error. + +/* + * SOCKET FLAG + */ +#define SF_ETHER_OWN (Sn_MR_MFEN) ///< In \ref Sn_MR_MACRAW, Receive only the packet as broadcast, multicast and own packet +#define SF_IGMP_VER2 (Sn_MR_MC) ///< In \ref Sn_MR_UDP with \ref SF_MULTI_ENABLE, Select IGMP version 2. +#define SF_TCP_NODELAY (Sn_MR_ND) ///< In \ref Sn_MR_TCP, Use to nodelayed ack. +#define SF_MULTI_ENABLE (Sn_MR_MULTI) ///< In \ref Sn_MR_UDP, Enable multicast mode. + +#if _WIZCHIP_ == 5500 + #define SF_BROAD_BLOCK (Sn_MR_BCASTB) ///< In \ref Sn_MR_UDP or \ref Sn_MR_MACRAW, Block broadcast packet. Valid only in W5500 + #define SF_MULTI_BLOCK (Sn_MR_MMB) ///< In \ref Sn_MR_MACRAW, Block multicast packet. Valid only in W5500 + #define SF_IPv6_BLOCK (Sn_MR_MIP6B) ///< In \ref Sn_MR_MACRAW, Block IPv6 packet. Valid only in W5500 + #define SF_UNI_BLOCK (Sn_MR_UCASTB) ///< In \ref Sn_MR_UDP with \ref SF_MULTI_ENABLE. Valid only in W5500 +#endif + +#define SF_IO_NONBLOCK 0x01 ///< Socket nonblock io mode. It used parameter in \ref socket(). + +/* + * UDP & MACRAW Packet Infomation + */ +#define PACK_FIRST 0x80 ///< In Non-TCP packet, It indicates to start receiving a packet. +#define PACK_REMAINED 0x01 ///< In Non-TCP packet, It indicates to remain a packet to be received. +#define PACK_COMPLETED 0x00 ///< In Non-TCP packet, It indicates to complete to receive a packet. + +// resets all global state associated with the socket interface +void WIZCHIP_EXPORT(socket_reset)(void); + +/** + * @ingroup WIZnet_socket_APIs + * @brief Open a socket. + * @details Initializes the socket with 'sn' passed as parameter and open. + * + * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>. + * @param protocol Protocol type to operate such as TCP, UDP and MACRAW. + * @param port Port number to be bined. + * @param flag Socket flags as \ref SF_ETHER_OWN, \ref SF_IGMP_VER2, \ref SF_TCP_NODELAY, \ref SF_MULTI_ENABLE, \ref SF_IO_NONBLOCK and so on.\n + * Valid flags only in W5500 : @ref SF_BROAD_BLOCK, @ref SF_MULTI_BLOCK, @ref SF_IPv6_BLOCK, and @ref SF_UNI_BLOCK. + * @sa Sn_MR + * + * @return @b Success : The socket number @b 'sn' passed as parameter\n + * @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number\n + * @ref SOCKERR_SOCKMODE - Not support socket mode as TCP, UDP, and so on. \n + * @ref SOCKERR_SOCKFLAG - Invaild socket flag. + */ +int8_t WIZCHIP_EXPORT(socket)(uint8_t sn, uint8_t protocol, uint16_t port, uint8_t flag); + +/** + * @ingroup WIZnet_socket_APIs + * @brief Close a socket. + * @details It closes the socket with @b'sn' passed as parameter. + * + * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>. + * + * @return @b Success : @ref SOCK_OK \n + * @b Fail : @ref SOCKERR_SOCKNUM - Invalid socket number + */ +int8_t WIZCHIP_EXPORT(close)(uint8_t sn); + +/** + * @ingroup WIZnet_socket_APIs + * @brief Listen to a connection request from a client. + * @details It is listening to a connection request from a client. + * If connection request is accepted successfully, the connection is established. Socket sn is used in passive(server) mode. + * + * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>. + * @return @b Success : @ref SOCK_OK \n + * @b Fail :\n @ref SOCKERR_SOCKINIT - Socket is not initialized \n + * @ref SOCKERR_SOCKCLOSED - Socket closed unexpectedly. + */ +int8_t WIZCHIP_EXPORT(listen)(uint8_t sn); + +/** + * @ingroup WIZnet_socket_APIs + * @brief Try to connect a server. + * @details It requests connection to the server with destination IP address and port number passed as parameter.\n + * @note It is valid only in TCP client mode. + * In block io mode, it does not return until connection is completed. + * In Non-block io mode, it return @ref SOCK_BUSY immediately. + * + * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>. + * @param addr Pointer variable of destination IP address. It should be allocated 4 bytes. + * @param port Destination port number. + * + * @return @b Success : @ref SOCK_OK \n + * @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number\n + * @ref SOCKERR_SOCKMODE - Invalid socket mode\n + * @ref SOCKERR_SOCKINIT - Socket is not initialized\n + * @ref SOCKERR_IPINVALID - Wrong server IP address\n + * @ref SOCKERR_PORTZERO - Server port zero\n + * @ref SOCKERR_TIMEOUT - Timeout occurred during request connection\n + * @ref SOCK_BUSY - In non-block io mode, it returned immediately\n + */ +int8_t WIZCHIP_EXPORT(connect)(uint8_t sn, uint8_t * addr, uint16_t port); + +/** + * @ingroup WIZnet_socket_APIs + * @brief Try to disconnect a connection socket. + * @details It sends request message to disconnect the TCP socket 'sn' passed as parameter to the server or client. + * @note It is valid only in TCP server or client mode. \n + * In block io mode, it does not return until disconnection is completed. \n + * In Non-block io mode, it return @ref SOCK_BUSY immediately. \n + + * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>. + * @return @b Success : @ref SOCK_OK \n + * @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number \n + * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n + * @ref SOCKERR_TIMEOUT - Timeout occurred \n + * @ref SOCK_BUSY - Socket is busy. + */ +int8_t WIZCHIP_EXPORT(disconnect)(uint8_t sn); + +/** + * @ingroup WIZnet_socket_APIs + * @brief Send data to the connected peer in TCP socket. + * @details It is used to send outgoing data to the connected socket. + * @note It is valid only in TCP server or client mode. It can't send data greater than socket buffer size. \n + * In block io mode, It doesn't return until data send is completed - socket buffer size is greater than data. \n + * In non-block io mode, It return @ref SOCK_BUSY immediately when socket buffer is not enough. \n + * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>. + * @param buf Pointer buffer containing data to be sent. + * @param len The byte length of data in buf. + * @return @b Success : The sent data size \n + * @b Fail : \n @ref SOCKERR_SOCKSTATUS - Invalid socket status for socket operation \n + * @ref SOCKERR_TIMEOUT - Timeout occurred \n + * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n + * @ref SOCKERR_SOCKNUM - Invalid socket number \n + * @ref SOCKERR_DATALEN - zero data length \n + * @ref SOCK_BUSY - Socket is busy. + */ +int32_t WIZCHIP_EXPORT(send)(uint8_t sn, uint8_t * buf, uint16_t len); + +/** + * @ingroup WIZnet_socket_APIs + * @brief Receive data from the connected peer. + * @details It is used to read incoming data from the connected socket.\n + * It waits for data as much as the application wants to receive. + * @note It is valid only in TCP server or client mode. It can't receive data greater than socket buffer size. \n + * In block io mode, it doesn't return until data reception is completed - data is filled as <I>len</I> in socket buffer. \n + * In non-block io mode, it return @ref SOCK_BUSY immediately when <I>len</I> is greater than data size in socket buffer. \n + * + * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>. + * @param buf Pointer buffer to read incoming data. + * @param len The max data length of data in buf. + * @return @b Success : The real received data size \n + * @b Fail :\n + * @ref SOCKERR_SOCKSTATUS - Invalid socket status for socket operation \n + * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n + * @ref SOCKERR_SOCKNUM - Invalid socket number \n + * @ref SOCKERR_DATALEN - zero data length \n + * @ref SOCK_BUSY - Socket is busy. + */ +int32_t WIZCHIP_EXPORT(recv)(uint8_t sn, uint8_t * buf, uint16_t len); + +/** + * @ingroup WIZnet_socket_APIs + * @brief Sends datagram to the peer with destination IP address and port number passed as parameter. + * @details It sends datagram of UDP or MACRAW to the peer with destination IP address and port number passed as parameter.\n + * Even if the connectionless socket has been previously connected to a specific address, + * the address and port number parameters override the destination address for that particular datagram only. + * @note In block io mode, It doesn't return until data send is completed - socket buffer size is greater than <I>len</I>. + * In non-block io mode, It return @ref SOCK_BUSY immediately when socket buffer is not enough. + * + * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>. + * @param buf Pointer buffer to send outgoing data. + * @param len The byte length of data in buf. + * @param addr Pointer variable of destination IP address. It should be allocated 4 bytes. + * @param port Destination port number. + * + * @return @b Success : The sent data size \n + * @b Fail :\n @ref SOCKERR_SOCKNUM - Invalid socket number \n + * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n + * @ref SOCKERR_SOCKSTATUS - Invalid socket status for socket operation \n + * @ref SOCKERR_DATALEN - zero data length \n + * @ref SOCKERR_IPINVALID - Wrong server IP address\n + * @ref SOCKERR_PORTZERO - Server port zero\n + * @ref SOCKERR_SOCKCLOSED - Socket unexpectedly closed \n + * @ref SOCKERR_TIMEOUT - Timeout occurred \n + * @ref SOCK_BUSY - Socket is busy. + */ +int32_t WIZCHIP_EXPORT(sendto)(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t port); + +/** + * @ingroup WIZnet_socket_APIs + * @brief Receive datagram of UDP or MACRAW + * @details This function is an application I/F function which is used to receive the data in other then TCP mode. \n + * This function is used to receive UDP and MAC_RAW mode, and handle the header as well. + * This function can divide to received the packet data. + * On the MACRAW SOCKET, the addr and port parameters are ignored. + * @note In block io mode, it doesn't return until data reception is completed - data is filled as <I>len</I> in socket buffer + * In non-block io mode, it return @ref SOCK_BUSY immediately when <I>len</I> is greater than data size in socket buffer. + * + * @param sn Socket number. It should be <b>0 ~ @ref \_WIZCHIP_SOCK_NUM_</b>. + * @param buf Pointer buffer to read incoming data. + * @param len The max data length of data in buf. + * When the received packet size <= len, receives data as packet sized. + * When others, receives data as len. + * @param addr Pointer variable of destination IP address. It should be allocated 4 bytes. + * It is valid only when the first call recvfrom for receiving the packet. + * When it is valid, @ref packinfo[7] should be set as '1' after call @ref getsockopt(sn, SO_PACKINFO, &packinfo). + * @param port Pointer variable of destination port number. + * It is valid only when the first call recvform for receiving the packet. +* When it is valid, @ref packinfo[7] should be set as '1' after call @ref getsockopt(sn, SO_PACKINFO, &packinfo). + * + * @return @b Success : This function return real received data size for success.\n + * @b Fail : @ref SOCKERR_DATALEN - zero data length \n + * @ref SOCKERR_SOCKMODE - Invalid operation in the socket \n + * @ref SOCKERR_SOCKNUM - Invalid socket number \n + * @ref SOCKBUSY - Socket is busy. + */ +int32_t WIZCHIP_EXPORT(recvfrom)(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t * addr, uint16_t *port); + + +///////////////////////////// +// SOCKET CONTROL & OPTION // +///////////////////////////// +#define SOCK_IO_BLOCK 0 ///< Socket Block IO Mode in @ref setsockopt(). +#define SOCK_IO_NONBLOCK 1 ///< Socket Non-block IO Mode in @ref setsockopt(). + +/** + * @defgroup DATA_TYPE DATA TYPE + */ + +/** + * @ingroup DATA_TYPE + * @brief The kind of Socket Interrupt. + * @sa Sn_IR, Sn_IMR, setSn_IR(), getSn_IR(), setSn_IMR(), getSn_IMR() + */ +typedef enum +{ + SIK_CONNECTED = (1 << 0), ///< connected + SIK_DISCONNECTED = (1 << 1), ///< disconnected + SIK_RECEIVED = (1 << 2), ///< data received + SIK_TIMEOUT = (1 << 3), ///< timeout occurred + SIK_SENT = (1 << 4), ///< send ok + SIK_ALL = 0x1F, ///< all interrupt +}sockint_kind; + +/** + * @ingroup DATA_TYPE + * @brief The type of @ref ctlsocket(). + */ +typedef enum +{ + CS_SET_IOMODE, ///< set socket IO mode with @ref SOCK_IO_BLOCK or @ref SOCK_IO_NONBLOCK + CS_GET_IOMODE, ///< get socket IO mode + CS_GET_MAXTXBUF, ///< get the size of socket buffer allocated in TX memory + CS_GET_MAXRXBUF, ///< get the size of socket buffer allocated in RX memory + CS_CLR_INTERRUPT, ///< clear the interrupt of socket with @ref sockint_kind + CS_GET_INTERRUPT, ///< get the socket interrupt. refer to @ref sockint_kind + CS_SET_INTMASK, ///< set the interrupt mask of socket with @ref sockint_kind + CS_GET_INTMASK ///< get the masked interrupt of socket. refer to @ref sockint_kind +}ctlsock_type; + + +/** + * @ingroup DATA_TYPE + * @brief The type of socket option in @ref setsockopt() or @ref getsockopt() + */ +typedef enum +{ + SO_FLAG, ///< Valid only in getsockopt(), For set flag of socket refer to <I>flag</I> in @ref socket(). + SO_TTL, ///< Set/Get TTL. @ref Sn_TTL ( @ref setSn_TTL(), @ref getSn_TTL() ) + SO_TOS, ///< Set/Get TOS. @ref Sn_TOS ( @ref setSn_TOS(), @ref getSn_TOS() ) + SO_MSS, ///< Set/Get MSS. @ref Sn_MSSR ( @ref setSn_MSSR(), @ref getSn_MSSR() ) + SO_DESTIP, ///< Set/Get the destination IP address. @ref Sn_DIPR ( @ref setSn_DIPR(), @ref getSn_DIPR() ) + SO_DESTPORT, ///< Set/Get the destination Port number. @ref Sn_DPORT ( @ref setSn_DPORT(), @ref getSn_DPORT() ) +#if _WIZCHIP_ != 5100 + SO_KEEPALIVESEND, ///< Valid only in setsockopt. Manually send keep-alive packet in TCP mode + #if _WIZCHIP_ > 5200 + SO_KEEPALIVEAUTO, ///< Set/Get keep-alive auto transmission timer in TCP mode + #endif +#endif + SO_SENDBUF, ///< Valid only in getsockopt. Get the free data size of Socekt TX buffer. @ref Sn_TX_FSR, @ref getSn_TX_FSR() + SO_RECVBUF, ///< Valid only in getsockopt. Get the received data size in socket RX buffer. @ref Sn_RX_RSR, @ref getSn_RX_RSR() + SO_STATUS, ///< Valid only in getsockopt. Get the socket status. @ref Sn_SR, @ref getSn_SR() + SO_REMAINSIZE, ///< Valid only in getsockopt. Get the remained packet size in other then TCP mode. + SO_PACKINFO ///< Valid only in getsockopt. Get the packet information as @ref PACK_FIRST, @ref PACK_REMAINED, and @ref PACK_COMPLETED in other then TCP mode. +}sockopt_type; + +/** + * @ingroup WIZnet_socket_APIs + * @brief Control socket. + * @details Control IO mode, Interrupt & Mask of socket and get the socket buffer information. + * Refer to @ref ctlsock_type. + * @param sn socket number + * @param cstype type of control socket. refer to @ref ctlsock_type. + * @param arg Data type and value is determined according to @ref ctlsock_type. \n + * <table> + * <tr> <td> @b cstype </td> <td> @b data type</td><td>@b value</td></tr> + * <tr> <td> @ref CS_SET_IOMODE \n @ref CS_GET_IOMODE </td> <td> uint8_t </td><td>@ref SOCK_IO_BLOCK @ref SOCK_IO_NONBLOCK</td></tr> + * <tr> <td> @ref CS_GET_MAXTXBUF \n @ref CS_GET_MAXRXBUF </td> <td> uint16_t </td><td> 0 ~ 16K </td></tr> + * <tr> <td> @ref CS_CLR_INTERRUPT \n @ref CS_GET_INTERRUPT \n @ref CS_SET_INTMASK \n @ref CS_GET_INTMASK </td> <td> @ref sockint_kind </td><td> @ref SIK_CONNECTED, etc. </td></tr> + * </table> + * @return @b Success @ref SOCK_OK \n + * @b fail @ref SOCKERR_ARG - Invalid argument\n + */ +int8_t WIZCHIP_EXPORT(ctlsocket)(uint8_t sn, ctlsock_type cstype, void* arg); + +/** + * @ingroup WIZnet_socket_APIs + * @brief set socket options + * @details Set socket option like as TTL, MSS, TOS, and so on. Refer to @ref sockopt_type. + * + * @param sn socket number + * @param sotype socket option type. refer to @ref sockopt_type + * @param arg Data type and value is determined according to <I>sotype</I>. \n + * <table> + * <tr> <td> @b sotype </td> <td> @b data type</td><td>@b value</td></tr> + * <tr> <td> @ref SO_TTL </td> <td> uint8_t </td><td> 0 ~ 255 </td> </tr> + * <tr> <td> @ref SO_TOS </td> <td> uint8_t </td><td> 0 ~ 255 </td> </tr> + * <tr> <td> @ref SO_MSS </td> <td> uint16_t </td><td> 0 ~ 65535 </td> </tr> + * <tr> <td> @ref SO_DESTIP </td> <td> uint8_t[4] </td><td> </td></tr> + * <tr> <td> @ref SO_DESTPORT </td> <td> uint16_t </td><td> 0 ~ 65535 </td></tr> + * <tr> <td> @ref SO_KEEPALIVESEND </td> <td> null </td><td> null </td></tr> + * <tr> <td> @ref SO_KEEPALIVEAUTO </td> <td> uint8_t </td><td> 0 ~ 255 </td></tr> + * </table> + * @return + * - @b Success : @ref SOCK_OK \n + * - @b Fail + * - @ref SOCKERR_SOCKNUM - Invalid Socket number \n + * - @ref SOCKERR_SOCKMODE - Invalid socket mode \n + * - @ref SOCKERR_SOCKOPT - Invalid socket option or its value \n + * - @ref SOCKERR_TIMEOUT - Timeout occurred when sending keep-alive packet \n + */ +int8_t WIZCHIP_EXPORT(setsockopt)(uint8_t sn, sockopt_type sotype, void* arg); + +/** + * @ingroup WIZnet_socket_APIs + * @brief get socket options + * @details Get socket option like as FLAG, TTL, MSS, and so on. Refer to @ref sockopt_type + * @param sn socket number + * @param sotype socket option type. refer to @ref sockopt_type + * @param arg Data type and value is determined according to <I>sotype</I>. \n + * <table> + * <tr> <td> @b sotype </td> <td>@b data type</td><td>@b value</td></tr> + * <tr> <td> @ref SO_FLAG </td> <td> uint8_t </td><td> @ref SF_ETHER_OWN, etc... </td> </tr> + * <tr> <td> @ref SO_TOS </td> <td> uint8_t </td><td> 0 ~ 255 </td> </tr> + * <tr> <td> @ref SO_MSS </td> <td> uint16_t </td><td> 0 ~ 65535 </td> </tr> + * <tr> <td> @ref SO_DESTIP </td> <td> uint8_t[4] </td><td> </td></tr> + * <tr> <td> @ref SO_DESTPORT </td> <td> uint16_t </td><td> </td></tr> + * <tr> <td> @ref SO_KEEPALIVEAUTO </td> <td> uint8_t </td><td> 0 ~ 255 </td></tr> + * <tr> <td> @ref SO_SENDBUF </td> <td> uint16_t </td><td> 0 ~ 65535 </td></tr> + * <tr> <td> @ref SO_RECVBUF </td> <td> uint16_t </td><td> 0 ~ 65535 </td></tr> + * <tr> <td> @ref SO_STATUS </td> <td> uint8_t </td><td> @ref SOCK_ESTABLISHED, etc.. </td></tr> + * <tr> <td> @ref SO_REMAINSIZE </td> <td> uint16_t </td><td> 0~ 65535 </td></tr> + * <tr> <td> @ref SO_PACKINFO </td> <td> uint8_t </td><td> @ref PACK_FIRST, etc... </td></tr> + * </table> + * @return + * - @b Success : @ref SOCK_OK \n + * - @b Fail + * - @ref SOCKERR_SOCKNUM - Invalid Socket number \n + * - @ref SOCKERR_SOCKOPT - Invalid socket option or its value \n + * - @ref SOCKERR_SOCKMODE - Invalid socket mode \n + * @note + * The option as PACK_REMAINED and SO_PACKINFO is valid only in NON-TCP mode and after call @ref recvfrom(). \n + * When SO_PACKINFO value is PACK_FIRST and the return value of recvfrom() is zero, + * This means the zero byte UDP data(UDP Header only) received. + */ +int8_t WIZCHIP_EXPORT(getsockopt)(uint8_t sn, sockopt_type sotype, void* arg); + +#endif // _WIZCHIP_SOCKET_H_ diff --git a/drivers/wiznet5k/ethernet/w5200/w5200.c b/drivers/wiznet5k/ethernet/w5200/w5200.c new file mode 100644 index 000000000..8c3780792 --- /dev/null +++ b/drivers/wiznet5k/ethernet/w5200/w5200.c @@ -0,0 +1,206 @@ +// dpgeorge: this file taken from w5500/w5500.c and adapted to W5200 + +//***************************************************************************** +// +//! \file w5500.c +//! \brief W5500 HAL Interface. +//! \version 1.0.1 +//! \date 2013/10/21 +//! \par Revision history +//! <2014/05/01> V1.0.2 +//! 1. Implicit type casting -> Explicit type casting. Refer to M20140501 +//! Fixed the problem on porting into under 32bit MCU +//! Issued by Mathias ClauBen, wizwiki forum ID Think01 and bobh +//! Thank for your interesting and serious advices. +//! <2013/10/21> 1st Release +//! <2013/12/20> V1.0.1 +//! 1. Remove warning +//! 2. WIZCHIP_READ_BUF WIZCHIP_WRITE_BUF in case _WIZCHIP_IO_MODE_SPI_FDM_ +//! for loop optimized(removed). refer to M20131220 +//! \author MidnightCow +//! \copyright +//! +//! Copyright (c) 2013, WIZnet Co., LTD. +//! All rights reserved. +//! +//! Redistribution and use in source and binary forms, with or without +//! modification, are permitted provided that the following conditions +//! are met: +//! +//! * Redistributions of source code must retain the above copyright +//! notice, this list of conditions and the following disclaimer. +//! * Redistributions in binary form must reproduce the above copyright +//! notice, this list of conditions and the following disclaimer in the +//! documentation and/or other materials provided with the distribution. +//! * Neither the name of the <ORGANIZATION> nor the names of its +//! contributors may be used to endorse or promote products derived +//! from this software without specific prior written permission. +//! +//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +//! THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + +#include "w5200.h" + +#define SMASK (0x7ff) /* tx buffer mask */ +#define RMASK (0x7ff) /* rx buffer mask */ +#define SSIZE (2048) /* max tx buffer size */ +#define RSIZE (2048) /* max rx buffer size */ + +#define TXBUF_BASE (0x8000) +#define RXBUF_BASE (0xc000) +#define SBASE(sn) (TXBUF_BASE + SSIZE * (sn)) /* tx buffer base for socket sn */ +#define RBASE(sn) (RXBUF_BASE + RSIZE * (sn)) /* rx buffer base for socket sn */ + +uint8_t WIZCHIP_READ(uint32_t AddrSel) { + WIZCHIP_CRITICAL_ENTER(); + WIZCHIP.CS._select(); + + uint8_t spi_data[4] = { + AddrSel >> 8, + AddrSel, + 0x00, + 0x01, + }; + WIZCHIP.IF.SPI._write_bytes(spi_data, 4); + uint8_t ret; + WIZCHIP.IF.SPI._read_bytes(&ret, 1); + + WIZCHIP.CS._deselect(); + WIZCHIP_CRITICAL_EXIT(); + + return ret; +} + +void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb) { + WIZCHIP_CRITICAL_ENTER(); + WIZCHIP.CS._select(); + + uint8_t spi_data[5] = { + AddrSel >> 8, + AddrSel, + 0x80, + 0x01, + wb, + }; + WIZCHIP.IF.SPI._write_bytes(spi_data, 5); + + WIZCHIP.CS._deselect(); + WIZCHIP_CRITICAL_EXIT(); +} + +void WIZCHIP_READ_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len) { + WIZCHIP_CRITICAL_ENTER(); + WIZCHIP.CS._select(); + + uint8_t spi_data[4] = { + AddrSel >> 8, + AddrSel, + 0x00 | ((len >> 8) & 0x7f), + len & 0xff, + }; + WIZCHIP.IF.SPI._write_bytes(spi_data, 4); + WIZCHIP.IF.SPI._read_bytes(pBuf, len); + + WIZCHIP.CS._deselect(); + WIZCHIP_CRITICAL_EXIT(); +} + +void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len) { + WIZCHIP_CRITICAL_ENTER(); + WIZCHIP.CS._select(); + + uint8_t spi_data[4] = { + AddrSel >> 8, + AddrSel, + 0x80 | ((len >> 8) & 0x7f), + len & 0xff, + }; + WIZCHIP.IF.SPI._write_bytes(spi_data, 4); + WIZCHIP.IF.SPI._write_bytes(pBuf, len); + + WIZCHIP.CS._deselect(); + WIZCHIP_CRITICAL_EXIT(); +} + +uint16_t getSn_TX_FSR(uint8_t sn) { + uint16_t val = 0, val1 = 0; + do { + val1 = (WIZCHIP_READ(Sn_TX_FSR(sn)) << 8) | WIZCHIP_READ(Sn_TX_FSR(sn) + 1); + if (val1 != 0) { + val = (WIZCHIP_READ(Sn_TX_FSR(sn)) << 8) | WIZCHIP_READ(Sn_TX_FSR(sn) + 1); + } + } while (val != val1); + return val; +} + +uint16_t getSn_RX_RSR(uint8_t sn) { + uint16_t val = 0, val1 = 0; + do { + val1 = (WIZCHIP_READ(Sn_RX_RSR(sn)) << 8) | WIZCHIP_READ(Sn_RX_RSR(sn) + 1); + if (val1 != 0) { + val = (WIZCHIP_READ(Sn_RX_RSR(sn)) << 8) | WIZCHIP_READ(Sn_RX_RSR(sn) + 1); + } + } while (val != val1); + return val; +} + +void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len) { + if (len == 0) { + return; + } + + uint16_t ptr = getSn_TX_WR(sn); + uint16_t offset = ptr & SMASK; + uint32_t addr = offset + SBASE(sn); + + if (offset + len > SSIZE) { + // implement wrap-around circular buffer + uint16_t size = SSIZE - offset; + WIZCHIP_WRITE_BUF(addr, wizdata, size); + WIZCHIP_WRITE_BUF(SBASE(sn), wizdata + size, len - size); + } else { + WIZCHIP_WRITE_BUF(addr, wizdata, len); + } + + ptr += len; + setSn_TX_WR(sn, ptr); +} + +void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len) { + if (len == 0) { + return; + } + + uint16_t ptr = getSn_RX_RD(sn); + uint16_t offset = ptr & RMASK; + uint16_t addr = RBASE(sn) + offset; + + if (offset + len > RSIZE) { + // implement wrap-around circular buffer + uint16_t size = RSIZE - offset; + WIZCHIP_READ_BUF(addr, wizdata, size); + WIZCHIP_READ_BUF(RBASE(sn), wizdata + size, len - size); + } else { + WIZCHIP_READ_BUF(addr, wizdata, len); + } + + ptr += len; + setSn_RX_RD(sn, ptr); +} + +void wiz_recv_ignore(uint8_t sn, uint16_t len) { + uint16_t ptr = getSn_RX_RD(sn); + ptr += len; + setSn_RX_RD(sn, ptr); +} diff --git a/drivers/wiznet5k/ethernet/w5200/w5200.h b/drivers/wiznet5k/ethernet/w5200/w5200.h new file mode 100644 index 000000000..63561940f --- /dev/null +++ b/drivers/wiznet5k/ethernet/w5200/w5200.h @@ -0,0 +1,2092 @@ +// dpgeorge: this file taken from w5500/w5500.h and adapted to W5200 + +//***************************************************************************** +// +//! \file w5500.h +//! \brief W5500 HAL Header File. +//! \version 1.0.0 +//! \date 2013/10/21 +//! \par Revision history +//! <2013/10/21> 1st Release +//! \author MidnightCow +//! \copyright +//! +//! Copyright (c) 2013, WIZnet Co., LTD. +//! All rights reserved. +//! +//! Redistribution and use in source and binary forms, with or without +//! modification, are permitted provided that the following conditions +//! are met: +//! +//! * Redistributions of source code must retain the above copyright +//! notice, this list of conditions and the following disclaimer. +//! * Redistributions in binary form must reproduce the above copyright +//! notice, this list of conditions and the following disclaimer in the +//! documentation and/or other materials provided with the distribution. +//! * Neither the name of the <ORGANIZATION> nor the names of its +//! contributors may be used to endorse or promote products derived +//! from this software without specific prior written permission. +//! +//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +//! THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + +#ifndef _W5200_H_ +#define _W5200_H_ + +#include <stdint.h> +#include "../wizchip_conf.h" +//#include "board.h" + +#define _W5200_IO_BASE_ 0x00000000 + +#define WIZCHIP_CREG_ADDR(addr) (_W5200_IO_BASE_ + (addr)) + +#define WIZCHIP_CH_BASE (0x4000) +#define WIZCHIP_CH_SIZE (0x100) +#define WIZCHIP_SREG_ADDR(sn, addr) (_W5200_IO_BASE_ + WIZCHIP_CH_BASE + (sn) * WIZCHIP_CH_SIZE + (addr)) + +////////////////////////////// +//-------------------------- defgroup --------------------------------- +/** + * @defgroup W5500 W5500 + * + * @brief WHIZCHIP register defines and I/O functions of @b W5500. + * + * - @ref WIZCHIP_register : @ref Common_register_group and @ref Socket_register_group + * - @ref WIZCHIP_IO_Functions : @ref Basic_IO_function, @ref Common_register_access_function and @ref Socket_register_access_function + */ + + +/** + * @defgroup WIZCHIP_register WIZCHIP register + * @ingroup W5500 + * + * @brief WHIZCHIP register defines register group of @b W5500. + * + * - @ref Common_register_group : Common register group + * - @ref Socket_register_group : \c SOCKET n register group + */ + + +/** + * @defgroup WIZCHIP_IO_Functions WIZCHIP I/O functions + * @ingroup W5500 + * + * @brief This supports the basic I/O functions for @ref WIZCHIP_register. + * + * - <b> Basic I/O function </b> \n + * WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() \n\n + * + * - @ref Common_register_group <b>access functions</b> \n + * -# @b Mode \n + * getMR(), setMR() + * -# @b Interrupt \n + * getIR(), setIR(), getIMR(), setIMR(), getSIR(), setSIR(), getSIMR(), setSIMR(), getINTLEVEL(), setINTLEVEL() + * -# <b> Network Information </b> \n + * getSHAR(), setSHAR(), getGAR(), setGAR(), getSUBR(), setSUBR(), getSIPR(), setSIPR() + * -# @b Retransmission \n + * getRCR(), setRCR(), getRTR(), setRTR() + * -# @b PPPoE \n + * getPTIMER(), setPTIMER(), getPMAGIC(), getPMAGIC(), getPSID(), setPSID(), getPHAR(), setPHAR(), getPMRU(), setPMRU() + * -# <b> ICMP packet </b>\n + * getUIPR(), getUPORTR() + * -# @b etc. \n + * getPHYCFGR(), setPHYCFGR(), getVERSIONR() \n\n + * + * - \ref Socket_register_group <b>access functions</b> \n + * -# <b> SOCKET control</b> \n + * getSn_MR(), setSn_MR(), getSn_CR(), setSn_CR(), getSn_IMR(), setSn_IMR(), getSn_IR(), setSn_IR() + * -# <b> SOCKET information</b> \n + * getSn_SR(), getSn_DHAR(), setSn_DHAR(), getSn_PORT(), setSn_PORT(), getSn_DIPR(), setSn_DIPR(), getSn_DPORT(), setSn_DPORT() + * getSn_MSSR(), setSn_MSSR() + * -# <b> SOCKET communication </b> \n + * getSn_RXBUF_SIZE(), setSn_RXBUF_SIZE(), getSn_TXBUF_SIZE(), setSn_TXBUF_SIZE() \n + * getSn_TX_RD(), getSn_TX_WR(), setSn_TX_WR() \n + * getSn_RX_RD(), setSn_RX_RD(), getSn_RX_WR() \n + * getSn_TX_FSR(), getSn_RX_RSR(), getSn_KPALVTR(), setSn_KPALVTR() + * -# <b> IP header field </b> \n + * getSn_FRAG(), setSn_FRAG(), getSn_TOS(), setSn_TOS() \n + * getSn_TTL(), setSn_TTL() + */ + + + +/** + * @defgroup Common_register_group Common register + * @ingroup WIZCHIP_register + * + * @brief Common register group\n + * It set the basic for the networking\n + * It set the configuration such as interrupt, network information, ICMP, etc. + * @details + * @sa MR : Mode register. + * @sa GAR, SUBR, SHAR, SIPR + * @sa INTLEVEL, IR, IMR, SIR, SIMR : Interrupt. + * @sa RTR, RCR : Data retransmission. + * @sa PTIMER, PMAGIC, PHAR, PSID, PMRU : PPPoE. + * @sa UIPR, UPORTR : ICMP message. + * @sa PHYCFGR, VERSIONR : etc. + */ + + + +/** + * @defgroup Socket_register_group Socket register + * @ingroup WIZCHIP_register + * + * @brief Socket register group.\n + * Socket register configures and control SOCKETn which is necessary to data communication. + * @details + * @sa Sn_MR, Sn_CR, Sn_IR, Sn_IMR : SOCKETn Control + * @sa Sn_SR, Sn_PORT, Sn_DHAR, Sn_DIPR, Sn_DPORT : SOCKETn Information + * @sa Sn_MSSR, Sn_TOS, Sn_TTL, Sn_KPALVTR, Sn_FRAG : Internet protocol. + * @sa Sn_RXBUF_SIZE, Sn_TXBUF_SIZE, Sn_TX_FSR, Sn_TX_RD, Sn_TX_WR, Sn_RX_RSR, Sn_RX_RD, Sn_RX_WR : Data communication + */ + + + + /** + * @defgroup Basic_IO_function Basic I/O function + * @ingroup WIZCHIP_IO_Functions + * @brief These are basic input/output functions to read values from register or write values to register. + */ + +/** + * @defgroup Common_register_access_function Common register access functions + * @ingroup WIZCHIP_IO_Functions + * @brief These are functions to access <b>common registers</b>. + */ + +/** + * @defgroup Socket_register_access_function Socket register access functions + * @ingroup WIZCHIP_IO_Functions + * @brief These are functions to access <b>socket registers</b>. + */ + +//------------------------------- defgroup end -------------------------------------------- +//----------------------------- W5500 Common Registers IOMAP ----------------------------- +/** + * @ingroup Common_register_group + * @brief Mode Register address(R/W)\n + * @ref MR is used for S/W reset, ping block mode, PPPoE mode and etc. + * @details Each bit of @ref MR defined as follows. + * <table> + * <tr> <td>7</td> <td>6</td> <td>5</td> <td>4</td> <td>3</td> <td>2</td> <td>1</td> <td>0</td> </tr> + * <tr> <td>RST</td> <td>Reserved</td> <td>WOL</td> <td>PB</td> <td>PPPoE</td> <td>Reserved</td> <td>FARP</td> <td>Reserved</td> </tr> + * </table> + * - \ref MR_RST : Reset + * - \ref MR_WOL : Wake on LAN + * - \ref MR_PB : Ping block + * - \ref MR_PPPOE : PPPoE mode + * - \ref MR_FARP : Force ARP mode + */ +#define MR WIZCHIP_CREG_ADDR(0x0000) + +/** + * @ingroup Common_register_group + * @brief Gateway IP Register address(R/W) + * @details @ref GAR configures the default gateway address. + */ +#define GAR WIZCHIP_CREG_ADDR(0x0001) + +/** + * @ingroup Common_register_group + * @brief Subnet mask Register address(R/W) + * @details @ref SUBR configures the subnet mask address. + */ +#define SUBR WIZCHIP_CREG_ADDR(0x0005) + +/** + * @ingroup Common_register_group + * @brief Source MAC Register address(R/W) + * @details @ref SHAR configures the source hardware address. + */ +#define SHAR WIZCHIP_CREG_ADDR(0x0009) + +/** + * @ingroup Common_register_group + * @brief Source IP Register address(R/W) + * @details @ref SIPR configures the source IP address. + */ +#define SIPR WIZCHIP_CREG_ADDR(0x000f) + +/** + * @ingroup Common_register_group + * @brief Set Interrupt low level timer register address(R/W) + * @details @ref INTLEVEL configures the Interrupt Assert Time. + */ +//#define INTLEVEL (_W5500_IO_BASE_ + (0x0013 << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief Interrupt Register(R/W) + * @details @ref IR indicates the interrupt status. Each bit of @ref IR will be still until the bit will be written to by the host. + * If @ref IR is not equal to x00 INTn PIN is asserted to low until it is x00\n\n + * Each bit of @ref IR defined as follows. + * <table> + * <tr> <td>7</td> <td>6</td> <td>5</td> <td>4</td> <td>3</td> <td>2</td> <td>1</td> <td>0</td> </tr> + * <tr> <td>CONFLICT</td> <td>UNREACH</td> <td>PPPoE</td> <td>MP</td> <td>Reserved</td> <td>Reserved</td> <td>Reserved</td> <td>Reserved</td> </tr> + * </table> + * - \ref IR_CONFLICT : IP conflict + * - \ref IR_UNREACH : Destination unreachable + * - \ref IR_PPPoE : PPPoE connection close + * - \ref IR_MP : Magic packet + */ +#define IR WIZCHIP_CREG_ADDR(0x0015) + +/** + * @ingroup Common_register_group + * @brief Interrupt mask register(R/W) + * @details @ref IMR is used to mask interrupts. Each bit of @ref IMR corresponds to each bit of @ref IR. + * When a bit of @ref IMR is and the corresponding bit of @ref IR is an interrupt will be issued. In other words, + * if a bit of @ref IMR is an interrupt will not be issued even if the corresponding bit of @ref IR is \n\n + * Each bit of @ref IMR defined as the following. + * <table> + * <tr> <td>7</td> <td>6</td> <td>5</td> <td>4</td> <td>3</td> <td>2</td> <td>1</td> <td>0</td> </tr> + * <tr> <td>IM_IR7</td> <td>IM_IR6</td> <td>IM_IR5</td> <td>IM_IR4</td> <td>Reserved</td> <td>Reserved</td> <td>Reserved</td> <td>Reserved</td> </tr> + * </table> + * - \ref IM_IR7 : IP Conflict Interrupt Mask + * - \ref IM_IR6 : Destination unreachable Interrupt Mask + * - \ref IM_IR5 : PPPoE Close Interrupt Mask + * - \ref IM_IR4 : Magic Packet Interrupt Mask + */ +#define IMR WIZCHIP_CREG_ADDR(0x0016) + +/** + * @ingroup Common_register_group + * @brief Socket Interrupt Register(R/W) + * @details @ref SIR indicates the interrupt status of Socket.\n + * Each bit of @ref SIR be still until @ref Sn_IR is cleared by the host.\n + * If @ref Sn_IR is not equal to x00 the n-th bit of @ref SIR is and INTn PIN is asserted until @ref SIR is x00 */ +//#define SIR (_W5500_IO_BASE_ + (0x0017 << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief Socket Interrupt Mask Register(R/W) + * @details Each bit of @ref SIMR corresponds to each bit of @ref SIR. + * When a bit of @ref SIMR is and the corresponding bit of @ref SIR is Interrupt will be issued. + * In other words, if a bit of @ref SIMR is an interrupt will be not issued even if the corresponding bit of @ref SIR is + */ +//#define SIMR (_W5500_IO_BASE_ + (0x0018 << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief Timeout register address( 1 is 100us )(R/W) + * @details @ref RTR configures the retransmission timeout period. The unit of timeout period is 100us and the default of @ref RTR is x07D0or 000 + * And so the default timeout period is 200ms(100us X 2000). During the time configured by @ref RTR, W5500 waits for the peer response + * to the packet that is transmitted by \ref Sn_CR (CONNECT, DISCON, CLOSE, SEND, SEND_MAC, SEND_KEEP command). + * If the peer does not respond within the @ref RTR time, W5500 retransmits the packet or issues timeout. + */ +#define RTR WIZCHIP_CREG_ADDR(0x0017) + +/** + * @ingroup Common_register_group + * @brief Retry count register(R/W) + * @details @ref RCR configures the number of time of retransmission. + * When retransmission occurs as many as ref RCR+1 Timeout interrupt is issued (@ref Sn_IR[TIMEOUT] = . + */ +#define RCR WIZCHIP_CREG_ADDR(0x0019) + +/** + * @ingroup Common_register_group + * @brief PPP LCP Request Timer register in PPPoE mode(R/W) + * @details @ref PTIMER configures the time for sending LCP echo request. The unit of time is 25ms. + */ +#define PTIMER WIZCHIP_CREG_ADDR(0x0028) + +/** + * @ingroup Common_register_group + * @brief PPP LCP Magic number register in PPPoE mode(R/W) + * @details @ref PMAGIC configures the 4bytes magic number to be used in LCP negotiation. + */ +#define PMAGIC WIZCHIP_CREG_ADDR(0x0029) + +/** + * @ingroup Common_register_group + * @brief PPP Destination MAC Register address(R/W) + * @details @ref PHAR configures the PPPoE server hardware address that is acquired during PPPoE connection process. + */ +//#define PHAR (_W5500_IO_BASE_ + (0x001E << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief PPP Session Identification Register(R/W) + * @details @ref PSID configures the PPPoE sever session ID acquired during PPPoE connection process. + */ +//#define PSID (_W5500_IO_BASE_ + (0x0024 << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief PPP Maximum Segment Size(MSS) register(R/W) + * @details @ref PMRU configures the maximum receive unit of PPPoE. + */ +//#define PMRU (_W5500_IO_BASE_ + (0x0026 << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief Unreachable IP register address in UDP mode(R) + * @details W5500 receives an ICMP packet(Destination port unreachable) when data is sent to a port number + * which socket is not open and @ref UNREACH bit of @ref IR becomes and @ref UIPR & @ref UPORTR indicates + * the destination IP address & port number respectively. + */ +//#define UIPR (_W5500_IO_BASE_ + (0x002a << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief Unreachable Port register address in UDP mode(R) + * @details W5500 receives an ICMP packet(Destination port unreachable) when data is sent to a port number + * which socket is not open and @ref UNREACH bit of @ref IR becomes and @ref UIPR & @ref UPORTR + * indicates the destination IP address & port number respectively. + */ +//#define UPORTR (_W5500_IO_BASE_ + (0x002e << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief PHY Status Register(R/W) + * @details @ref PHYCFGR configures PHY operation mode and resets PHY. In addition, @ref PHYCFGR indicates the status of PHY such as duplex, Speed, Link. + */ +//#define PHYCFGR (_W5500_IO_BASE_ + (0x002E << 8) + (WIZCHIP_CREG_BLOCK << 3)) +#define PHYSTATUS WIZCHIP_CREG_ADDR(0x0035) + +// Reserved (_W5500_IO_BASE_ + (0x002F << 8) + (WIZCHIP_CREG_BLOCK << 3)) +// Reserved (_W5500_IO_BASE_ + (0x0030 << 8) + (WIZCHIP_CREG_BLOCK << 3)) +// Reserved (_W5500_IO_BASE_ + (0x0031 << 8) + (WIZCHIP_CREG_BLOCK << 3)) +// Reserved (_W5500_IO_BASE_ + (0x0032 << 8) + (WIZCHIP_CREG_BLOCK << 3)) +// Reserved (_W5500_IO_BASE_ + (0x0033 << 8) + (WIZCHIP_CREG_BLOCK << 3)) +// Reserved (_W5500_IO_BASE_ + (0x0034 << 8) + (WIZCHIP_CREG_BLOCK << 3)) +// Reserved (_W5500_IO_BASE_ + (0x0035 << 8) + (WIZCHIP_CREG_BLOCK << 3)) +// Reserved (_W5500_IO_BASE_ + (0x0036 << 8) + (WIZCHIP_CREG_BLOCK << 3)) +// Reserved (_W5500_IO_BASE_ + (0x0037 << 8) + (WIZCHIP_CREG_BLOCK << 3)) +// Reserved (_W5500_IO_BASE_ + (0x0038 << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief chip version register address(R) + * @details @ref VERSIONR always indicates the W5500 version as @b 0x04. + */ +//#define VERSIONR (_W5200_IO_BASE_ + (0x0039 << 8) + (WIZCHIP_CREG_BLOCK << 3)) + + +//----------------------------- W5500 Socket Registers IOMAP ----------------------------- +/** + * @ingroup Socket_register_group + * @brief socket Mode register(R/W) + * @details @ref Sn_MR configures the option or protocol type of Socket n.\n\n + * Each bit of @ref Sn_MR defined as the following. + * <table> + * <tr> <td>7</td> <td>6</td> <td>5</td> <td>4</td> <td>3</td> <td>2</td> <td>1</td> <td>0</td> </tr> + * <tr> <td>MULTI/MFEN</td> <td>BCASTB</td> <td>ND/MC/MMB</td> <td>UCASTB/MIP6B</td> <td>Protocol[3]</td> <td>Protocol[2]</td> <td>Protocol[1]</td> <td>Protocol[0]</td> </tr> + * </table> + * - @ref Sn_MR_MULTI : Support UDP Multicasting + * - @ref Sn_MR_BCASTB : Broadcast block <b>in UDP Multicasting</b> + * - @ref Sn_MR_ND : No Delayed Ack(TCP) flag + * - @ref Sn_MR_MC : IGMP version used <b>in UDP mulitcasting</b> + * - @ref Sn_MR_MMB : Multicast Blocking <b>in @ref Sn_MR_MACRAW mode</b> + * - @ref Sn_MR_UCASTB : Unicast Block <b>in UDP Multicating</b> + * - @ref Sn_MR_MIP6B : IPv6 packet Blocking <b>in @ref Sn_MR_MACRAW mode</b> + * - <b>Protocol</b> + * <table> + * <tr> <td><b>Protocol[3]</b></td> <td><b>Protocol[2]</b></td> <td><b>Protocol[1]</b></td> <td><b>Protocol[0]</b></td> <td>@b Meaning</td> </tr> + * <tr> <td>0</td> <td>0</td> <td>0</td> <td>0</td> <td>Closed</td> </tr> + * <tr> <td>0</td> <td>0</td> <td>0</td> <td>1</td> <td>TCP</td> </tr> + * <tr> <td>0</td> <td>0</td> <td>1</td> <td>0</td> <td>UDP</td> </tr> + * <tr> <td>0</td> <td>1</td> <td>0</td> <td>0</td> <td>MACRAW</td> </tr> + * </table> + * - @ref Sn_MR_MACRAW : MAC LAYER RAW SOCK \n + * - @ref Sn_MR_UDP : UDP + * - @ref Sn_MR_TCP : TCP + * - @ref Sn_MR_CLOSE : Unused socket + * @note MACRAW mode should be only used in Socket 0. + */ +#define Sn_MR(N) WIZCHIP_SREG_ADDR(N, 0x0000) + +/** + * @ingroup Socket_register_group + * @brief Socket command register(R/W) + * @details This is used to set the command for Socket n such as OPEN, CLOSE, CONNECT, LISTEN, SEND, and RECEIVE.\n + * After W5500 accepts the command, the @ref Sn_CR register is automatically cleared to 0x00. + * Even though @ref Sn_CR is cleared to 0x00, the command is still being processed.\n + * To check whether the command is completed or not, please check the @ref Sn_IR or @ref Sn_SR. + * - @ref Sn_CR_OPEN : Initialize or open socket. + * - @ref Sn_CR_LISTEN : Wait connection request in TCP mode(<b>Server mode</b>) + * - @ref Sn_CR_CONNECT : Send connection request in TCP mode(<b>Client mode</b>) + * - @ref Sn_CR_DISCON : Send closing request in TCP mode. + * - @ref Sn_CR_CLOSE : Close socket. + * - @ref Sn_CR_SEND : Update TX buffer pointer and send data. + * - @ref Sn_CR_SEND_MAC : Send data with MAC address, so without ARP process. + * - @ref Sn_CR_SEND_KEEP : Send keep alive message. + * - @ref Sn_CR_RECV : Update RX buffer pointer and receive data. + */ +#define Sn_CR(N) WIZCHIP_SREG_ADDR(N, 0x0001) + +/** + * @ingroup Socket_register_group + * @brief Socket interrupt register(R) + * @details @ref Sn_IR indicates the status of Socket Interrupt such as establishment, termination, receiving data, timeout).\n + * When an interrupt occurs and the corresponding bit of @ref Sn_IMR is the corresponding bit of @ref Sn_IR becomes \n + * In order to clear the @ref Sn_IR bit, the host should write the bit to \n + * <table> + * <tr> <td>7</td> <td>6</td> <td>5</td> <td>4</td> <td>3</td> <td>2</td> <td>1</td> <td>0</td> </tr> + * <tr> <td>Reserved</td> <td>Reserved</td> <td>Reserved</td> <td>SEND_OK</td> <td>TIMEOUT</td> <td>RECV</td> <td>DISCON</td> <td>CON</td> </tr> + * </table> + * - \ref Sn_IR_SENDOK : <b>SEND_OK Interrupt</b> + * - \ref Sn_IR_TIMEOUT : <b>TIMEOUT Interrupt</b> + * - \ref Sn_IR_RECV : <b>RECV Interrupt</b> + * - \ref Sn_IR_DISCON : <b>DISCON Interrupt</b> + * - \ref Sn_IR_CON : <b>CON Interrupt</b> + */ +#define Sn_IR(N) WIZCHIP_SREG_ADDR(N, 0x0002) + +/** + * @ingroup Socket_register_group + * @brief Socket status register(R) + * @details @ref Sn_SR indicates the status of Socket n.\n + * The status of Socket n is changed by @ref Sn_CR or some special control packet as SYN, FIN packet in TCP. + * @par Normal status + * - @ref SOCK_CLOSED : Closed + * - @ref SOCK_INIT : Initiate state + * - @ref SOCK_LISTEN : Listen state + * - @ref SOCK_ESTABLISHED : Success to connect + * - @ref SOCK_CLOSE_WAIT : Closing state + * - @ref SOCK_UDP : UDP socket + * - @ref SOCK_MACRAW : MAC raw mode socket + *@par Temporary status during changing the status of Socket n. + * - @ref SOCK_SYNSENT : This indicates Socket n sent the connect-request packet (SYN packet) to a peer. + * - @ref SOCK_SYNRECV : It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer. + * - @ref SOCK_FIN_WAIT : Connection state + * - @ref SOCK_CLOSING : Closing state + * - @ref SOCK_TIME_WAIT : Closing state + * - @ref SOCK_LAST_ACK : Closing state + */ +#define Sn_SR(N) WIZCHIP_SREG_ADDR(N, 0x0003) + +/** + * @ingroup Socket_register_group + * @brief source port register(R/W) + * @details @ref Sn_PORT configures the source port number of Socket n. + * It is valid when Socket n is used in TCP/UPD mode. It should be set before OPEN command is ordered. + */ +#define Sn_PORT(N) WIZCHIP_SREG_ADDR(N, 0x0004) + +/** + * @ingroup Socket_register_group + * @brief Peer MAC register address(R/W) + * @details @ref Sn_DHAR configures the destination hardware address of Socket n when using SEND_MAC command in UDP mode or + * it indicates that it is acquired in ARP-process by CONNECT/SEND command. + */ +#define Sn_DHAR(N) WIZCHIP_SREG_ADDR(N, 0x0006) + +/** + * @ingroup Socket_register_group + * @brief Peer IP register address(R/W) + * @details @ref Sn_DIPR configures or indicates the destination IP address of Socket n. It is valid when Socket n is used in TCP/UDP mode. + * In TCP client mode, it configures an IP address of �TCP serverbefore CONNECT command. + * In TCP server mode, it indicates an IP address of �TCP clientafter successfully establishing connection. + * In UDP mode, it configures an IP address of peer to be received the UDP packet by SEND or SEND_MAC command. + */ +#define Sn_DIPR(N) WIZCHIP_SREG_ADDR(N, 0x000c) + +/** + * @ingroup Socket_register_group + * @brief Peer port register address(R/W) + * @details @ref Sn_DPORT configures or indicates the destination port number of Socket n. It is valid when Socket n is used in TCP/UDP mode. + * In �TCP clientmode, it configures the listen port number of �TCP serverbefore CONNECT command. + * In �TCP Servermode, it indicates the port number of TCP client after successfully establishing connection. + * In UDP mode, it configures the port number of peer to be transmitted the UDP packet by SEND/SEND_MAC command. + */ +#define Sn_DPORT(N) WIZCHIP_SREG_ADDR(N, 0x0010) + +/** + * @ingroup Socket_register_group + * @brief Maximum Segment Size(Sn_MSSR0) register address(R/W) + * @details @ref Sn_MSSR configures or indicates the MTU(Maximum Transfer Unit) of Socket n. + */ +#define Sn_MSSR(N) WIZCHIP_SREG_ADDR(N, 0x0012) + +// Reserved (_W5500_IO_BASE_ + (0x0014 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +/** + * @ingroup Socket_register_group + * @brief IP Type of Service(TOS) Register(R/W) + * @details @ref Sn_TOS configures the TOS(Type Of Service field in IP Header) of Socket n. + * It is set before OPEN command. + */ +#define Sn_TOS(N) WIZCHIP_SREG_ADDR(N, 0x0015) +/** + * @ingroup Socket_register_group + * @brief IP Time to live(TTL) Register(R/W) + * @details @ref Sn_TTL configures the TTL(Time To Live field in IP header) of Socket n. + * It is set before OPEN command. + */ +#define Sn_TTL(N) WIZCHIP_SREG_ADDR(N, 0x0016) +// Reserved (_W5500_IO_BASE_ + (0x0017 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) +// Reserved (_W5500_IO_BASE_ + (0x0018 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) +// Reserved (_W5500_IO_BASE_ + (0x0019 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) +// Reserved (_W5500_IO_BASE_ + (0x001A << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) +// Reserved (_W5500_IO_BASE_ + (0x001B << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) +// Reserved (_W5500_IO_BASE_ + (0x001C << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) +// Reserved (_W5500_IO_BASE_ + (0x001D << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +/** + * @ingroup Socket_register_group + * @brief Receive memory size register(R/W) + * @details @ref Sn_RXBUF_SIZE configures the RX buffer block size of Socket n. + * Socket n RX Buffer Block size can be configured with 1,2,4,8, and 16 Kbytes. + * If a different size is configured, the data cannot be normally received from a peer. + * Although Socket n RX Buffer Block size is initially configured to 2Kbytes, + * user can re-configure its size using @ref Sn_RXBUF_SIZE. The total sum of @ref Sn_RXBUF_SIZE can not be exceed 16Kbytes. + * When exceeded, the data reception error is occurred. + */ +#define Sn_RXBUF_SIZE(N) WIZCHIP_SREG_ADDR(N, 0x001e) + +/** + * @ingroup Socket_register_group + * @brief Transmit memory size register(R/W) + * @details @ref Sn_TXBUF_SIZE configures the TX buffer block size of Socket n. Socket n TX Buffer Block size can be configured with 1,2,4,8, and 16 Kbytes. + * If a different size is configured, the data can�t be normally transmitted to a peer. + * Although Socket n TX Buffer Block size is initially configured to 2Kbytes, + * user can be re-configure its size using @ref Sn_TXBUF_SIZE. The total sum of @ref Sn_TXBUF_SIZE can not be exceed 16Kbytes. + * When exceeded, the data transmission error is occurred. + */ +#define Sn_TXBUF_SIZE(N) WIZCHIP_SREG_ADDR(N, 0x001f) + +/** + * @ingroup Socket_register_group + * @brief Transmit free memory size register(R) + * @details @ref Sn_TX_FSR indicates the free size of Socket n TX Buffer Block. It is initialized to the configured size by @ref Sn_TXBUF_SIZE. + * Data bigger than @ref Sn_TX_FSR should not be saved in the Socket n TX Buffer because the bigger data overwrites the previous saved data not yet sent. + * Therefore, check before saving the data to the Socket n TX Buffer, and if data is equal or smaller than its checked size, + * transmit the data with SEND/SEND_MAC command after saving the data in Socket n TX buffer. But, if data is bigger than its checked size, + * transmit the data after dividing into the checked size and saving in the Socket n TX buffer. + */ +#define Sn_TX_FSR(N) WIZCHIP_SREG_ADDR(N, 0x0020) + +/** + * @ingroup Socket_register_group + * @brief Transmit memory read pointer register address(R) + * @details @ref Sn_TX_RD is initialized by OPEN command. However, if Sn_MR(P[3:0]) is TCP mode(001, it is re-initialized while connecting with TCP. + * After its initialization, it is auto-increased by SEND command. + * SEND command transmits the saved data from the current @ref Sn_TX_RD to the @ref Sn_TX_WR in the Socket n TX Buffer. + * After transmitting the saved data, the SEND command increases the @ref Sn_TX_RD as same as the @ref Sn_TX_WR. + * If its increment value exceeds the maximum value 0xFFFF, (greater than 0x10000 and the carry bit occurs), + * then the carry bit is ignored and will automatically update with the lower 16bits value. + */ +#define Sn_TX_RD(N) WIZCHIP_SREG_ADDR(N, 0x0022) + +/** + * @ingroup Socket_register_group + * @brief Transmit memory write pointer register address(R/W) + * @details @ref Sn_TX_WR is initialized by OPEN command. However, if Sn_MR(P[3:0]) is TCP mode(001, it is re-initialized while connecting with TCP.\n + * It should be read or be updated like as follows.\n + * 1. Read the starting address for saving the transmitting data.\n + * 2. Save the transmitting data from the starting address of Socket n TX buffer.\n + * 3. After saving the transmitting data, update @ref Sn_TX_WR to the increased value as many as transmitting data size. + * If the increment value exceeds the maximum value 0xFFFF(greater than 0x10000 and the carry bit occurs), + * then the carry bit is ignored and will automatically update with the lower 16bits value.\n + * 4. Transmit the saved data in Socket n TX Buffer by using SEND/SEND command + */ +#define Sn_TX_WR(N) WIZCHIP_SREG_ADDR(N, 0x0024) + +/** + * @ingroup Socket_register_group + * @brief Received data size register(R) + * @details @ref Sn_RX_RSR indicates the data size received and saved in Socket n RX Buffer. + * @ref Sn_RX_RSR does not exceed the @ref Sn_RXBUF_SIZE and is calculated as the difference between + * �Socket n RX Write Pointer (@ref Sn_RX_WR)and �Socket n RX Read Pointer (@ref Sn_RX_RD) + */ +#define Sn_RX_RSR(N) WIZCHIP_SREG_ADDR(N, 0x0026) + +/** + * @ingroup Socket_register_group + * @brief Read point of Receive memory(R/W) + * @details @ref Sn_RX_RD is initialized by OPEN command. Make sure to be read or updated as follows.\n + * 1. Read the starting save address of the received data.\n + * 2. Read data from the starting address of Socket n RX Buffer.\n + * 3. After reading the received data, Update @ref Sn_RX_RD to the increased value as many as the reading size. + * If the increment value exceeds the maximum value 0xFFFF, that is, is greater than 0x10000 and the carry bit occurs, + * update with the lower 16bits value ignored the carry bit.\n + * 4. Order RECV command is for notifying the updated @ref Sn_RX_RD to W5500. + */ +#define Sn_RX_RD(N) WIZCHIP_SREG_ADDR(N, 0x0028) + +/** + * @ingroup Socket_register_group + * @brief Write point of Receive memory(R) + * @details @ref Sn_RX_WR is initialized by OPEN command and it is auto-increased by the data reception. + * If the increased value exceeds the maximum value 0xFFFF, (greater than 0x10000 and the carry bit occurs), + * then the carry bit is ignored and will automatically update with the lower 16bits value. + */ +#define Sn_RX_WR(N) WIZCHIP_SREG_ADDR(N, 0x002a) + +/** + * @ingroup Socket_register_group + * @brief socket interrupt mask register(R) + * @details @ref Sn_IMR masks the interrupt of Socket n. + * Each bit corresponds to each bit of @ref Sn_IR. When a Socket n Interrupt is occurred and the corresponding bit of @ref Sn_IMR is + * the corresponding bit of @ref Sn_IR becomes When both the corresponding bit of @ref Sn_IMR and @ref Sn_IR are and the n-th bit of @ref IR is + * Host is interrupted by asserted INTn PIN to low. + */ +//#define Sn_IMR(N) (_W5500_IO_BASE_ + (0x002C << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +/** + * @ingroup Socket_register_group + * @brief Fragment field value in IP header register(R/W) + * @details @ref Sn_FRAG configures the FRAG(Fragment field in IP header). + */ +//#define Sn_FRAG(N) (_W5500_IO_BASE_ + (0x002D << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +/** + * @ingroup Socket_register_group + * @brief Keep Alive Timer register(R/W) + * @details @ref Sn_KPALVTR configures the transmitting timer of �KEEP ALIVE(KA)packet of SOCKETn. It is valid only in TCP mode, + * and ignored in other modes. The time unit is 5s. + * KA packet is transmittable after @ref Sn_SR is changed to SOCK_ESTABLISHED and after the data is transmitted or received to/from a peer at least once. + * In case of '@ref Sn_KPALVTR > 0', W5500 automatically transmits KA packet after time-period for checking the TCP connection (Auto-keepalive-process). + * In case of '@ref Sn_KPALVTR = 0', Auto-keep-alive-process will not operate, + * and KA packet can be transmitted by SEND_KEEP command by the host (Manual-keep-alive-process). + * Manual-keep-alive-process is ignored in case of '@ref Sn_KPALVTR > 0'. + */ +//#define Sn_KPALVTR(N) (_W5500_IO_BASE_ + (0x002F << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +//#define Sn_TSR(N) (_W5500_IO_BASE_ + (0x0030 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + + +//----------------------------- W5500 Register values ----------------------------- + +/* MODE register values */ +/** + * @brief Reset + * @details If this bit is All internal registers will be initialized. It will be automatically cleared as after S/W reset. + */ +#define MR_RST 0x80 + +/** + * @brief Wake on LAN + * @details 0 : Disable WOL mode\n + * 1 : Enable WOL mode\n + * If WOL mode is enabled and the received magic packet over UDP has been normally processed, the Interrupt PIN (INTn) asserts to low. + * When using WOL mode, the UDP Socket should be opened with any source port number. (Refer to Socket n Mode Register (@ref Sn_MR) for opening Socket.) + * @note The magic packet over UDP supported by W5500 consists of 6 bytes synchronization stream (xFFFFFFFFFFFF and + * 16 times Target MAC address stream in UDP payload. The options such like password are ignored. You can use any UDP source port number for WOL mode. + */ +#define MR_WOL 0x20 + +/** + * @brief Ping block + * @details 0 : Disable Ping block\n + * 1 : Enable Ping block\n + * If the bit is it blocks the response to a ping request. + */ +#define MR_PB 0x10 + +/** + * @brief Enable PPPoE + * @details 0 : DisablePPPoE mode\n + * 1 : EnablePPPoE mode\n + * If you use ADSL, this bit should be + */ +#define MR_PPPOE 0x08 + +/** + * @brief Enable UDP_FORCE_ARP CHECHK + * @details 0 : Disable Force ARP mode\n + * 1 : Enable Force ARP mode\n + * In Force ARP mode, It forces on sending ARP Request whenever data is sent. + */ +#define MR_FARP 0x02 + +/* IR register values */ +/** + * @brief Check IP conflict. + * @details Bit is set as when own source IP address is same with the sender IP address in the received ARP request. + */ +#define IR_CONFLICT 0x80 + +/** + * @brief Get the destination unreachable message in UDP sending. + * @details When receiving the ICMP (Destination port unreachable) packet, this bit is set as + * When this bit is Destination Information such as IP address and Port number may be checked with the corresponding @ref UIPR & @ref UPORTR. + */ +#define IR_UNREACH 0x40 + +/** + * @brief Get the PPPoE close message. + * @details When PPPoE is disconnected during PPPoE mode, this bit is set. + */ +#define IR_PPPoE 0x20 + +/** + * @brief Get the magic packet interrupt. + * @details When WOL mode is enabled and receives the magic packet over UDP, this bit is set. + */ +#define IR_MP 0x10 + + +/* PHYCFGR register value */ +#define PHYCFGR_RST ~(1<<7) //< For PHY reset, must operate AND mask. +#define PHYCFGR_OPMD (1<<6) // Configre PHY with OPMDC value +#define PHYCFGR_OPMDC_ALLA (7<<3) +#define PHYCFGR_OPMDC_PDOWN (6<<3) +#define PHYCFGR_OPMDC_NA (5<<3) +#define PHYCFGR_OPMDC_100FA (4<<3) +#define PHYCFGR_OPMDC_100F (3<<3) +#define PHYCFGR_OPMDC_100H (2<<3) +#define PHYCFGR_OPMDC_10F (1<<3) +#define PHYCFGR_OPMDC_10H (0<<3) +#define PHYCFGR_DPX_FULL (1<<2) +#define PHYCFGR_DPX_HALF (0<<2) +#define PHYCFGR_SPD_100 (1<<1) +#define PHYCFGR_SPD_10 (0<<1) +#define PHYCFGR_LNK_ON (1<<0) +#define PHYCFGR_LNK_OFF (0<<0) + +// PHYSTATUS register +#define PHYSTATUS_POWERDOWN (0x08) +#define PHYSTATUS_LINK (0x20) + +/* IMR register values */ +/** + * @brief IP Conflict Interrupt Mask. + * @details 0: Disable IP Conflict Interrupt\n + * 1: Enable IP Conflict Interrupt + */ +#define IM_IR7 0x80 + +/** + * @brief Destination unreachable Interrupt Mask. + * @details 0: Disable Destination unreachable Interrupt\n + * 1: Enable Destination unreachable Interrupt + */ +#define IM_IR6 0x40 + +/** + * @brief PPPoE Close Interrupt Mask. + * @details 0: Disable PPPoE Close Interrupt\n + * 1: Enable PPPoE Close Interrupt + */ +#define IM_IR5 0x20 + +/** + * @brief Magic Packet Interrupt Mask. + * @details 0: Disable Magic Packet Interrupt\n + * 1: Enable Magic Packet Interrupt + */ +#define IM_IR4 0x10 + +/* Sn_MR Default values */ +/** + * @brief Support UDP Multicasting + * @details 0 : disable Multicasting\n + * 1 : enable Multicasting\n + * This bit is applied only during UDP mode(P[3:0] = 010.\n + * To use multicasting, @ref Sn_DIPR & @ref Sn_DPORT should be respectively configured with the multicast group IP address & port number + * before Socket n is opened by OPEN command of @ref Sn_CR. + */ +#define Sn_MR_MULTI 0x80 + +/** + * @brief Broadcast block in UDP Multicasting. + * @details 0 : disable Broadcast Blocking\n + * 1 : enable Broadcast Blocking\n + * This bit blocks to receive broadcasting packet during UDP mode(P[3:0] = 010.\m + * In addition, This bit does when MACRAW mode(P[3:0] = 100 + */ +//#define Sn_MR_BCASTB 0x40 + +/** + * @brief No Delayed Ack(TCP), Multicast flag + * @details 0 : Disable No Delayed ACK option\n + * 1 : Enable No Delayed ACK option\n + * This bit is applied only during TCP mode (P[3:0] = 001.\n + * When this bit is It sends the ACK packet without delay as soon as a Data packet is received from a peer.\n + * When this bit is It sends the ACK packet after waiting for the timeout time configured by @ref RTR. + */ +#define Sn_MR_ND 0x20 + +/** + * @brief Unicast Block in UDP Multicasting + * @details 0 : disable Unicast Blocking\n + * 1 : enable Unicast Blocking\n + * This bit blocks receiving the unicast packet during UDP mode(P[3:0] = 010 and MULTI = + */ +//#define Sn_MR_UCASTB 0x10 + +/** + * @brief MAC LAYER RAW SOCK + * @details This configures the protocol mode of Socket n. + * @note MACRAW mode should be only used in Socket 0. + */ +#define Sn_MR_MACRAW 0x04 + +#define Sn_MR_IPRAW 0x03 /**< IP LAYER RAW SOCK */ + +/** + * @brief UDP + * @details This configures the protocol mode of Socket n. + */ +#define Sn_MR_UDP 0x02 + +/** + * @brief TCP + * @details This configures the protocol mode of Socket n. + */ +#define Sn_MR_TCP 0x01 + +/** + * @brief Unused socket + * @details This configures the protocol mode of Socket n. + */ +#define Sn_MR_CLOSE 0x00 + +/* Sn_MR values used with Sn_MR_MACRAW */ +/** + * @brief MAC filter enable in @ref Sn_MR_MACRAW mode + * @details 0 : disable MAC Filtering\n + * 1 : enable MAC Filtering\n + * This bit is applied only during MACRAW mode(P[3:0] = 100.\n + * When set as W5500 can only receive broadcasting packet or packet sent to itself. + * When this bit is W5500 can receive all packets on Ethernet. + * If user wants to implement Hybrid TCP/IP stack, + * it is recommended that this bit is set as for reducing host overhead to process the all received packets. + */ +#define Sn_MR_MFEN Sn_MR_MULTI + +/** + * @brief Multicast Blocking in @ref Sn_MR_MACRAW mode + * @details 0 : using IGMP version 2\n + * 1 : using IGMP version 1\n + * This bit is applied only during UDP mode(P[3:0] = 010 and MULTI = + * It configures the version for IGMP messages (Join/Leave/Report). + */ +#define Sn_MR_MMB Sn_MR_ND + +/** + * @brief IPv6 packet Blocking in @ref Sn_MR_MACRAW mode + * @details 0 : disable IPv6 Blocking\n + * 1 : enable IPv6 Blocking\n + * This bit is applied only during MACRAW mode (P[3:0] = 100. It blocks to receiving the IPv6 packet. + */ +#define Sn_MR_MIP6B Sn_MR_UCASTB + +/* Sn_MR value used with Sn_MR_UDP & Sn_MR_MULTI */ +/** + * @brief IGMP version used in UDP mulitcasting + * @details 0 : disable Multicast Blocking\n + * 1 : enable Multicast Blocking\n + * This bit is applied only when MACRAW mode(P[3:0] = 100. It blocks to receive the packet with multicast MAC address. + */ +#define Sn_MR_MC Sn_MR_ND + +/* Sn_MR alternate values */ +/** + * @brief For Berkeley Socket API + */ +#define SOCK_STREAM Sn_MR_TCP + +/** + * @brief For Berkeley Socket API + */ +#define SOCK_DGRAM Sn_MR_UDP + + +/* Sn_CR values */ +/** + * @brief Initialize or open socket + * @details Socket n is initialized and opened according to the protocol selected in Sn_MR(P3:P0). + * The table below shows the value of @ref Sn_SR corresponding to @ref Sn_MR.\n + * <table> + * <tr> <td>\b Sn_MR (P[3:0])</td> <td>\b Sn_SR</td> </tr> + * <tr> <td>Sn_MR_CLOSE (000</td> <td></td> </tr> + * <tr> <td>Sn_MR_TCP (001</td> <td>SOCK_INIT (0x13)</td> </tr> + * <tr> <td>Sn_MR_UDP (010</td> <td>SOCK_UDP (0x22)</td> </tr> + * <tr> <td>S0_MR_MACRAW (100</td> <td>SOCK_MACRAW (0x02)</td> </tr> + * </table> + */ +#define Sn_CR_OPEN 0x01 + +/** + * @brief Wait connection request in TCP mode(Server mode) + * @details This is valid only in TCP mode (Sn_MR(P3:P0) = Sn_MR_TCP). + * In this mode, Socket n operates as a �TCP serverand waits for connection-request (SYN packet) from any �TCP client + * The @ref Sn_SR changes the state from SOCK_INIT to SOCKET_LISTEN. + * When a �TCP clientconnection request is successfully established, + * the @ref Sn_SR changes from SOCK_LISTEN to SOCK_ESTABLISHED and the Sn_IR(0) becomes + * But when a �TCP clientconnection request is failed, Sn_IR(3) becomes and the status of @ref Sn_SR changes to SOCK_CLOSED. + */ +#define Sn_CR_LISTEN 0x02 + +/** + * @brief Send connection request in TCP mode(Client mode) + * @details To connect, a connect-request (SYN packet) is sent to b>TCP server</b>configured by @ref Sn_DIPR & Sn_DPORT(destination address & port). + * If the connect-request is successful, the @ref Sn_SR is changed to @ref SOCK_ESTABLISHED and the Sn_IR(0) becomes \n\n + * The connect-request fails in the following three cases.\n + * 1. When a @b ARPTO occurs (@ref Sn_IR[3] = ) because destination hardware address is not acquired through the ARP-process.\n + * 2. When a @b SYN/ACK packet is not received and @b TCPTO (Sn_IR(3) = )\n + * 3. When a @b RST packet is received instead of a @b SYN/ACK packet. In these cases, @ref Sn_SR is changed to @ref SOCK_CLOSED. + * @note This is valid only in TCP mode and operates when Socket n acts as b>TCP client</b> + */ +#define Sn_CR_CONNECT 0x04 + +/** + * @brief Send closing request in TCP mode + * @details Regardless of b>TCP server</b>or b>TCP client</b> the DISCON command processes the disconnect-process (b>Active close</b>or b>Passive close</b>.\n + * @par Active close + * it transmits disconnect-request(FIN packet) to the connected peer\n + * @par Passive close + * When FIN packet is received from peer, a FIN packet is replied back to the peer.\n + * @details When the disconnect-process is successful (that is, FIN/ACK packet is received successfully), @ref Sn_SR is changed to @ref SOCK_CLOSED.\n + * Otherwise, TCPTO occurs (Sn_IR(3)=)= and then @ref Sn_SR is changed to @ref SOCK_CLOSED. + * @note Valid only in TCP mode. + */ +#define Sn_CR_DISCON 0x08 + +/** + * @brief Close socket + * @details Sn_SR is changed to @ref SOCK_CLOSED. + */ +#define Sn_CR_CLOSE 0x10 + +/** + * @brief Update TX buffer pointer and send data + * @details SEND transmits all the data in the Socket n TX buffer.\n + * For more details, please refer to Socket n TX Free Size Register (@ref Sn_TX_FSR), Socket n, + * TX Write Pointer Register(@ref Sn_TX_WR), and Socket n TX Read Pointer Register(@ref Sn_TX_RD). + */ +#define Sn_CR_SEND 0x20 + +/** + * @brief Send data with MAC address, so without ARP process + * @details The basic operation is same as SEND.\n + * Normally SEND transmits data after destination hardware address is acquired by the automatic ARP-process(Address Resolution Protocol).\n + * But SEND_MAC transmits data without the automatic ARP-process.\n + * In this case, the destination hardware address is acquired from @ref Sn_DHAR configured by host, instead of APR-process. + * @note Valid only in UDP mode. + */ +#define Sn_CR_SEND_MAC 0x21 + +/** + * @brief Send keep alive message + * @details It checks the connection status by sending 1byte keep-alive packet.\n + * If the peer can not respond to the keep-alive packet during timeout time, the connection is terminated and the timeout interrupt will occur. + * @note Valid only in TCP mode. + */ +#define Sn_CR_SEND_KEEP 0x22 + +/** + * @brief Update RX buffer pointer and receive data + * @details RECV completes the processing of the received data in Socket n RX Buffer by using a RX read pointer register (@ref Sn_RX_RD).\n + * For more details, refer to Socket n RX Received Size Register (@ref Sn_RX_RSR), Socket n RX Write Pointer Register (@ref Sn_RX_WR), + * and Socket n RX Read Pointer Register (@ref Sn_RX_RD). + */ +#define Sn_CR_RECV 0x40 + +/* Sn_IR values */ +/** + * @brief SEND_OK Interrupt + * @details This is issued when SEND command is completed. + */ +#define Sn_IR_SENDOK 0x10 + +/** + * @brief TIMEOUT Interrupt + * @details This is issued when ARPTO or TCPTO occurs. + */ +#define Sn_IR_TIMEOUT 0x08 + +/** + * @brief RECV Interrupt + * @details This is issued whenever data is received from a peer. + */ +#define Sn_IR_RECV 0x04 + +/** + * @brief DISCON Interrupt + * @details This is issued when FIN or FIN/ACK packet is received from a peer. + */ +#define Sn_IR_DISCON 0x02 + +/** + * @brief CON Interrupt + * @details This is issued one time when the connection with peer is successful and then @ref Sn_SR is changed to @ref SOCK_ESTABLISHED. + */ +#define Sn_IR_CON 0x01 + +/* Sn_SR values */ +/** + * @brief Closed + * @details This indicates that Socket n is released.\N + * When DICON, CLOSE command is ordered, or when a timeout occurs, it is changed to @ref SOCK_CLOSED regardless of previous status. + */ +#define SOCK_CLOSED 0x00 + +/** + * @brief Initiate state + * @details This indicates Socket n is opened with TCP mode.\N + * It is changed to @ref SOCK_INIT when Sn_MR(P[3:0]) = 001and OPEN command is ordered.\N + * After @ref SOCK_INIT, user can use LISTEN /CONNECT command. + */ +#define SOCK_INIT 0x13 + +/** + * @brief Listen state + * @details This indicates Socket n is operating as b>TCP server</b>mode and waiting for connection-request (SYN packet) from a peer (b>TCP client</b>.\n + * It will change to @ref SOCK_ESTALBLISHED when the connection-request is successfully accepted.\n + * Otherwise it will change to @ref SOCK_CLOSED after TCPTO occurred (Sn_IR(TIMEOUT) = . + */ +#define SOCK_LISTEN 0x14 + +/** + * @brief Connection state + * @details This indicates Socket n sent the connect-request packet (SYN packet) to a peer.\n + * It is temporarily shown when @ref Sn_SR is changed from @ref SOCK_INIT to @ref SOCK_ESTABLISHED by CONNECT command.\n + * If connect-accept(SYN/ACK packet) is received from the peer at SOCK_SYNSENT, it changes to @ref SOCK_ESTABLISHED.\n + * Otherwise, it changes to @ref SOCK_CLOSED after TCPTO (@ref Sn_IR[TIMEOUT] = is occurred. + */ +#define SOCK_SYNSENT 0x15 + +/** + * @brief Connection state + * @details It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer.\n + * If socket n sends the response (SYN/ACK packet) to the peer successfully, it changes to @ref SOCK_ESTABLISHED. \n + * If not, it changes to @ref SOCK_CLOSED after timeout occurs (@ref Sn_IR[TIMEOUT] = . + */ +#define SOCK_SYNRECV 0x16 + +/** + * @brief Success to connect + * @details This indicates the status of the connection of Socket n.\n + * It changes to @ref SOCK_ESTABLISHED when the b>TCP SERVER</b>processed the SYN packet from the b>TCP CLIENT</b>during @ref SOCK_LISTEN, or + * when the CONNECT command is successful.\n + * During @ref SOCK_ESTABLISHED, DATA packet can be transferred using SEND or RECV command. + */ +#define SOCK_ESTABLISHED 0x17 + +/** + * @brief Closing state + * @details These indicate Socket n is closing.\n + * These are shown in disconnect-process such as active-close and passive-close.\n + * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED. + */ +#define SOCK_FIN_WAIT 0x18 + +/** + * @brief Closing state + * @details These indicate Socket n is closing.\n + * These are shown in disconnect-process such as active-close and passive-close.\n + * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED. + */ +#define SOCK_CLOSING 0x1A + +/** + * @brief Closing state + * @details These indicate Socket n is closing.\n + * These are shown in disconnect-process such as active-close and passive-close.\n + * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED. + */ +#define SOCK_TIME_WAIT 0x1B + +/** + * @brief Closing state + * @details This indicates Socket n received the disconnect-request (FIN packet) from the connected peer.\n + * This is half-closing status, and data can be transferred.\n + * For full-closing, DISCON command is used. But For just-closing, CLOSE command is used. + */ +#define SOCK_CLOSE_WAIT 0x1C + +/** + * @brief Closing state + * @details This indicates Socket n is waiting for the response (FIN/ACK packet) to the disconnect-request (FIN packet) by passive-close.\n + * It changes to @ref SOCK_CLOSED when Socket n received the response successfully, or when timeout occurs (@ref Sn_IR[TIMEOUT] = . + */ +#define SOCK_LAST_ACK 0x1D + +/** + * @brief UDP socket + * @details This indicates Socket n is opened in UDP mode(Sn_MR(P[3:0]) = 010.\n + * It changes to SOCK_UPD when Sn_MR(P[3:0]) = 010 and OPEN command is ordered.\n + * Unlike TCP mode, data can be transfered without the connection-process. + */ +#define SOCK_UDP 0x22 + +//#define SOCK_IPRAW 0x32 /**< IP raw mode socket */ + +/** + * @brief MAC raw mode socket + * @details This indicates Socket 0 is opened in MACRAW mode (S0_MR(P[3:0]) = 100and is valid only in Socket 0.\n + * It changes to SOCK_MACRAW when S0_MR(P[3:0] = 100and OPEN command is ordered.\n + * Like UDP mode socket, MACRAW mode Socket 0 can transfer a MAC packet (Ethernet frame) without the connection-process. + */ +#define SOCK_MACRAW 0x42 + +//#define SOCK_PPPOE 0x5F + +/* IP PROTOCOL */ +#define IPPROTO_IP 0 //< Dummy for IP +#define IPPROTO_ICMP 1 //< Control message protocol +#define IPPROTO_IGMP 2 //< Internet group management protocol +#define IPPROTO_GGP 3 //< Gateway^2 (deprecated) +#define IPPROTO_TCP 6 //< TCP +#define IPPROTO_PUP 12 //< PUP +#define IPPROTO_UDP 17 //< UDP +#define IPPROTO_IDP 22 //< XNS idp +#define IPPROTO_ND 77 //< UNOFFICIAL net disk protocol +#define IPPROTO_RAW 255 //< Raw IP packet + + +/** + * @brief Enter a critical section + * + * @details It is provided to protect your shared code which are executed without distribution. \n \n + * + * In non-OS environment, It can be just implemented by disabling whole interrupt.\n + * In OS environment, You can replace it to critical section api supported by OS. + * + * \sa WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() + * \sa WIZCHIP_CRITICAL_EXIT() + */ +#define WIZCHIP_CRITICAL_ENTER() WIZCHIP.CRIS._enter() + +/** + * @brief Exit a critical section + * + * @details It is provided to protect your shared code which are executed without distribution. \n\n + * + * In non-OS environment, It can be just implemented by disabling whole interrupt. \n + * In OS environment, You can replace it to critical section api supported by OS. + * + * @sa WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() + * @sa WIZCHIP_CRITICAL_ENTER() + */ +#ifdef _exit +#undef _exit +#endif +#define WIZCHIP_CRITICAL_EXIT() WIZCHIP.CRIS._exit() + + + +//////////////////////// +// Basic I/O Function // +//////////////////////// + +/** + * @ingroup Basic_IO_function + * @brief It reads 1 byte value from a register. + * @param AddrSel Register address + * @return The value of register + */ +uint8_t WIZCHIP_READ (uint32_t AddrSel); + +/** + * @ingroup Basic_IO_function + * @brief It writes 1 byte value to a register. + * @param AddrSel Register address + * @param wb Write data + * @return void + */ +void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb ); + +/** + * @ingroup Basic_IO_function + * @brief It reads sequence data from registers. + * @param AddrSel Register address + * @param pBuf Pointer buffer to read data + * @param len Data length + */ +void WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, uint16_t len); + +/** + * @ingroup Basic_IO_function + * @brief It writes sequence data to registers. + * @param AddrSel Register address + * @param pBuf Pointer buffer to write data + * @param len Data length + */ +void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len); + +///////////////////////////////// +// Common Register I/O function // +///////////////////////////////// +/** + * @ingroup Common_register_access_function + * @brief Set Mode Register + * @param (uint8_t)mr The value to be set. + * @sa getMR() + */ +#define setMR(mr) \ + WIZCHIP_WRITE(MR,mr) + + +/** + * @ingroup Common_register_access_function + * @brief Get Mode Register + * @return uint8_t. The value of Mode register. + * @sa setMR() + */ +#define getMR() \ + WIZCHIP_READ(MR) + +/** + * @ingroup Common_register_access_function + * @brief Set gateway IP address + * @param (uint8_t*)gar Pointer variable to set gateway IP address. It should be allocated 4 bytes. + * @sa getGAR() + */ +#define setGAR(gar) \ + WIZCHIP_WRITE_BUF(GAR,gar,4) + +/** + * @ingroup Common_register_access_function + * @brief Get gateway IP address + * @param (uint8_t*)gar Pointer variable to get gateway IP address. It should be allocated 4 bytes. + * @sa setGAR() + */ +#define getGAR(gar) \ + WIZCHIP_READ_BUF(GAR,gar,4) + +/** + * @ingroup Common_register_access_function + * @brief Set subnet mask address + * @param (uint8_t*)subr Pointer variable to set subnet mask address. It should be allocated 4 bytes. + * @sa getSUBR() + */ +#define setSUBR(subr) \ + WIZCHIP_WRITE_BUF(SUBR, subr,4) + + +/** + * @ingroup Common_register_access_function + * @brief Get subnet mask address + * @param (uint8_t*)subr Pointer variable to get subnet mask address. It should be allocated 4 bytes. + * @sa setSUBR() + */ +#define getSUBR(subr) \ + WIZCHIP_READ_BUF(SUBR, subr, 4) + +/** + * @ingroup Common_register_access_function + * @brief Set local MAC address + * @param (uint8_t*)shar Pointer variable to set local MAC address. It should be allocated 6 bytes. + * @sa getSHAR() + */ +#define setSHAR(shar) \ + WIZCHIP_WRITE_BUF(SHAR, shar, 6) + +/** + * @ingroup Common_register_access_function + * @brief Get local MAC address + * @param (uint8_t*)shar Pointer variable to get local MAC address. It should be allocated 6 bytes. + * @sa setSHAR() + */ +#define getSHAR(shar) \ + WIZCHIP_READ_BUF(SHAR, shar, 6) + +/** + * @ingroup Common_register_access_function + * @brief Set local IP address + * @param (uint8_t*)sipr Pointer variable to set local IP address. It should be allocated 4 bytes. + * @sa getSIPR() + */ +#define setSIPR(sipr) \ + WIZCHIP_WRITE_BUF(SIPR, sipr, 4) + +/** + * @ingroup Common_register_access_function + * @brief Get local IP address + * @param (uint8_t*)sipr Pointer variable to get local IP address. It should be allocated 4 bytes. + * @sa setSIPR() + */ +#define getSIPR(sipr) \ + WIZCHIP_READ_BUF(SIPR, sipr, 4) + +/** + * @ingroup Common_register_access_function + * @brief Set INTLEVEL register + * @param (uint16_t)intlevel Value to set @ref INTLEVEL register. + * @sa getINTLEVEL() + */ +// dpgeorge: not yet implemented +#define setINTLEVEL(intlevel) (void)intlevel +#if 0 +#define setINTLEVEL(intlevel) {\ + WIZCHIP_WRITE(INTLEVEL, (uint8_t)(intlevel >> 8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(INTLEVEL,1), (uint8_t) intlevel); \ + } +#endif + + +/** + * @ingroup Common_register_access_function + * @brief Get INTLEVEL register + * @return uint16_t. Value of @ref INTLEVEL register. + * @sa setINTLEVEL() + */ +// dpgeorge: not yet implemented +#define getINTLEVEL() (0) +#if 0 +#define getINTLEVEL() \ + ((WIZCHIP_READ(INTLEVEL) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(INTLEVEL,1))) +#endif + +/** + * @ingroup Common_register_access_function + * @brief Set @ref IR register + * @param (uint8_t)ir Value to set @ref IR register. + * @sa getIR() + */ +#define setIR(ir) \ + WIZCHIP_WRITE(IR, (ir & 0xF0)) + +/** + * @ingroup Common_register_access_function + * @brief Get @ref IR register + * @return uint8_t. Value of @ref IR register. + * @sa setIR() + */ +#define getIR() \ + (WIZCHIP_READ(IR) & 0xF0) +/** + * @ingroup Common_register_access_function + * @brief Set @ref IMR register + * @param (uint8_t)imr Value to set @ref IMR register. + * @sa getIMR() + */ +#define setIMR(imr) \ + WIZCHIP_WRITE(IMR, imr) + +/** + * @ingroup Common_register_access_function + * @brief Get @ref IMR register + * @return uint8_t. Value of @ref IMR register. + * @sa setIMR() + */ +#define getIMR() \ + WIZCHIP_READ(IMR) + + +/** + * @ingroup Common_register_access_function + * @brief Set @ref SIR register + * @param (uint8_t)sir Value to set @ref SIR register. + * @sa getSIR() + */ +// dpgeorge: not yet implemented +#define setSIR(sir) ((void)sir) +#if 0 +#define setSIR(sir) \ + WIZCHIP_WRITE(SIR, sir) +#endif + +/** + * @ingroup Common_register_access_function + * @brief Get @ref SIR register + * @return uint8_t. Value of @ref SIR register. + * @sa setSIR() + */ +// dpgeorge: not yet implemented +#define getSIR() (0) +#if 0 +#define getSIR() \ + WIZCHIP_READ(SIR) +#endif + +/** + * @ingroup Common_register_access_function + * @brief Set @ref SIMR register + * @param (uint8_t)simr Value to set @ref SIMR register. + * @sa getSIMR() + */ +// dpgeorge: not yet implemented +#define setSIMR(simr) ((void)simr) +#if 0 +#define setSIMR(simr) \ + WIZCHIP_WRITE(SIMR, simr) +#endif + +/** + * @ingroup Common_register_access_function + * @brief Get @ref SIMR register + * @return uint8_t. Value of @ref SIMR register. + * @sa setSIMR() + */ +// dpgeorge: not yet implemented +#define getSIMR() (0) +#if 0 +#define getSIMR() \ + WIZCHIP_READ(SIMR) +#endif + +/** + * @ingroup Common_register_access_function + * @brief Set @ref RTR register + * @param (uint16_t)rtr Value to set @ref RTR register. + * @sa getRTR() + */ +#define setRTR(rtr) {\ + WIZCHIP_WRITE(RTR, (uint8_t)(rtr >> 8)); \ + WIZCHIP_WRITE(RTR + 1, (uint8_t) rtr); \ + } + +/** + * @ingroup Common_register_access_function + * @brief Get @ref RTR register + * @return uint16_t. Value of @ref RTR register. + * @sa setRTR() + */ +#define getRTR() \ + ((WIZCHIP_READ(RTR) << 8) + WIZCHIP_READ(RTR + 1)) + +/** + * @ingroup Common_register_access_function + * @brief Set @ref RCR register + * @param (uint8_t)rcr Value to set @ref RCR register. + * @sa getRCR() + */ +#define setRCR(rcr) \ + WIZCHIP_WRITE(RCR, rcr) + +/** + * @ingroup Common_register_access_function + * @brief Get @ref RCR register + * @return uint8_t. Value of @ref RCR register. + * @sa setRCR() + */ +#define getRCR() \ + WIZCHIP_READ(RCR) + +//================================================== test done =========================================================== + +/** + * @ingroup Common_register_access_function + * @brief Set @ref PTIMER register + * @param (uint8_t)ptimer Value to set @ref PTIMER register. + * @sa getPTIMER() + */ +#define setPTIMER(ptimer) \ + WIZCHIP_WRITE(PTIMER, ptimer) + +/** + * @ingroup Common_register_access_function + * @brief Get @ref PTIMER register + * @return uint8_t. Value of @ref PTIMER register. + * @sa setPTIMER() + */ +#define getPTIMER() \ + WIZCHIP_READ(PTIMER) + +/** + * @ingroup Common_register_access_function + * @brief Set @ref PMAGIC register + * @param (uint8_t)pmagic Value to set @ref PMAGIC register. + * @sa getPMAGIC() + */ +#define setPMAGIC(pmagic) \ + WIZCHIP_WRITE(PMAGIC, pmagic) + +/** + * @ingroup Common_register_access_function + * @brief Get @ref PMAGIC register + * @return uint8_t. Value of @ref PMAGIC register. + * @sa setPMAGIC() + */ +#define getPMAGIC() \ + WIZCHIP_READ(PMAGIC) + +/** + * @ingroup Common_register_access_function + * @brief Set PHAR address + * @param (uint8_t*)phar Pointer variable to set PPP destination MAC register address. It should be allocated 6 bytes. + * @sa getPHAR() + */ +#if 0 +#define setPHAR(phar) \ + WIZCHIP_WRITE_BUF(PHAR, phar, 6) + +/** + * @ingroup Common_register_access_function + * @brief Get local IP address + * @param (uint8_t*)phar Pointer variable to PPP destination MAC register address. It should be allocated 6 bytes. + * @sa setPHAR() + */ +#define getPHAR(phar) \ + WIZCHIP_READ_BUF(PHAR, phar, 6) + +/** + * @ingroup Common_register_access_function + * @brief Set @ref PSID register + * @param (uint16_t)psid Value to set @ref PSID register. + * @sa getPSID() + */ +#define setPSID(psid) {\ + WIZCHIP_WRITE(PSID, (uint8_t)(psid >> 8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(PSID,1), (uint8_t) psid); \ + } + +/** + * @ingroup Common_register_access_function + * @brief Get @ref PSID register + * @return uint16_t. Value of @ref PSID register. + * @sa setPSID() + */ +//uint16_t getPSID(void); +#define getPSID() \ + ((WIZCHIP_READ(PSID) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(PSID,1))) + +/** + * @ingroup Common_register_access_function + * @brief Set @ref PMRU register + * @param (uint16_t)pmru Value to set @ref PMRU register. + * @sa getPMRU() + */ +#define setPMRU(pmru) { \ + WIZCHIP_WRITE(PMRU, (uint8_t)(pmru>>8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(PMRU,1), (uint8_t) pmru); \ + } + +/** + * @ingroup Common_register_access_function + * @brief Get @ref PMRU register + * @return uint16_t. Value of @ref PMRU register. + * @sa setPMRU() + */ +#define getPMRU() \ + ((WIZCHIP_READ(PMRU) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(PMRU,1))) + +/** + * @ingroup Common_register_access_function + * @brief Get unreachable IP address + * @param (uint8_t*)uipr Pointer variable to get unreachable IP address. It should be allocated 4 bytes. + */ +#define getUIPR(uipr) \ + WIZCHIP_READ_BUF(UIPR,uipr,6) + +/** + * @ingroup Common_register_access_function + * @brief Get @ref UPORTR register + * @return uint16_t. Value of @ref UPORTR register. + */ +#define getUPORTR() \ + ((WIZCHIP_READ(UPORTR) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(UPORTR,1))) + +/** + * @ingroup Common_register_access_function + * @brief Set @ref PHYCFGR register + * @param (uint8_t)phycfgr Value to set @ref PHYCFGR register. + * @sa getPHYCFGR() + */ +#define setPHYCFGR(phycfgr) \ + WIZCHIP_WRITE(PHYCFGR, phycfgr) +#endif + +/** + * @ingroup Common_register_access_function + * @brief Get @ref PHYCFGR register + * @return uint8_t. Value of @ref PHYCFGR register. + * @sa setPHYCFGR() + */ +#define getPHYSTATUS() \ + WIZCHIP_READ(PHYSTATUS) + +/** + * @ingroup Common_register_access_function + * @brief Get @ref VERSIONR register + * @return uint8_t. Value of @ref VERSIONR register. + */ +/* +#define getVERSIONR() \ + WIZCHIP_READ(VERSIONR) + */ +///////////////////////////////////// + +/////////////////////////////////// +// Socket N register I/O function // +/////////////////////////////////// +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_MR register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @param (uint8_t)mr Value to set @ref Sn_MR + * @sa getSn_MR() + */ +#define setSn_MR(sn, mr) \ + WIZCHIP_WRITE(Sn_MR(sn),mr) + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_MR register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @return uint8_t. Value of @ref Sn_MR. + * @sa setSn_MR() + */ +#define getSn_MR(sn) \ + WIZCHIP_READ(Sn_MR(sn)) + +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_CR register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @param (uint8_t)cr Value to set @ref Sn_CR + * @sa getSn_CR() + */ +#define setSn_CR(sn, cr) \ + WIZCHIP_WRITE(Sn_CR(sn), cr) + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_CR register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @return uint8_t. Value of @ref Sn_CR. + * @sa setSn_CR() + */ +#define getSn_CR(sn) \ + WIZCHIP_READ(Sn_CR(sn)) + +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_IR register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @param (uint8_t)ir Value to set @ref Sn_IR + * @sa getSn_IR() + */ +#define setSn_IR(sn, ir) \ + WIZCHIP_WRITE(Sn_IR(sn), (ir & 0x1F)) + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_IR register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @return uint8_t. Value of @ref Sn_IR. + * @sa setSn_IR() + */ +#define getSn_IR(sn) \ + (WIZCHIP_READ(Sn_IR(sn)) & 0x1F) + +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_IMR register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @param (uint8_t)imr Value to set @ref Sn_IMR + * @sa getSn_IMR() + */ +// dpgeorge: not yet implemented +#define setSn_IMR(sn, imr) (void)sn; (void)imr +#if 0 +#define setSn_IMR(sn, imr) \ + WIZCHIP_WRITE(Sn_IMR(sn), (imr & 0x1F)) +#endif + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_IMR register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @return uint8_t. Value of @ref Sn_IMR. + * @sa setSn_IMR() + */ +// dpgeorge: not yet implemented +#define getSn_IMR(sn) (0) +#if 0 +#define getSn_IMR(sn) \ + (WIZCHIP_READ(Sn_IMR(sn)) & 0x1F) +#endif + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_SR register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @return uint8_t. Value of @ref Sn_SR. + */ +#define getSn_SR(sn) \ + WIZCHIP_READ(Sn_SR(sn)) + +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_PORT register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @param (uint16_t)port Value to set @ref Sn_PORT. + * @sa getSn_PORT() + */ +#define setSn_PORT(sn, port) { \ + WIZCHIP_WRITE(Sn_PORT(sn), (uint8_t)(port >> 8)); \ + WIZCHIP_WRITE(Sn_PORT(sn) + 1, (uint8_t) port); \ + } + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_PORT register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @return uint16_t. Value of @ref Sn_PORT. + * @sa setSn_PORT() + */ +#define getSn_PORT(sn) \ + ((WIZCHIP_READ(Sn_PORT(sn)) << 8) | WIZCHIP_READ(Sn_PORT(sn) + 1)) + +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_DHAR register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @param (uint8_t*)dhar Pointer variable to set socket n destination hardware address. It should be allocated 6 bytes. + * @sa getSn_DHAR() + */ +#define setSn_DHAR(sn, dhar) \ + WIZCHIP_WRITE_BUF(Sn_DHAR(sn), dhar, 6) + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_MR register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @param (uint8_t*)dhar Pointer variable to get socket n destination hardware address. It should be allocated 6 bytes. + * @sa setSn_DHAR() + */ +#define getSn_DHAR(sn, dhar) \ + WIZCHIP_READ_BUF(Sn_DHAR(sn), dhar, 6) + +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_DIPR register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @param (uint8_t*)dipr Pointer variable to set socket n destination IP address. It should be allocated 4 bytes. + * @sa getSn_DIPR() + */ +#define setSn_DIPR(sn, dipr) \ + WIZCHIP_WRITE_BUF(Sn_DIPR(sn), dipr, 4) + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_DIPR register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @param (uint8_t*)dipr Pointer variable to get socket n destination IP address. It should be allocated 4 bytes. + * @sa SetSn_DIPR() + */ +#define getSn_DIPR(sn, dipr) \ + WIZCHIP_READ_BUF(Sn_DIPR(sn), dipr, 4) + +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_DPORT register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @param (uint16_t)dport Value to set @ref Sn_DPORT + * @sa getSn_DPORT() + */ +#define setSn_DPORT(sn, dport) { \ + WIZCHIP_WRITE(Sn_DPORT(sn), (uint8_t) (dport>>8)); \ + WIZCHIP_WRITE(Sn_DPORT(sn) + 1, (uint8_t) dport); \ + } + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_DPORT register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @return uint16_t. Value of @ref Sn_DPORT. + * @sa setSn_DPORT() + */ +#define getSn_DPORT(sn) \ + ((WIZCHIP_READ(Sn_DPORT(sn)) << 8) + WIZCHIP_READ((Sn_DPORT(sn)+1))) + +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_MSSR register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @param (uint16_t)mss Value to set @ref Sn_MSSR + * @sa setSn_MSSR() + */ +#define setSn_MSSR(sn, mss) { \ + WIZCHIP_WRITE(Sn_MSSR(sn), (uint8_t)(mss>>8)); \ + WIZCHIP_WRITE((Sn_MSSR(sn)+1), (uint8_t) mss); \ + } + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_MSSR register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @return uint16_t. Value of @ref Sn_MSSR. + * @sa setSn_MSSR() + */ +#define getSn_MSSR(sn) \ + ((WIZCHIP_READ(Sn_MSSR(sn)) << 8) + WIZCHIP_READ((Sn_MSSR(sn)+1))) + +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_TOS register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @param (uint8_t)tos Value to set @ref Sn_TOS + * @sa getSn_TOS() + */ +#define setSn_TOS(sn, tos) \ + WIZCHIP_WRITE(Sn_TOS(sn), tos) + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_TOS register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @return uint8_t. Value of Sn_TOS. + * @sa setSn_TOS() + */ +#define getSn_TOS(sn) \ + WIZCHIP_READ(Sn_TOS(sn)) + +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_TTL register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @param (uint8_t)ttl Value to set @ref Sn_TTL + * @sa getSn_TTL() + */ +#define setSn_TTL(sn, ttl) \ + WIZCHIP_WRITE(Sn_TTL(sn), ttl) + + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_TTL register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @return uint8_t. Value of @ref Sn_TTL. + * @sa setSn_TTL() + */ +#define getSn_TTL(sn) \ + WIZCHIP_READ(Sn_TTL(sn)) + + +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_RXBUF_SIZE register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @param (uint8_t)rxbufsize Value to set @ref Sn_RXBUF_SIZE + * @sa getSn_RXBUF_SIZE() + */ +#define setSn_RXBUF_SIZE(sn, rxbufsize) \ + WIZCHIP_WRITE(Sn_RXBUF_SIZE(sn),rxbufsize) + + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_RXBUF_SIZE register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @return uint8_t. Value of @ref Sn_RXBUF_SIZE. + * @sa setSn_RXBUF_SIZE() + */ +#define getSn_RXBUF_SIZE(sn) \ + WIZCHIP_READ(Sn_RXBUF_SIZE(sn)) + +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_TXBUF_SIZE register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @param (uint8_t)txbufsize Value to set @ref Sn_TXBUF_SIZE + * @sa getSn_TXBUF_SIZE() + */ +#define setSn_TXBUF_SIZE(sn, txbufsize) \ + WIZCHIP_WRITE(Sn_TXBUF_SIZE(sn), txbufsize) + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_TXBUF_SIZE register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @return uint8_t. Value of @ref Sn_TXBUF_SIZE. + * @sa setSn_TXBUF_SIZE() + */ +#define getSn_TXBUF_SIZE(sn) \ + WIZCHIP_READ(Sn_TXBUF_SIZE(sn)) + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_TX_FSR register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @return uint16_t. Value of @ref Sn_TX_FSR. + */ +uint16_t getSn_TX_FSR(uint8_t sn); + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_TX_RD register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @return uint16_t. Value of @ref Sn_TX_RD. + */ +#define getSn_TX_RD(sn) \ + ((WIZCHIP_READ(Sn_TX_RD(sn)) << 8) + WIZCHIP_READ((Sn_TX_RD(sn)+1))) + +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_TX_WR register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @param (uint16_t)txwr Value to set @ref Sn_TX_WR + * @sa GetSn_TX_WR() + */ +#define setSn_TX_WR(sn, txwr) { \ + WIZCHIP_WRITE(Sn_TX_WR(sn), (uint8_t)(txwr>>8)); \ + WIZCHIP_WRITE((Sn_TX_WR(sn)+1), (uint8_t) txwr); \ + } + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_TX_WR register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @return uint16_t. Value of @ref Sn_TX_WR. + * @sa setSn_TX_WR() + */ +#define getSn_TX_WR(sn) \ + ((WIZCHIP_READ(Sn_TX_WR(sn)) << 8) + WIZCHIP_READ((Sn_TX_WR(sn)+1))) + + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_RX_RSR register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @return uint16_t. Value of @ref Sn_RX_RSR. + */ +uint16_t getSn_RX_RSR(uint8_t sn); + + +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_RX_RD register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @param (uint16_t)rxrd Value to set @ref Sn_RX_RD + * @sa getSn_RX_RD() + */ +#define setSn_RX_RD(sn, rxrd) { \ + WIZCHIP_WRITE(Sn_RX_RD(sn), (uint8_t)(rxrd>>8)); \ + WIZCHIP_WRITE((Sn_RX_RD(sn)+1), (uint8_t) rxrd); \ + } + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_RX_RD register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @regurn uint16_t. Value of @ref Sn_RX_RD. + * @sa setSn_RX_RD() + */ +#define getSn_RX_RD(sn) \ + ((WIZCHIP_READ(Sn_RX_RD(sn)) << 8) + WIZCHIP_READ((Sn_RX_RD(sn)+1))) + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_RX_WR register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @return uint16_t. Value of @ref Sn_RX_WR. + */ +#define getSn_RX_WR(sn) \ + ((WIZCHIP_READ(Sn_RX_WR(sn)) << 8) + WIZCHIP_READ((Sn_RX_WR(sn)+1))) + + +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_FRAG register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @param (uint16_t)frag Value to set @ref Sn_FRAG + * @sa getSn_FRAD() + */ +#if 0 // dpgeorge +#define setSn_FRAG(sn, frag) { \ + WIZCHIP_WRITE(Sn_FRAG(sn), (uint8_t)(frag >>8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_FRAG(sn),1), (uint8_t) frag); \ + } + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_FRAG register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @return uint16_t. Value of @ref Sn_FRAG. + * @sa setSn_FRAG() + */ +#define getSn_FRAG(sn) \ + ((WIZCHIP_READ(Sn_FRAG(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_FRAG(sn),1))) + +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_KPALVTR register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @param (uint8_t)kpalvt Value to set @ref Sn_KPALVTR + * @sa getSn_KPALVTR() + */ +#define setSn_KPALVTR(sn, kpalvt) \ + WIZCHIP_WRITE(Sn_KPALVTR(sn), kpalvt) + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_KPALVTR register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @return uint8_t. Value of @ref Sn_KPALVTR. + * @sa setSn_KPALVTR() + */ +#define getSn_KPALVTR(sn) \ + WIZCHIP_READ(Sn_KPALVTR(sn)) + +////////////////////////////////////// +#endif + +///////////////////////////////////// +// Sn_TXBUF & Sn_RXBUF IO function // +///////////////////////////////////// +/** + * @brief Gets the max buffer size of socket sn passed as parameter. + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @return uint16_t. Value of Socket n RX max buffer size. + */ +#define getSn_RxMAX(sn) \ + (getSn_RXBUF_SIZE(sn) << 10) + +/** + * @brief Gets the max buffer size of socket sn passed as parameters. + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @return uint16_t. Value of Socket n TX max buffer size. + */ +//uint16_t getSn_TxMAX(uint8_t sn); +#define getSn_TxMAX(sn) \ + (getSn_TXBUF_SIZE(sn) << 10) + +void wiz_init(void); + +/** + * @ingroup Basic_IO_function + * @brief It copies data to internal TX memory + * + * @details This function reads the Tx write pointer register and after that, + * it copies the <i>wizdata(pointer buffer)</i> of the length of <i>len(variable)</i> bytes to internal TX memory + * and updates the Tx write pointer register. + * This function is being called by send() and sendto() function also. + * + * @note User should read upper byte first and lower byte later to get proper value. + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @param wizdata Pointer buffer to write data + * @param len Data length + * @sa wiz_recv_data() + */ +void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len); + +/** + * @ingroup Basic_IO_function + * @brief It copies data to your buffer from internal RX memory + * + * @details This function read the Rx read pointer register and after that, + * it copies the received data from internal RX memory + * to <i>wizdata(pointer variable)</i> of the length of <i>len(variable)</i> bytes. + * This function is being called by recv() also. + * + * @note User should read upper byte first and lower byte later to get proper value. + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @param wizdata Pointer buffer to read data + * @param len Data length + * @sa wiz_send_data() + */ +void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len); + +/** + * @ingroup Basic_IO_function + * @brief It discard the received data in RX memory. + * @details It discards the data of the length of <i>len(variable)</i> bytes in internal RX memory. + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @param len Data length + */ +void wiz_recv_ignore(uint8_t sn, uint16_t len); + +#endif // _W5500_H_ diff --git a/drivers/wiznet5k/ethernet/w5500/w5500.c b/drivers/wiznet5k/ethernet/w5500/w5500.c new file mode 100644 index 000000000..3107b1b71 --- /dev/null +++ b/drivers/wiznet5k/ethernet/w5500/w5500.c @@ -0,0 +1,247 @@ +//***************************************************************************** +// +//! \file w5500.c +//! \brief W5500 HAL Interface. +//! \version 1.0.1 +//! \date 2013/10/21 +//! \par Revision history +//! <2014/05/01> V1.0.2 +//! 1. Implicit type casting -> Explicit type casting. Refer to M20140501 +//! Fixed the problem on porting into under 32bit MCU +//! Issued by Mathias ClauBen, wizwiki forum ID Think01 and bobh +//! Thank for your interesting and serious advices. +//! <2013/10/21> 1st Release +//! <2013/12/20> V1.0.1 +//! 1. Remove warning +//! 2. WIZCHIP_READ_BUF WIZCHIP_WRITE_BUF in case _WIZCHIP_IO_MODE_SPI_FDM_ +//! for loop optimized(removed). refer to M20131220 +//! \author MidnightCow +//! \copyright +//! +//! Copyright (c) 2013, WIZnet Co., LTD. +//! All rights reserved. +//! +//! Redistribution and use in source and binary forms, with or without +//! modification, are permitted provided that the following conditions +//! are met: +//! +//! * Redistributions of source code must retain the above copyright +//! notice, this list of conditions and the following disclaimer. +//! * Redistributions in binary form must reproduce the above copyright +//! notice, this list of conditions and the following disclaimer in the +//! documentation and/or other materials provided with the distribution. +//! * Neither the name of the <ORGANIZATION> nor the names of its +//! contributors may be used to endorse or promote products derived +//! from this software without specific prior written permission. +//! +//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +//! THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** +//#include <stdio.h> +#include "w5500.h" + +#define _W5500_SPI_VDM_OP_ 0x00 +#define _W5500_SPI_FDM_OP_LEN1_ 0x01 +#define _W5500_SPI_FDM_OP_LEN2_ 0x02 +#define _W5500_SPI_FDM_OP_LEN4_ 0x03 + +//////////////////////////////////////////////////// + +#define LPC_SSP0 (0) + +static void Chip_SSP_ReadFrames_Blocking(int dummy, uint8_t *buf, uint32_t len) { + WIZCHIP.IF.SPI._read_bytes(buf, len); +} + +static void Chip_SSP_WriteFrames_Blocking(int dummy, const uint8_t *buf, uint32_t len) { + WIZCHIP.IF.SPI._write_bytes(buf, len); +} + +uint8_t WIZCHIP_READ(uint32_t AddrSel) +{ + uint8_t ret; + uint8_t spi_data[3]; + + WIZCHIP_CRITICAL_ENTER(); + WIZCHIP.CS._select(); + + AddrSel |= (_W5500_SPI_READ_ | _W5500_SPI_VDM_OP_); + + //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16); + //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8); + //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0); + //ret = WIZCHIP.IF.SPI._read_byte(); + spi_data[0] = (AddrSel & 0x00FF0000) >> 16; + spi_data[1] = (AddrSel & 0x0000FF00) >> 8; + spi_data[2] = (AddrSel & 0x000000FF) >> 0; + Chip_SSP_WriteFrames_Blocking(LPC_SSP0, spi_data, 3); + Chip_SSP_ReadFrames_Blocking(LPC_SSP0, &ret, 1); + + WIZCHIP.CS._deselect(); + WIZCHIP_CRITICAL_EXIT(); + return ret; +} + +void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb ) +{ + uint8_t spi_data[4]; + + WIZCHIP_CRITICAL_ENTER(); + WIZCHIP.CS._select(); + + AddrSel |= (_W5500_SPI_WRITE_ | _W5500_SPI_VDM_OP_); + + //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16); + //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8); + //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0); + //WIZCHIP.IF.SPI._write_byte(wb); + spi_data[0] = (AddrSel & 0x00FF0000) >> 16; + spi_data[1] = (AddrSel & 0x0000FF00) >> 8; + spi_data[2] = (AddrSel & 0x000000FF) >> 0; + spi_data[3] = wb; + Chip_SSP_WriteFrames_Blocking(LPC_SSP0, spi_data, 4); + + WIZCHIP.CS._deselect(); + WIZCHIP_CRITICAL_EXIT(); +} + +void WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, uint16_t len) +{ + uint8_t spi_data[3]; + //uint16_t i; + + WIZCHIP_CRITICAL_ENTER(); + WIZCHIP.CS._select(); + + AddrSel |= (_W5500_SPI_READ_ | _W5500_SPI_VDM_OP_); + + //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16); + //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8); + //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0); + //for(i = 0; i < len; i++) + // pBuf[i] = WIZCHIP.IF.SPI._read_byte(); + spi_data[0] = (AddrSel & 0x00FF0000) >> 16; + spi_data[1] = (AddrSel & 0x0000FF00) >> 8; + spi_data[2] = (AddrSel & 0x000000FF) >> 0; + Chip_SSP_WriteFrames_Blocking(LPC_SSP0, spi_data, 3); + Chip_SSP_ReadFrames_Blocking(LPC_SSP0, pBuf, len); + + WIZCHIP.CS._deselect(); + WIZCHIP_CRITICAL_EXIT(); +} + +void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len) +{ + uint8_t spi_data[3]; + //uint16_t i; + + WIZCHIP_CRITICAL_ENTER(); + WIZCHIP.CS._select(); + + AddrSel |= (_W5500_SPI_WRITE_ | _W5500_SPI_VDM_OP_); + + //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16); + //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >> 8); + //WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >> 0); + //for(i = 0; i < len; i++) + // WIZCHIP.IF.SPI._write_byte(pBuf[i]); + spi_data[0] = (AddrSel & 0x00FF0000) >> 16; + spi_data[1] = (AddrSel & 0x0000FF00) >> 8; + spi_data[2] = (AddrSel & 0x000000FF) >> 0; + Chip_SSP_WriteFrames_Blocking(LPC_SSP0, spi_data, 3); + Chip_SSP_WriteFrames_Blocking(LPC_SSP0, pBuf, len); + + WIZCHIP.CS._deselect(); + WIZCHIP_CRITICAL_EXIT(); +} + + +uint16_t getSn_TX_FSR(uint8_t sn) +{ + uint16_t val=0,val1=0; + + do + { + val1 = WIZCHIP_READ(Sn_TX_FSR(sn)); + val1 = (val1 << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn),1)); + if (val1 != 0) + { + val = WIZCHIP_READ(Sn_TX_FSR(sn)); + val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_FSR(sn),1)); + } + }while (val != val1); + return val; +} + + +uint16_t getSn_RX_RSR(uint8_t sn) +{ + uint16_t val=0,val1=0; + + do + { + val1 = WIZCHIP_READ(Sn_RX_RSR(sn)); + val1 = (val1 << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),1)); + if (val1 != 0) + { + val = WIZCHIP_READ(Sn_RX_RSR(sn)); + val = (val << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RSR(sn),1)); + } + }while (val != val1); + return val; +} + +void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len) +{ + uint16_t ptr = 0; + uint32_t addrsel = 0; + + if(len == 0) return; + ptr = getSn_TX_WR(sn); + //M20140501 : implict type casting -> explict type casting + //addrsel = (ptr << 8) + (WIZCHIP_TXBUF_BLOCK(sn) << 3); + addrsel = ((uint32_t)ptr << 8) + (WIZCHIP_TXBUF_BLOCK(sn) << 3); + // + WIZCHIP_WRITE_BUF(addrsel,wizdata, len); + + ptr += len; + setSn_TX_WR(sn,ptr); +} + +void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len) +{ + uint16_t ptr = 0; + uint32_t addrsel = 0; + + if(len == 0) return; + ptr = getSn_RX_RD(sn); + //M20140501 : implict type casting -> explict type casting + //addrsel = ((ptr << 8) + (WIZCHIP_RXBUF_BLOCK(sn) << 3); + addrsel = ((uint32_t)ptr << 8) + (WIZCHIP_RXBUF_BLOCK(sn) << 3); + // + WIZCHIP_READ_BUF(addrsel, wizdata, len); + ptr += len; + + setSn_RX_RD(sn,ptr); +} + + +void wiz_recv_ignore(uint8_t sn, uint16_t len) +{ + uint16_t ptr = 0; + + ptr = getSn_RX_RD(sn); + ptr += len; + setSn_RX_RD(sn,ptr); +} + diff --git a/drivers/wiznet5k/ethernet/w5500/w5500.h b/drivers/wiznet5k/ethernet/w5500/w5500.h new file mode 100644 index 000000000..c2afb180e --- /dev/null +++ b/drivers/wiznet5k/ethernet/w5500/w5500.h @@ -0,0 +1,2057 @@ +//***************************************************************************** +// +//! \file w5500.h +//! \brief W5500 HAL Header File. +//! \version 1.0.0 +//! \date 2013/10/21 +//! \par Revision history +//! <2013/10/21> 1st Release +//! \author MidnightCow +//! \copyright +//! +//! Copyright (c) 2013, WIZnet Co., LTD. +//! All rights reserved. +//! +//! Redistribution and use in source and binary forms, with or without +//! modification, are permitted provided that the following conditions +//! are met: +//! +//! * Redistributions of source code must retain the above copyright +//! notice, this list of conditions and the following disclaimer. +//! * Redistributions in binary form must reproduce the above copyright +//! notice, this list of conditions and the following disclaimer in the +//! documentation and/or other materials provided with the distribution. +//! * Neither the name of the <ORGANIZATION> nor the names of its +//! contributors may be used to endorse or promote products derived +//! from this software without specific prior written permission. +//! +//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +//! THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + +#ifndef _W5500_H_ +#define _W5500_H_ + +#include <stdint.h> +#include "../wizchip_conf.h" + +#define _W5500_IO_BASE_ 0x00000000 + +#define _W5500_SPI_READ_ (0x00 << 2) //< SPI interface Read operation in Control Phase +#define _W5500_SPI_WRITE_ (0x01 << 2) //< SPI interface Write operation in Control Phase + +#define WIZCHIP_CREG_BLOCK 0x00 //< Common register block +#define WIZCHIP_SREG_BLOCK(N) (1+4*N) //< Socket N register block +#define WIZCHIP_TXBUF_BLOCK(N) (2+4*N) //< Socket N Tx buffer address block +#define WIZCHIP_RXBUF_BLOCK(N) (3+4*N) //< Socket N Rx buffer address block + +#define WIZCHIP_OFFSET_INC(ADDR, N) (ADDR + (N<<8)) //< Increase offset address + + +/////////////////////////////////////// +// Definition For Legacy Chip Driver // +/////////////////////////////////////// +#define IINCHIP_READ(ADDR) WIZCHIP_READ(ADDR) ///< The defined for legacy chip driver +#define IINCHIP_WRITE(ADDR,VAL) WIZCHIP_WRITE(ADDR,VAL) ///< The defined for legacy chip driver +#define IINCHIP_READ_BUF(ADDR,BUF,LEN) WIZCHIP_READ_BUF(ADDR,BUF,LEN) ///< The defined for legacy chip driver +#define IINCHIP_WRITE_BUF(ADDR,BUF,LEN) WIZCHIP_WRITE(ADDR,BUF,LEN) ///< The defined for legacy chip driver + +////////////////////////////// +//-------------------------- defgroup --------------------------------- +/** + * @defgroup W5500 W5500 + * + * @brief WHIZCHIP register defines and I/O functions of @b W5500. + * + * - @ref WIZCHIP_register : @ref Common_register_group and @ref Socket_register_group + * - @ref WIZCHIP_IO_Functions : @ref Basic_IO_function, @ref Common_register_access_function and @ref Socket_register_access_function + */ + + +/** + * @defgroup WIZCHIP_register WIZCHIP register + * @ingroup W5500 + * + * @brief WHIZCHIP register defines register group of @b W5500. + * + * - @ref Common_register_group : Common register group + * - @ref Socket_register_group : \c SOCKET n register group + */ + + +/** + * @defgroup WIZCHIP_IO_Functions WIZCHIP I/O functions + * @ingroup W5500 + * + * @brief This supports the basic I/O functions for @ref WIZCHIP_register. + * + * - <b> Basic I/O function </b> \n + * WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() \n\n + * + * - @ref Common_register_group <b>access functions</b> \n + * -# @b Mode \n + * getMR(), setMR() + * -# @b Interrupt \n + * getIR(), setIR(), getIMR(), setIMR(), getSIR(), setSIR(), getSIMR(), setSIMR(), getINTLEVEL(), setINTLEVEL() + * -# <b> Network Information </b> \n + * getSHAR(), setSHAR(), getGAR(), setGAR(), getSUBR(), setSUBR(), getSIPR(), setSIPR() + * -# @b Retransmission \n + * getRCR(), setRCR(), getRTR(), setRTR() + * -# @b PPPoE \n + * getPTIMER(), setPTIMER(), getPMAGIC(), getPMAGIC(), getPSID(), setPSID(), getPHAR(), setPHAR(), getPMRU(), setPMRU() + * -# <b> ICMP packet </b>\n + * getUIPR(), getUPORTR() + * -# @b etc. \n + * getPHYCFGR(), setPHYCFGR(), getVERSIONR() \n\n + * + * - \ref Socket_register_group <b>access functions</b> \n + * -# <b> SOCKET control</b> \n + * getSn_MR(), setSn_MR(), getSn_CR(), setSn_CR(), getSn_IMR(), setSn_IMR(), getSn_IR(), setSn_IR() + * -# <b> SOCKET information</b> \n + * getSn_SR(), getSn_DHAR(), setSn_DHAR(), getSn_PORT(), setSn_PORT(), getSn_DIPR(), setSn_DIPR(), getSn_DPORT(), setSn_DPORT() + * getSn_MSSR(), setSn_MSSR() + * -# <b> SOCKET communication </b> \n + * getSn_RXBUF_SIZE(), setSn_RXBUF_SIZE(), getSn_TXBUF_SIZE(), setSn_TXBUF_SIZE() \n + * getSn_TX_RD(), getSn_TX_WR(), setSn_TX_WR() \n + * getSn_RX_RD(), setSn_RX_RD(), getSn_RX_WR() \n + * getSn_TX_FSR(), getSn_RX_RSR(), getSn_KPALVTR(), setSn_KPALVTR() + * -# <b> IP header field </b> \n + * getSn_FRAG(), setSn_FRAG(), getSn_TOS(), setSn_TOS() \n + * getSn_TTL(), setSn_TTL() + */ + + + +/** + * @defgroup Common_register_group Common register + * @ingroup WIZCHIP_register + * + * @brief Common register group\n + * It set the basic for the networking\n + * It set the configuration such as interrupt, network information, ICMP, etc. + * @details + * @sa MR : Mode register. + * @sa GAR, SUBR, SHAR, SIPR + * @sa INTLEVEL, IR, IMR, SIR, SIMR : Interrupt. + * @sa RTR, RCR : Data retransmission. + * @sa PTIMER, PMAGIC, PHAR, PSID, PMRU : PPPoE. + * @sa UIPR, UPORTR : ICMP message. + * @sa PHYCFGR, VERSIONR : etc. + */ + + + +/** + * @defgroup Socket_register_group Socket register + * @ingroup WIZCHIP_register + * + * @brief Socket register group.\n + * Socket register configures and control SOCKETn which is necessary to data communication. + * @details + * @sa Sn_MR, Sn_CR, Sn_IR, Sn_IMR : SOCKETn Control + * @sa Sn_SR, Sn_PORT, Sn_DHAR, Sn_DIPR, Sn_DPORT : SOCKETn Information + * @sa Sn_MSSR, Sn_TOS, Sn_TTL, Sn_KPALVTR, Sn_FRAG : Internet protocol. + * @sa Sn_RXBUF_SIZE, Sn_TXBUF_SIZE, Sn_TX_FSR, Sn_TX_RD, Sn_TX_WR, Sn_RX_RSR, Sn_RX_RD, Sn_RX_WR : Data communication + */ + + + + /** + * @defgroup Basic_IO_function Basic I/O function + * @ingroup WIZCHIP_IO_Functions + * @brief These are basic input/output functions to read values from register or write values to register. + */ + +/** + * @defgroup Common_register_access_function Common register access functions + * @ingroup WIZCHIP_IO_Functions + * @brief These are functions to access <b>common registers</b>. + */ + +/** + * @defgroup Socket_register_access_function Socket register access functions + * @ingroup WIZCHIP_IO_Functions + * @brief These are functions to access <b>socket registers</b>. + */ + +//------------------------------- defgroup end -------------------------------------------- +//----------------------------- W5500 Common Registers IOMAP ----------------------------- +/** + * @ingroup Common_register_group + * @brief Mode Register address(R/W)\n + * @ref MR is used for S/W reset, ping block mode, PPPoE mode and etc. + * @details Each bit of @ref MR defined as follows. + * <table> + * <tr> <td>7</td> <td>6</td> <td>5</td> <td>4</td> <td>3</td> <td>2</td> <td>1</td> <td>0</td> </tr> + * <tr> <td>RST</td> <td>Reserved</td> <td>WOL</td> <td>PB</td> <td>PPPoE</td> <td>Reserved</td> <td>FARP</td> <td>Reserved</td> </tr> + * </table> + * - \ref MR_RST : Reset + * - \ref MR_WOL : Wake on LAN + * - \ref MR_PB : Ping block + * - \ref MR_PPPOE : PPPoE mode + * - \ref MR_FARP : Force ARP mode + */ +#define MR (_W5500_IO_BASE_ + (0x0000 << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief Gateway IP Register address(R/W) + * @details @ref GAR configures the default gateway address. + */ +#define GAR (_W5500_IO_BASE_ + (0x0001 << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief Subnet mask Register address(R/W) + * @details @ref SUBR configures the subnet mask address. + */ +#define SUBR (_W5500_IO_BASE_ + (0x0005 << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief Source MAC Register address(R/W) + * @details @ref SHAR configures the source hardware address. + */ +#define SHAR (_W5500_IO_BASE_ + (0x0009 << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief Source IP Register address(R/W) + * @details @ref SIPR configures the source IP address. + */ +#define SIPR (_W5500_IO_BASE_ + (0x000F << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief Set Interrupt low level timer register address(R/W) + * @details @ref INTLEVEL configures the Interrupt Assert Time. + */ +#define INTLEVEL (_W5500_IO_BASE_ + (0x0013 << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief Interrupt Register(R/W) + * @details @ref IR indicates the interrupt status. Each bit of @ref IR will be still until the bit will be written to by the host. + * If @ref IR is not equal to x00 INTn PIN is asserted to low until it is x00\n\n + * Each bit of @ref IR defined as follows. + * <table> + * <tr> <td>7</td> <td>6</td> <td>5</td> <td>4</td> <td>3</td> <td>2</td> <td>1</td> <td>0</td> </tr> + * <tr> <td>CONFLICT</td> <td>UNREACH</td> <td>PPPoE</td> <td>MP</td> <td>Reserved</td> <td>Reserved</td> <td>Reserved</td> <td>Reserved</td> </tr> + * </table> + * - \ref IR_CONFLICT : IP conflict + * - \ref IR_UNREACH : Destination unreachable + * - \ref IR_PPPoE : PPPoE connection close + * - \ref IR_MP : Magic packet + */ +#define IR (_W5500_IO_BASE_ + (0x0015 << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief Interrupt mask register(R/W) + * @details @ref IMR is used to mask interrupts. Each bit of @ref IMR corresponds to each bit of @ref IR. + * When a bit of @ref IMR is and the corresponding bit of @ref IR is an interrupt will be issued. In other words, + * if a bit of @ref IMR is an interrupt will not be issued even if the corresponding bit of @ref IR is \n\n + * Each bit of @ref IMR defined as the following. + * <table> + * <tr> <td>7</td> <td>6</td> <td>5</td> <td>4</td> <td>3</td> <td>2</td> <td>1</td> <td>0</td> </tr> + * <tr> <td>IM_IR7</td> <td>IM_IR6</td> <td>IM_IR5</td> <td>IM_IR4</td> <td>Reserved</td> <td>Reserved</td> <td>Reserved</td> <td>Reserved</td> </tr> + * </table> + * - \ref IM_IR7 : IP Conflict Interrupt Mask + * - \ref IM_IR6 : Destination unreachable Interrupt Mask + * - \ref IM_IR5 : PPPoE Close Interrupt Mask + * - \ref IM_IR4 : Magic Packet Interrupt Mask + */ +#define IMR (_W5500_IO_BASE_ + (0x0016 << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief Socket Interrupt Register(R/W) + * @details @ref SIR indicates the interrupt status of Socket.\n + * Each bit of @ref SIR be still until @ref Sn_IR is cleared by the host.\n + * If @ref Sn_IR is not equal to x00 the n-th bit of @ref SIR is and INTn PIN is asserted until @ref SIR is x00 */ +#define SIR (_W5500_IO_BASE_ + (0x0017 << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief Socket Interrupt Mask Register(R/W) + * @details Each bit of @ref SIMR corresponds to each bit of @ref SIR. + * When a bit of @ref SIMR is and the corresponding bit of @ref SIR is Interrupt will be issued. + * In other words, if a bit of @ref SIMR is an interrupt will be not issued even if the corresponding bit of @ref SIR is + */ +#define SIMR (_W5500_IO_BASE_ + (0x0018 << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief Timeout register address( 1 is 100us )(R/W) + * @details @ref RTR configures the retransmission timeout period. The unit of timeout period is 100us and the default of @ref RTR is x07D0or 000 + * And so the default timeout period is 200ms(100us X 2000). During the time configured by @ref RTR, W5500 waits for the peer response + * to the packet that is transmitted by \ref Sn_CR (CONNECT, DISCON, CLOSE, SEND, SEND_MAC, SEND_KEEP command). + * If the peer does not respond within the @ref RTR time, W5500 retransmits the packet or issues timeout. + */ +#define RTR (_W5500_IO_BASE_ + (0x0019 << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief Retry count register(R/W) + * @details @ref RCR configures the number of time of retransmission. + * When retransmission occurs as many as ref RCR+1 Timeout interrupt is issued (@ref Sn_IR[TIMEOUT] = . + */ +#define RCR (_W5500_IO_BASE_ + (0x001B << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief PPP LCP Request Timer register in PPPoE mode(R/W) + * @details @ref PTIMER configures the time for sending LCP echo request. The unit of time is 25ms. + */ +#define PTIMER (_W5500_IO_BASE_ + (0x001C << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief PPP LCP Magic number register in PPPoE mode(R/W) + * @details @ref PMAGIC configures the 4bytes magic number to be used in LCP negotiation. + */ +#define PMAGIC (_W5500_IO_BASE_ + (0x001D << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief PPP Destination MAC Register address(R/W) + * @details @ref PHAR configures the PPPoE server hardware address that is acquired during PPPoE connection process. + */ +#define PHAR (_W5500_IO_BASE_ + (0x001E << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief PPP Session Identification Register(R/W) + * @details @ref PSID configures the PPPoE sever session ID acquired during PPPoE connection process. + */ +#define PSID (_W5500_IO_BASE_ + (0x0024 << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief PPP Maximum Segment Size(MSS) register(R/W) + * @details @ref PMRU configures the maximum receive unit of PPPoE. + */ +#define PMRU (_W5500_IO_BASE_ + (0x0026 << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief Unreachable IP register address in UDP mode(R) + * @details W5500 receives an ICMP packet(Destination port unreachable) when data is sent to a port number + * which socket is not open and @ref UNREACH bit of @ref IR becomes and @ref UIPR & @ref UPORTR indicates + * the destination IP address & port number respectively. + */ +#define UIPR (_W5500_IO_BASE_ + (0x0028 << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief Unreachable Port register address in UDP mode(R) + * @details W5500 receives an ICMP packet(Destination port unreachable) when data is sent to a port number + * which socket is not open and @ref UNREACH bit of @ref IR becomes and @ref UIPR & @ref UPORTR + * indicates the destination IP address & port number respectively. + */ +#define UPORTR (_W5500_IO_BASE_ + (0x002C << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief PHY Status Register(R/W) + * @details @ref PHYCFGR configures PHY operation mode and resets PHY. In addition, @ref PHYCFGR indicates the status of PHY such as duplex, Speed, Link. + */ +#define PHYCFGR (_W5500_IO_BASE_ + (0x002E << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +// Reserved (_W5500_IO_BASE_ + (0x002F << 8) + (WIZCHIP_CREG_BLOCK << 3)) +// Reserved (_W5500_IO_BASE_ + (0x0030 << 8) + (WIZCHIP_CREG_BLOCK << 3)) +// Reserved (_W5500_IO_BASE_ + (0x0031 << 8) + (WIZCHIP_CREG_BLOCK << 3)) +// Reserved (_W5500_IO_BASE_ + (0x0032 << 8) + (WIZCHIP_CREG_BLOCK << 3)) +// Reserved (_W5500_IO_BASE_ + (0x0033 << 8) + (WIZCHIP_CREG_BLOCK << 3)) +// Reserved (_W5500_IO_BASE_ + (0x0034 << 8) + (WIZCHIP_CREG_BLOCK << 3)) +// Reserved (_W5500_IO_BASE_ + (0x0035 << 8) + (WIZCHIP_CREG_BLOCK << 3)) +// Reserved (_W5500_IO_BASE_ + (0x0036 << 8) + (WIZCHIP_CREG_BLOCK << 3)) +// Reserved (_W5500_IO_BASE_ + (0x0037 << 8) + (WIZCHIP_CREG_BLOCK << 3)) +// Reserved (_W5500_IO_BASE_ + (0x0038 << 8) + (WIZCHIP_CREG_BLOCK << 3)) + +/** + * @ingroup Common_register_group + * @brief chip version register address(R) + * @details @ref VERSIONR always indicates the W5500 version as @b 0x04. + */ +#define VERSIONR (_W5500_IO_BASE_ + (0x0039 << 8) + (WIZCHIP_CREG_BLOCK << 3)) + + +//----------------------------- W5500 Socket Registers IOMAP ----------------------------- +/** + * @ingroup Socket_register_group + * @brief socket Mode register(R/W) + * @details @ref Sn_MR configures the option or protocol type of Socket n.\n\n + * Each bit of @ref Sn_MR defined as the following. + * <table> + * <tr> <td>7</td> <td>6</td> <td>5</td> <td>4</td> <td>3</td> <td>2</td> <td>1</td> <td>0</td> </tr> + * <tr> <td>MULTI/MFEN</td> <td>BCASTB</td> <td>ND/MC/MMB</td> <td>UCASTB/MIP6B</td> <td>Protocol[3]</td> <td>Protocol[2]</td> <td>Protocol[1]</td> <td>Protocol[0]</td> </tr> + * </table> + * - @ref Sn_MR_MULTI : Support UDP Multicasting + * - @ref Sn_MR_BCASTB : Broadcast block <b>in UDP Multicasting</b> + * - @ref Sn_MR_ND : No Delayed Ack(TCP) flag + * - @ref Sn_MR_MC : IGMP version used <b>in UDP mulitcasting</b> + * - @ref Sn_MR_MMB : Multicast Blocking <b>in @ref Sn_MR_MACRAW mode</b> + * - @ref Sn_MR_UCASTB : Unicast Block <b>in UDP Multicating</b> + * - @ref Sn_MR_MIP6B : IPv6 packet Blocking <b>in @ref Sn_MR_MACRAW mode</b> + * - <b>Protocol</b> + * <table> + * <tr> <td><b>Protocol[3]</b></td> <td><b>Protocol[2]</b></td> <td><b>Protocol[1]</b></td> <td><b>Protocol[0]</b></td> <td>@b Meaning</td> </tr> + * <tr> <td>0</td> <td>0</td> <td>0</td> <td>0</td> <td>Closed</td> </tr> + * <tr> <td>0</td> <td>0</td> <td>0</td> <td>1</td> <td>TCP</td> </tr> + * <tr> <td>0</td> <td>0</td> <td>1</td> <td>0</td> <td>UDP</td> </tr> + * <tr> <td>0</td> <td>1</td> <td>0</td> <td>0</td> <td>MACRAW</td> </tr> + * </table> + * - @ref Sn_MR_MACRAW : MAC LAYER RAW SOCK \n + * - @ref Sn_MR_UDP : UDP + * - @ref Sn_MR_TCP : TCP + * - @ref Sn_MR_CLOSE : Unused socket + * @note MACRAW mode should be only used in Socket 0. + */ +#define Sn_MR(N) (_W5500_IO_BASE_ + (0x0000 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +/** + * @ingroup Socket_register_group + * @brief Socket command register(R/W) + * @details This is used to set the command for Socket n such as OPEN, CLOSE, CONNECT, LISTEN, SEND, and RECEIVE.\n + * After W5500 accepts the command, the @ref Sn_CR register is automatically cleared to 0x00. + * Even though @ref Sn_CR is cleared to 0x00, the command is still being processed.\n + * To check whether the command is completed or not, please check the @ref Sn_IR or @ref Sn_SR. + * - @ref Sn_CR_OPEN : Initialize or open socket. + * - @ref Sn_CR_LISTEN : Wait connection request in TCP mode(<b>Server mode</b>) + * - @ref Sn_CR_CONNECT : Send connection request in TCP mode(<b>Client mode</b>) + * - @ref Sn_CR_DISCON : Send closing request in TCP mode. + * - @ref Sn_CR_CLOSE : Close socket. + * - @ref Sn_CR_SEND : Update TX buffer pointer and send data. + * - @ref Sn_CR_SEND_MAC : Send data with MAC address, so without ARP process. + * - @ref Sn_CR_SEND_KEEP : Send keep alive message. + * - @ref Sn_CR_RECV : Update RX buffer pointer and receive data. + */ +#define Sn_CR(N) (_W5500_IO_BASE_ + (0x0001 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +/** + * @ingroup Socket_register_group + * @brief Socket interrupt register(R) + * @details @ref Sn_IR indicates the status of Socket Interrupt such as establishment, termination, receiving data, timeout).\n + * When an interrupt occurs and the corresponding bit of @ref Sn_IMR is the corresponding bit of @ref Sn_IR becomes \n + * In order to clear the @ref Sn_IR bit, the host should write the bit to \n + * <table> + * <tr> <td>7</td> <td>6</td> <td>5</td> <td>4</td> <td>3</td> <td>2</td> <td>1</td> <td>0</td> </tr> + * <tr> <td>Reserved</td> <td>Reserved</td> <td>Reserved</td> <td>SEND_OK</td> <td>TIMEOUT</td> <td>RECV</td> <td>DISCON</td> <td>CON</td> </tr> + * </table> + * - \ref Sn_IR_SENDOK : <b>SEND_OK Interrupt</b> + * - \ref Sn_IR_TIMEOUT : <b>TIMEOUT Interrupt</b> + * - \ref Sn_IR_RECV : <b>RECV Interrupt</b> + * - \ref Sn_IR_DISCON : <b>DISCON Interrupt</b> + * - \ref Sn_IR_CON : <b>CON Interrupt</b> + */ +#define Sn_IR(N) (_W5500_IO_BASE_ + (0x0002 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +/** + * @ingroup Socket_register_group + * @brief Socket status register(R) + * @details @ref Sn_SR indicates the status of Socket n.\n + * The status of Socket n is changed by @ref Sn_CR or some special control packet as SYN, FIN packet in TCP. + * @par Normal status + * - @ref SOCK_CLOSED : Closed + * - @ref SOCK_INIT : Initiate state + * - @ref SOCK_LISTEN : Listen state + * - @ref SOCK_ESTABLISHED : Success to connect + * - @ref SOCK_CLOSE_WAIT : Closing state + * - @ref SOCK_UDP : UDP socket + * - @ref SOCK_MACRAW : MAC raw mode socket + *@par Temporary status during changing the status of Socket n. + * - @ref SOCK_SYNSENT : This indicates Socket n sent the connect-request packet (SYN packet) to a peer. + * - @ref SOCK_SYNRECV : It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer. + * - @ref SOCK_FIN_WAIT : Connection state + * - @ref SOCK_CLOSING : Closing state + * - @ref SOCK_TIME_WAIT : Closing state + * - @ref SOCK_LAST_ACK : Closing state + */ +#define Sn_SR(N) (_W5500_IO_BASE_ + (0x0003 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +/** + * @ingroup Socket_register_group + * @brief source port register(R/W) + * @details @ref Sn_PORT configures the source port number of Socket n. + * It is valid when Socket n is used in TCP/UPD mode. It should be set before OPEN command is ordered. + */ +#define Sn_PORT(N) (_W5500_IO_BASE_ + (0x0004 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +/** + * @ingroup Socket_register_group + * @brief Peer MAC register address(R/W) + * @details @ref Sn_DHAR configures the destination hardware address of Socket n when using SEND_MAC command in UDP mode or + * it indicates that it is acquired in ARP-process by CONNECT/SEND command. + */ +#define Sn_DHAR(N) (_W5500_IO_BASE_ + (0x0006 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +/** + * @ingroup Socket_register_group + * @brief Peer IP register address(R/W) + * @details @ref Sn_DIPR configures or indicates the destination IP address of Socket n. It is valid when Socket n is used in TCP/UDP mode. + * In TCP client mode, it configures an IP address of �TCP serverbefore CONNECT command. + * In TCP server mode, it indicates an IP address of �TCP clientafter successfully establishing connection. + * In UDP mode, it configures an IP address of peer to be received the UDP packet by SEND or SEND_MAC command. + */ +#define Sn_DIPR(N) (_W5500_IO_BASE_ + (0x000C << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +/** + * @ingroup Socket_register_group + * @brief Peer port register address(R/W) + * @details @ref Sn_DPORT configures or indicates the destination port number of Socket n. It is valid when Socket n is used in TCP/UDP mode. + * In �TCP clientmode, it configures the listen port number of �TCP serverbefore CONNECT command. + * In �TCP Servermode, it indicates the port number of TCP client after successfully establishing connection. + * In UDP mode, it configures the port number of peer to be transmitted the UDP packet by SEND/SEND_MAC command. + */ +#define Sn_DPORT(N) (_W5500_IO_BASE_ + (0x0010 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +/** + * @ingroup Socket_register_group + * @brief Maximum Segment Size(Sn_MSSR0) register address(R/W) + * @details @ref Sn_MSSR configures or indicates the MTU(Maximum Transfer Unit) of Socket n. + */ +#define Sn_MSSR(N) (_W5500_IO_BASE_ + (0x0012 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +// Reserved (_W5500_IO_BASE_ + (0x0014 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +/** + * @ingroup Socket_register_group + * @brief IP Type of Service(TOS) Register(R/W) + * @details @ref Sn_TOS configures the TOS(Type Of Service field in IP Header) of Socket n. + * It is set before OPEN command. + */ +#define Sn_TOS(N) (_W5500_IO_BASE_ + (0x0015 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) +/** + * @ingroup Socket_register_group + * @brief IP Time to live(TTL) Register(R/W) + * @details @ref Sn_TTL configures the TTL(Time To Live field in IP header) of Socket n. + * It is set before OPEN command. + */ +#define Sn_TTL(N) (_W5500_IO_BASE_ + (0x0016 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) +// Reserved (_W5500_IO_BASE_ + (0x0017 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) +// Reserved (_W5500_IO_BASE_ + (0x0018 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) +// Reserved (_W5500_IO_BASE_ + (0x0019 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) +// Reserved (_W5500_IO_BASE_ + (0x001A << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) +// Reserved (_W5500_IO_BASE_ + (0x001B << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) +// Reserved (_W5500_IO_BASE_ + (0x001C << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) +// Reserved (_W5500_IO_BASE_ + (0x001D << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +/** + * @ingroup Socket_register_group + * @brief Receive memory size register(R/W) + * @details @ref Sn_RXBUF_SIZE configures the RX buffer block size of Socket n. + * Socket n RX Buffer Block size can be configured with 1,2,4,8, and 16 Kbytes. + * If a different size is configured, the data cannot be normally received from a peer. + * Although Socket n RX Buffer Block size is initially configured to 2Kbytes, + * user can re-configure its size using @ref Sn_RXBUF_SIZE. The total sum of @ref Sn_RXBUF_SIZE can not be exceed 16Kbytes. + * When exceeded, the data reception error is occurred. + */ +#define Sn_RXBUF_SIZE(N) (_W5500_IO_BASE_ + (0x001E << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +/** + * @ingroup Socket_register_group + * @brief Transmit memory size register(R/W) + * @details @ref Sn_TXBUF_SIZE configures the TX buffer block size of Socket n. Socket n TX Buffer Block size can be configured with 1,2,4,8, and 16 Kbytes. + * If a different size is configured, the data can�t be normally transmitted to a peer. + * Although Socket n TX Buffer Block size is initially configured to 2Kbytes, + * user can be re-configure its size using @ref Sn_TXBUF_SIZE. The total sum of @ref Sn_TXBUF_SIZE can not be exceed 16Kbytes. + * When exceeded, the data transmission error is occurred. + */ +#define Sn_TXBUF_SIZE(N) (_W5500_IO_BASE_ + (0x001F << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +/** + * @ingroup Socket_register_group + * @brief Transmit free memory size register(R) + * @details @ref Sn_TX_FSR indicates the free size of Socket n TX Buffer Block. It is initialized to the configured size by @ref Sn_TXBUF_SIZE. + * Data bigger than @ref Sn_TX_FSR should not be saved in the Socket n TX Buffer because the bigger data overwrites the previous saved data not yet sent. + * Therefore, check before saving the data to the Socket n TX Buffer, and if data is equal or smaller than its checked size, + * transmit the data with SEND/SEND_MAC command after saving the data in Socket n TX buffer. But, if data is bigger than its checked size, + * transmit the data after dividing into the checked size and saving in the Socket n TX buffer. + */ +#define Sn_TX_FSR(N) (_W5500_IO_BASE_ + (0x0020 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +/** + * @ingroup Socket_register_group + * @brief Transmit memory read pointer register address(R) + * @details @ref Sn_TX_RD is initialized by OPEN command. However, if Sn_MR(P[3:0]) is TCP mode(001, it is re-initialized while connecting with TCP. + * After its initialization, it is auto-increased by SEND command. + * SEND command transmits the saved data from the current @ref Sn_TX_RD to the @ref Sn_TX_WR in the Socket n TX Buffer. + * After transmitting the saved data, the SEND command increases the @ref Sn_TX_RD as same as the @ref Sn_TX_WR. + * If its increment value exceeds the maximum value 0xFFFF, (greater than 0x10000 and the carry bit occurs), + * then the carry bit is ignored and will automatically update with the lower 16bits value. + */ +#define Sn_TX_RD(N) (_W5500_IO_BASE_ + (0x0022 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +/** + * @ingroup Socket_register_group + * @brief Transmit memory write pointer register address(R/W) + * @details @ref Sn_TX_WR is initialized by OPEN command. However, if Sn_MR(P[3:0]) is TCP mode(001, it is re-initialized while connecting with TCP.\n + * It should be read or be updated like as follows.\n + * 1. Read the starting address for saving the transmitting data.\n + * 2. Save the transmitting data from the starting address of Socket n TX buffer.\n + * 3. After saving the transmitting data, update @ref Sn_TX_WR to the increased value as many as transmitting data size. + * If the increment value exceeds the maximum value 0xFFFF(greater than 0x10000 and the carry bit occurs), + * then the carry bit is ignored and will automatically update with the lower 16bits value.\n + * 4. Transmit the saved data in Socket n TX Buffer by using SEND/SEND command + */ +#define Sn_TX_WR(N) (_W5500_IO_BASE_ + (0x0024 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +/** + * @ingroup Socket_register_group + * @brief Received data size register(R) + * @details @ref Sn_RX_RSR indicates the data size received and saved in Socket n RX Buffer. + * @ref Sn_RX_RSR does not exceed the @ref Sn_RXBUF_SIZE and is calculated as the difference between + * �Socket n RX Write Pointer (@ref Sn_RX_WR)and �Socket n RX Read Pointer (@ref Sn_RX_RD) + */ +#define Sn_RX_RSR(N) (_W5500_IO_BASE_ + (0x0026 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +/** + * @ingroup Socket_register_group + * @brief Read point of Receive memory(R/W) + * @details @ref Sn_RX_RD is initialized by OPEN command. Make sure to be read or updated as follows.\n + * 1. Read the starting save address of the received data.\n + * 2. Read data from the starting address of Socket n RX Buffer.\n + * 3. After reading the received data, Update @ref Sn_RX_RD to the increased value as many as the reading size. + * If the increment value exceeds the maximum value 0xFFFF, that is, is greater than 0x10000 and the carry bit occurs, + * update with the lower 16bits value ignored the carry bit.\n + * 4. Order RECV command is for notifying the updated @ref Sn_RX_RD to W5500. + */ +#define Sn_RX_RD(N) (_W5500_IO_BASE_ + (0x0028 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +/** + * @ingroup Socket_register_group + * @brief Write point of Receive memory(R) + * @details @ref Sn_RX_WR is initialized by OPEN command and it is auto-increased by the data reception. + * If the increased value exceeds the maximum value 0xFFFF, (greater than 0x10000 and the carry bit occurs), + * then the carry bit is ignored and will automatically update with the lower 16bits value. + */ +#define Sn_RX_WR(N) (_W5500_IO_BASE_ + (0x002A << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +/** + * @ingroup Socket_register_group + * @brief socket interrupt mask register(R) + * @details @ref Sn_IMR masks the interrupt of Socket n. + * Each bit corresponds to each bit of @ref Sn_IR. When a Socket n Interrupt is occurred and the corresponding bit of @ref Sn_IMR is + * the corresponding bit of @ref Sn_IR becomes When both the corresponding bit of @ref Sn_IMR and @ref Sn_IR are and the n-th bit of @ref IR is + * Host is interrupted by asserted INTn PIN to low. + */ +#define Sn_IMR(N) (_W5500_IO_BASE_ + (0x002C << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +/** + * @ingroup Socket_register_group + * @brief Fragment field value in IP header register(R/W) + * @details @ref Sn_FRAG configures the FRAG(Fragment field in IP header). + */ +#define Sn_FRAG(N) (_W5500_IO_BASE_ + (0x002D << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +/** + * @ingroup Socket_register_group + * @brief Keep Alive Timer register(R/W) + * @details @ref Sn_KPALVTR configures the transmitting timer of �KEEP ALIVE(KA)packet of SOCKETn. It is valid only in TCP mode, + * and ignored in other modes. The time unit is 5s. + * KA packet is transmittable after @ref Sn_SR is changed to SOCK_ESTABLISHED and after the data is transmitted or received to/from a peer at least once. + * In case of '@ref Sn_KPALVTR > 0', W5500 automatically transmits KA packet after time-period for checking the TCP connection (Auto-keepalive-process). + * In case of '@ref Sn_KPALVTR = 0', Auto-keep-alive-process will not operate, + * and KA packet can be transmitted by SEND_KEEP command by the host (Manual-keep-alive-process). + * Manual-keep-alive-process is ignored in case of '@ref Sn_KPALVTR > 0'. + */ +#define Sn_KPALVTR(N) (_W5500_IO_BASE_ + (0x002F << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + +//#define Sn_TSR(N) (_W5500_IO_BASE_ + (0x0030 << 8) + (WIZCHIP_SREG_BLOCK(N) << 3)) + + +//----------------------------- W5500 Register values ----------------------------- + +/* MODE register values */ +/** + * @brief Reset + * @details If this bit is All internal registers will be initialized. It will be automatically cleared as after S/W reset. + */ +#define MR_RST 0x80 + +/** + * @brief Wake on LAN + * @details 0 : Disable WOL mode\n + * 1 : Enable WOL mode\n + * If WOL mode is enabled and the received magic packet over UDP has been normally processed, the Interrupt PIN (INTn) asserts to low. + * When using WOL mode, the UDP Socket should be opened with any source port number. (Refer to Socket n Mode Register (@ref Sn_MR) for opening Socket.) + * @note The magic packet over UDP supported by W5500 consists of 6 bytes synchronization stream (xFFFFFFFFFFFF and + * 16 times Target MAC address stream in UDP payload. The options such like password are ignored. You can use any UDP source port number for WOL mode. + */ +#define MR_WOL 0x20 + +/** + * @brief Ping block + * @details 0 : Disable Ping block\n + * 1 : Enable Ping block\n + * If the bit is it blocks the response to a ping request. + */ +#define MR_PB 0x10 + +/** + * @brief Enable PPPoE + * @details 0 : DisablePPPoE mode\n + * 1 : EnablePPPoE mode\n + * If you use ADSL, this bit should be + */ +#define MR_PPPOE 0x08 + +/** + * @brief Enable UDP_FORCE_ARP CHECHK + * @details 0 : Disable Force ARP mode\n + * 1 : Enable Force ARP mode\n + * In Force ARP mode, It forces on sending ARP Request whenever data is sent. + */ +#define MR_FARP 0x02 + +/* IR register values */ +/** + * @brief Check IP conflict. + * @details Bit is set as when own source IP address is same with the sender IP address in the received ARP request. + */ +#define IR_CONFLICT 0x80 + +/** + * @brief Get the destination unreachable message in UDP sending. + * @details When receiving the ICMP (Destination port unreachable) packet, this bit is set as + * When this bit is Destination Information such as IP address and Port number may be checked with the corresponding @ref UIPR & @ref UPORTR. + */ +#define IR_UNREACH 0x40 + +/** + * @brief Get the PPPoE close message. + * @details When PPPoE is disconnected during PPPoE mode, this bit is set. + */ +#define IR_PPPoE 0x20 + +/** + * @brief Get the magic packet interrupt. + * @details When WOL mode is enabled and receives the magic packet over UDP, this bit is set. + */ +#define IR_MP 0x10 + + +/* PHYCFGR register value */ +#define PHYCFGR_RST ~(1<<7) //< For PHY reset, must operate AND mask. +#define PHYCFGR_OPMD (1<<6) // Configre PHY with OPMDC value +#define PHYCFGR_OPMDC_ALLA (7<<3) +#define PHYCFGR_OPMDC_PDOWN (6<<3) +#define PHYCFGR_OPMDC_NA (5<<3) +#define PHYCFGR_OPMDC_100FA (4<<3) +#define PHYCFGR_OPMDC_100F (3<<3) +#define PHYCFGR_OPMDC_100H (2<<3) +#define PHYCFGR_OPMDC_10F (1<<3) +#define PHYCFGR_OPMDC_10H (0<<3) +#define PHYCFGR_DPX_FULL (1<<2) +#define PHYCFGR_DPX_HALF (0<<2) +#define PHYCFGR_SPD_100 (1<<1) +#define PHYCFGR_SPD_10 (0<<1) +#define PHYCFGR_LNK_ON (1<<0) +#define PHYCFGR_LNK_OFF (0<<0) + +/* IMR register values */ +/** + * @brief IP Conflict Interrupt Mask. + * @details 0: Disable IP Conflict Interrupt\n + * 1: Enable IP Conflict Interrupt + */ +#define IM_IR7 0x80 + +/** + * @brief Destination unreachable Interrupt Mask. + * @details 0: Disable Destination unreachable Interrupt\n + * 1: Enable Destination unreachable Interrupt + */ +#define IM_IR6 0x40 + +/** + * @brief PPPoE Close Interrupt Mask. + * @details 0: Disable PPPoE Close Interrupt\n + * 1: Enable PPPoE Close Interrupt + */ +#define IM_IR5 0x20 + +/** + * @brief Magic Packet Interrupt Mask. + * @details 0: Disable Magic Packet Interrupt\n + * 1: Enable Magic Packet Interrupt + */ +#define IM_IR4 0x10 + +/* Sn_MR Default values */ +/** + * @brief Support UDP Multicasting + * @details 0 : disable Multicasting\n + * 1 : enable Multicasting\n + * This bit is applied only during UDP mode(P[3:0] = 010.\n + * To use multicasting, @ref Sn_DIPR & @ref Sn_DPORT should be respectively configured with the multicast group IP address & port number + * before Socket n is opened by OPEN command of @ref Sn_CR. + */ +#define Sn_MR_MULTI 0x80 + +/** + * @brief Broadcast block in UDP Multicasting. + * @details 0 : disable Broadcast Blocking\n + * 1 : enable Broadcast Blocking\n + * This bit blocks to receive broadcasting packet during UDP mode(P[3:0] = 010.\m + * In addition, This bit does when MACRAW mode(P[3:0] = 100 + */ +#define Sn_MR_BCASTB 0x40 + +/** + * @brief No Delayed Ack(TCP), Multicast flag + * @details 0 : Disable No Delayed ACK option\n + * 1 : Enable No Delayed ACK option\n + * This bit is applied only during TCP mode (P[3:0] = 001.\n + * When this bit is It sends the ACK packet without delay as soon as a Data packet is received from a peer.\n + * When this bit is It sends the ACK packet after waiting for the timeout time configured by @ref RTR. + */ +#define Sn_MR_ND 0x20 + +/** + * @brief Unicast Block in UDP Multicasting + * @details 0 : disable Unicast Blocking\n + * 1 : enable Unicast Blocking\n + * This bit blocks receiving the unicast packet during UDP mode(P[3:0] = 010 and MULTI = + */ +#define Sn_MR_UCASTB 0x10 + +/** + * @brief MAC LAYER RAW SOCK + * @details This configures the protocol mode of Socket n. + * @note MACRAW mode should be only used in Socket 0. + */ +#define Sn_MR_MACRAW 0x04 + +//#define Sn_MR_IPRAW 0x03 /**< IP LAYER RAW SOCK */ + +/** + * @brief UDP + * @details This configures the protocol mode of Socket n. + */ +#define Sn_MR_UDP 0x02 + +/** + * @brief TCP + * @details This configures the protocol mode of Socket n. + */ +#define Sn_MR_TCP 0x01 + +/** + * @brief Unused socket + * @details This configures the protocol mode of Socket n. + */ +#define Sn_MR_CLOSE 0x00 + +/* Sn_MR values used with Sn_MR_MACRAW */ +/** + * @brief MAC filter enable in @ref Sn_MR_MACRAW mode + * @details 0 : disable MAC Filtering\n + * 1 : enable MAC Filtering\n + * This bit is applied only during MACRAW mode(P[3:0] = 100.\n + * When set as W5500 can only receive broadcasting packet or packet sent to itself. + * When this bit is W5500 can receive all packets on Ethernet. + * If user wants to implement Hybrid TCP/IP stack, + * it is recommended that this bit is set as for reducing host overhead to process the all received packets. + */ +#define Sn_MR_MFEN Sn_MR_MULTI + +/** + * @brief Multicast Blocking in @ref Sn_MR_MACRAW mode + * @details 0 : using IGMP version 2\n + * 1 : using IGMP version 1\n + * This bit is applied only during UDP mode(P[3:0] = 010 and MULTI = + * It configures the version for IGMP messages (Join/Leave/Report). + */ +#define Sn_MR_MMB Sn_MR_ND + +/** + * @brief IPv6 packet Blocking in @ref Sn_MR_MACRAW mode + * @details 0 : disable IPv6 Blocking\n + * 1 : enable IPv6 Blocking\n + * This bit is applied only during MACRAW mode (P[3:0] = 100. It blocks to receiving the IPv6 packet. + */ +#define Sn_MR_MIP6B Sn_MR_UCASTB + +/* Sn_MR value used with Sn_MR_UDP & Sn_MR_MULTI */ +/** + * @brief IGMP version used in UDP mulitcasting + * @details 0 : disable Multicast Blocking\n + * 1 : enable Multicast Blocking\n + * This bit is applied only when MACRAW mode(P[3:0] = 100. It blocks to receive the packet with multicast MAC address. + */ +#define Sn_MR_MC Sn_MR_ND + +/* Sn_MR alternate values */ +/** + * @brief For Berkeley Socket API + */ +#define SOCK_STREAM Sn_MR_TCP + +/** + * @brief For Berkeley Socket API + */ +#define SOCK_DGRAM Sn_MR_UDP + + +/* Sn_CR values */ +/** + * @brief Initialize or open socket + * @details Socket n is initialized and opened according to the protocol selected in Sn_MR(P3:P0). + * The table below shows the value of @ref Sn_SR corresponding to @ref Sn_MR.\n + * <table> + * <tr> <td>\b Sn_MR (P[3:0])</td> <td>\b Sn_SR</td> </tr> + * <tr> <td>Sn_MR_CLOSE (000</td> <td></td> </tr> + * <tr> <td>Sn_MR_TCP (001</td> <td>SOCK_INIT (0x13)</td> </tr> + * <tr> <td>Sn_MR_UDP (010</td> <td>SOCK_UDP (0x22)</td> </tr> + * <tr> <td>S0_MR_MACRAW (100</td> <td>SOCK_MACRAW (0x02)</td> </tr> + * </table> + */ +#define Sn_CR_OPEN 0x01 + +/** + * @brief Wait connection request in TCP mode(Server mode) + * @details This is valid only in TCP mode (Sn_MR(P3:P0) = Sn_MR_TCP). + * In this mode, Socket n operates as a �TCP serverand waits for connection-request (SYN packet) from any �TCP client + * The @ref Sn_SR changes the state from SOCK_INIT to SOCKET_LISTEN. + * When a �TCP clientconnection request is successfully established, + * the @ref Sn_SR changes from SOCK_LISTEN to SOCK_ESTABLISHED and the Sn_IR(0) becomes + * But when a �TCP clientconnection request is failed, Sn_IR(3) becomes and the status of @ref Sn_SR changes to SOCK_CLOSED. + */ +#define Sn_CR_LISTEN 0x02 + +/** + * @brief Send connection request in TCP mode(Client mode) + * @details To connect, a connect-request (SYN packet) is sent to b>TCP server</b>configured by @ref Sn_DIPR & Sn_DPORT(destination address & port). + * If the connect-request is successful, the @ref Sn_SR is changed to @ref SOCK_ESTABLISHED and the Sn_IR(0) becomes \n\n + * The connect-request fails in the following three cases.\n + * 1. When a @b ARPTO occurs (@ref Sn_IR[3] = ) because destination hardware address is not acquired through the ARP-process.\n + * 2. When a @b SYN/ACK packet is not received and @b TCPTO (Sn_IR(3) = )\n + * 3. When a @b RST packet is received instead of a @b SYN/ACK packet. In these cases, @ref Sn_SR is changed to @ref SOCK_CLOSED. + * @note This is valid only in TCP mode and operates when Socket n acts as b>TCP client</b> + */ +#define Sn_CR_CONNECT 0x04 + +/** + * @brief Send closing request in TCP mode + * @details Regardless of b>TCP server</b>or b>TCP client</b> the DISCON command processes the disconnect-process (b>Active close</b>or b>Passive close</b>.\n + * @par Active close + * it transmits disconnect-request(FIN packet) to the connected peer\n + * @par Passive close + * When FIN packet is received from peer, a FIN packet is replied back to the peer.\n + * @details When the disconnect-process is successful (that is, FIN/ACK packet is received successfully), @ref Sn_SR is changed to @ref SOCK_CLOSED.\n + * Otherwise, TCPTO occurs (Sn_IR(3)=)= and then @ref Sn_SR is changed to @ref SOCK_CLOSED. + * @note Valid only in TCP mode. + */ +#define Sn_CR_DISCON 0x08 + +/** + * @brief Close socket + * @details Sn_SR is changed to @ref SOCK_CLOSED. + */ +#define Sn_CR_CLOSE 0x10 + +/** + * @brief Update TX buffer pointer and send data + * @details SEND transmits all the data in the Socket n TX buffer.\n + * For more details, please refer to Socket n TX Free Size Register (@ref Sn_TX_FSR), Socket n, + * TX Write Pointer Register(@ref Sn_TX_WR), and Socket n TX Read Pointer Register(@ref Sn_TX_RD). + */ +#define Sn_CR_SEND 0x20 + +/** + * @brief Send data with MAC address, so without ARP process + * @details The basic operation is same as SEND.\n + * Normally SEND transmits data after destination hardware address is acquired by the automatic ARP-process(Address Resolution Protocol).\n + * But SEND_MAC transmits data without the automatic ARP-process.\n + * In this case, the destination hardware address is acquired from @ref Sn_DHAR configured by host, instead of APR-process. + * @note Valid only in UDP mode. + */ +#define Sn_CR_SEND_MAC 0x21 + +/** + * @brief Send keep alive message + * @details It checks the connection status by sending 1byte keep-alive packet.\n + * If the peer can not respond to the keep-alive packet during timeout time, the connection is terminated and the timeout interrupt will occur. + * @note Valid only in TCP mode. + */ +#define Sn_CR_SEND_KEEP 0x22 + +/** + * @brief Update RX buffer pointer and receive data + * @details RECV completes the processing of the received data in Socket n RX Buffer by using a RX read pointer register (@ref Sn_RX_RD).\n + * For more details, refer to Socket n RX Received Size Register (@ref Sn_RX_RSR), Socket n RX Write Pointer Register (@ref Sn_RX_WR), + * and Socket n RX Read Pointer Register (@ref Sn_RX_RD). + */ +#define Sn_CR_RECV 0x40 + +/* Sn_IR values */ +/** + * @brief SEND_OK Interrupt + * @details This is issued when SEND command is completed. + */ +#define Sn_IR_SENDOK 0x10 + +/** + * @brief TIMEOUT Interrupt + * @details This is issued when ARPTO or TCPTO occurs. + */ +#define Sn_IR_TIMEOUT 0x08 + +/** + * @brief RECV Interrupt + * @details This is issued whenever data is received from a peer. + */ +#define Sn_IR_RECV 0x04 + +/** + * @brief DISCON Interrupt + * @details This is issued when FIN or FIN/ACK packet is received from a peer. + */ +#define Sn_IR_DISCON 0x02 + +/** + * @brief CON Interrupt + * @details This is issued one time when the connection with peer is successful and then @ref Sn_SR is changed to @ref SOCK_ESTABLISHED. + */ +#define Sn_IR_CON 0x01 + +/* Sn_SR values */ +/** + * @brief Closed + * @details This indicates that Socket n is released.\N + * When DICON, CLOSE command is ordered, or when a timeout occurs, it is changed to @ref SOCK_CLOSED regardless of previous status. + */ +#define SOCK_CLOSED 0x00 + +/** + * @brief Initiate state + * @details This indicates Socket n is opened with TCP mode.\N + * It is changed to @ref SOCK_INIT when Sn_MR(P[3:0]) = 001and OPEN command is ordered.\N + * After @ref SOCK_INIT, user can use LISTEN /CONNECT command. + */ +#define SOCK_INIT 0x13 + +/** + * @brief Listen state + * @details This indicates Socket n is operating as b>TCP server</b>mode and waiting for connection-request (SYN packet) from a peer (b>TCP client</b>.\n + * It will change to @ref SOCK_ESTALBLISHED when the connection-request is successfully accepted.\n + * Otherwise it will change to @ref SOCK_CLOSED after TCPTO occurred (Sn_IR(TIMEOUT) = . + */ +#define SOCK_LISTEN 0x14 + +/** + * @brief Connection state + * @details This indicates Socket n sent the connect-request packet (SYN packet) to a peer.\n + * It is temporarily shown when @ref Sn_SR is changed from @ref SOCK_INIT to @ref SOCK_ESTABLISHED by CONNECT command.\n + * If connect-accept(SYN/ACK packet) is received from the peer at SOCK_SYNSENT, it changes to @ref SOCK_ESTABLISHED.\n + * Otherwise, it changes to @ref SOCK_CLOSED after TCPTO (@ref Sn_IR[TIMEOUT] = is occurred. + */ +#define SOCK_SYNSENT 0x15 + +/** + * @brief Connection state + * @details It indicates Socket n successfully received the connect-request packet (SYN packet) from a peer.\n + * If socket n sends the response (SYN/ACK packet) to the peer successfully, it changes to @ref SOCK_ESTABLISHED. \n + * If not, it changes to @ref SOCK_CLOSED after timeout occurs (@ref Sn_IR[TIMEOUT] = . + */ +#define SOCK_SYNRECV 0x16 + +/** + * @brief Success to connect + * @details This indicates the status of the connection of Socket n.\n + * It changes to @ref SOCK_ESTABLISHED when the b>TCP SERVER</b>processed the SYN packet from the b>TCP CLIENT</b>during @ref SOCK_LISTEN, or + * when the CONNECT command is successful.\n + * During @ref SOCK_ESTABLISHED, DATA packet can be transferred using SEND or RECV command. + */ +#define SOCK_ESTABLISHED 0x17 + +/** + * @brief Closing state + * @details These indicate Socket n is closing.\n + * These are shown in disconnect-process such as active-close and passive-close.\n + * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED. + */ +#define SOCK_FIN_WAIT 0x18 + +/** + * @brief Closing state + * @details These indicate Socket n is closing.\n + * These are shown in disconnect-process such as active-close and passive-close.\n + * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED. + */ +#define SOCK_CLOSING 0x1A + +/** + * @brief Closing state + * @details These indicate Socket n is closing.\n + * These are shown in disconnect-process such as active-close and passive-close.\n + * When Disconnect-process is successfully completed, or when timeout occurs, these change to @ref SOCK_CLOSED. + */ +#define SOCK_TIME_WAIT 0x1B + +/** + * @brief Closing state + * @details This indicates Socket n received the disconnect-request (FIN packet) from the connected peer.\n + * This is half-closing status, and data can be transferred.\n + * For full-closing, DISCON command is used. But For just-closing, CLOSE command is used. + */ +#define SOCK_CLOSE_WAIT 0x1C + +/** + * @brief Closing state + * @details This indicates Socket n is waiting for the response (FIN/ACK packet) to the disconnect-request (FIN packet) by passive-close.\n + * It changes to @ref SOCK_CLOSED when Socket n received the response successfully, or when timeout occurs (@ref Sn_IR[TIMEOUT] = . + */ +#define SOCK_LAST_ACK 0x1D + +/** + * @brief UDP socket + * @details This indicates Socket n is opened in UDP mode(Sn_MR(P[3:0]) = 010.\n + * It changes to SOCK_UPD when Sn_MR(P[3:0]) = 010 and OPEN command is ordered.\n + * Unlike TCP mode, data can be transfered without the connection-process. + */ +#define SOCK_UDP 0x22 + +//#define SOCK_IPRAW 0x32 /**< IP raw mode socket */ + +/** + * @brief MAC raw mode socket + * @details This indicates Socket 0 is opened in MACRAW mode (S0_MR(P[3:0]) = 100and is valid only in Socket 0.\n + * It changes to SOCK_MACRAW when S0_MR(P[3:0] = 100and OPEN command is ordered.\n + * Like UDP mode socket, MACRAW mode Socket 0 can transfer a MAC packet (Ethernet frame) without the connection-process. + */ +#define SOCK_MACRAW 0x42 + +//#define SOCK_PPPOE 0x5F + +/* IP PROTOCOL */ +#define IPPROTO_IP 0 //< Dummy for IP +#define IPPROTO_ICMP 1 //< Control message protocol +#define IPPROTO_IGMP 2 //< Internet group management protocol +#define IPPROTO_GGP 3 //< Gateway^2 (deprecated) +#define IPPROTO_TCP 6 //< TCP +#define IPPROTO_PUP 12 //< PUP +#define IPPROTO_UDP 17 //< UDP +#define IPPROTO_IDP 22 //< XNS idp +#define IPPROTO_ND 77 //< UNOFFICIAL net disk protocol +#define IPPROTO_RAW 255 //< Raw IP packet + + +/** + * @brief Enter a critical section + * + * @details It is provided to protect your shared code which are executed without distribution. \n \n + * + * In non-OS environment, It can be just implemented by disabling whole interrupt.\n + * In OS environment, You can replace it to critical section api supported by OS. + * + * \sa WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() + * \sa WIZCHIP_CRITICAL_EXIT() + */ +#define WIZCHIP_CRITICAL_ENTER() WIZCHIP.CRIS._enter() + +/** + * @brief Exit a critical section + * + * @details It is provided to protect your shared code which are executed without distribution. \n\n + * + * In non-OS environment, It can be just implemented by disabling whole interrupt. \n + * In OS environment, You can replace it to critical section api supported by OS. + * + * @sa WIZCHIP_READ(), WIZCHIP_WRITE(), WIZCHIP_READ_BUF(), WIZCHIP_WRITE_BUF() + * @sa WIZCHIP_CRITICAL_ENTER() + */ +#ifdef _exit +#undef _exit +#endif +#define WIZCHIP_CRITICAL_EXIT() WIZCHIP.CRIS._exit() + + + +//////////////////////// +// Basic I/O Function // +//////////////////////// + +/** + * @ingroup Basic_IO_function + * @brief It reads 1 byte value from a register. + * @param AddrSel Register address + * @return The value of register + */ +uint8_t WIZCHIP_READ (uint32_t AddrSel); + +/** + * @ingroup Basic_IO_function + * @brief It writes 1 byte value to a register. + * @param AddrSel Register address + * @param wb Write data + * @return void + */ +void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t wb ); + +/** + * @ingroup Basic_IO_function + * @brief It reads sequence data from registers. + * @param AddrSel Register address + * @param pBuf Pointer buffer to read data + * @param len Data length + */ +void WIZCHIP_READ_BUF (uint32_t AddrSel, uint8_t* pBuf, uint16_t len); + +/** + * @ingroup Basic_IO_function + * @brief It writes sequence data to registers. + * @param AddrSel Register address + * @param pBuf Pointer buffer to write data + * @param len Data length + */ +void WIZCHIP_WRITE_BUF(uint32_t AddrSel, uint8_t* pBuf, uint16_t len); + +///////////////////////////////// +// Common Register I/O function // +///////////////////////////////// +/** + * @ingroup Common_register_access_function + * @brief Set Mode Register + * @param (uint8_t)mr The value to be set. + * @sa getMR() + */ +#define setMR(mr) \ + WIZCHIP_WRITE(MR,mr) + + +/** + * @ingroup Common_register_access_function + * @brief Get Mode Register + * @return uint8_t. The value of Mode register. + * @sa setMR() + */ +#define getMR() \ + WIZCHIP_READ(MR) + +/** + * @ingroup Common_register_access_function + * @brief Set gateway IP address + * @param (uint8_t*)gar Pointer variable to set gateway IP address. It should be allocated 4 bytes. + * @sa getGAR() + */ +#define setGAR(gar) \ + WIZCHIP_WRITE_BUF(GAR,gar,4) + +/** + * @ingroup Common_register_access_function + * @brief Get gateway IP address + * @param (uint8_t*)gar Pointer variable to get gateway IP address. It should be allocated 4 bytes. + * @sa setGAR() + */ +#define getGAR(gar) \ + WIZCHIP_READ_BUF(GAR,gar,4) + +/** + * @ingroup Common_register_access_function + * @brief Set subnet mask address + * @param (uint8_t*)subr Pointer variable to set subnet mask address. It should be allocated 4 bytes. + * @sa getSUBR() + */ +#define setSUBR(subr) \ + WIZCHIP_WRITE_BUF(SUBR, subr,4) + + +/** + * @ingroup Common_register_access_function + * @brief Get subnet mask address + * @param (uint8_t*)subr Pointer variable to get subnet mask address. It should be allocated 4 bytes. + * @sa setSUBR() + */ +#define getSUBR(subr) \ + WIZCHIP_READ_BUF(SUBR, subr, 4) + +/** + * @ingroup Common_register_access_function + * @brief Set local MAC address + * @param (uint8_t*)shar Pointer variable to set local MAC address. It should be allocated 6 bytes. + * @sa getSHAR() + */ +#define setSHAR(shar) \ + WIZCHIP_WRITE_BUF(SHAR, shar, 6) + +/** + * @ingroup Common_register_access_function + * @brief Get local MAC address + * @param (uint8_t*)shar Pointer variable to get local MAC address. It should be allocated 6 bytes. + * @sa setSHAR() + */ +#define getSHAR(shar) \ + WIZCHIP_READ_BUF(SHAR, shar, 6) + +/** + * @ingroup Common_register_access_function + * @brief Set local IP address + * @param (uint8_t*)sipr Pointer variable to set local IP address. It should be allocated 4 bytes. + * @sa getSIPR() + */ +#define setSIPR(sipr) \ + WIZCHIP_WRITE_BUF(SIPR, sipr, 4) + +/** + * @ingroup Common_register_access_function + * @brief Get local IP address + * @param (uint8_t*)sipr Pointer variable to get local IP address. It should be allocated 4 bytes. + * @sa setSIPR() + */ +#define getSIPR(sipr) \ + WIZCHIP_READ_BUF(SIPR, sipr, 4) + +/** + * @ingroup Common_register_access_function + * @brief Set INTLEVEL register + * @param (uint16_t)intlevel Value to set @ref INTLEVEL register. + * @sa getINTLEVEL() + */ +#define setINTLEVEL(intlevel) {\ + WIZCHIP_WRITE(INTLEVEL, (uint8_t)(intlevel >> 8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(INTLEVEL,1), (uint8_t) intlevel); \ + } + + +/** + * @ingroup Common_register_access_function + * @brief Get INTLEVEL register + * @return uint16_t. Value of @ref INTLEVEL register. + * @sa setINTLEVEL() + */ +#define getINTLEVEL() \ + ((WIZCHIP_READ(INTLEVEL) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(INTLEVEL,1))) + +/** + * @ingroup Common_register_access_function + * @brief Set @ref IR register + * @param (uint8_t)ir Value to set @ref IR register. + * @sa getIR() + */ +#define setIR(ir) \ + WIZCHIP_WRITE(IR, (ir & 0xF0)) + +/** + * @ingroup Common_register_access_function + * @brief Get @ref IR register + * @return uint8_t. Value of @ref IR register. + * @sa setIR() + */ +#define getIR() \ + (WIZCHIP_READ(IR) & 0xF0) +/** + * @ingroup Common_register_access_function + * @brief Set @ref IMR register + * @param (uint8_t)imr Value to set @ref IMR register. + * @sa getIMR() + */ +#define setIMR(imr) \ + WIZCHIP_WRITE(IMR, imr) + +/** + * @ingroup Common_register_access_function + * @brief Get @ref IMR register + * @return uint8_t. Value of @ref IMR register. + * @sa setIMR() + */ +#define getIMR() \ + WIZCHIP_READ(IMR) + + +/** + * @ingroup Common_register_access_function + * @brief Set @ref SIR register + * @param (uint8_t)sir Value to set @ref SIR register. + * @sa getSIR() + */ +#define setSIR(sir) \ + WIZCHIP_WRITE(SIR, sir) + +/** + * @ingroup Common_register_access_function + * @brief Get @ref SIR register + * @return uint8_t. Value of @ref SIR register. + * @sa setSIR() + */ +#define getSIR() \ + WIZCHIP_READ(SIR) +/** + * @ingroup Common_register_access_function + * @brief Set @ref SIMR register + * @param (uint8_t)simr Value to set @ref SIMR register. + * @sa getSIMR() + */ +#define setSIMR(simr) \ + WIZCHIP_WRITE(SIMR, simr) + +/** + * @ingroup Common_register_access_function + * @brief Get @ref SIMR register + * @return uint8_t. Value of @ref SIMR register. + * @sa setSIMR() + */ +#define getSIMR() \ + WIZCHIP_READ(SIMR) + +/** + * @ingroup Common_register_access_function + * @brief Set @ref RTR register + * @param (uint16_t)rtr Value to set @ref RTR register. + * @sa getRTR() + */ +#define setRTR(rtr) {\ + WIZCHIP_WRITE(RTR, (uint8_t)(rtr >> 8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(RTR,1), (uint8_t) rtr); \ + } + +/** + * @ingroup Common_register_access_function + * @brief Get @ref RTR register + * @return uint16_t. Value of @ref RTR register. + * @sa setRTR() + */ +#define getRTR() \ + ((WIZCHIP_READ(RTR) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(RTR,1))) + +/** + * @ingroup Common_register_access_function + * @brief Set @ref RCR register + * @param (uint8_t)rcr Value to set @ref RCR register. + * @sa getRCR() + */ +#define setRCR(rcr) \ + WIZCHIP_WRITE(RCR, rcr) + +/** + * @ingroup Common_register_access_function + * @brief Get @ref RCR register + * @return uint8_t. Value of @ref RCR register. + * @sa setRCR() + */ +#define getRCR() \ + WIZCHIP_READ(RCR) + +//================================================== test done =========================================================== + +/** + * @ingroup Common_register_access_function + * @brief Set @ref PTIMER register + * @param (uint8_t)ptimer Value to set @ref PTIMER register. + * @sa getPTIMER() + */ +#define setPTIMER(ptimer) \ + WIZCHIP_WRITE(PTIMER, ptimer) + +/** + * @ingroup Common_register_access_function + * @brief Get @ref PTIMER register + * @return uint8_t. Value of @ref PTIMER register. + * @sa setPTIMER() + */ +#define getPTIMER() \ + WIZCHIP_READ(PTIMER) + +/** + * @ingroup Common_register_access_function + * @brief Set @ref PMAGIC register + * @param (uint8_t)pmagic Value to set @ref PMAGIC register. + * @sa getPMAGIC() + */ +#define setPMAGIC(pmagic) \ + WIZCHIP_WRITE(PMAGIC, pmagic) + +/** + * @ingroup Common_register_access_function + * @brief Get @ref PMAGIC register + * @return uint8_t. Value of @ref PMAGIC register. + * @sa setPMAGIC() + */ +#define getPMAGIC() \ + WIZCHIP_READ(PMAGIC) + +/** + * @ingroup Common_register_access_function + * @brief Set PHAR address + * @param (uint8_t*)phar Pointer variable to set PPP destination MAC register address. It should be allocated 6 bytes. + * @sa getPHAR() + */ +#define setPHAR(phar) \ + WIZCHIP_WRITE_BUF(PHAR, phar, 6) + +/** + * @ingroup Common_register_access_function + * @brief Get local IP address + * @param (uint8_t*)phar Pointer variable to PPP destination MAC register address. It should be allocated 6 bytes. + * @sa setPHAR() + */ +#define getPHAR(phar) \ + WIZCHIP_READ_BUF(PHAR, phar, 6) + +/** + * @ingroup Common_register_access_function + * @brief Set @ref PSID register + * @param (uint16_t)psid Value to set @ref PSID register. + * @sa getPSID() + */ +#define setPSID(psid) {\ + WIZCHIP_WRITE(PSID, (uint8_t)(psid >> 8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(PSID,1), (uint8_t) psid); \ + } + +/** + * @ingroup Common_register_access_function + * @brief Get @ref PSID register + * @return uint16_t. Value of @ref PSID register. + * @sa setPSID() + */ +//uint16_t getPSID(void); +#define getPSID() \ + ((WIZCHIP_READ(PSID) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(PSID,1))) + +/** + * @ingroup Common_register_access_function + * @brief Set @ref PMRU register + * @param (uint16_t)pmru Value to set @ref PMRU register. + * @sa getPMRU() + */ +#define setPMRU(pmru) { \ + WIZCHIP_WRITE(PMRU, (uint8_t)(pmru>>8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(PMRU,1), (uint8_t) pmru); \ + } + +/** + * @ingroup Common_register_access_function + * @brief Get @ref PMRU register + * @return uint16_t. Value of @ref PMRU register. + * @sa setPMRU() + */ +#define getPMRU() \ + ((WIZCHIP_READ(PMRU) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(PMRU,1))) + +/** + * @ingroup Common_register_access_function + * @brief Get unreachable IP address + * @param (uint8_t*)uipr Pointer variable to get unreachable IP address. It should be allocated 4 bytes. + */ +#define getUIPR(uipr) \ + WIZCHIP_READ_BUF(UIPR,uipr,6) + +/** + * @ingroup Common_register_access_function + * @brief Get @ref UPORTR register + * @return uint16_t. Value of @ref UPORTR register. + */ +#define getUPORTR() \ + ((WIZCHIP_READ(UPORTR) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(UPORTR,1))) + +/** + * @ingroup Common_register_access_function + * @brief Set @ref PHYCFGR register + * @param (uint8_t)phycfgr Value to set @ref PHYCFGR register. + * @sa getPHYCFGR() + */ +#define setPHYCFGR(phycfgr) \ + WIZCHIP_WRITE(PHYCFGR, phycfgr) + +/** + * @ingroup Common_register_access_function + * @brief Get @ref PHYCFGR register + * @return uint8_t. Value of @ref PHYCFGR register. + * @sa setPHYCFGR() + */ +#define getPHYCFGR() \ + WIZCHIP_READ(PHYCFGR) + +/** + * @ingroup Common_register_access_function + * @brief Get @ref VERSIONR register + * @return uint8_t. Value of @ref VERSIONR register. + */ +#define getVERSIONR() \ + WIZCHIP_READ(VERSIONR) + +///////////////////////////////////// + +/////////////////////////////////// +// Socket N register I/O function // +/////////////////////////////////// +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_MR register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @param (uint8_t)mr Value to set @ref Sn_MR + * @sa getSn_MR() + */ +#define setSn_MR(sn, mr) \ + WIZCHIP_WRITE(Sn_MR(sn),mr) + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_MR register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @return uint8_t. Value of @ref Sn_MR. + * @sa setSn_MR() + */ +#define getSn_MR(sn) \ + WIZCHIP_READ(Sn_MR(sn)) + +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_CR register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @param (uint8_t)cr Value to set @ref Sn_CR + * @sa getSn_CR() + */ +#define setSn_CR(sn, cr) \ + WIZCHIP_WRITE(Sn_CR(sn), cr) + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_CR register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @return uint8_t. Value of @ref Sn_CR. + * @sa setSn_CR() + */ +#define getSn_CR(sn) \ + WIZCHIP_READ(Sn_CR(sn)) + +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_IR register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @param (uint8_t)ir Value to set @ref Sn_IR + * @sa getSn_IR() + */ +#define setSn_IR(sn, ir) \ + WIZCHIP_WRITE(Sn_IR(sn), (ir & 0x1F)) + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_IR register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @return uint8_t. Value of @ref Sn_IR. + * @sa setSn_IR() + */ +#define getSn_IR(sn) \ + (WIZCHIP_READ(Sn_IR(sn)) & 0x1F) + +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_IMR register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @param (uint8_t)imr Value to set @ref Sn_IMR + * @sa getSn_IMR() + */ +#define setSn_IMR(sn, imr) \ + WIZCHIP_WRITE(Sn_IMR(sn), (imr & 0x1F)) + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_IMR register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @return uint8_t. Value of @ref Sn_IMR. + * @sa setSn_IMR() + */ +#define getSn_IMR(sn) \ + (WIZCHIP_READ(Sn_IMR(sn)) & 0x1F) + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_SR register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @return uint8_t. Value of @ref Sn_SR. + */ +#define getSn_SR(sn) \ + WIZCHIP_READ(Sn_SR(sn)) + +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_PORT register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @param (uint16_t)port Value to set @ref Sn_PORT. + * @sa getSn_PORT() + */ +#define setSn_PORT(sn, port) { \ + WIZCHIP_WRITE(Sn_PORT(sn), (uint8_t)(port >> 8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_PORT(sn),1), (uint8_t) port); \ + } + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_PORT register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @return uint16_t. Value of @ref Sn_PORT. + * @sa setSn_PORT() + */ +#define getSn_PORT(sn) \ + ((WIZCHIP_READ(Sn_PORT(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_PORT(sn),1))) + +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_DHAR register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @param (uint8_t*)dhar Pointer variable to set socket n destination hardware address. It should be allocated 6 bytes. + * @sa getSn_DHAR() + */ +#define setSn_DHAR(sn, dhar) \ + WIZCHIP_WRITE_BUF(Sn_DHAR(sn), dhar, 6) + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_MR register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @param (uint8_t*)dhar Pointer variable to get socket n destination hardware address. It should be allocated 6 bytes. + * @sa setSn_DHAR() + */ +#define getSn_DHAR(sn, dhar) \ + WIZCHIP_READ_BUF(Sn_DHAR(sn), dhar, 6) + +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_DIPR register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @param (uint8_t*)dipr Pointer variable to set socket n destination IP address. It should be allocated 4 bytes. + * @sa getSn_DIPR() + */ +#define setSn_DIPR(sn, dipr) \ + WIZCHIP_WRITE_BUF(Sn_DIPR(sn), dipr, 4) + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_DIPR register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @param (uint8_t*)dipr Pointer variable to get socket n destination IP address. It should be allocated 4 bytes. + * @sa SetSn_DIPR() + */ +#define getSn_DIPR(sn, dipr) \ + WIZCHIP_READ_BUF(Sn_DIPR(sn), dipr, 4) + +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_DPORT register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @param (uint16_t)dport Value to set @ref Sn_DPORT + * @sa getSn_DPORT() + */ +#define setSn_DPORT(sn, dport) { \ + WIZCHIP_WRITE(Sn_DPORT(sn), (uint8_t) (dport>>8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_DPORT(sn),1), (uint8_t) dport); \ + } + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_DPORT register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @return uint16_t. Value of @ref Sn_DPORT. + * @sa setSn_DPORT() + */ +#define getSn_DPORT(sn) \ + ((WIZCHIP_READ(Sn_DPORT(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_DPORT(sn),1))) + +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_MSSR register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @param (uint16_t)mss Value to set @ref Sn_MSSR + * @sa setSn_MSSR() + */ +#define setSn_MSSR(sn, mss) { \ + WIZCHIP_WRITE(Sn_MSSR(sn), (uint8_t)(mss>>8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_MSSR(sn),1), (uint8_t) mss); \ + } + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_MSSR register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @return uint16_t. Value of @ref Sn_MSSR. + * @sa setSn_MSSR() + */ +#define getSn_MSSR(sn) \ + ((WIZCHIP_READ(Sn_MSSR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_MSSR(sn),1))) + +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_TOS register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @param (uint8_t)tos Value to set @ref Sn_TOS + * @sa getSn_TOS() + */ +#define setSn_TOS(sn, tos) \ + WIZCHIP_WRITE(Sn_TOS(sn), tos) + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_TOS register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @return uint8_t. Value of Sn_TOS. + * @sa setSn_TOS() + */ +#define getSn_TOS(sn) \ + WIZCHIP_READ(Sn_TOS(sn)) + +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_TTL register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @param (uint8_t)ttl Value to set @ref Sn_TTL + * @sa getSn_TTL() + */ +#define setSn_TTL(sn, ttl) \ + WIZCHIP_WRITE(Sn_TTL(sn), ttl) + + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_TTL register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @return uint8_t. Value of @ref Sn_TTL. + * @sa setSn_TTL() + */ +#define getSn_TTL(sn) \ + WIZCHIP_READ(Sn_TTL(sn)) + + +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_RXBUF_SIZE register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @param (uint8_t)rxbufsize Value to set @ref Sn_RXBUF_SIZE + * @sa getSn_RXBUF_SIZE() + */ +#define setSn_RXBUF_SIZE(sn, rxbufsize) \ + WIZCHIP_WRITE(Sn_RXBUF_SIZE(sn),rxbufsize) + + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_RXBUF_SIZE register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @return uint8_t. Value of @ref Sn_RXBUF_SIZE. + * @sa setSn_RXBUF_SIZE() + */ +#define getSn_RXBUF_SIZE(sn) \ + WIZCHIP_READ(Sn_RXBUF_SIZE(sn)) + +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_TXBUF_SIZE register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @param (uint8_t)txbufsize Value to set @ref Sn_TXBUF_SIZE + * @sa getSn_TXBUF_SIZE() + */ +#define setSn_TXBUF_SIZE(sn, txbufsize) \ + WIZCHIP_WRITE(Sn_TXBUF_SIZE(sn), txbufsize) + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_TXBUF_SIZE register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @return uint8_t. Value of @ref Sn_TXBUF_SIZE. + * @sa setSn_TXBUF_SIZE() + */ +#define getSn_TXBUF_SIZE(sn) \ + WIZCHIP_READ(Sn_TXBUF_SIZE(sn)) + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_TX_FSR register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @return uint16_t. Value of @ref Sn_TX_FSR. + */ +uint16_t getSn_TX_FSR(uint8_t sn); + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_TX_RD register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @return uint16_t. Value of @ref Sn_TX_RD. + */ +#define getSn_TX_RD(sn) \ + ((WIZCHIP_READ(Sn_TX_RD(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_RD(sn),1))) + +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_TX_WR register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @param (uint16_t)txwr Value to set @ref Sn_TX_WR + * @sa GetSn_TX_WR() + */ +#define setSn_TX_WR(sn, txwr) { \ + WIZCHIP_WRITE(Sn_TX_WR(sn), (uint8_t)(txwr>>8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_TX_WR(sn),1), (uint8_t) txwr); \ + } + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_TX_WR register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @return uint16_t. Value of @ref Sn_TX_WR. + * @sa setSn_TX_WR() + */ +#define getSn_TX_WR(sn) \ + ((WIZCHIP_READ(Sn_TX_WR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_TX_WR(sn),1))) + + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_RX_RSR register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @return uint16_t. Value of @ref Sn_RX_RSR. + */ +uint16_t getSn_RX_RSR(uint8_t sn); + + +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_RX_RD register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @param (uint16_t)rxrd Value to set @ref Sn_RX_RD + * @sa getSn_RX_RD() + */ +#define setSn_RX_RD(sn, rxrd) { \ + WIZCHIP_WRITE(Sn_RX_RD(sn), (uint8_t)(rxrd>>8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_RX_RD(sn),1), (uint8_t) rxrd); \ + } + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_RX_RD register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @regurn uint16_t. Value of @ref Sn_RX_RD. + * @sa setSn_RX_RD() + */ +#define getSn_RX_RD(sn) \ + ((WIZCHIP_READ(Sn_RX_RD(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_RD(sn),1))) + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_RX_WR register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @return uint16_t. Value of @ref Sn_RX_WR. + */ +#define getSn_RX_WR(sn) \ + ((WIZCHIP_READ(Sn_RX_WR(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_RX_WR(sn),1))) + + +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_FRAG register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @param (uint16_t)frag Value to set @ref Sn_FRAG + * @sa getSn_FRAD() + */ +#define setSn_FRAG(sn, frag) { \ + WIZCHIP_WRITE(Sn_FRAG(sn), (uint8_t)(frag >>8)); \ + WIZCHIP_WRITE(WIZCHIP_OFFSET_INC(Sn_FRAG(sn),1), (uint8_t) frag); \ + } + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_FRAG register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @return uint16_t. Value of @ref Sn_FRAG. + * @sa setSn_FRAG() + */ +#define getSn_FRAG(sn) \ + ((WIZCHIP_READ(Sn_FRAG(sn)) << 8) + WIZCHIP_READ(WIZCHIP_OFFSET_INC(Sn_FRAG(sn),1))) + +/** + * @ingroup Socket_register_access_function + * @brief Set @ref Sn_KPALVTR register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @param (uint8_t)kpalvt Value to set @ref Sn_KPALVTR + * @sa getSn_KPALVTR() + */ +#define setSn_KPALVTR(sn, kpalvt) \ + WIZCHIP_WRITE(Sn_KPALVTR(sn), kpalvt) + +/** + * @ingroup Socket_register_access_function + * @brief Get @ref Sn_KPALVTR register + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @return uint8_t. Value of @ref Sn_KPALVTR. + * @sa setSn_KPALVTR() + */ +#define getSn_KPALVTR(sn) \ + WIZCHIP_READ(Sn_KPALVTR(sn)) + +////////////////////////////////////// + +///////////////////////////////////// +// Sn_TXBUF & Sn_RXBUF IO function // +///////////////////////////////////// +/** + * @brief Gets the max buffer size of socket sn passed as parameter. + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @return uint16_t. Value of Socket n RX max buffer size. + */ +#define getSn_RxMAX(sn) \ + (getSn_RXBUF_SIZE(sn) << 10) + +/** + * @brief Gets the max buffer size of socket sn passed as parameters. + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @return uint16_t. Value of Socket n TX max buffer size. + */ +//uint16_t getSn_TxMAX(uint8_t sn); +#define getSn_TxMAX(sn) \ + (getSn_TXBUF_SIZE(sn) << 10) + +/** + * @ingroup Basic_IO_function + * @brief It copies data to internal TX memory + * + * @details This function reads the Tx write pointer register and after that, + * it copies the <i>wizdata(pointer buffer)</i> of the length of <i>len(variable)</i> bytes to internal TX memory + * and updates the Tx write pointer register. + * This function is being called by send() and sendto() function also. + * + * @note User should read upper byte first and lower byte later to get proper value. + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @param wizdata Pointer buffer to write data + * @param len Data length + * @sa wiz_recv_data() + */ +void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len); + +/** + * @ingroup Basic_IO_function + * @brief It copies data to your buffer from internal RX memory + * + * @details This function read the Rx read pointer register and after that, + * it copies the received data from internal RX memory + * to <i>wizdata(pointer variable)</i> of the length of <i>len(variable)</i> bytes. + * This function is being called by recv() also. + * + * @note User should read upper byte first and lower byte later to get proper value. + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @param wizdata Pointer buffer to read data + * @param len Data length + * @sa wiz_send_data() + */ +void wiz_recv_data(uint8_t sn, uint8_t *wizdata, uint16_t len); + +/** + * @ingroup Basic_IO_function + * @brief It discard the received data in RX memory. + * @details It discards the data of the length of <i>len(variable)</i> bytes in internal RX memory. + * @param (uint8_t)sn Socket number. It should be <b>0 ~ 7</b>. + * @param len Data length + */ +void wiz_recv_ignore(uint8_t sn, uint16_t len); + +#endif // _W5500_H_ diff --git a/drivers/wiznet5k/ethernet/wizchip_conf.c b/drivers/wiznet5k/ethernet/wizchip_conf.c new file mode 100644 index 000000000..3e54d2c90 --- /dev/null +++ b/drivers/wiznet5k/ethernet/wizchip_conf.c @@ -0,0 +1,662 @@ +//****************************************************************************/ +//! +//! \file wizchip_conf.c +//! \brief WIZCHIP Config Header File. +//! \version 1.0.1 +//! \date 2013/10/21 +//! \par Revision history +//! <2014/05/01> V1.0.1 Refer to M20140501 +//! 1. Explicit type casting in wizchip_bus_readbyte() & wizchip_bus_writebyte() +// Issued by Mathias ClauBen. +//! uint32_t type converts into ptrdiff_t first. And then recoverting it into uint8_t* +//! For remove the warning when pointer type size is not 32bit. +//! If ptrdiff_t doesn't support in your complier, You should must replace ptrdiff_t into your suitable pointer type. +//! <2013/10/21> 1st Release +//! \author MidnightCow +//! \copyright +//! +//! Copyright (c) 2013, WIZnet Co., LTD. +//! All rights reserved. +//! +//! Redistribution and use in source and binary forms, with or without +//! modification, are permitted provided that the following conditions +//! are met: +//! +//! * Redistributions of source code must retain the above copyright +//! notice, this list of conditions and the following disclaimer. +//! * Redistributions in binary form must reproduce the above copyright +//! notice, this list of conditions and the following disclaimer in the +//! documentation and/or other materials provided with the distribution. +//! * Neither the name of the <ORGANIZATION> nor the names of its +//! contributors may be used to endorse or promote products derived +//! from this software without specific prior written permission. +//! +//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +//! THE POSSIBILITY OF SUCH DAMAGE. +// +//*****************************************************************************/ +//A20140501 : for use the type - ptrdiff_t +#include <stddef.h> +// + +#include "wizchip_conf.h" +#include "socket.h" + +/** + * @brief Default function to enable interrupt. + * @note This function help not to access wrong address. If you do not describe this function or register any functions, + * null function is called. + */ +void wizchip_cris_enter(void) {}; +/** + * @brief Default function to disable interrupt. + * @note This function help not to access wrong address. If you do not describe this function or register any functions, + * null function is called. + */ +void wizchip_cris_exit(void) {}; +/** + * @brief Default function to select chip. + * @note This function help not to access wrong address. If you do not describe this function or register any functions, + * null function is called. + */ +void wizchip_cs_select(void) {}; +/** + * @brief Default function to deselect chip. + * @note This function help not to access wrong address. If you do not describe this function or register any functions, + * null function is called. + */ +void wizchip_cs_deselect(void) {}; +/** + * @brief Default function to read in direct or indirect interface. + * @note This function help not to access wrong address. If you do not describe this function or register any functions, + * null function is called. + */ + //M20140501 : Explict pointer type casting +//uint8_t wizchip_bus_readbyte(uint32_t AddrSel) { return * ((volatile uint8_t *) AddrSel); }; +uint8_t wizchip_bus_readbyte(uint32_t AddrSel) { return * ((volatile uint8_t *)((ptrdiff_t) AddrSel)); }; +/** + * @brief Default function to write in direct or indirect interface. + * @note This function help not to access wrong address. If you do not describe this function or register any functions, + * null function is called. + */ + +//M20140501 : Explict pointer type casting +//void wizchip_bus_writebyte(uint32_t AddrSel, uint8_t wb) { *((volatile uint8_t*) AddrSel) = wb; }; +void wizchip_bus_writebyte(uint32_t AddrSel, uint8_t wb) { *((volatile uint8_t*)((ptrdiff_t)AddrSel)) = wb; }; + +/** + * @brief Default function to read in SPI interface. + * @note This function help not to access wrong address. If you do not describe this function or register any functions, + * null function is called. + */ +void wizchip_spi_readbytes(uint8_t *buf, uint32_t len) {} +/** + * @brief Default function to write in SPI interface. + * @note This function help not to access wrong address. If you do not describe this function or register any functions, + * null function is called. + */ +void wizchip_spi_writebytes(const uint8_t *buf, uint32_t len) {} + +/** + * @\ref _WIZCHIP instance + */ +_WIZCHIP WIZCHIP = + { + .id = _WIZCHIP_ID_, + .if_mode = _WIZCHIP_IO_MODE_, + .CRIS._enter = wizchip_cris_enter, + .CRIS._exit = wizchip_cris_exit, + .CS._select = wizchip_cs_select, + .CS._deselect = wizchip_cs_deselect, + .IF.BUS._read_byte = wizchip_bus_readbyte, + .IF.BUS._write_byte = wizchip_bus_writebyte +// .IF.SPI._read_byte = wizchip_spi_readbyte, +// .IF.SPI._write_byte = wizchip_spi_writebyte + }; + +#if _WIZCHIP_ == 5200 // for W5200 ARP errata +static uint8_t _SUBN_[4]; // subnet +#endif +static uint8_t _DNS_[4]; // DNS server ip address +static dhcp_mode _DHCP_; // DHCP mode + +void reg_wizchip_cris_cbfunc(void(*cris_en)(void), void(*cris_ex)(void)) +{ + if(!cris_en || !cris_ex) + { + WIZCHIP.CRIS._enter = wizchip_cris_enter; + WIZCHIP.CRIS._exit = wizchip_cris_exit; + } + else + { + WIZCHIP.CRIS._enter = cris_en; + WIZCHIP.CRIS._exit = cris_ex; + } +} + +void reg_wizchip_cs_cbfunc(void(*cs_sel)(void), void(*cs_desel)(void)) +{ + if(!cs_sel || !cs_desel) + { + WIZCHIP.CS._select = wizchip_cs_select; + WIZCHIP.CS._deselect = wizchip_cs_deselect; + } + else + { + WIZCHIP.CS._select = cs_sel; + WIZCHIP.CS._deselect = cs_desel; + } +} + +void reg_wizchip_bus_cbfunc(uint8_t(*bus_rb)(uint32_t addr), void (*bus_wb)(uint32_t addr, uint8_t wb)) +{ + while(!(WIZCHIP.if_mode & _WIZCHIP_IO_MODE_BUS_)); + + if(!bus_rb || !bus_wb) + { + WIZCHIP.IF.BUS._read_byte = wizchip_bus_readbyte; + WIZCHIP.IF.BUS._write_byte = wizchip_bus_writebyte; + } + else + { + WIZCHIP.IF.BUS._read_byte = bus_rb; + WIZCHIP.IF.BUS._write_byte = bus_wb; + } +} + +void reg_wizchip_spi_cbfunc(void (*spi_rb)(uint8_t *, uint32_t), void (*spi_wb)(const uint8_t *, uint32_t)) +{ + while(!(WIZCHIP.if_mode & _WIZCHIP_IO_MODE_SPI_)); + + if(!spi_rb || !spi_wb) + { + WIZCHIP.IF.SPI._read_bytes = wizchip_spi_readbytes; + WIZCHIP.IF.SPI._write_bytes = wizchip_spi_writebytes; + } + else + { + WIZCHIP.IF.SPI._read_bytes = spi_rb; + WIZCHIP.IF.SPI._write_bytes = spi_wb; + } +} + +int8_t ctlwizchip(ctlwizchip_type cwtype, void* arg) +{ + uint8_t tmp = 0; + uint8_t* ptmp[2] = {0,0}; + switch(cwtype) + { + case CW_RESET_WIZCHIP: + wizchip_sw_reset(); + break; + case CW_INIT_WIZCHIP: + if(arg != 0) + { + ptmp[0] = (uint8_t*)arg; + ptmp[1] = ptmp[0] + _WIZCHIP_SOCK_NUM_; + } + return wizchip_init(ptmp[0], ptmp[1]); + case CW_CLR_INTERRUPT: + wizchip_clrinterrupt(*((intr_kind*)arg)); + break; + case CW_GET_INTERRUPT: + *((intr_kind*)arg) = wizchip_getinterrupt(); + break; + case CW_SET_INTRMASK: + wizchip_setinterruptmask(*((intr_kind*)arg)); + break; + case CW_GET_INTRMASK: + *((intr_kind*)arg) = wizchip_getinterruptmask(); + break; + #if _WIZCHIP_ > 5100 + case CW_SET_INTRTIME: + setINTLEVEL(*(uint16_t*)arg); + break; + case CW_GET_INTRTIME: + *(uint16_t*)arg = getINTLEVEL(); + break; + #endif + case CW_GET_ID: + ((uint8_t*)arg)[0] = WIZCHIP.id[0]; + ((uint8_t*)arg)[1] = WIZCHIP.id[1]; + ((uint8_t*)arg)[2] = WIZCHIP.id[2]; + ((uint8_t*)arg)[3] = WIZCHIP.id[3]; + ((uint8_t*)arg)[4] = WIZCHIP.id[4]; + ((uint8_t*)arg)[5] = 0; + break; + #if _WIZCHIP_ == 5500 + case CW_RESET_PHY: + wizphy_reset(); + break; + case CW_SET_PHYCONF: + wizphy_setphyconf((wiz_PhyConf*)arg); + break; + case CW_GET_PHYCONF: + wizphy_getphyconf((wiz_PhyConf*)arg); + break; + case CW_GET_PHYSTATUS: + break; + case CW_SET_PHYPOWMODE: + return wizphy_setphypmode(*(uint8_t*)arg); + #endif + case CW_GET_PHYPOWMODE: + tmp = wizphy_getphypmode(); + if((int8_t)tmp == -1) return -1; + *(uint8_t*)arg = tmp; + break; + case CW_GET_PHYLINK: + tmp = wizphy_getphylink(); + if((int8_t)tmp == -1) return -1; + *(uint8_t*)arg = tmp; + break; + default: + return -1; + } + return 0; +} + + +int8_t ctlnetwork(ctlnetwork_type cntype, void* arg) +{ + + switch(cntype) + { + case CN_SET_NETINFO: + wizchip_setnetinfo((wiz_NetInfo*)arg); + break; + case CN_GET_NETINFO: + wizchip_getnetinfo((wiz_NetInfo*)arg); + break; + case CN_SET_NETMODE: + return wizchip_setnetmode(*(netmode_type*)arg); + case CN_GET_NETMODE: + *(netmode_type*)arg = wizchip_getnetmode(); + break; + case CN_SET_TIMEOUT: + wizchip_settimeout((wiz_NetTimeout*)arg); + break; + case CN_GET_TIMEOUT: + wizchip_gettimeout((wiz_NetTimeout*)arg); + break; + default: + return -1; + } + return 0; +} + +void wizchip_sw_reset(void) +{ + uint8_t gw[4], sn[4], sip[4]; + uint8_t mac[6]; + getSHAR(mac); + getGAR(gw); getSUBR(sn); getSIPR(sip); + setMR(MR_RST); + getMR(); // for delay + setSHAR(mac); + setGAR(gw); + setSUBR(sn); + setSIPR(sip); +} + +int8_t wizchip_init(uint8_t* txsize, uint8_t* rxsize) +{ + int8_t i; + int8_t tmp = 0; + wizchip_sw_reset(); + if(txsize) + { + tmp = 0; + for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++) + tmp += txsize[i]; + if(tmp > 16) return -1; + for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++) + setSn_TXBUF_SIZE(i, txsize[i]); + } + if(rxsize) + { + tmp = 0; + for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++) + tmp += rxsize[i]; + if(tmp > 16) return -1; + for(i = 0 ; i < _WIZCHIP_SOCK_NUM_; i++) + setSn_RXBUF_SIZE(i, rxsize[i]); + } + + WIZCHIP_EXPORT(socket_reset)(); + + return 0; +} + +void wizchip_clrinterrupt(intr_kind intr) +{ + uint8_t ir = (uint8_t)intr; + uint8_t sir = (uint8_t)((uint16_t)intr >> 8); +#if _WIZCHIP_ < 5500 + ir |= (1<<4); // IK_WOL +#endif +#if _WIZCHIP_ == 5200 + ir |= (1 << 6); +#endif + +#if _WIZCHIP_ < 5200 + sir &= 0x0F; +#endif + +#if _WIZCHIP_ == 5100 + ir |= sir; + setIR(ir); +#else + setIR(ir); + setSIR(sir); +#endif +} + +intr_kind wizchip_getinterrupt(void) +{ + uint8_t ir = 0; + uint8_t sir = 0; + uint16_t ret = 0; +#if _WIZCHIP_ == 5100 + ir = getIR(); + sir = ir 0x0F; +#else + ir = getIR(); + sir = getSIR(); +#endif + +#if _WIZCHIP_ < 5500 + ir &= ~(1<<4); // IK_WOL +#endif +#if _WIZCHIP_ == 5200 + ir &= ~(1 << 6); +#endif + ret = sir; + ret = (ret << 8) + ir; + return (intr_kind)ret; +} + +void wizchip_setinterruptmask(intr_kind intr) +{ + uint8_t imr = (uint8_t)intr; + uint8_t simr = (uint8_t)((uint16_t)intr >> 8); +#if _WIZCHIP_ < 5500 + imr &= ~(1<<4); // IK_WOL +#endif +#if _WIZCHIP_ == 5200 + imr &= ~(1 << 6); +#endif + +#if _WIZCHIP_ < 5200 + simr &= 0x0F; +#endif + +#if _WIZCHIP_ == 5100 + imr |= simr; + setIMR(imr); +#else + setIMR(imr); + setSIMR(simr); +#endif +} + +intr_kind wizchip_getinterruptmask(void) +{ + uint8_t imr = 0; + uint8_t simr = 0; + uint16_t ret = 0; +#if _WIZCHIP_ == 5100 + imr = getIMR(); + simr = imr 0x0F; +#else + imr = getIMR(); + simr = getSIMR(); +#endif + +#if _WIZCHIP_ < 5500 + imr &= ~(1<<4); // IK_WOL +#endif +#if _WIZCHIP_ == 5200 + imr &= ~(1 << 6); // IK_DEST_UNREACH +#endif + ret = simr; + ret = (ret << 8) + imr; + return (intr_kind)ret; +} + +int8_t wizphy_getphylink(void) +{ + int8_t tmp; +#if _WIZCHIP_ == 5200 + if(getPHYSTATUS() & PHYSTATUS_LINK) + tmp = PHY_LINK_ON; + else + tmp = PHY_LINK_OFF; +#elif _WIZCHIP_ == 5500 + if(getPHYCFGR() & PHYCFGR_LNK_ON) + tmp = PHY_LINK_ON; + else + tmp = PHY_LINK_OFF; +#else + tmp = -1; +#endif + return tmp; +} + +#if _WIZCHIP_ > 5100 + +int8_t wizphy_getphypmode(void) +{ + int8_t tmp = 0; + #if _WIZCHIP_ == 5200 + if(getPHYSTATUS() & PHYSTATUS_POWERDOWN) + tmp = PHY_POWER_DOWN; + else + tmp = PHY_POWER_NORM; + #elif _WIZCHIP_ == 5500 + if(getPHYCFGR() & PHYCFGR_OPMDC_PDOWN) + tmp = PHY_POWER_DOWN; + else + tmp = PHY_POWER_NORM; + #else + tmp = -1; + #endif + return tmp; +} +#endif + +#if _WIZCHIP_ == 5500 +void wizphy_reset(void) +{ + uint8_t tmp = getPHYCFGR(); + tmp &= PHYCFGR_RST; + setPHYCFGR(tmp); + tmp = getPHYCFGR(); + tmp |= ~PHYCFGR_RST; + setPHYCFGR(tmp); +} + +void wizphy_setphyconf(wiz_PhyConf* phyconf) +{ + uint8_t tmp = 0; + if(phyconf->by == PHY_CONFBY_SW) + tmp |= PHYCFGR_OPMD; + else + tmp &= ~PHYCFGR_OPMD; + if(phyconf->mode == PHY_MODE_AUTONEGO) + tmp |= PHYCFGR_OPMDC_ALLA; + else + { + if(phyconf->duplex == PHY_DUPLEX_FULL) + { + if(phyconf->speed == PHY_SPEED_100) + tmp |= PHYCFGR_OPMDC_100F; + else + tmp |= PHYCFGR_OPMDC_10F; + } + else + { + if(phyconf->speed == PHY_SPEED_100) + tmp |= PHYCFGR_OPMDC_100H; + else + tmp |= PHYCFGR_OPMDC_10H; + } + } + setPHYCFGR(tmp); + wizphy_reset(); +} + +void wizphy_getphyconf(wiz_PhyConf* phyconf) +{ + uint8_t tmp = 0; + tmp = getPHYCFGR(); + phyconf->by = (tmp & PHYCFGR_OPMD) ? PHY_CONFBY_SW : PHY_CONFBY_HW; + switch(tmp & PHYCFGR_OPMDC_ALLA) + { + case PHYCFGR_OPMDC_ALLA: + case PHYCFGR_OPMDC_100FA: + phyconf->mode = PHY_MODE_AUTONEGO; + break; + default: + phyconf->mode = PHY_MODE_MANUAL; + break; + } + switch(tmp & PHYCFGR_OPMDC_ALLA) + { + case PHYCFGR_OPMDC_100FA: + case PHYCFGR_OPMDC_100F: + case PHYCFGR_OPMDC_100H: + phyconf->speed = PHY_SPEED_100; + break; + default: + phyconf->speed = PHY_SPEED_10; + break; + } + switch(tmp & PHYCFGR_OPMDC_ALLA) + { + case PHYCFGR_OPMDC_100FA: + case PHYCFGR_OPMDC_100F: + case PHYCFGR_OPMDC_10F: + phyconf->duplex = PHY_DUPLEX_FULL; + break; + default: + phyconf->duplex = PHY_DUPLEX_HALF; + break; + } +} + +void wizphy_getphystat(wiz_PhyConf* phyconf) +{ + uint8_t tmp = getPHYCFGR(); + phyconf->duplex = (tmp & PHYCFGR_DPX_FULL) ? PHY_DUPLEX_FULL : PHY_DUPLEX_HALF; + phyconf->speed = (tmp & PHYCFGR_SPD_100) ? PHY_SPEED_100 : PHY_SPEED_10; +} + +int8_t wizphy_setphypmode(uint8_t pmode) +{ + uint8_t tmp = 0; + tmp = getPHYCFGR(); + if((tmp & PHYCFGR_OPMD)== 0) return -1; + tmp &= ~PHYCFGR_OPMDC_ALLA; + if( pmode == PHY_POWER_DOWN) + tmp |= PHYCFGR_OPMDC_PDOWN; + else + tmp |= PHYCFGR_OPMDC_ALLA; + setPHYCFGR(tmp); + wizphy_reset(); + tmp = getPHYCFGR(); + if( pmode == PHY_POWER_DOWN) + { + if(tmp & PHYCFGR_OPMDC_PDOWN) return 0; + } + else + { + if(tmp & PHYCFGR_OPMDC_ALLA) return 0; + } + return -1; +} +#endif + + +void wizchip_setnetinfo(wiz_NetInfo* pnetinfo) +{ + setSHAR(pnetinfo->mac); + setGAR(pnetinfo->gw); + setSUBR(pnetinfo->sn); + setSIPR(pnetinfo->ip); +#if _WIZCHIP_ == 5200 // for W5200 ARP errata + _SUBN_[0] = pnetinfo->sn[0]; + _SUBN_[1] = pnetinfo->sn[1]; + _SUBN_[2] = pnetinfo->sn[2]; + _SUBN_[3] = pnetinfo->sn[3]; +#endif + _DNS_[0] = pnetinfo->dns[0]; + _DNS_[1] = pnetinfo->dns[1]; + _DNS_[2] = pnetinfo->dns[2]; + _DNS_[3] = pnetinfo->dns[3]; + _DHCP_ = pnetinfo->dhcp; +} + +void wizchip_getnetinfo(wiz_NetInfo* pnetinfo) +{ + getSHAR(pnetinfo->mac); + getGAR(pnetinfo->gw); + getSUBR(pnetinfo->sn); + getSIPR(pnetinfo->ip); +#if _WIZCHIP_ == 5200 // for W5200 ARP errata + pnetinfo->sn[0] = _SUBN_[0]; + pnetinfo->sn[1] = _SUBN_[1]; + pnetinfo->sn[2] = _SUBN_[2]; + pnetinfo->sn[3] = _SUBN_[3]; +#endif + pnetinfo->dns[0]= _DNS_[0]; + pnetinfo->dns[1]= _DNS_[1]; + pnetinfo->dns[2]= _DNS_[2]; + pnetinfo->dns[3]= _DNS_[3]; + pnetinfo->dhcp = _DHCP_; +} + +#if _WIZCHIP_ == 5200 // for W5200 ARP errata +uint8_t *wizchip_getsubn(void) { + return _SUBN_; +} +#endif + +int8_t wizchip_setnetmode(netmode_type netmode) +{ + uint8_t tmp = 0; +#if _WIZCHIP_ != 5500 + if(netmode & ~(NM_WAKEONLAN | NM_PPPOE | NM_PINGBLOCK)) return -1; +#else + if(netmode & ~(NM_WAKEONLAN | NM_PPPOE | NM_PINGBLOCK | NM_FORCEARP)) return -1; +#endif + tmp = getMR(); + tmp |= (uint8_t)netmode; + setMR(tmp); + return 0; +} + +netmode_type wizchip_getnetmode(void) +{ + return (netmode_type) getMR(); +} + +void wizchip_settimeout(wiz_NetTimeout* nettime) +{ + setRCR(nettime->retry_cnt); + setRTR(nettime->time_100us); +} + +void wizchip_gettimeout(wiz_NetTimeout* nettime) +{ + nettime->retry_cnt = getRCR(); + nettime->time_100us = getRTR(); +} diff --git a/drivers/wiznet5k/ethernet/wizchip_conf.h b/drivers/wiznet5k/ethernet/wizchip_conf.h new file mode 100644 index 000000000..10f12a794 --- /dev/null +++ b/drivers/wiznet5k/ethernet/wizchip_conf.h @@ -0,0 +1,554 @@ +//***************************************************************************** +// +//! \file wizchip_conf.h +//! \brief WIZCHIP Config Header File. +//! \version 1.0.0 +//! \date 2013/10/21 +//! \par Revision history +//! <2013/10/21> 1st Release +//! \author MidnightCow +//! \copyright +//! +//! Copyright (c) 2013, WIZnet Co., LTD. +//! All rights reserved. +//! +//! Redistribution and use in source and binary forms, with or without +//! modification, are permitted provided that the following conditions +//! are met: +//! +//! * Redistributions of source code must retain the above copyright +//! notice, this list of conditions and the following disclaimer. +//! * Redistributions in binary form must reproduce the above copyright +//! notice, this list of conditions and the following disclaimer in the +//! documentation and/or other materials provided with the distribution. +//! * Neither the name of the <ORGANIZATION> nor the names of its +//! contributors may be used to endorse or promote products derived +//! from this software without specific prior written permission. +//! +//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +//! THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + +/** + * @defgroup extra_functions 2. WIZnet Extra Functions + * + * @brief These functions is optional function. It could be replaced at WIZCHIP I/O function because they were made by WIZCHIP I/O functions. + * @details There are functions of configuring WIZCHIP, network, interrupt, phy, network information and timer. \n + * + */ + +#ifndef _WIZCHIP_CONF_H_ +#define _WIZCHIP_CONF_H_ + +#include <stdint.h> +/** + * @brief Select WIZCHIP. + * @todo You should select one, \b 5100, \b 5200 ,\b 5500 or etc. \n\n + * ex> <code> #define \_WIZCHIP_ 5500 </code> + */ +#ifndef _WIZCHIP_ +#define _WIZCHIP_ 5200 // 5100, 5200, 5500 +#endif + +#define _WIZCHIP_IO_MODE_NONE_ 0x0000 +#define _WIZCHIP_IO_MODE_BUS_ 0x0100 /**< Bus interface mode */ +#define _WIZCHIP_IO_MODE_SPI_ 0x0200 /**< SPI interface mode */ +//#define _WIZCHIP_IO_MODE_IIC_ 0x0400 +//#define _WIZCHIP_IO_MODE_SDIO_ 0x0800 +// Add to +// + +#define _WIZCHIP_IO_MODE_BUS_DIR_ (_WIZCHIP_IO_MODE_BUS_ + 1) /**< BUS interface mode for direct */ +#define _WIZCHIP_IO_MODE_BUS_INDIR_ (_WIZCHIP_IO_MODE_BUS_ + 2) /**< BUS interface mode for indirect */ + +#define _WIZCHIP_IO_MODE_SPI_VDM_ (_WIZCHIP_IO_MODE_SPI_ + 1) /**< SPI interface mode for variable length data*/ +#define _WIZCHIP_IO_MODE_SPI_FDM_ (_WIZCHIP_IO_MODE_SPI_ + 2) /**< SPI interface mode for fixed length data mode*/ + + +#if (_WIZCHIP_ == 5100) + #define _WIZCHIP_ID_ "W5100\0" +/** + * @brief Define interface mode. + * @todo you should select interface mode as chip. Select one of @ref \_WIZCHIP_IO_MODE_SPI_ , @ref \_WIZCHIP_IO_MODE_BUS_DIR_ or @ref \_WIZCHIP_IO_MODE_BUS_INDIR_ + */ + +// #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_BUS_DIR_ +// #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_BUS_INDIR_ + #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_ + +#elif (_WIZCHIP_ == 5200) + #define _WIZCHIP_ID_ "W5200\0" +/** + * @brief Define interface mode. + * @todo you should select interface mode as chip. Select one of @ref \_WIZCHIP_IO_MODE_SPI_ or @ref \_WIZCHIP_IO_MODE_BUS_INDIR_ + */ +// #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_BUS_INDIR_ + #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_ + #include "w5200/w5200.h" +#elif (_WIZCHIP_ == 5500) + #define _WIZCHIP_ID_ "W5500\0" + +/** + * @brief Define interface mode. \n + * @todo Should select interface mode as chip. + * - @ref \_WIZCHIP_IO_MODE_SPI_ \n + * -@ref \_WIZCHIP_IO_MODE_SPI_VDM_ : Valid only in @ref \_WIZCHIP_ == 5500 \n + * -@ref \_WIZCHIP_IO_MODE_SPI_FDM_ : Valid only in @ref \_WIZCHIP_ == 5500 \n + * - @ref \_WIZCHIP_IO_MODE_BUS_ \n + * - @ref \_WIZCHIP_IO_MODE_BUS_DIR_ \n + * - @ref \_WIZCHIP_IO_MODE_BUS_INDIR_ \n + * - Others will be defined in future. \n\n + * ex> <code> #define \_WIZCHIP_IO_MODE_ \_WIZCHIP_IO_MODE_SPI_VDM_ </code> + * + */ + //#define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_FDM_ + #define _WIZCHIP_IO_MODE_ _WIZCHIP_IO_MODE_SPI_VDM_ + #include "w5500/w5500.h" +#else + #error "Unknown defined _WIZCHIP_. You should define one of 5100, 5200, and 5500 !!!" +#endif + +#ifndef _WIZCHIP_IO_MODE_ + #error "Undefined _WIZCHIP_IO_MODE_. You should define it !!!" +#endif + +/** + * @brief Define I/O base address when BUS IF mode. + * @todo Should re-define it to fit your system when BUS IF Mode (@ref \_WIZCHIP_IO_MODE_BUS_, + * @ref \_WIZCHIP_IO_MODE_BUS_DIR_, @ref \_WIZCHIP_IO_MODE_BUS_INDIR_). \n\n + * ex> <code> #define \_WIZCHIP_IO_BASE_ 0x00008000 </code> + */ +#define _WIZCHIP_IO_BASE_ 0x00000000 // + +#if _WIZCHIP_IO_MODE_ & _WIZCHIP_IO_MODE_BUS_ + #ifndef _WIZCHIP_IO_BASE_ + #error "You should be define _WIZCHIP_IO_BASE to fit your system memory map." + #endif +#endif + +#if _WIZCHIP_ > 5100 + #define _WIZCHIP_SOCK_NUM_ 8 ///< The count of independant socket of @b WIZCHIP +#else + #define _WIZCHIP_SOCK_NUM_ 4 ///< The count of independant socket of @b WIZCHIP +#endif + + +/******************************************************** +* WIZCHIP BASIC IF functions for SPI, SDIO, I2C , ETC. +*********************************************************/ +/** + * @ingroup DATA_TYPE + * @brief The set of callback functions for W5500:@ref WIZCHIP_IO_Functions W5200:@ref WIZCHIP_IO_Functions_W5200 + */ +typedef struct __WIZCHIP +{ + uint16_t if_mode; ///< host interface mode + uint8_t id[6]; ///< @b WIZCHIP ID such as @b 5100, @b 5200, @b 5500, and so on. + /** + * The set of critical section callback func. + */ + struct _CRIS + { + void (*_enter) (void); ///< crtical section enter + void (*_exit) (void); ///< critial section exit + }CRIS; + /** + * The set of @ref\_WIZCHIP_ select control callback func. + */ + struct _CS + { + void (*_select) (void); ///< @ref \_WIZCHIP_ selected + void (*_deselect)(void); ///< @ref \_WIZCHIP_ deselected + }CS; + /** + * The set of interface IO callback func. + */ + union _IF + { + /** + * For BUS interface IO + */ + struct + { + uint8_t (*_read_byte) (uint32_t AddrSel); + void (*_write_byte) (uint32_t AddrSel, uint8_t wb); + }BUS; + /** + * For SPI interface IO + */ + struct + { + void (*_read_bytes) (uint8_t *buf, uint32_t len); + void (*_write_bytes) (const uint8_t *buf, uint32_t len); + }SPI; + // To be added + // + }IF; +}_WIZCHIP; + +extern _WIZCHIP WIZCHIP; + +/** + * @ingroup DATA_TYPE + * WIZCHIP control type enumration used in @ref ctlwizchip(). + */ +typedef enum +{ + CW_RESET_WIZCHIP, ///< Resets WIZCHIP by softly + CW_INIT_WIZCHIP, ///< Inializes to WIZCHIP with SOCKET buffer size 2 or 1 dimension array typed uint8_t. + CW_GET_INTERRUPT, ///< Get Interrupt status of WIZCHIP + CW_CLR_INTERRUPT, ///< Clears interrupt + CW_SET_INTRMASK, ///< Masks interrupt + CW_GET_INTRMASK, ///< Get interrupt mask + CW_SET_INTRTIME, ///< Set interval time between the current and next interrupt. + CW_GET_INTRTIME, ///< Set interval time between the current and next interrupt. + CW_GET_ID, ///< Gets WIZCHIP name. + +#if _WIZCHIP_ == 5500 + CW_RESET_PHY, ///< Resets internal PHY. Valid Only W5000 + CW_SET_PHYCONF, ///< When PHY configured by interal register, PHY operation mode (Manual/Auto, 10/100, Half/Full). Valid Only W5000 + CW_GET_PHYCONF, ///< Get PHY operation mode in interal register. Valid Only W5000 + CW_GET_PHYSTATUS, ///< Get real PHY status on operating. Valid Only W5000 + CW_SET_PHYPOWMODE, ///< Set PHY power mode as noraml and down when PHYSTATUS.OPMD == 1. Valid Only W5000 +#endif + CW_GET_PHYPOWMODE, ///< Get PHY Power mode as down or normal + CW_GET_PHYLINK ///< Get PHY Link status +}ctlwizchip_type; + +/** + * @ingroup DATA_TYPE + * Network control type enumration used in @ref ctlnetwork(). + */ +typedef enum +{ + CN_SET_NETINFO, ///< Set Network with @ref wiz_NetInfo + CN_GET_NETINFO, ///< Get Network with @ref wiz_NetInfo + CN_SET_NETMODE, ///< Set network mode as WOL, PPPoE, Ping Block, and Force ARP mode + CN_GET_NETMODE, ///< Get network mode as WOL, PPPoE, Ping Block, and Force ARP mode + CN_SET_TIMEOUT, ///< Set network timeout as retry count and time. + CN_GET_TIMEOUT, ///< Get network timeout as retry count and time. +}ctlnetwork_type; + +/** + * @ingroup DATA_TYPE + * Interrupt kind when CW_SET_INTRRUPT, CW_GET_INTERRUPT, CW_SET_INTRMASK + * and CW_GET_INTRMASK is used in @ref ctlnetwork(). + * It can be used with OR operation. + */ +typedef enum +{ +#if _WIZCHIP_ > 5200 + IK_WOL = (1 << 4), ///< Wake On Lan by receiving the magic packet. Valid in W500. +#endif + + IK_PPPOE_TERMINATED = (1 << 5), ///< PPPoE Disconnected + +#if _WIZCHIP_ != 5200 + IK_DEST_UNREACH = (1 << 6), ///< Destination IP & Port Unreable, No use in W5200 +#endif + + IK_IP_CONFLICT = (1 << 7), ///< IP conflict occurred + + IK_SOCK_0 = (1 << 8), ///< Socket 0 interrupt + IK_SOCK_1 = (1 << 9), ///< Socket 1 interrupt + IK_SOCK_2 = (1 << 10), ///< Socket 2 interrupt + IK_SOCK_3 = (1 << 11), ///< Socket 3 interrupt +#if _WIZCHIP_ > 5100 + IK_SOCK_4 = (1 << 12), ///< Socket 4 interrupt, No use in 5100 + IK_SOCK_5 = (1 << 13), ///< Socket 5 interrupt, No use in 5100 + IK_SOCK_6 = (1 << 14), ///< Socket 6 interrupt, No use in 5100 + IK_SOCK_7 = (1 << 15), ///< Socket 7 interrupt, No use in 5100 +#endif + +#if _WIZCHIP_ > 5100 + IK_SOCK_ALL = (0xFF << 8) ///< All Socket interrpt +#else + IK_SOCK_ALL = (0x0F << 8) ///< All Socket interrpt +#endif +}intr_kind; + +#define PHY_CONFBY_HW 0 ///< Configured PHY operation mode by HW pin +#define PHY_CONFBY_SW 1 ///< Configured PHY operation mode by SW register +#define PHY_MODE_MANUAL 0 ///< Configured PHY operation mode with user setting. +#define PHY_MODE_AUTONEGO 1 ///< Configured PHY operation mode with auto-negotiation +#define PHY_SPEED_10 0 ///< Link Speed 10 +#define PHY_SPEED_100 1 ///< Link Speed 100 +#define PHY_DUPLEX_HALF 0 ///< Link Half-Duplex +#define PHY_DUPLEX_FULL 1 ///< Link Full-Duplex +#define PHY_LINK_OFF 0 ///< Link Off +#define PHY_LINK_ON 1 ///< Link On +#define PHY_POWER_NORM 0 ///< PHY power normal mode +#define PHY_POWER_DOWN 1 ///< PHY power down mode + + +#if _WIZCHIP_ == 5500 +/** + * @ingroup DATA_TYPE + * It configures PHY configuration when CW_SET PHYCONF or CW_GET_PHYCONF in W5500, + * and it indicates the real PHY status configured by HW or SW in all WIZCHIP. \n + * Valid only in W5500. + */ +typedef struct wiz_PhyConf_t +{ + uint8_t by; ///< set by @ref PHY_CONFBY_HW or @ref PHY_CONFBY_SW + uint8_t mode; ///< set by @ref PHY_MODE_MANUAL or @ref PHY_MODE_AUTONEGO + uint8_t speed; ///< set by @ref PHY_SPEED_10 or @ref PHY_SPEED_100 + uint8_t duplex; ///< set by @ref PHY_DUPLEX_HALF @ref PHY_DUPLEX_FULL + //uint8_t power; ///< set by @ref PHY_POWER_NORM or @ref PHY_POWER_DOWN + //uint8_t link; ///< Valid only in CW_GET_PHYSTATUS. set by @ref PHY_LINK_ON or PHY_DUPLEX_OFF + }wiz_PhyConf; +#endif + +/** + * @ingroup DATA_TYPE + * It used in setting dhcp_mode of @ref wiz_NetInfo. + */ +typedef enum +{ + NETINFO_STATIC = 1, ///< Static IP configuration by manually. + NETINFO_DHCP ///< Dynamic IP configruation from a DHCP sever +}dhcp_mode; + +/** + * @ingroup DATA_TYPE + * Network Information for WIZCHIP + */ +typedef struct wiz_NetInfo_t +{ + uint8_t mac[6]; ///< Source Mac Address + uint8_t ip[4]; ///< Source IP Address + uint8_t sn[4]; ///< Subnet Mask + uint8_t gw[4]; ///< Gateway IP Address + uint8_t dns[4]; ///< DNS server IP Address + dhcp_mode dhcp; ///< 1 - Static, 2 - DHCP +}wiz_NetInfo; + +/** + * @ingroup DATA_TYPE + * Network mode + */ +typedef enum +{ +#if _WIZCHIP_ == 5500 + NM_FORCEARP = (1<<1), ///< Force to APP send whenever udp data is sent. Valid only in W5500 +#endif + NM_WAKEONLAN = (1<<5), ///< Wake On Lan + NM_PINGBLOCK = (1<<4), ///< Block ping-request + NM_PPPOE = (1<<3), ///< PPPoE mode +}netmode_type; + +/** + * @ingroup DATA_TYPE + * Used in CN_SET_TIMEOUT or CN_GET_TIMEOUT of @ref ctlwizchip() for timeout configruation. + */ +typedef struct wiz_NetTimeout_t +{ + uint8_t retry_cnt; ///< retry count + uint16_t time_100us; ///< time unit 100us +}wiz_NetTimeout; + +/** + *@brief Registers call back function for critical section of I/O functions such as + *\ref WIZCHIP_READ, @ref WIZCHIP_WRITE, @ref WIZCHIP_READ_BUF and @ref WIZCHIP_WRITE_BUF. + *@param cris_en : callback function for critical section enter. + *@param cris_ex : callback function for critical section exit. + *@todo Describe @ref WIZCHIP_CRITICAL_ENTER and @ref WIZCHIP_CRITICAL_EXIT marco or register your functions. + *@note If you do not describe or register, default functions(@ref wizchip_cris_enter & @ref wizchip_cris_exit) is called. + */ +void reg_wizchip_cris_cbfunc(void(*cris_en)(void), void(*cris_ex)(void)); + + +/** + *@brief Registers call back function for WIZCHIP select & deselect. + *@param cs_sel : callback function for WIZCHIP select + *@param cs_desel : callback fucntion for WIZCHIP deselect + *@todo Describe @ref wizchip_cs_select and @ref wizchip_cs_deselect function or register your functions. + *@note If you do not describe or register, null function is called. + */ +void reg_wizchip_cs_cbfunc(void(*cs_sel)(void), void(*cs_desel)(void)); + +/** + *@brief Registers call back function for bus interface. + *@param bus_rb : callback function to read byte data using system bus + *@param bus_wb : callback function to write byte data using system bus + *@todo Describe @ref wizchip_bus_readbyte and @ref wizchip_bus_writebyte function + *or register your functions. + *@note If you do not describe or register, null function is called. + */ +void reg_wizchip_bus_cbfunc(uint8_t (*bus_rb)(uint32_t addr), void (*bus_wb)(uint32_t addr, uint8_t wb)); + +/** + *@brief Registers call back function for SPI interface. + *@param spi_rb : callback function to read byte usig SPI + *@param spi_wb : callback function to write byte usig SPI + *@todo Describe \ref wizchip_spi_readbyte and \ref wizchip_spi_writebyte function + *or register your functions. + *@note If you do not describe or register, null function is called. + */ +void reg_wizchip_spi_cbfunc(void (*spi_rb)(uint8_t *, uint32_t), void (*spi_wb)(const uint8_t *, uint32_t)); + +/** + * @ingroup extra_functions + * @brief Controls to the WIZCHIP. + * @details Resets WIZCHIP & internal PHY, Configures PHY mode, Monitor PHY(Link,Speed,Half/Full/Auto), + * controls interrupt & mask and so on. + * @param cwtype : Decides to the control type + * @param arg : arg type is dependent on cwtype. + * @return 0 : Success \n + * -1 : Fail because of invalid \ref ctlwizchip_type or unsupported \ref ctlwizchip_type in WIZCHIP + */ +int8_t ctlwizchip(ctlwizchip_type cwtype, void* arg); + +/** + * @ingroup extra_functions + * @brief Controls to network. + * @details Controls to network environment, mode, timeout and so on. + * @param cntype : Input. Decides to the control type + * @param arg : Inout. arg type is dependent on cntype. + * @return -1 : Fail because of invalid \ref ctlnetwork_type or unsupported \ref ctlnetwork_type in WIZCHIP \n + * 0 : Success + */ +int8_t ctlnetwork(ctlnetwork_type cntype, void* arg); + + +/* + * The following functions are implemented for internal use. + * but You can call these functions for code size reduction instead of ctlwizchip() and ctlnetwork(). + */ + +/** + * @ingroup extra_functions + * @brief Reset WIZCHIP by softly. + */ +void wizchip_sw_reset(void); + +/** + * @ingroup extra_functions + * @brief Initializes WIZCHIP with socket buffer size + * @param txsize Socket tx buffer sizes. If null, initialized the default size 2KB. + * @param rxsize Socket rx buffer sizes. If null, initialized the default size 2KB. + * @return 0 : succcess \n + * -1 : fail. Invalid buffer size + */ +int8_t wizchip_init(uint8_t* txsize, uint8_t* rxsize); + +/** + * @ingroup extra_functions + * @brief Clear Interrupt of WIZCHIP. + * @param intr : @ref intr_kind value operated OR. It can type-cast to uint16_t. + */ +void wizchip_clrinterrupt(intr_kind intr); + +/** + * @ingroup extra_functions + * @brief Get Interrupt of WIZCHIP. + * @return @ref intr_kind value operated OR. It can type-cast to uint16_t. + */ +intr_kind wizchip_getinterrupt(void); + +/** + * @ingroup extra_functions + * @brief Mask or Unmask Interrupt of WIZCHIP. + * @param intr : @ref intr_kind value operated OR. It can type-cast to uint16_t. + */ +void wizchip_setinterruptmask(intr_kind intr); + +/** + * @ingroup extra_functions + * @brief Get Interrupt mask of WIZCHIP. + * @return : The operated OR vaule of @ref intr_kind. It can type-cast to uint16_t. + */ +intr_kind wizchip_getinterruptmask(void); + +#if _WIZCHIP_ > 5100 + int8_t wizphy_getphylink(void); ///< get the link status of phy in WIZCHIP. No use in W5100 + int8_t wizphy_getphypmode(void); ///< get the power mode of PHY in WIZCHIP. No use in W5100 +#endif + +#if _WIZCHIP_ == 5500 + void wizphy_reset(void); ///< Reset phy. Vailid only in W5500 +/** + * @ingroup extra_functions + * @brief Set the phy information for WIZCHIP without power mode + * @param phyconf : @ref wiz_PhyConf + */ + void wizphy_setphyconf(wiz_PhyConf* phyconf); + /** + * @ingroup extra_functions + * @brief Get phy configuration information. + * @param phyconf : @ref wiz_PhyConf + */ + void wizphy_getphyconf(wiz_PhyConf* phyconf); + /** + * @ingroup extra_functions + * @brief Get phy status. + * @param phyconf : @ref wiz_PhyConf + */ + void wizphy_getphystat(wiz_PhyConf* phyconf); + /** + * @ingroup extra_functions + * @brief set the power mode of phy inside WIZCHIP. Refer to @ref PHYCFGR in W5500, @ref PHYSTATUS in W5200 + * @param pmode Settig value of power down mode. + */ + int8_t wizphy_setphypmode(uint8_t pmode); +#endif + +/** +* @ingroup extra_functions + * @brief Set the network information for WIZCHIP + * @param pnetinfo : @ref wizNetInfo + */ +void wizchip_setnetinfo(wiz_NetInfo* pnetinfo); + +/** + * @ingroup extra_functions + * @brief Get the network information for WIZCHIP + * @param pnetinfo : @ref wizNetInfo + */ +void wizchip_getnetinfo(wiz_NetInfo* pnetinfo); + +#if _WIZCHIP_ == 5200 // for W5200 ARP errata +uint8_t *wizchip_getsubn(void); +#endif + +/** + * @ingroup extra_functions + * @brief Set the network mode such WOL, PPPoE, Ping Block, and etc. + * @param pnetinfo Value of network mode. Refer to @ref netmode_type. + */ +int8_t wizchip_setnetmode(netmode_type netmode); + +/** + * @ingroup extra_functions + * @brief Get the network mode such WOL, PPPoE, Ping Block, and etc. + * @return Value of network mode. Refer to @ref netmode_type. + */ +netmode_type wizchip_getnetmode(void); + +/** + * @ingroup extra_functions + * @brief Set retry time value(@ref RTR) and retry count(@ref RCR). + * @details @ref RTR configures the retransmission timeout period and @ref RCR configures the number of time of retransmission. + * @param nettime @ref RTR value and @ref RCR value. Refer to @ref wiz_NetTimeout. + */ +void wizchip_settimeout(wiz_NetTimeout* nettime); + +/** + * @ingroup extra_functions + * @brief Get retry time value(@ref RTR) and retry count(@ref RCR). + * @details @ref RTR configures the retransmission timeout period and @ref RCR configures the number of time of retransmission. + * @param nettime @ref RTR value and @ref RCR value. Refer to @ref wiz_NetTimeout. + */ +void wizchip_gettimeout(wiz_NetTimeout* nettime); + +#endif // _WIZCHIP_CONF_H_ diff --git a/drivers/wiznet5k/internet/dhcp/dhcp.c b/drivers/wiznet5k/internet/dhcp/dhcp.c new file mode 100644 index 000000000..c56e64474 --- /dev/null +++ b/drivers/wiznet5k/internet/dhcp/dhcp.c @@ -0,0 +1,979 @@ +//***************************************************************************** +// +//! \file dhcp.c +//! \brief DHCP APIs implement file. +//! \details Processig DHCP protocol as DISCOVER, OFFER, REQUEST, ACK, NACK and DECLINE. +//! \version 1.1.0 +//! \date 2013/11/18 +//! \par Revision history +//! <2018/10/09> Modified by Nick Moore for CircuitPython +//! <2013/11/18> 1st Release +//! <2012/12/20> V1.1.0 +//! 1. Optimize code +//! 2. Add reg_dhcp_cbfunc() +//! 3. Add DHCP_stop() +//! 4. Integrate check_DHCP_state() & DHCP_run() to DHCP_run() +//! 5. Don't care system endian +//! 6. Add comments +//! <2012/12/26> V1.1.1 +//! 1. Modify variable declaration: dhcp_tick_1s is declared volatile for code optimization +//! \author Eric Jung & MidnightCow +//! \copyright +//! +//! Copyright (c) 2013, WIZnet Co., LTD. +//! All rights reserved. +//! +//! Redistribution and use in source and binary forms, with or without +//! modification, are permitted provided that the following conditions +//! are met: +//! +//! * Redistributions of source code must retain the above copyright +//! notice, this list of conditions and the following disclaimer. +//! * Redistributions in binary form must reproduce the above copyright +//! notice, this list of conditions and the following disclaimer in the +//! documentation and/or other materials provided with the distribution. +//! * Neither the name of the <ORGANIZATION> nor the names of its +//! contributors may be used to endorse or promote products derived +//! from this software without specific prior written permission. +//! +//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +//! THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + +//#include "Ethernet/socket.h" +//#include "Internet/DHCP/dhcp.h" +#include "../../ethernet/socket.h" +#include "dhcp.h" + +/* If you want to display debug & processing message, Define _DHCP_DEBUG_ in dhcp.h */ + +#ifdef _DHCP_DEBUG_ + #include <stdio.h> +#endif + +/* DHCP state machine. */ +#define STATE_DHCP_INIT 0 ///< Initialize +#define STATE_DHCP_DISCOVER 1 ///< send DISCOVER and wait OFFER +#define STATE_DHCP_REQUEST 2 ///< send REQEUST and wait ACK or NACK +#define STATE_DHCP_LEASED 3 ///< ReceiveD ACK and IP leased +#define STATE_DHCP_REREQUEST 4 ///< send REQUEST for maintaining leased IP +#define STATE_DHCP_RELEASE 5 ///< No use +#define STATE_DHCP_STOP 6 ///< Stop processing DHCP + +#define DHCP_FLAGSBROADCAST 0x8000 ///< The broadcast value of flags in @ref RIP_MSG +#define DHCP_FLAGSUNICAST 0x0000 ///< The unicast value of flags in @ref RIP_MSG + +/* DHCP message OP code */ +#define DHCP_BOOTREQUEST 1 ///< Request Message used in op of @ref RIP_MSG +#define DHCP_BOOTREPLY 2 ///< Reply Message used i op of @ref RIP_MSG + +/* DHCP message type */ +#define DHCP_DISCOVER 1 ///< DISCOVER message in OPT of @ref RIP_MSG +#define DHCP_OFFER 2 ///< OFFER message in OPT of @ref RIP_MSG +#define DHCP_REQUEST 3 ///< REQUEST message in OPT of @ref RIP_MSG +#define DHCP_DECLINE 4 ///< DECLINE message in OPT of @ref RIP_MSG +#define DHCP_ACK 5 ///< ACK message in OPT of @ref RIP_MSG +#define DHCP_NAK 6 ///< NACK message in OPT of @ref RIP_MSG +#define DHCP_RELEASE 7 ///< RELEASE message in OPT of @ref RIP_MSG. No use +#define DHCP_INFORM 8 ///< INFORM message in OPT of @ref RIP_MSG. No use + +#define DHCP_HTYPE10MB 1 ///< Used in type of @ref RIP_MSG +#define DHCP_HTYPE100MB 2 ///< Used in type of @ref RIP_MSG + +#define DHCP_HLENETHERNET 6 ///< Used in hlen of @ref RIP_MSG +#define DHCP_HOPS 0 ///< Used in hops of @ref RIP_MSG +#define DHCP_SECS 0 ///< Used in secs of @ref RIP_MSG + +#define INFINITE_LEASETIME 0xffffffff ///< Infinite lease time + +#define OPT_SIZE 312 /// Max OPT size of @ref RIP_MSG +#define RIP_MSG_SIZE (236+OPT_SIZE) /// Max size of @ref RIP_MSG + +/* + * @brief DHCP option and value (cf. RFC1533) + */ +enum +{ + padOption = 0, + subnetMask = 1, + timerOffset = 2, + routersOnSubnet = 3, + timeServer = 4, + nameServer = 5, + dns = 6, + logServer = 7, + cookieServer = 8, + lprServer = 9, + impressServer = 10, + resourceLocationServer = 11, + hostName = 12, + bootFileSize = 13, + meritDumpFile = 14, + domainName = 15, + swapServer = 16, + rootPath = 17, + extentionsPath = 18, + IPforwarding = 19, + nonLocalSourceRouting = 20, + policyFilter = 21, + maxDgramReasmSize = 22, + defaultIPTTL = 23, + pathMTUagingTimeout = 24, + pathMTUplateauTable = 25, + ifMTU = 26, + allSubnetsLocal = 27, + broadcastAddr = 28, + performMaskDiscovery = 29, + maskSupplier = 30, + performRouterDiscovery = 31, + routerSolicitationAddr = 32, + staticRoute = 33, + trailerEncapsulation = 34, + arpCacheTimeout = 35, + ethernetEncapsulation = 36, + tcpDefaultTTL = 37, + tcpKeepaliveInterval = 38, + tcpKeepaliveGarbage = 39, + nisDomainName = 40, + nisServers = 41, + ntpServers = 42, + vendorSpecificInfo = 43, + netBIOSnameServer = 44, + netBIOSdgramDistServer = 45, + netBIOSnodeType = 46, + netBIOSscope = 47, + xFontServer = 48, + xDisplayManager = 49, + dhcpRequestedIPaddr = 50, + dhcpIPaddrLeaseTime = 51, + dhcpOptionOverload = 52, + dhcpMessageType = 53, + dhcpServerIdentifier = 54, + dhcpParamRequest = 55, + dhcpMsg = 56, + dhcpMaxMsgSize = 57, + dhcpT1value = 58, + dhcpT2value = 59, + dhcpClassIdentifier = 60, + dhcpClientIdentifier = 61, + endOption = 255 +}; + +/* + * @brief DHCP message format + */ +typedef struct { + uint8_t op; ///< @ref DHCP_BOOTREQUEST or @ref DHCP_BOOTREPLY + uint8_t htype; ///< @ref DHCP_HTYPE10MB or @ref DHCP_HTYPE100MB + uint8_t hlen; ///< @ref DHCP_HLENETHERNET + uint8_t hops; ///< @ref DHCP_HOPS + uint32_t xid; ///< @ref DHCP_XID This increase one every DHCP transaction. + uint16_t secs; ///< @ref DHCP_SECS + uint16_t flags; ///< @ref DHCP_FLAGSBROADCAST or @ref DHCP_FLAGSUNICAST + uint8_t ciaddr[4]; ///< @ref Request IP to DHCP sever + uint8_t yiaddr[4]; ///< @ref Offered IP from DHCP server + uint8_t siaddr[4]; ///< No use + uint8_t giaddr[4]; ///< No use + uint8_t chaddr[16]; ///< DHCP client 6bytes MAC address. Others is filled to zero + uint8_t sname[64]; ///< No use + uint8_t file[128]; ///< No use + uint8_t OPT[OPT_SIZE]; ///< Option +} RIP_MSG; + + + +uint8_t DHCP_SOCKET; // Socket number for DHCP + +uint8_t DHCP_SIP[4]; // DHCP Server IP address + +// Network information from DHCP Server +uint8_t OLD_allocated_ip[4] = {0, }; // Previous IP address +uint8_t DHCP_allocated_ip[4] = {0, }; // IP address from DHCP +uint8_t DHCP_allocated_gw[4] = {0, }; // Gateway address from DHCP +uint8_t DHCP_allocated_sn[4] = {0, }; // Subnet mask from DHCP +uint8_t DHCP_allocated_dns[4] = {0, }; // DNS address from DHCP + + +int8_t dhcp_state = STATE_DHCP_INIT; // DHCP state +int8_t dhcp_retry_count = 0; + +uint32_t dhcp_lease_time = INFINITE_LEASETIME; +volatile uint32_t dhcp_tick_1s = 0; // unit 1 second +uint32_t dhcp_tick_next = DHCP_WAIT_TIME ; + +uint32_t DHCP_XID; // Any number + +RIP_MSG* pDHCPMSG; // Buffer pointer for DHCP processing + +uint8_t HOST_NAME[] = DCHP_HOST_NAME; + +uint8_t DHCP_CHADDR[6]; // DHCP Client MAC address. + +/* The default callback function */ +void default_ip_assign(void); +void default_ip_update(void); +void default_ip_conflict(void); + +/* Callback handler */ +void (*dhcp_ip_assign)(void) = default_ip_assign; /* handler to be called when the IP address from DHCP server is first assigned */ +void (*dhcp_ip_update)(void) = default_ip_update; /* handler to be called when the IP address from DHCP server is updated */ +void (*dhcp_ip_conflict)(void) = default_ip_conflict; /* handler to be called when the IP address from DHCP server is conflict */ + +void reg_dhcp_cbfunc(void(*ip_assign)(void), void(*ip_update)(void), void(*ip_conflict)(void)); + + +/* send DISCOVER message to DHCP server */ +void send_DHCP_DISCOVER(void); + +/* send REQEUST message to DHCP server */ +void send_DHCP_REQUEST(void); + +/* send DECLINE message to DHCP server */ +void send_DHCP_DECLINE(void); + +/* IP conflict check by sending ARP-request to leased IP and wait ARP-response. */ +int8_t check_DHCP_leasedIP(void); + +/* check the timeout in DHCP process */ +uint8_t check_DHCP_timeout(void); + +/* Intialize to timeout process. */ +void reset_DHCP_timeout(void); + +/* Parse message as OFFER and ACK and NACK from DHCP server.*/ +int8_t parseDHCPCMSG(void); + +/* The default handler of ip assign first */ +void default_ip_assign(void) +{ + setSIPR(DHCP_allocated_ip); + setSUBR(DHCP_allocated_sn); + setGAR (DHCP_allocated_gw); +} + +/* The default handler of ip changed */ +void default_ip_update(void) +{ + /* WIZchip Software Reset */ + setMR(MR_RST); + getMR(); // for delay + default_ip_assign(); + setSHAR(DHCP_CHADDR); +} + +/* The default handler of ip changed */ +void default_ip_conflict(void) +{ + // WIZchip Software Reset + setMR(MR_RST); + getMR(); // for delay + setSHAR(DHCP_CHADDR); +} + +/* register the call back func. */ +void reg_dhcp_cbfunc(void(*ip_assign)(void), void(*ip_update)(void), void(*ip_conflict)(void)) +{ + dhcp_ip_assign = default_ip_assign; + dhcp_ip_update = default_ip_update; + dhcp_ip_conflict = default_ip_conflict; + if(ip_assign) dhcp_ip_assign = ip_assign; + if(ip_update) dhcp_ip_update = ip_update; + if(ip_conflict) dhcp_ip_conflict = ip_conflict; +} + +/* make the common DHCP message */ +void makeDHCPMSG(void) +{ + uint8_t bk_mac[6]; + uint8_t* ptmp; + uint8_t i; + getSHAR(bk_mac); + pDHCPMSG->op = DHCP_BOOTREQUEST; + pDHCPMSG->htype = DHCP_HTYPE10MB; + pDHCPMSG->hlen = DHCP_HLENETHERNET; + pDHCPMSG->hops = DHCP_HOPS; + ptmp = (uint8_t*)(&pDHCPMSG->xid); + *(ptmp+0) = (uint8_t)((DHCP_XID & 0xFF000000) >> 24); + *(ptmp+1) = (uint8_t)((DHCP_XID & 0x00FF0000) >> 16); + *(ptmp+2) = (uint8_t)((DHCP_XID & 0x0000FF00) >> 8); + *(ptmp+3) = (uint8_t)((DHCP_XID & 0x000000FF) >> 0); + pDHCPMSG->secs = DHCP_SECS; + ptmp = (uint8_t*)(&pDHCPMSG->flags); + *(ptmp+0) = (uint8_t)((DHCP_FLAGSBROADCAST & 0xFF00) >> 8); + *(ptmp+1) = (uint8_t)((DHCP_FLAGSBROADCAST & 0x00FF) >> 0); + + pDHCPMSG->ciaddr[0] = 0; + pDHCPMSG->ciaddr[1] = 0; + pDHCPMSG->ciaddr[2] = 0; + pDHCPMSG->ciaddr[3] = 0; + + pDHCPMSG->yiaddr[0] = 0; + pDHCPMSG->yiaddr[1] = 0; + pDHCPMSG->yiaddr[2] = 0; + pDHCPMSG->yiaddr[3] = 0; + + pDHCPMSG->siaddr[0] = 0; + pDHCPMSG->siaddr[1] = 0; + pDHCPMSG->siaddr[2] = 0; + pDHCPMSG->siaddr[3] = 0; + + pDHCPMSG->giaddr[0] = 0; + pDHCPMSG->giaddr[1] = 0; + pDHCPMSG->giaddr[2] = 0; + pDHCPMSG->giaddr[3] = 0; + + pDHCPMSG->chaddr[0] = DHCP_CHADDR[0]; + pDHCPMSG->chaddr[1] = DHCP_CHADDR[1]; + pDHCPMSG->chaddr[2] = DHCP_CHADDR[2]; + pDHCPMSG->chaddr[3] = DHCP_CHADDR[3]; + pDHCPMSG->chaddr[4] = DHCP_CHADDR[4]; + pDHCPMSG->chaddr[5] = DHCP_CHADDR[5]; + + for (i = 6; i < 16; i++) pDHCPMSG->chaddr[i] = 0; + for (i = 0; i < 64; i++) pDHCPMSG->sname[i] = 0; + for (i = 0; i < 128; i++) pDHCPMSG->file[i] = 0; + + // MAGIC_COOKIE + pDHCPMSG->OPT[0] = (uint8_t)((MAGIC_COOKIE & 0xFF000000) >> 24); + pDHCPMSG->OPT[1] = (uint8_t)((MAGIC_COOKIE & 0x00FF0000) >> 16); + pDHCPMSG->OPT[2] = (uint8_t)((MAGIC_COOKIE & 0x0000FF00) >> 8); + pDHCPMSG->OPT[3] = (uint8_t) (MAGIC_COOKIE & 0x000000FF) >> 0; +} + +/* SEND DHCP DISCOVER */ +void send_DHCP_DISCOVER(void) +{ + uint16_t i; + uint8_t ip[4]; + uint16_t k = 0; + + makeDHCPMSG(); + + k = 4; // because MAGIC_COOKIE already made by makeDHCPMSG() + + // Option Request Param + pDHCPMSG->OPT[k++] = dhcpMessageType; + pDHCPMSG->OPT[k++] = 0x01; + pDHCPMSG->OPT[k++] = DHCP_DISCOVER; + + // Client identifier + pDHCPMSG->OPT[k++] = dhcpClientIdentifier; + pDHCPMSG->OPT[k++] = 0x07; + pDHCPMSG->OPT[k++] = 0x01; + pDHCPMSG->OPT[k++] = DHCP_CHADDR[0]; + pDHCPMSG->OPT[k++] = DHCP_CHADDR[1]; + pDHCPMSG->OPT[k++] = DHCP_CHADDR[2]; + pDHCPMSG->OPT[k++] = DHCP_CHADDR[3]; + pDHCPMSG->OPT[k++] = DHCP_CHADDR[4]; + pDHCPMSG->OPT[k++] = DHCP_CHADDR[5]; + + // host name + pDHCPMSG->OPT[k++] = hostName; + pDHCPMSG->OPT[k++] = 0; // fill zero length of hostname + for(i = 0 ; HOST_NAME[i] != 0; i++) + pDHCPMSG->OPT[k++] = HOST_NAME[i]; + pDHCPMSG->OPT[k++] = DHCP_CHADDR[3]; + pDHCPMSG->OPT[k++] = DHCP_CHADDR[4]; + pDHCPMSG->OPT[k++] = DHCP_CHADDR[5]; + pDHCPMSG->OPT[k - (i+3+1)] = i+3; // length of hostname + + pDHCPMSG->OPT[k++] = dhcpParamRequest; + pDHCPMSG->OPT[k++] = 0x06; // length of request + pDHCPMSG->OPT[k++] = subnetMask; + pDHCPMSG->OPT[k++] = routersOnSubnet; + pDHCPMSG->OPT[k++] = dns; + pDHCPMSG->OPT[k++] = domainName; + pDHCPMSG->OPT[k++] = dhcpT1value; + pDHCPMSG->OPT[k++] = dhcpT2value; + pDHCPMSG->OPT[k++] = endOption; + + for (i = k; i < OPT_SIZE; i++) pDHCPMSG->OPT[i] = 0; + + // send broadcasting packet + ip[0] = 255; + ip[1] = 255; + ip[2] = 255; + ip[3] = 255; + +#ifdef _DHCP_DEBUG_ + printf("> Send DHCP_DISCOVER\r\n"); +#endif + + WIZCHIP_EXPORT(sendto)(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT); +} + +/* SEND DHCP REQUEST */ +void send_DHCP_REQUEST(void) +{ + int i; + uint8_t ip[4]; + uint16_t k = 0; + + makeDHCPMSG(); + + if(dhcp_state == STATE_DHCP_LEASED || dhcp_state == STATE_DHCP_REREQUEST) + { + *((uint8_t*)(&pDHCPMSG->flags)) = ((DHCP_FLAGSUNICAST & 0xFF00)>> 8); + *((uint8_t*)(&pDHCPMSG->flags)+1) = (DHCP_FLAGSUNICAST & 0x00FF); + pDHCPMSG->ciaddr[0] = DHCP_allocated_ip[0]; + pDHCPMSG->ciaddr[1] = DHCP_allocated_ip[1]; + pDHCPMSG->ciaddr[2] = DHCP_allocated_ip[2]; + pDHCPMSG->ciaddr[3] = DHCP_allocated_ip[3]; + ip[0] = DHCP_SIP[0]; + ip[1] = DHCP_SIP[1]; + ip[2] = DHCP_SIP[2]; + ip[3] = DHCP_SIP[3]; + } + else + { + ip[0] = 255; + ip[1] = 255; + ip[2] = 255; + ip[3] = 255; + } + + k = 4; // because MAGIC_COOKIE already made by makeDHCPMSG() + + // Option Request Param. + pDHCPMSG->OPT[k++] = dhcpMessageType; + pDHCPMSG->OPT[k++] = 0x01; + pDHCPMSG->OPT[k++] = DHCP_REQUEST; + + pDHCPMSG->OPT[k++] = dhcpClientIdentifier; + pDHCPMSG->OPT[k++] = 0x07; + pDHCPMSG->OPT[k++] = 0x01; + pDHCPMSG->OPT[k++] = DHCP_CHADDR[0]; + pDHCPMSG->OPT[k++] = DHCP_CHADDR[1]; + pDHCPMSG->OPT[k++] = DHCP_CHADDR[2]; + pDHCPMSG->OPT[k++] = DHCP_CHADDR[3]; + pDHCPMSG->OPT[k++] = DHCP_CHADDR[4]; + pDHCPMSG->OPT[k++] = DHCP_CHADDR[5]; + + if(ip[3] == 255) // if(dchp_state == STATE_DHCP_LEASED || dchp_state == DHCP_REREQUEST_STATE) + { + pDHCPMSG->OPT[k++] = dhcpRequestedIPaddr; + pDHCPMSG->OPT[k++] = 0x04; + pDHCPMSG->OPT[k++] = DHCP_allocated_ip[0]; + pDHCPMSG->OPT[k++] = DHCP_allocated_ip[1]; + pDHCPMSG->OPT[k++] = DHCP_allocated_ip[2]; + pDHCPMSG->OPT[k++] = DHCP_allocated_ip[3]; + + pDHCPMSG->OPT[k++] = dhcpServerIdentifier; + pDHCPMSG->OPT[k++] = 0x04; + pDHCPMSG->OPT[k++] = DHCP_SIP[0]; + pDHCPMSG->OPT[k++] = DHCP_SIP[1]; + pDHCPMSG->OPT[k++] = DHCP_SIP[2]; + pDHCPMSG->OPT[k++] = DHCP_SIP[3]; + } + + // host name + pDHCPMSG->OPT[k++] = hostName; + pDHCPMSG->OPT[k++] = 0; // length of hostname + for(i = 0 ; HOST_NAME[i] != 0; i++) + pDHCPMSG->OPT[k++] = HOST_NAME[i]; + pDHCPMSG->OPT[k++] = DHCP_CHADDR[3]; + pDHCPMSG->OPT[k++] = DHCP_CHADDR[4]; + pDHCPMSG->OPT[k++] = DHCP_CHADDR[5]; + pDHCPMSG->OPT[k - (i+3+1)] = i+3; // length of hostname + + pDHCPMSG->OPT[k++] = dhcpParamRequest; + pDHCPMSG->OPT[k++] = 0x08; + pDHCPMSG->OPT[k++] = subnetMask; + pDHCPMSG->OPT[k++] = routersOnSubnet; + pDHCPMSG->OPT[k++] = dns; + pDHCPMSG->OPT[k++] = domainName; + pDHCPMSG->OPT[k++] = dhcpT1value; + pDHCPMSG->OPT[k++] = dhcpT2value; + pDHCPMSG->OPT[k++] = performRouterDiscovery; + pDHCPMSG->OPT[k++] = staticRoute; + pDHCPMSG->OPT[k++] = endOption; + + for (i = k; i < OPT_SIZE; i++) pDHCPMSG->OPT[i] = 0; + +#ifdef _DHCP_DEBUG_ + printf("> Send DHCP_REQUEST\r\n"); +#endif + + WIZCHIP_EXPORT(sendto)(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT); + +} + +/* SEND DHCP DHCPDECLINE */ +void send_DHCP_DECLINE(void) +{ + int i; + uint8_t ip[4]; + uint16_t k = 0; + + makeDHCPMSG(); + + k = 4; // because MAGIC_COOKIE already made by makeDHCPMSG() + + *((uint8_t*)(&pDHCPMSG->flags)) = ((DHCP_FLAGSUNICAST & 0xFF00)>> 8); + *((uint8_t*)(&pDHCPMSG->flags)+1) = (DHCP_FLAGSUNICAST & 0x00FF); + + // Option Request Param. + pDHCPMSG->OPT[k++] = dhcpMessageType; + pDHCPMSG->OPT[k++] = 0x01; + pDHCPMSG->OPT[k++] = DHCP_DECLINE; + + pDHCPMSG->OPT[k++] = dhcpClientIdentifier; + pDHCPMSG->OPT[k++] = 0x07; + pDHCPMSG->OPT[k++] = 0x01; + pDHCPMSG->OPT[k++] = DHCP_CHADDR[0]; + pDHCPMSG->OPT[k++] = DHCP_CHADDR[1]; + pDHCPMSG->OPT[k++] = DHCP_CHADDR[2]; + pDHCPMSG->OPT[k++] = DHCP_CHADDR[3]; + pDHCPMSG->OPT[k++] = DHCP_CHADDR[4]; + pDHCPMSG->OPT[k++] = DHCP_CHADDR[5]; + + pDHCPMSG->OPT[k++] = dhcpRequestedIPaddr; + pDHCPMSG->OPT[k++] = 0x04; + pDHCPMSG->OPT[k++] = DHCP_allocated_ip[0]; + pDHCPMSG->OPT[k++] = DHCP_allocated_ip[1]; + pDHCPMSG->OPT[k++] = DHCP_allocated_ip[2]; + pDHCPMSG->OPT[k++] = DHCP_allocated_ip[3]; + + pDHCPMSG->OPT[k++] = dhcpServerIdentifier; + pDHCPMSG->OPT[k++] = 0x04; + pDHCPMSG->OPT[k++] = DHCP_SIP[0]; + pDHCPMSG->OPT[k++] = DHCP_SIP[1]; + pDHCPMSG->OPT[k++] = DHCP_SIP[2]; + pDHCPMSG->OPT[k++] = DHCP_SIP[3]; + + pDHCPMSG->OPT[k++] = endOption; + + for (i = k; i < OPT_SIZE; i++) pDHCPMSG->OPT[i] = 0; + + //send broadcasting packet + ip[0] = 0xFF; + ip[1] = 0xFF; + ip[2] = 0xFF; + ip[3] = 0xFF; + +#ifdef _DHCP_DEBUG_ + printf("\r\n> Send DHCP_DECLINE\r\n"); +#endif + + WIZCHIP_EXPORT(sendto)(DHCP_SOCKET, (uint8_t *)pDHCPMSG, RIP_MSG_SIZE, ip, DHCP_SERVER_PORT); +} + +/* PARSE REPLY pDHCPMSG */ +int8_t parseDHCPMSG(void) +{ + uint8_t svr_addr[6]; + uint16_t svr_port; + uint16_t len; + + uint8_t * p; + uint8_t * e; + uint8_t type; + uint8_t opt_len; + + if((len = getSn_RX_RSR(DHCP_SOCKET)) > 0) + { + len = WIZCHIP_EXPORT(recvfrom)(DHCP_SOCKET, (uint8_t *)pDHCPMSG, len, svr_addr, &svr_port); + #ifdef _DHCP_DEBUG_ + printf("DHCP message : %d.%d.%d.%d(%d) %d received. \r\n",svr_addr[0],svr_addr[1],svr_addr[2], svr_addr[3],svr_port, len); + #endif + } + else return 0; + if (svr_port == DHCP_SERVER_PORT) { + // compare mac address + if ( (pDHCPMSG->chaddr[0] != DHCP_CHADDR[0]) || (pDHCPMSG->chaddr[1] != DHCP_CHADDR[1]) || + (pDHCPMSG->chaddr[2] != DHCP_CHADDR[2]) || (pDHCPMSG->chaddr[3] != DHCP_CHADDR[3]) || + (pDHCPMSG->chaddr[4] != DHCP_CHADDR[4]) || (pDHCPMSG->chaddr[5] != DHCP_CHADDR[5]) ) + return 0; + type = 0; + p = (uint8_t *)(&pDHCPMSG->op); + p = p + 240; // 240 = sizeof(RIP_MSG) + MAGIC_COOKIE size in RIP_MSG.opt - sizeof(RIP_MSG.opt) + e = p + (len - 240); + + while ( p < e ) { + + switch ( *p ) { + + case endOption : + p = e; // for break while(p < e) + break; + case padOption : + p++; + break; + case dhcpMessageType : + p++; + p++; + type = *p++; + break; + case subnetMask : + p++; + p++; + DHCP_allocated_sn[0] = *p++; + DHCP_allocated_sn[1] = *p++; + DHCP_allocated_sn[2] = *p++; + DHCP_allocated_sn[3] = *p++; + break; + case routersOnSubnet : + p++; + opt_len = *p++; + DHCP_allocated_gw[0] = *p++; + DHCP_allocated_gw[1] = *p++; + DHCP_allocated_gw[2] = *p++; + DHCP_allocated_gw[3] = *p++; + p = p + (opt_len - 4); + break; + case dns : + p++; + opt_len = *p++; + DHCP_allocated_dns[0] = *p++; + DHCP_allocated_dns[1] = *p++; + DHCP_allocated_dns[2] = *p++; + DHCP_allocated_dns[3] = *p++; + p = p + (opt_len - 4); + break; + case dhcpIPaddrLeaseTime : + p++; + opt_len = *p++; + dhcp_lease_time = *p++; + dhcp_lease_time = (dhcp_lease_time << 8) + *p++; + dhcp_lease_time = (dhcp_lease_time << 8) + *p++; + dhcp_lease_time = (dhcp_lease_time << 8) + *p++; + #ifdef _DHCP_DEBUG_ + dhcp_lease_time = 10; + #endif + break; + case dhcpServerIdentifier : + p++; + opt_len = *p++; + DHCP_SIP[0] = *p++; + DHCP_SIP[1] = *p++; + DHCP_SIP[2] = *p++; + DHCP_SIP[3] = *p++; + break; + default : + p++; + opt_len = *p++; + p += opt_len; + break; + } // switch + } // while + } // if + return type; +} + +uint8_t DHCP_run(void) +{ + uint8_t type; + uint8_t ret; + + if(dhcp_state == STATE_DHCP_STOP) return DHCP_STOPPED; + + if(getSn_SR(DHCP_SOCKET) != SOCK_UDP) + WIZCHIP_EXPORT(socket)(DHCP_SOCKET, Sn_MR_UDP, DHCP_CLIENT_PORT, 0x00); + + ret = DHCP_RUNNING; + type = parseDHCPMSG(); + + switch ( dhcp_state ) { + case STATE_DHCP_INIT : + DHCP_allocated_ip[0] = 0; + DHCP_allocated_ip[1] = 0; + DHCP_allocated_ip[2] = 0; + DHCP_allocated_ip[3] = 0; + send_DHCP_DISCOVER(); + dhcp_state = STATE_DHCP_DISCOVER; + break; + case STATE_DHCP_DISCOVER : + if (type == DHCP_OFFER){ +#ifdef _DHCP_DEBUG_ + printf("> Receive DHCP_OFFER\r\n"); +#endif + DHCP_allocated_ip[0] = pDHCPMSG->yiaddr[0]; + DHCP_allocated_ip[1] = pDHCPMSG->yiaddr[1]; + DHCP_allocated_ip[2] = pDHCPMSG->yiaddr[2]; + DHCP_allocated_ip[3] = pDHCPMSG->yiaddr[3]; + + send_DHCP_REQUEST(); + dhcp_state = STATE_DHCP_REQUEST; + } else ret = check_DHCP_timeout(); + break; + + case STATE_DHCP_REQUEST : + if (type == DHCP_ACK) { + +#ifdef _DHCP_DEBUG_ + printf("> Receive DHCP_ACK\r\n"); +#endif + if (check_DHCP_leasedIP()) { + // Network info assignment from DHCP + dhcp_ip_assign(); + reset_DHCP_timeout(); + + dhcp_state = STATE_DHCP_LEASED; + } else { + // IP address conflict occurred + reset_DHCP_timeout(); + dhcp_ip_conflict(); + dhcp_state = STATE_DHCP_INIT; + } + } else if (type == DHCP_NAK) { + +#ifdef _DHCP_DEBUG_ + printf("> Receive DHCP_NACK\r\n"); +#endif + + reset_DHCP_timeout(); + + dhcp_state = STATE_DHCP_DISCOVER; + } else ret = check_DHCP_timeout(); + break; + + case STATE_DHCP_LEASED : + ret = DHCP_IP_LEASED; + if ((dhcp_lease_time != INFINITE_LEASETIME) && ((dhcp_lease_time/2) < dhcp_tick_1s)) { + +#ifdef _DHCP_DEBUG_ + printf("> Maintains the IP address \r\n"); +#endif + + type = 0; + OLD_allocated_ip[0] = DHCP_allocated_ip[0]; + OLD_allocated_ip[1] = DHCP_allocated_ip[1]; + OLD_allocated_ip[2] = DHCP_allocated_ip[2]; + OLD_allocated_ip[3] = DHCP_allocated_ip[3]; + + DHCP_XID++; + + send_DHCP_REQUEST(); + + reset_DHCP_timeout(); + + dhcp_state = STATE_DHCP_REREQUEST; + } + break; + + case STATE_DHCP_REREQUEST : + ret = DHCP_IP_LEASED; + if (type == DHCP_ACK) { + dhcp_retry_count = 0; + if (OLD_allocated_ip[0] != DHCP_allocated_ip[0] || + OLD_allocated_ip[1] != DHCP_allocated_ip[1] || + OLD_allocated_ip[2] != DHCP_allocated_ip[2] || + OLD_allocated_ip[3] != DHCP_allocated_ip[3]) + { + ret = DHCP_IP_CHANGED; + dhcp_ip_update(); + #ifdef _DHCP_DEBUG_ + printf(">IP changed.\r\n"); + #endif + + } + #ifdef _DHCP_DEBUG_ + else printf(">IP is continued.\r\n"); + #endif + reset_DHCP_timeout(); + dhcp_state = STATE_DHCP_LEASED; + } else if (type == DHCP_NAK) { + +#ifdef _DHCP_DEBUG_ + printf("> Receive DHCP_NACK, Failed to maintain ip\r\n"); +#endif + + reset_DHCP_timeout(); + + dhcp_state = STATE_DHCP_DISCOVER; + } else ret = check_DHCP_timeout(); + break; + default : + break; + } + + return ret; +} + +void DHCP_stop(void) +{ + WIZCHIP_EXPORT(close)(DHCP_SOCKET); + dhcp_state = STATE_DHCP_STOP; +} + +uint8_t check_DHCP_timeout(void) +{ + uint8_t ret = DHCP_RUNNING; + + if (dhcp_retry_count < MAX_DHCP_RETRY) { + if (dhcp_tick_next < dhcp_tick_1s) { + + switch ( dhcp_state ) { + case STATE_DHCP_DISCOVER : +// printf("<<timeout>> state : STATE_DHCP_DISCOVER\r\n"); + send_DHCP_DISCOVER(); + break; + + case STATE_DHCP_REQUEST : +// printf("<<timeout>> state : STATE_DHCP_REQUEST\r\n"); + + send_DHCP_REQUEST(); + break; + + case STATE_DHCP_REREQUEST : +// printf("<<timeout>> state : STATE_DHCP_REREQUEST\r\n"); + + send_DHCP_REQUEST(); + break; + + default : + break; + } + + dhcp_tick_1s = 0; + dhcp_tick_next = dhcp_tick_1s + DHCP_WAIT_TIME; + dhcp_retry_count++; + } + } else { // timeout occurred + + switch(dhcp_state) { + case STATE_DHCP_DISCOVER: + dhcp_state = STATE_DHCP_INIT; + ret = DHCP_FAILED; + break; + case STATE_DHCP_REQUEST: + case STATE_DHCP_REREQUEST: + send_DHCP_DISCOVER(); + dhcp_state = STATE_DHCP_DISCOVER; + break; + default : + break; + } + reset_DHCP_timeout(); + } + return ret; +} + +int8_t check_DHCP_leasedIP(void) +{ + uint8_t tmp; + int32_t ret; + + //WIZchip RCR value changed for ARP Timeout count control + tmp = getRCR(); + setRCR(0x03); + + // IP conflict detection : ARP request - ARP reply + // Broadcasting ARP Request for check the IP conflict using UDP sendto() function + ret = WIZCHIP_EXPORT(sendto)(DHCP_SOCKET, (uint8_t *)"CHECK_IP_CONFLICT", 17, DHCP_allocated_ip, 5000); + + // RCR value restore + setRCR(tmp); + + if(ret == SOCKERR_TIMEOUT) { + // UDP send Timeout occurred : allocated IP address is unique, DHCP Success + +#ifdef _DHCP_DEBUG_ + printf("\r\n> Check leased IP - OK\r\n"); +#endif + + return 1; + } else { + // Received ARP reply or etc : IP address conflict occur, DHCP Failed + send_DHCP_DECLINE(); + + ret = dhcp_tick_1s; + while((dhcp_tick_1s - ret) < 2) ; // wait for 1s over; wait to complete to send DECLINE message; + + return 0; + } +} + +void DHCP_init(uint8_t s, DHCP_INIT_BUFFER_TYPE* buf) +{ + uint8_t zeroip[4] = {0,0,0,0}; + getSHAR(DHCP_CHADDR); + if((DHCP_CHADDR[0] | DHCP_CHADDR[1] | DHCP_CHADDR[2] | DHCP_CHADDR[3] | DHCP_CHADDR[4] | DHCP_CHADDR[5]) == 0x00) + { + // assign temporary mac address, you should be set SHAR before call this function. + DHCP_CHADDR[0] = 0x00; + DHCP_CHADDR[1] = 0x08; + DHCP_CHADDR[2] = 0xdc; + DHCP_CHADDR[3] = 0x00; + DHCP_CHADDR[4] = 0x00; + DHCP_CHADDR[5] = 0x00; + setSHAR(DHCP_CHADDR); + } + + DHCP_SOCKET = s; // SOCK_DHCP + pDHCPMSG = (RIP_MSG*)buf; + DHCP_XID = 0x12345678; + + // WIZchip Netinfo Clear + setSIPR(zeroip); + setSIPR(zeroip); + setGAR(zeroip); + + reset_DHCP_timeout(); + dhcp_state = STATE_DHCP_INIT; +} + + +/* Rset the DHCP timeout count and retry count. */ +void reset_DHCP_timeout(void) +{ + dhcp_tick_1s = 0; + dhcp_tick_next = DHCP_WAIT_TIME; + dhcp_retry_count = 0; +} + +void DHCP_time_handler(void) +{ + dhcp_tick_1s++; +} + +void getIPfromDHCP(uint8_t* ip) +{ + ip[0] = DHCP_allocated_ip[0]; + ip[1] = DHCP_allocated_ip[1]; + ip[2] = DHCP_allocated_ip[2]; + ip[3] = DHCP_allocated_ip[3]; +} + +void getGWfromDHCP(uint8_t* ip) +{ + ip[0] =DHCP_allocated_gw[0]; + ip[1] =DHCP_allocated_gw[1]; + ip[2] =DHCP_allocated_gw[2]; + ip[3] =DHCP_allocated_gw[3]; +} + +void getSNfromDHCP(uint8_t* ip) +{ + ip[0] = DHCP_allocated_sn[0]; + ip[1] = DHCP_allocated_sn[1]; + ip[2] = DHCP_allocated_sn[2]; + ip[3] = DHCP_allocated_sn[3]; +} + +void getDNSfromDHCP(uint8_t* ip) +{ + ip[0] = DHCP_allocated_dns[0]; + ip[1] = DHCP_allocated_dns[1]; + ip[2] = DHCP_allocated_dns[2]; + ip[3] = DHCP_allocated_dns[3]; +} + +uint32_t getDHCPLeasetime(void) +{ + return dhcp_lease_time; +} + + + + diff --git a/drivers/wiznet5k/internet/dhcp/dhcp.h b/drivers/wiznet5k/internet/dhcp/dhcp.h new file mode 100644 index 000000000..881bf5a6c --- /dev/null +++ b/drivers/wiznet5k/internet/dhcp/dhcp.h @@ -0,0 +1,152 @@ +//***************************************************************************** +// +//! \file dhcp.h +//! \brief DHCP APIs Header file. +//! \details Processig DHCP protocol as DISCOVER, OFFER, REQUEST, ACK, NACK and DECLINE. +//! \version 1.1.0 +//! \date 2013/11/18 +//! \par Revision history +//! <2013/11/18> 1st Release +//! <2012/12/20> V1.1.0 +//! 1. Move unreferenced DEFINE to dhcp.c +//! <2012/12/26> V1.1.1 +//! \author Eric Jung & MidnightCow +//! \copyright +//! +//! Copyright (c) 2013, WIZnet Co., LTD. +//! All rights reserved. +//! +//! Redistribution and use in source and binary forms, with or without +//! modification, are permitted provided that the following conditions +//! are met: +//! +//! * Redistributions of source code must retain the above copyright +//! notice, this list of conditions and the following disclaimer. +//! * Redistributions in binary form must reproduce the above copyright +//! notice, this list of conditions and the following disclaimer in the +//! documentation and/or other materials provided with the distribution. +//! * Neither the name of the <ORGANIZATION> nor the names of its +//! contributors may be used to endorse or promote products derived +//! from this software without specific prior written permission. +//! +//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +//! THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** +#ifndef _DHCP_H_ +#define _DHCP_H_ + +/* + * @brief + * @details If you want to display debug & processing message, Define _DHCP_DEBUG_ + * @note If defined, it depends on <stdio.h> + */ + +//#define _DHCP_DEBUG_ + +/* Retry to processing DHCP */ +#define MAX_DHCP_RETRY 2 ///< Maximum retry count +#define DHCP_WAIT_TIME 3 ///< Wait Time 3s (was 10s) + +/* UDP port numbers for DHCP */ +#define DHCP_SERVER_PORT 67 ///< DHCP server port number +#define DHCP_CLIENT_PORT 68 ///< DHCP client port number + +#define MAGIC_COOKIE 0x63825363 ///< Any number. You can be modified it any number + +#define DCHP_HOST_NAME "WIZnet\0" + +/* + * @brief return value of @ref DHCP_run() + */ +enum +{ + DHCP_FAILED = 0, ///< Processing Fail + DHCP_RUNNING, ///< Processing DHCP protocol + DHCP_IP_ASSIGN, ///< First Occupy IP from DHPC server (if cbfunc == null, act as default default_ip_assign) + DHCP_IP_CHANGED, ///< Change IP address by new IP address from DHCP (if cbfunc == null, act as default default_ip_update) + DHCP_IP_LEASED, ///< Stand by + DHCP_STOPPED ///< Stop processing DHCP protocol +}; + +#define DHCP_INIT_BUFFER_TYPE uint32_t +#define DHCP_INIT_BUFFER_SIZE (137) +/* + * @brief DHCP client initialization (outside of the main loop) + * @param s - socket number + * @param buf - buffer for processing DHCP message + */ +void DHCP_init(uint8_t s, DHCP_INIT_BUFFER_TYPE* buf); + +/* + * @brief DHCP 1s Tick Timer handler + * @note SHOULD BE register to your system 1s Tick timer handler + */ +void DHCP_time_handler(void); + +/* + * @brief Register call back function + * @param ip_assign - callback func when IP is assigned from DHCP server first + * @param ip_update - callback func when IP is changed + * @prarm ip_conflict - callback func when the assigned IP is conflict with others. + */ +void reg_dhcp_cbfunc(void(*ip_assign)(void), void(*ip_update)(void), void(*ip_conflict)(void)); + +/* + * @brief DHCP client in the main loop + * @return The value is as the follow \n + * @ref DHCP_FAILED \n + * @ref DHCP_RUNNING \n + * @ref DHCP_IP_ASSIGN \n + * @ref DHCP_IP_CHANGED \n + * @ref DHCP_IP_LEASED \n + * @ref DHCP_STOPPED \n + * + * @note This function is always called by you main task. + */ +uint8_t DHCP_run(void); + +/* + * @brief Stop DHCP processing + * @note If you want to restart. call DHCP_init() and DHCP_run() + */ +void DHCP_stop(void); + +/* Get Network information assigned from DHCP server */ +/* + * @brief Get IP address + * @param ip - IP address to be returned + */ +void getIPfromDHCP(uint8_t* ip); +/* + * @brief Get Gateway address + * @param ip - Gateway address to be returned + */ +void getGWfromDHCP(uint8_t* ip); +/* + * @brief Get Subnet mask value + * @param ip - Subnet mask to be returned + */ +void getSNfromDHCP(uint8_t* ip); +/* + * @brief Get DNS address + * @param ip - DNS address to be returned + */ +void getDNSfromDHCP(uint8_t* ip); + +/* + * @brief Get the leased time by DHCP sever + * @return unit 1s + */ +uint32_t getDHCPLeasetime(void); + +#endif /* _DHCP_H_ */ diff --git a/drivers/wiznet5k/internet/dns/dns.c b/drivers/wiznet5k/internet/dns/dns.c new file mode 100644 index 000000000..daf4db123 --- /dev/null +++ b/drivers/wiznet5k/internet/dns/dns.c @@ -0,0 +1,572 @@ +//***************************************************************************** +// +//! \file dns.c +//! \brief DNS APIs Implement file. +//! \details Send DNS query & Receive DNS reponse. \n +//! It depends on stdlib.h & string.h in ansi-c library +//! \version 1.1.0 +//! \date 2013/11/18 +//! \par Revision history +//! <2013/10/21> 1st Release +//! <2013/12/20> V1.1.0 +//! 1. Remove secondary DNS server in DNS_run +//! If 1st DNS_run failed, call DNS_run with 2nd DNS again +//! 2. DNS_timerHandler -> DNS_time_handler +//! 3. Remove the unused define +//! 4. Integrated dns.h dns.c & dns_parse.h dns_parse.c into dns.h & dns.c +//! <2013/12/20> V1.1.0 +//! <2018/10/04> Modified HAL_GetTick for use with CircuitPython by Nick Moore +//! +//! \author Eric Jung & MidnightCow +//! \copyright +//! +//! Copyright (c) 2013, WIZnet Co., LTD. +//! All rights reserved. +//! +//! Redistribution and use in source and binary forms, with or without +//! modification, are permitted provided that the following conditions +//! are met: +//! +//! * Redistributions of source code must retain the above copyright +//! notice, this list of conditions and the following disclaimer. +//! * Redistributions in binary form must reproduce the above copyright +//! notice, this list of conditions and the following disclaimer in the +//! documentation and/or other materials provided with the distribution. +//! * Neither the name of the <ORGANIZATION> nor the names of its +//! contributors may be used to endorse or promote products derived +//! from this software without specific prior written permission. +//! +//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +//! THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + +#include <string.h> +#include <stdlib.h> +#include "tick.h" + +//#include "Ethernet/socket.h" +//#include "Internet/DNS/dns.h" +#include "../../ethernet/socket.h" +#include "dns.h" + +#ifdef _DNS_DEBUG_ + #include <stdio.h> +#endif + +#define INITRTT 2000L /* Initial smoothed response time */ +#define MAXCNAME (MAX_DOMAIN_NAME + (MAX_DOMAIN_NAME>>1)) /* Maximum amount of cname recursion */ + +#define TYPE_A 1 /* Host address */ +#define TYPE_NS 2 /* Name server */ +#define TYPE_MD 3 /* Mail destination (obsolete) */ +#define TYPE_MF 4 /* Mail forwarder (obsolete) */ +#define TYPE_CNAME 5 /* Canonical name */ +#define TYPE_SOA 6 /* Start of Authority */ +#define TYPE_MB 7 /* Mailbox name (experimental) */ +#define TYPE_MG 8 /* Mail group member (experimental) */ +#define TYPE_MR 9 /* Mail rename name (experimental) */ +#define TYPE_NULL 10 /* Null (experimental) */ +#define TYPE_WKS 11 /* Well-known sockets */ +#define TYPE_PTR 12 /* Pointer record */ +#define TYPE_HINFO 13 /* Host information */ +#define TYPE_MINFO 14 /* Mailbox information (experimental)*/ +#define TYPE_MX 15 /* Mail exchanger */ +#define TYPE_TXT 16 /* Text strings */ +#define TYPE_ANY 255 /* Matches any type */ + +#define CLASS_IN 1 /* The ARPA Internet */ + +/* Round trip timing parameters */ +#define AGAIN 8 /* Average RTT gain = 1/8 */ +#define LAGAIN 3 /* Log2(AGAIN) */ +#define DGAIN 4 /* Mean deviation gain = 1/4 */ +#define LDGAIN 2 /* log2(DGAIN) */ + +/* Header for all domain messages */ +struct dhdr +{ + uint16_t id; /* Identification */ + uint8_t qr; /* Query/Response */ +#define QUERY 0 +#define RESPONSE 1 + uint8_t opcode; +#define IQUERY 1 + uint8_t aa; /* Authoratative answer */ + uint8_t tc; /* Truncation */ + uint8_t rd; /* Recursion desired */ + uint8_t ra; /* Recursion available */ + uint8_t rcode; /* Response code */ +#define NO_ERROR 0 +#define FORMAT_ERROR 1 +#define SERVER_FAIL 2 +#define NAME_ERROR 3 +#define NOT_IMPL 4 +#define REFUSED 5 + uint16_t qdcount; /* Question count */ + uint16_t ancount; /* Answer count */ + uint16_t nscount; /* Authority (name server) count */ + uint16_t arcount; /* Additional record count */ +}; + + +uint8_t* pDNSMSG; // DNS message buffer +uint8_t DNS_SOCKET; // SOCKET number for DNS +uint16_t DNS_MSGID; // DNS message ID + + +uint32_t HAL_GetTick(void) { + return ticks_ms; +} + +uint32_t hal_sys_tick; + +/* converts uint16_t from network buffer to a host byte order integer. */ +uint16_t get16(uint8_t * s) +{ + uint16_t i; + i = *s++ << 8; + i = i + *s; + return i; +} + +/* copies uint16_t to the network buffer with network byte order. */ +uint8_t * put16(uint8_t * s, uint16_t i) +{ + *s++ = i >> 8; + *s++ = i; + return s; +} + + +/* + * CONVERT A DOMAIN NAME TO THE HUMAN-READABLE FORM + * + * Description : This function converts a compressed domain name to the human-readable form + * Arguments : msg - is a pointer to the reply message + * compressed - is a pointer to the domain name in reply message. + * buf - is a pointer to the buffer for the human-readable form name. + * len - is the MAX. size of buffer. + * Returns : the length of compressed message + */ +int parse_name(uint8_t * msg, uint8_t * compressed, char * buf, int16_t len) +{ + uint16_t slen; /* Length of current segment */ + uint8_t * cp; + int clen = 0; /* Total length of compressed name */ + int indirect = 0; /* Set if indirection encountered */ + int nseg = 0; /* Total number of segments in name */ + + cp = compressed; + + for (;;) + { + slen = *cp++; /* Length of this segment */ + + if (!indirect) clen++; + + if ((slen & 0xc0) == 0xc0) + { + if (!indirect) + clen++; + indirect = 1; + /* Follow indirection */ + cp = &msg[((slen & 0x3f)<<8) + *cp]; + slen = *cp++; + } + + if (slen == 0) /* zero length == all done */ + break; + + len -= slen + 1; + + if (len < 0) return -1; + + if (!indirect) clen += slen; + + while (slen-- != 0) *buf++ = (char)*cp++; + *buf++ = '.'; + nseg++; + } + + if (nseg == 0) + { + /* Root name; represent as single dot */ + *buf++ = '.'; + len--; + } + + *buf++ = '\0'; + len--; + + return clen; /* Length of compressed message */ +} + +/* + * PARSE QUESTION SECTION + * + * Description : This function parses the question record of the reply message. + * Arguments : msg - is a pointer to the reply message + * cp - is a pointer to the question record. + * Returns : a pointer the to next record. + */ +uint8_t * dns_question(uint8_t * msg, uint8_t * cp) +{ + int len; + char name[MAXCNAME]; + + len = parse_name(msg, cp, name, MAXCNAME); + + + if (len == -1) return 0; + + cp += len; + cp += 2; /* type */ + cp += 2; /* class */ + + return cp; +} + + +/* + * PARSE ANSER SECTION + * + * Description : This function parses the answer record of the reply message. + * Arguments : msg - is a pointer to the reply message + * cp - is a pointer to the answer record. + * Returns : a pointer the to next record. + */ +uint8_t * dns_answer(uint8_t * msg, uint8_t * cp, uint8_t * ip_from_dns) +{ + int len, type; + char name[MAXCNAME]; + + len = parse_name(msg, cp, name, MAXCNAME); + + if (len == -1) return 0; + + cp += len; + type = get16(cp); + cp += 2; /* type */ + cp += 2; /* class */ + cp += 4; /* ttl */ + cp += 2; /* len */ + + + switch (type) + { + case TYPE_A: + /* Just read the address directly into the structure */ + ip_from_dns[0] = *cp++; + ip_from_dns[1] = *cp++; + ip_from_dns[2] = *cp++; + ip_from_dns[3] = *cp++; + break; + case TYPE_CNAME: + case TYPE_MB: + case TYPE_MG: + case TYPE_MR: + case TYPE_NS: + case TYPE_PTR: + /* These types all consist of a single domain name */ + /* convert it to ASCII format */ + len = parse_name(msg, cp, name, MAXCNAME); + if (len == -1) return 0; + + cp += len; + break; + case TYPE_HINFO: + len = *cp++; + cp += len; + + len = *cp++; + cp += len; + break; + case TYPE_MX: + cp += 2; + /* Get domain name of exchanger */ + len = parse_name(msg, cp, name, MAXCNAME); + if (len == -1) return 0; + + cp += len; + break; + case TYPE_SOA: + /* Get domain name of name server */ + len = parse_name(msg, cp, name, MAXCNAME); + if (len == -1) return 0; + + cp += len; + + /* Get domain name of responsible person */ + len = parse_name(msg, cp, name, MAXCNAME); + if (len == -1) return 0; + + cp += len; + + cp += 4; + cp += 4; + cp += 4; + cp += 4; + cp += 4; + break; + case TYPE_TXT: + /* Just stash */ + break; + default: + /* Ignore */ + break; + } + + return cp; +} + +/* + * PARSE THE DNS REPLY + * + * Description : This function parses the reply message from DNS server. + * Arguments : dhdr - is a pointer to the header for DNS message + * buf - is a pointer to the reply message. + * len - is the size of reply message. + * Returns : -1 - Domain name length is too big + * 0 - Fail (Timeout or parse error) + * 1 - Success, + */ +int8_t parseDNSMSG(struct dhdr * pdhdr, uint8_t * pbuf, uint8_t * ip_from_dns) +{ + uint16_t tmp; + uint16_t i; + uint8_t * msg; + uint8_t * cp; + + msg = pbuf; + memset(pdhdr, 0, sizeof(*pdhdr)); + + pdhdr->id = get16(&msg[0]); + tmp = get16(&msg[2]); + if (tmp & 0x8000) pdhdr->qr = 1; + + pdhdr->opcode = (tmp >> 11) & 0xf; + + if (tmp & 0x0400) pdhdr->aa = 1; + if (tmp & 0x0200) pdhdr->tc = 1; + if (tmp & 0x0100) pdhdr->rd = 1; + if (tmp & 0x0080) pdhdr->ra = 1; + + pdhdr->rcode = tmp & 0xf; + pdhdr->qdcount = get16(&msg[4]); + pdhdr->ancount = get16(&msg[6]); + pdhdr->nscount = get16(&msg[8]); + pdhdr->arcount = get16(&msg[10]); + + + /* Now parse the variable length sections */ + cp = &msg[12]; + + /* Question section */ + for (i = 0; i < pdhdr->qdcount; i++) + { + cp = dns_question(msg, cp); + if(!cp) + { +#ifdef _DNS_DEBUG_ + printf("MAX_DOMAIN_NAME is too small, it should be redefined in dns.h\r\n"); +#endif + return -1; + } + } + + /* Answer section */ + for (i = 0; i < pdhdr->ancount; i++) + { + cp = dns_answer(msg, cp, ip_from_dns); + if(!cp) + { +#ifdef _DNS_DEBUG_ + printf("MAX_DOMAIN_NAME is too small, it should be redefined in dns.h\r\n"); +#endif + return -1; + } + + } + + /* Name server (authority) section */ + for (i = 0; i < pdhdr->nscount; i++) + { + ; + } + + /* Additional section */ + for (i = 0; i < pdhdr->arcount; i++) + { + ; + } + + if(pdhdr->rcode == 0) return 1; // No error + else return 0; +} + + +/* + * MAKE DNS QUERY MESSAGE + * + * Description : This function makes DNS query message. + * Arguments : op - Recursion desired + * name - is a pointer to the domain name. + * buf - is a pointer to the buffer for DNS message. + * len - is the MAX. size of buffer. + * Returns : the pointer to the DNS message. + */ +int16_t dns_makequery(uint16_t op, char * name, uint8_t * buf, uint16_t len) +{ + uint8_t *cp; + char *cp1; + char sname[MAXCNAME]; + char *dname; + uint16_t p; + uint16_t dlen; + + cp = buf; + + DNS_MSGID++; + cp = put16(cp, DNS_MSGID); + p = (op << 11) | 0x0100; /* Recursion desired */ + cp = put16(cp, p); + cp = put16(cp, 1); + cp = put16(cp, 0); + cp = put16(cp, 0); + cp = put16(cp, 0); + + strcpy(sname, name); + dname = sname; + dlen = strlen(dname); + for (;;) + { + /* Look for next dot */ + cp1 = strchr(dname, '.'); + + if (cp1 != NULL) len = cp1 - dname; /* More to come */ + else len = dlen; /* Last component */ + + *cp++ = len; /* Write length of component */ + if (len == 0) break; + + /* Copy component up to (but not including) dot */ + memcpy(cp, dname, len); + cp += len; + if (cp1 == NULL) + { + *cp++ = 0; /* Last one; write null and finish */ + break; + } + dname += len+1; + dlen -= len+1; + } + + cp = put16(cp, 0x0001); /* type */ + cp = put16(cp, 0x0001); /* class */ + + return ((int16_t)((uint32_t)(cp) - (uint32_t)(buf))); +} + +/* + * CHECK DNS TIMEOUT + * + * Description : This function check the DNS timeout + * Arguments : None. + * Returns : -1 - timeout occurred, 0 - timer over, but no timeout, 1 - no timer over, no timeout occur + * Note : timeout : retry count and timer both over. + */ + +int8_t check_DNS_timeout(void) +{ + static uint8_t retry_count; + + uint32_t tick = HAL_GetTick(); + if(tick - hal_sys_tick >= DNS_WAIT_TIME * 1000) + { + hal_sys_tick = tick; + if(retry_count >= MAX_DNS_RETRY) { + retry_count = 0; + return -1; // timeout occurred + } + retry_count++; + return 0; // timer over, but no timeout + } + + return 1; // no timer over, no timeout occur +} + + + +/* DNS CLIENT INIT */ +void DNS_init(uint8_t s, uint8_t * buf) +{ + DNS_SOCKET = s; // SOCK_DNS + pDNSMSG = buf; // User's shared buffer + DNS_MSGID = DNS_MSG_ID; +} + +/* DNS CLIENT RUN */ +int8_t DNS_run(uint8_t * dns_ip, uint8_t * name, uint8_t * ip_from_dns) +{ + int8_t ret; + struct dhdr dhp; + uint8_t ip[4]; + uint16_t len, port; + int8_t ret_check_timeout; + + hal_sys_tick = HAL_GetTick(); + + // Socket open + WIZCHIP_EXPORT(socket)(DNS_SOCKET, Sn_MR_UDP, 0, 0); + +#ifdef _DNS_DEBUG_ + printf("> DNS Query to DNS Server : %d.%d.%d.%d\r\n", dns_ip[0], dns_ip[1], dns_ip[2], dns_ip[3]); +#endif + + len = dns_makequery(0, (char *)name, pDNSMSG, MAX_DNS_BUF_SIZE); + WIZCHIP_EXPORT(sendto)(DNS_SOCKET, pDNSMSG, len, dns_ip, IPPORT_DOMAIN); + + while (1) + { + if ((len = getSn_RX_RSR(DNS_SOCKET)) > 0) + { + if (len > MAX_DNS_BUF_SIZE) len = MAX_DNS_BUF_SIZE; + len = WIZCHIP_EXPORT(recvfrom)(DNS_SOCKET, pDNSMSG, len, ip, &port); + #ifdef _DNS_DEBUG_ + printf("> Receive DNS message from %d.%d.%d.%d(%d). len = %d\r\n", ip[0], ip[1], ip[2], ip[3],port,len); + #endif + ret = parseDNSMSG(&dhp, pDNSMSG, ip_from_dns); + break; + } + // Check Timeout + ret_check_timeout = check_DNS_timeout(); + if (ret_check_timeout < 0) { + +#ifdef _DNS_DEBUG_ + printf("> DNS Server is not responding : %d.%d.%d.%d\r\n", dns_ip[0], dns_ip[1], dns_ip[2], dns_ip[3]); +#endif + return 0; // timeout occurred + } + else if (ret_check_timeout == 0) { + +#ifdef _DNS_DEBUG_ + printf("> DNS Timeout\r\n"); +#endif + WIZCHIP_EXPORT(sendto)(DNS_SOCKET, pDNSMSG, len, dns_ip, IPPORT_DOMAIN); + } + } + WIZCHIP_EXPORT(close)(DNS_SOCKET); + // Return value + // 0 > : failed / 1 - success + return ret; +} diff --git a/drivers/wiznet5k/internet/dns/dns.h b/drivers/wiznet5k/internet/dns/dns.h new file mode 100644 index 000000000..de0039515 --- /dev/null +++ b/drivers/wiznet5k/internet/dns/dns.h @@ -0,0 +1,96 @@ +//***************************************************************************** +// +//! \file dns.h +//! \brief DNS APIs Header file. +//! \details Send DNS query & Receive DNS reponse. +//! \version 1.1.0 +//! \date 2013/11/18 +//! \par Revision history +//! <2013/10/21> 1st Release +//! <2013/12/20> V1.1.0 +//! 1. Remove secondary DNS server in DNS_run +//! If 1st DNS_run failed, call DNS_run with 2nd DNS again +//! 2. DNS_timerHandler -> DNS_time_handler +//! 3. Move the no reference define to dns.c +//! 4. Integrated dns.h dns.c & dns_parse.h dns_parse.c into dns.h & dns.c +//! <2013/12/20> V1.1.0 +//! +//! \author Eric Jung & MidnightCow +//! \copyright +//! +//! Copyright (c) 2013, WIZnet Co., LTD. +//! All rights reserved. +//! +//! Redistribution and use in source and binary forms, with or without +//! modification, are permitted provided that the following conditions +//! are met: +//! +//! * Redistributions of source code must retain the above copyright +//! notice, this list of conditions and the following disclaimer. +//! * Redistributions in binary form must reproduce the above copyright +//! notice, this list of conditions and the following disclaimer in the +//! documentation and/or other materials provided with the distribution. +//! * Neither the name of the <ORGANIZATION> nor the names of its +//! contributors may be used to endorse or promote products derived +//! from this software without specific prior written permission. +//! +//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +//! THE POSSIBILITY OF SUCH DAMAGE. +// +//***************************************************************************** + +#ifndef _DNS_H_ +#define _DNS_H_ + +#include <stdint.h> +/* + * @brief Define it for Debug & Monitor DNS processing. + * @note If defined, it depends on <stdio.h> + */ + +//#define _DNS_DEBUG_ + +#define MAX_DNS_BUF_SIZE 256 ///< maximum size of DNS buffer. */ +/* + * @brief Maximum length of your queried Domain name + * @todo SHOULD BE defined it equal as or greater than your Domain name length + null character(1) + * @note SHOULD BE careful to stack overflow because it is allocated 1.5 times as MAX_DOMAIN_NAME in stack. + */ +#define MAX_DOMAIN_NAME 32 // for example "www.google.com" + +#define MAX_DNS_RETRY 2 ///< Requery Count +#define DNS_WAIT_TIME 4 ///< Wait response time. unit 1s. + +#define IPPORT_DOMAIN 53 ///< DNS server port number + +#define DNS_MSG_ID 0x1122 ///< ID for DNS message. You can be modified it any number +/* + * @brief DNS process initialize + * @param s : Socket number for DNS + * @param buf : Buffer for DNS message + */ +void DNS_init(uint8_t s, uint8_t * buf); + +/* + * @brief DNS process + * @details Send DNS query and receive DNS response + * @param dns_ip : DNS server ip address + * @param name : Domain name to be queried + * @param ip_from_dns : IP address from DNS server + * @return -1 : failed. @ref MAX_DOMIN_NAME is too small \n + * 0 : failed (Timeout or Parse error)\n + * 1 : success + * @note This function blocks until success or fail. max time = @ref MAX_DNS_RETRY * @ref DNS_WAIT_TIME + */ +int8_t DNS_run(uint8_t * dns_ip, uint8_t * name, uint8_t * ip_from_dns); + +#endif /* _DNS_H_ */ diff --git a/frozen/Adafruit_CircuitPython_BusDevice b/frozen/Adafruit_CircuitPython_BusDevice -Subproject 07919641470edb602585c6a91f7b8eacf17e664 +Subproject d86fc7e81d51465ca1eae6f8c1141f81f065f5a diff --git a/frozen/Adafruit_CircuitPython_CircuitPlayground b/frozen/Adafruit_CircuitPython_CircuitPlayground -Subproject d0aa6dc56d66decfae92daced7384c1e3518a66 +Subproject f4ee725fb93fd1a31666d3f71d10c94eb96df7c diff --git a/frozen/Adafruit_CircuitPython_Crickit b/frozen/Adafruit_CircuitPython_Crickit -Subproject 44f52c5dacd9fc605565e5794e95c9a785aaf69 +Subproject 412392c8bdb6b4378e007eb7974c76b92fa9ff1 diff --git a/frozen/Adafruit_CircuitPython_DotStar b/frozen/Adafruit_CircuitPython_DotStar -Subproject af25424ee7dbebea3e5d77390c017018ffa52d3 +Subproject 03c24157d46672c723021686f7a838cfeb2db2b diff --git a/frozen/Adafruit_CircuitPython_HID b/frozen/Adafruit_CircuitPython_HID -Subproject 5c2f6ef1ed80f24b6a3878067d40350d3725e19 +Subproject f5e70e09250f2a25ebb6487a30a763041644c5d diff --git a/frozen/Adafruit_CircuitPython_IRRemote b/frozen/Adafruit_CircuitPython_IRRemote -Subproject c29e10b590efbdf06163897b49cd0c2bea82ad6 +Subproject ec11164ec6682094a48d0f9848d2c4c89c08f3b diff --git a/frozen/Adafruit_CircuitPython_LIS3DH b/frozen/Adafruit_CircuitPython_LIS3DH -Subproject c4152a0d87a04903ae0e612eb381af440c9e28b +Subproject 6298cd363811ad6ac10d4325c898be87a70d7bb diff --git a/frozen/Adafruit_CircuitPython_Motor b/frozen/Adafruit_CircuitPython_Motor -Subproject e0b709f1710555da67705360870ba0d14ced7e0 +Subproject 4421e79661002ff8da6c0c4f22940ec843ee300 diff --git a/frozen/Adafruit_CircuitPython_NeoPixel b/frozen/Adafruit_CircuitPython_NeoPixel -Subproject e9f50cb6678a1684591ee021b95a3c4b51786fe +Subproject 72e8f3855ecd136641d536a49311c38ee4f76f3 diff --git a/frozen/Adafruit_CircuitPython_Thermistor b/frozen/Adafruit_CircuitPython_Thermistor -Subproject 00f4ebca6c740b76c1c464f83d514ac20b0600e +Subproject eae584918e72ff5fa323825470f276b31829ef9 diff --git a/frozen/Adafruit_CircuitPython_seesaw b/frozen/Adafruit_CircuitPython_seesaw -Subproject 340cd17fad0c29d3a70d6e298a30ecc753df054 +Subproject c92c22ff029ee05bd392299cf25887e9af48903 diff --git a/lib/oofatfs/ff.c b/lib/oofatfs/ff.c index 4e8680545..b0984756b 100644 --- a/lib/oofatfs/ff.c +++ b/lib/oofatfs/ff.c @@ -2579,8 +2579,8 @@ FRESULT create_name ( /* FR_OK: successful, FR_INVALID_NAME: could not create if (w < 0x80 && chk_chr("\"*:<>\?|\x7F", w)) return FR_INVALID_NAME; /* Reject illegal characters for LFN */ lfn[di++] = w; /* Store the Unicode character */ } - cf = ((w < ' ') || ((w == '/' || w == '\\') && p[si+1] < ' ')) ? NS_LAST : 0; /* Set last segment flag if end of the path */ *path = &p[si]; /* Return pointer to the next segment */ + cf = (w < ' ') ? NS_LAST : 0; /* Set last segment flag if end of the path */ #if _FS_RPATH != 0 if ((di == 1 && lfn[di - 1] == '.') || (di == 2 && lfn[di - 1] == '.' && lfn[di - 2] == '.')) { /* Is this segment a dot name? */ diff --git a/lib/tinyusb b/lib/tinyusb -Subproject 583326e535454f16b06ebdb9cc06869602a5564 +Subproject 47fabe42edaae4a5da6aa0d48c664a918457875 diff --git a/lib/utils/stdout_helpers.c b/lib/utils/stdout_helpers.c index 3de119757..4323e8a08 100644 --- a/lib/utils/stdout_helpers.c +++ b/lib/utils/stdout_helpers.c @@ -12,11 +12,21 @@ // Send "cooked" string of given length, where every occurrence of // LF character is replaced with CR LF. void mp_hal_stdout_tx_strn_cooked(const char *str, size_t len) { - while (len--) { - if (*str == '\n') { + bool last_cr = false; + while (len > 0) { + size_t i = 0; + if (str[0] == '\n' && !last_cr) { mp_hal_stdout_tx_strn("\r", 1); + i = 1; } - mp_hal_stdout_tx_strn(str++, 1); + // Lump all characters on the next line together. + while((last_cr || str[i] != '\n') && i < len) { + last_cr = str[i] == '\r'; + i++; + } + mp_hal_stdout_tx_strn(str, i); + str = &str[i]; + len -= i; } } diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index 513ec8efd..34467c7b5 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-09-21 12:23-0400\n" +"POT-Creation-Date: 2018-11-09 16:20-0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -147,78 +147,78 @@ msgstr "" msgid "invalid arguments" msgstr "" -#: lib/utils/pyexec.c:97 py/builtinimport.c:253 +#: lib/utils/pyexec.c:97 py/builtinimport.c:251 msgid "script compilation not supported" msgstr "" -#: main.c:143 +#: main.c:154 msgid " output:\n" msgstr "" -#: main.c:157 main.c:230 +#: main.c:168 main.c:241 msgid "" "Auto-reload is on. Simply save files over USB to run them or enter REPL to " "disable.\n" msgstr "" -#: main.c:159 +#: main.c:170 msgid "Running in safe mode! Auto-reload is off.\n" msgstr "" -#: main.c:161 main.c:232 +#: main.c:172 main.c:243 msgid "Auto-reload is off.\n" msgstr "" -#: main.c:175 +#: main.c:186 msgid "Running in safe mode! Not running saved code.\n" msgstr "" -#: main.c:191 +#: main.c:202 msgid "WARNING: Your code filename has two extensions\n" msgstr "" -#: main.c:239 +#: main.c:250 msgid "You requested starting safe mode by " msgstr "" -#: main.c:242 +#: main.c:253 msgid "To exit, please reset the board without " msgstr "" -#: main.c:249 +#: main.c:260 msgid "" "You are running in safe mode which means something really bad happened.\n" msgstr "" -#: main.c:251 +#: main.c:262 msgid "Looks like our core CircuitPython code crashed hard. Whoops!\n" msgstr "" -#: main.c:252 +#: main.c:263 msgid "Please file an issue here with the contents of your CIRCUITPY drive:\n" msgstr "" -#: main.c:255 +#: main.c:266 msgid "" "The microcontroller's power dipped. Please make sure your power supply " "provides\n" msgstr "" -#: main.c:256 +#: main.c:267 msgid "" "enough power for the whole circuit and press reset (after ejecting " "CIRCUITPY).\n" msgstr "" -#: main.c:260 +#: main.c:271 msgid "Press any key to enter the REPL. Use CTRL-D to reload." msgstr "" -#: main.c:416 +#: main.c:429 msgid "soft reboot\n" msgstr "" -#: ports/atmel-samd/audio_dma.c:285 +#: ports/atmel-samd/audio_dma.c:209 #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c:361 msgid "All sync event channels in use" msgstr "" @@ -291,12 +291,12 @@ msgid "Too many channels in sample." msgstr "" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:305 -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:339 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:417 msgid "No DMA channel found" msgstr "" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:308 -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:341 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:419 msgid "Unable to allocate buffers for signed conversion" msgstr "" @@ -312,43 +312,44 @@ msgstr "" msgid "sampling rate out of range" msgstr "" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:69 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:132 msgid "DAC already in use" msgstr "" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:73 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:136 msgid "Right channel unsupported" msgstr "" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:76 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:139 #: ports/atmel-samd/common-hal/pulseio/PWMOut.c:116 #: ports/atmel-samd/common-hal/touchio/TouchIn.c:65 msgid "Invalid pin" msgstr "" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:84 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:147 msgid "Invalid pin for left channel" msgstr "" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:88 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:151 msgid "Invalid pin for right channel" msgstr "" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:91 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:154 msgid "Cannot output both channels on the same pin" msgstr "" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:176 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:243 #: ports/atmel-samd/common-hal/pulseio/PWMOut.c:189 #: ports/atmel-samd/common-hal/pulseio/PulseOut.c:110 +#: ports/nrf/common-hal/pulseio/PulseOut.c:107 msgid "All timers in use" msgstr "" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:218 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:285 msgid "All event channels in use" msgstr "" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:297 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:375 #, c-format msgid "Sample rate too high. It must be less than %d" msgstr "" @@ -358,10 +359,10 @@ msgid "Not enough pins available" msgstr "" #: ports/atmel-samd/common-hal/busio/I2C.c:78 -#: ports/atmel-samd/common-hal/busio/SPI.c:132 +#: ports/atmel-samd/common-hal/busio/SPI.c:171 #: ports/atmel-samd/common-hal/busio/UART.c:119 #: ports/atmel-samd/common-hal/i2cslave/I2CSlave.c:45 -#: ports/nrf/common-hal/busio/I2C.c:77 +#: ports/nrf/common-hal/busio/I2C.c:82 msgid "Invalid pins" msgstr "" @@ -378,10 +379,12 @@ msgid "bytes > 8 bits not supported" msgstr "" #: ports/atmel-samd/common-hal/busio/UART.c:72 +#: ports/nrf/common-hal/busio/UART.c:82 msgid "tx and rx cannot both be None" msgstr "" #: ports/atmel-samd/common-hal/busio/UART.c:145 +#: ports/nrf/common-hal/busio/UART.c:115 msgid "Failed to allocate RX buffer" msgstr "" @@ -390,15 +393,17 @@ msgid "Could not initialize UART" msgstr "" #: ports/atmel-samd/common-hal/busio/UART.c:240 +#: ports/nrf/common-hal/busio/UART.c:149 msgid "No RX pin" msgstr "" #: ports/atmel-samd/common-hal/busio/UART.c:294 +#: ports/nrf/common-hal/busio/UART.c:195 msgid "No TX pin" msgstr "" #: ports/atmel-samd/common-hal/digitalio/DigitalInOut.c:170 -#: ports/nrf/common-hal/digitalio/DigitalInOut.c:142 +#: ports/nrf/common-hal/digitalio/DigitalInOut.c:147 msgid "Cannot get pull while in output mode" msgstr "" @@ -409,7 +414,8 @@ msgstr "" #: ports/atmel-samd/common-hal/pulseio/PWMOut.c:120 #: ports/atmel-samd/common-hal/pulseio/PWMOut.c:369 -#: ports/nrf/common-hal/pulseio/PWMOut.c:227 +#: ports/nrf/common-hal/pulseio/PWMOut.c:119 +#: ports/nrf/common-hal/pulseio/PWMOut.c:233 msgid "Invalid PWM frequency" msgstr "" @@ -457,30 +463,10 @@ msgstr "" msgid "calibration value out of range +/-127" msgstr "" -#: ports/atmel-samd/common-hal/storage/__init__.c:48 -msgid "Cannot remount '/' when USB is active." -msgstr "" - #: ports/atmel-samd/common-hal/touchio/TouchIn.c:75 msgid "No free GCLKs" msgstr "" -#: ports/atmel-samd/common-hal/usb_hid/Device.c:78 -#: ports/nrf/common-hal/usb_hid/Device.c:45 -#, c-format -msgid "Buffer incorrect size. Should be %d bytes." -msgstr "" - -#: ports/atmel-samd/common-hal/usb_hid/Device.c:82 -#: ports/nrf/common-hal/usb_hid/Device.c:53 -msgid "USB Busy" -msgstr "" - -#: ports/atmel-samd/common-hal/usb_hid/Device.c:82 -#: ports/nrf/common-hal/usb_hid/Device.c:59 -msgid "USB Error" -msgstr "" - #: ports/esp8266/common-hal/analogio/AnalogIn.c:43 msgid "Pin %q does not have ADC capabilities" msgstr "" @@ -690,130 +676,165 @@ msgstr "" msgid "AnalogOut functionality not supported" msgstr "" -#: ports/nrf/common-hal/busio/I2C.c:91 -msgid "All I2C peripherals are in use" +#: ports/nrf/common-hal/bleio/Adapter.c:41 +#, c-format +msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX" msgstr "" -#: ports/nrf/common-hal/busio/SPI.c:109 -msgid "All SPI peripherals are in use" +#: ports/nrf/common-hal/bleio/Adapter.c:125 +#, c-format +msgid "Failed to change softdevice state, error: 0x%08lX" msgstr "" -#: ports/nrf/common-hal/busio/SPI.c:170 -msgid "Baud rate too high for this SPI peripheral" +#: ports/nrf/common-hal/bleio/Adapter.c:135 +#, c-format +msgid "Failed to get softdevice state, error: 0x%08lX" msgstr "" -#: ports/nrf/common-hal/busio/UART.c:43 ports/nrf/common-hal/busio/UART.c:47 -#: ports/nrf/common-hal/busio/UART.c:51 ports/nrf/common-hal/busio/UART.c:60 -#: ports/nrf/common-hal/busio/UART.c:66 ports/nrf/common-hal/busio/UART.c:71 -#: ports/nrf/common-hal/busio/UART.c:76 ports/nrf/common-hal/busio/UART.c:81 -#: ports/nrf/common-hal/busio/UART.c:86 ports/nrf/common-hal/busio/UART.c:90 -msgid "busio.UART not yet implemented" +#: ports/nrf/common-hal/bleio/Adapter.c:155 +#, c-format +msgid "Failed to get local address, error: 0x%08lX" msgstr "" -#: ports/nrf/common-hal/microcontroller/Processor.c:49 +#: ports/nrf/common-hal/bleio/Characteristic.c:52 #, c-format -msgid "Can not get temperature. status: 0x%02x" +msgid "Failed to write gatts value, status: 0x%08lX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:199 -msgid "Cannot apply GAP parameters." +#: ports/nrf/common-hal/bleio/Characteristic.c:76 +#, c-format +msgid "Failed to notify attribute value, status: 0x%08lX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:213 -msgid "Cannot set PPCP parameters." +#: ports/nrf/common-hal/bleio/Characteristic.c:91 +#, c-format +msgid "Failed to read attribute value, status: 0x%08lX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:245 -msgid "Can not query for the device address." +#: ports/nrf/common-hal/bleio/Characteristic.c:119 +#: ports/nrf/common-hal/bleio/Device.c:272 +#: ports/nrf/common-hal/bleio/Device.c:307 +#, c-format +msgid "Failed to acquire mutex, status: 0x%08lX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:264 -msgid "Can not add Vendor Specific 128-bit UUID." +#: ports/nrf/common-hal/bleio/Characteristic.c:126 +#, c-format +msgid "Failed to write attribute value, status: 0x%08lX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:284 -#: ports/nrf/drivers/bluetooth/ble_drv.c:298 -msgid "Can not add Service." +#: ports/nrf/common-hal/bleio/Characteristic.c:138 +#: ports/nrf/common-hal/bleio/Device.c:284 +#: ports/nrf/common-hal/bleio/Device.c:319 +#: ports/nrf/common-hal/bleio/Device.c:354 +#: ports/nrf/common-hal/bleio/Device.c:391 +#, c-format +msgid "Failed to release mutex, status: 0x%08lX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:373 -msgid "Can not add Characteristic." +#: ports/nrf/common-hal/bleio/Device.c:81 +#: ports/nrf/common-hal/bleio/Device.c:114 +msgid "Can not fit data into the advertisment packet" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:400 -msgid "Can not apply device name in the stack." +#: ports/nrf/common-hal/bleio/Device.c:266 +#, c-format +msgid "Failed to discover serivices, status: 0x%08lX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:464 -#: ports/nrf/drivers/bluetooth/ble_drv.c:514 -msgid "Can not encode UUID, to check length." +#: ports/nrf/common-hal/bleio/Device.c:403 +#: ports/nrf/common-hal/bleio/Scanner.c:76 +#, c-format +msgid "Failed to continue scanning, status: 0x%0xlX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:470 -#: ports/nrf/drivers/bluetooth/ble_drv.c:520 -msgid "Can encode UUID into the advertisment packet." +#: ports/nrf/common-hal/bleio/Device.c:436 +#, c-format +msgid "Failed to connect, status: 0x%08lX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:545 -msgid "Can not fit data into the advertisment packet." +#: ports/nrf/common-hal/bleio/Device.c:513 +#, c-format +msgid "Failed to add service, status: 0x%08lX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:558 -#: ports/nrf/drivers/bluetooth/ble_drv.c:604 +#: ports/nrf/common-hal/bleio/Device.c:531 #, c-format -msgid "Can not apply advertisment data. status: 0x%02x" +msgid "Failed to start advertisment, status: 0x%08lX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:614 +#: ports/nrf/common-hal/bleio/Device.c:549 #, c-format -msgid "Can not start advertisment. status: 0x%02x" +msgid "Failed to stop advertisment, status: 0x%08lX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:631 +#: ports/nrf/common-hal/bleio/Device.c:575 +#: ports/nrf/common-hal/bleio/Scanner.c:103 #, c-format -msgid "Can not stop advertisment. status: 0x%02x" +msgid "Failed to start scanning, status: 0x%0xlX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:650 -#: ports/nrf/drivers/bluetooth/ble_drv.c:726 +#: ports/nrf/common-hal/bleio/Device.c:592 #, c-format -msgid "Can not read attribute value. status: 0x%02x" +msgid "Failed to create mutex, status: 0x%0xlX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:667 -#: ports/nrf/drivers/bluetooth/ble_drv.c:756 +#: ports/nrf/common-hal/bleio/Service.c:83 #, c-format -msgid "Can not write attribute value. status: 0x%02x" +msgid "Failed to add characteristic, status: 0x%08lX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:691 +#: ports/nrf/common-hal/bleio/UUID.c:97 #, c-format -msgid "Can not notify attribute value. status: 0x%02x" +msgid "Failed to add Vendor Specific UUID, status: 0x%08lX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:784 -#, c-format -msgid "Can not start scanning. status: 0x%02x" +#: ports/nrf/common-hal/bleio/UUID.c:102 +msgid "Invalid UUID string length" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:829 +#: ports/nrf/common-hal/bleio/UUID.c:109 +#: shared-bindings/bleio/Characteristic.c:125 +#: shared-bindings/bleio/Service.c:105 +msgid "Invalid UUID parameter" +msgstr "" + +#: ports/nrf/common-hal/busio/I2C.c:96 +msgid "All I2C peripherals are in use" +msgstr "" + +#: ports/nrf/common-hal/busio/SPI.c:133 +msgid "All SPI peripherals are in use" +msgstr "" + +#: ports/nrf/common-hal/busio/UART.c:48 #, c-format -msgid "Can not connect. status: 0x%02x" +msgid "error = 0x%08lX" msgstr "" -#: ports/nrf/modules/ubluepy/ubluepy_characteristic.c:68 -#: ports/nrf/modules/ubluepy/ubluepy_service.c:80 -#: ports/nrf/modules/ubluepy/ubluepy_service.c:132 -#: ports/nrf/modules/ubluepy/ubluepy_uuid.c:137 -msgid "Invalid UUID parameter" +#: ports/nrf/common-hal/busio/UART.c:86 +msgid "Invalid buffer size" msgstr "" -#: ports/nrf/modules/ubluepy/ubluepy_service.c:73 -msgid "Invalid Service type" +#: ports/nrf/common-hal/busio/UART.c:90 +msgid "Odd parity is not supported" msgstr "" -#: ports/nrf/modules/ubluepy/ubluepy_uuid.c:127 -msgid "Invalid UUID string length" +#: ports/nrf/common-hal/busio/UART.c:322 ports/nrf/common-hal/busio/UART.c:326 +#: ports/nrf/common-hal/busio/UART.c:331 ports/nrf/common-hal/busio/UART.c:336 +#: ports/nrf/common-hal/busio/UART.c:342 ports/nrf/common-hal/busio/UART.c:347 +#: ports/nrf/common-hal/busio/UART.c:352 ports/nrf/common-hal/busio/UART.c:356 +#: ports/nrf/common-hal/busio/UART.c:364 +msgid "busio.UART not available" +msgstr "" + +#: ports/nrf/common-hal/microcontroller/Processor.c:49 +#, c-format +msgid "Can not get temperature. status: 0x%02x" +msgstr "" + +#: ports/nrf/common-hal/pulseio/PWMOut.c:161 +msgid "All PWM peripherals are in use" msgstr "" #: ports/unix/modffi.c:138 @@ -917,19 +938,33 @@ msgstr "" msgid "bad compile mode" msgstr "" -#: py/builtinimport.c:338 +#: py/builtinhelp.c:137 +msgid "Plus any modules on the filesystem\n" +msgstr "" + +#: py/builtinhelp.c:183 +#, c-format +msgid "" +"Welcome to Adafruit CircuitPython %s!\n" +"\n" +"Please visit learn.adafruit.com/category/circuitpython for project guides.\n" +"\n" +"To list built-in modules please do `help(\"modules\")`.\n" +msgstr "" + +#: py/builtinimport.c:336 msgid "cannot perform relative import" msgstr "" -#: py/builtinimport.c:422 py/builtinimport.c:534 +#: py/builtinimport.c:420 py/builtinimport.c:532 msgid "module not found" msgstr "" -#: py/builtinimport.c:425 py/builtinimport.c:537 +#: py/builtinimport.c:423 py/builtinimport.c:535 msgid "no module named '%q'" msgstr "" -#: py/builtinimport.c:512 +#: py/builtinimport.c:510 msgid "relative import" msgstr "" @@ -1078,38 +1113,85 @@ msgstr "" msgid "'data' requires integer arguments" msgstr "" -#: py/emitinlinextensa.c:86 -msgid "can only have up to 4 parameters to Xtensa assembly" +#: py/emitinlinethumb.c:102 +msgid "can only have up to 4 parameters to Thumb assembly" msgstr "" -#: py/emitinlinextensa.c:91 py/emitinlinextensa.c:96 -msgid "parameters must be registers in sequence a2 to a5" +#: py/emitinlinethumb.c:107 py/emitinlinethumb.c:112 +msgid "parameters must be registers in sequence r0 to r3" +msgstr "" + +#: py/emitinlinethumb.c:188 py/emitinlinethumb.c:230 +#, c-format +msgid "'%s' expects at most r%d" msgstr "" -#: py/emitinlinextensa.c:162 +#: py/emitinlinethumb.c:197 py/emitinlinextensa.c:162 #, c-format msgid "'%s' expects a register" msgstr "" -#: py/emitinlinextensa.c:169 +#: py/emitinlinethumb.c:211 +#, c-format +msgid "'%s' expects a special register" +msgstr "" + +#: py/emitinlinethumb.c:239 +#, c-format +msgid "'%s' expects an FPU register" +msgstr "" + +#: py/emitinlinethumb.c:292 +#, c-format +msgid "'%s' expects {r0, r1, ...}" +msgstr "" + +#: py/emitinlinethumb.c:299 py/emitinlinextensa.c:169 #, c-format msgid "'%s' expects an integer" msgstr "" -#: py/emitinlinextensa.c:174 +#: py/emitinlinethumb.c:304 #, c-format -msgid "'%s' integer %d is not within range %d..%d" +msgid "'%s' integer 0x%x does not fit in mask 0x%x" +msgstr "" + +#: py/emitinlinethumb.c:328 +#, c-format +msgid "'%s' expects an address of the form [a, b]" msgstr "" -#: py/emitinlinextensa.c:182 +#: py/emitinlinethumb.c:334 py/emitinlinextensa.c:182 #, c-format msgid "'%s' expects a label" msgstr "" -#: py/emitinlinextensa.c:193 +#: py/emitinlinethumb.c:345 py/emitinlinextensa.c:193 msgid "label '%q' not defined" msgstr "" +#: py/emitinlinethumb.c:806 +#, c-format +msgid "unsupported Thumb instruction '%s' with %d arguments" +msgstr "" + +#: py/emitinlinethumb.c:810 +msgid "branch not in range" +msgstr "" + +#: py/emitinlinextensa.c:86 +msgid "can only have up to 4 parameters to Xtensa assembly" +msgstr "" + +#: py/emitinlinextensa.c:91 py/emitinlinextensa.c:96 +msgid "parameters must be registers in sequence a2 to a5" +msgstr "" + +#: py/emitinlinextensa.c:174 +#, c-format +msgid "'%s' integer %d is not within range %d..%d" +msgstr "" + #: py/emitinlinextensa.c:327 #, c-format msgid "unsupported Xtensa instruction '%s' with %d arguments" @@ -1929,7 +2011,7 @@ msgid "AnalogOut is only 16 bits. Value must be less than 65536." msgstr "" #: shared-bindings/audiobusio/I2SOut.c:225 -#: shared-bindings/audioio/AudioOut.c:223 +#: shared-bindings/audioio/AudioOut.c:226 msgid "Not playing" msgstr "" @@ -1966,6 +2048,22 @@ msgid "" "destination buffer must be a bytearray or array of type 'B' for bit_depth = 8" msgstr "" +#: shared-bindings/audioio/Mixer.c:94 +msgid "Invalid voice count" +msgstr "" + +#: shared-bindings/audioio/Mixer.c:99 +msgid "Invalid channel count" +msgstr "" + +#: shared-bindings/audioio/Mixer.c:103 +msgid "Sample rate must be positive" +msgstr "" + +#: shared-bindings/audioio/Mixer.c:107 +msgid "bits_per_sample must be 8 or 16" +msgstr "" + #: shared-bindings/audioio/RawSample.c:98 msgid "" "sample_source buffer must be a bytearray or array of type 'h', 'H', 'b' or " @@ -1990,22 +2088,46 @@ msgstr "" msgid "Buffer must be at least length 1" msgstr "" -#: shared-bindings/bitbangio/SPI.c:151 shared-bindings/busio/SPI.c:168 +#: shared-bindings/bitbangio/SPI.c:151 shared-bindings/busio/SPI.c:175 msgid "Invalid polarity" msgstr "" -#: shared-bindings/bitbangio/SPI.c:155 shared-bindings/busio/SPI.c:172 +#: shared-bindings/bitbangio/SPI.c:155 shared-bindings/busio/SPI.c:179 msgid "Invalid phase" msgstr "" -#: shared-bindings/bitbangio/SPI.c:159 shared-bindings/busio/SPI.c:176 +#: shared-bindings/bitbangio/SPI.c:159 shared-bindings/busio/SPI.c:183 msgid "Invalid number of bits" msgstr "" -#: shared-bindings/bitbangio/SPI.c:284 shared-bindings/busio/SPI.c:341 +#: shared-bindings/bitbangio/SPI.c:284 shared-bindings/busio/SPI.c:348 msgid "buffer slices must be of equal length" msgstr "" +#: shared-bindings/bleio/Address.c:101 +msgid "Wrong address length" +msgstr "" + +#: shared-bindings/bleio/Address.c:107 +msgid "Wrong number of bytes provided" +msgstr "" + +#: shared-bindings/bleio/Device.c:210 +msgid "Can't add services in Central mode" +msgstr "" + +#: shared-bindings/bleio/Device.c:226 +msgid "Can't connect in Peripheral mode" +msgstr "" + +#: shared-bindings/bleio/Device.c:256 +msgid "Can't change the name in Central mode" +msgstr "" + +#: shared-bindings/bleio/Device.c:277 shared-bindings/bleio/Device.c:313 +msgid "Can't advertise in Central mode" +msgstr "" + #: shared-bindings/busio/I2C.c:120 msgid "Function requires lock." msgstr "" @@ -2120,7 +2242,7 @@ msgstr "" #: shared-bindings/microcontroller/Pin.c:89 #: shared-bindings/neopixel_write/__init__.c:67 -#: shared-bindings/pulseio/PulseOut.c:75 +#: shared-bindings/pulseio/PulseOut.c:76 msgid "Expected a %q" msgstr "" @@ -2163,7 +2285,7 @@ msgstr "" #: shared-bindings/pulseio/PWMOut.c:195 msgid "" -"PWM frequency not writeable when variable_frequency is False on construction." +"PWM frequency not writable when variable_frequency is False on construction." msgstr "" #: shared-bindings/pulseio/PulseIn.c:275 @@ -2182,7 +2304,7 @@ msgstr "" msgid "Read-only" msgstr "" -#: shared-bindings/pulseio/PulseOut.c:134 +#: shared-bindings/pulseio/PulseOut.c:135 msgid "Array must contain halfwords (type 'H')" msgstr "" @@ -2211,6 +2333,10 @@ msgstr "" msgid "RTC calibration is not supported on this board" msgstr "" +#: shared-bindings/socket/__init__.c:516 shared-module/network/__init__.c:81 +msgid "no available NIC" +msgstr "" + #: shared-bindings/storage/__init__.c:77 msgid "filesystem must provide mount method" msgstr "" @@ -2235,15 +2361,15 @@ msgstr "" msgid "time.struct_time() takes a 9-sequence" msgstr "" -#: shared-bindings/time/__init__.c:169 shared-bindings/time/__init__.c:250 +#: shared-bindings/time/__init__.c:169 shared-bindings/time/__init__.c:264 msgid "Tuple or struct_time argument required" msgstr "" -#: shared-bindings/time/__init__.c:174 shared-bindings/time/__init__.c:255 +#: shared-bindings/time/__init__.c:174 shared-bindings/time/__init__.c:269 msgid "function takes exactly 9 arguments" msgstr "" -#: shared-bindings/time/__init__.c:226 shared-bindings/time/__init__.c:259 +#: shared-bindings/time/__init__.c:240 shared-bindings/time/__init__.c:273 msgid "timestamp out of range for platform time_t" msgstr "" @@ -2256,6 +2382,34 @@ msgid "" "Object has been deinitialized and can no longer be used. Create a new object." msgstr "" +#: shared-module/audioio/Mixer.c:47 shared-module/audioio/WaveFile.c:117 +msgid "Couldn't allocate first buffer" +msgstr "" + +#: shared-module/audioio/Mixer.c:53 shared-module/audioio/WaveFile.c:123 +msgid "Couldn't allocate second buffer" +msgstr "" + +#: shared-module/audioio/Mixer.c:82 +msgid "Voice index too high" +msgstr "" + +#: shared-module/audioio/Mixer.c:85 +msgid "The sample's sample rate does not match the mixer's" +msgstr "" + +#: shared-module/audioio/Mixer.c:88 +msgid "The sample's channel count does not match the mixer's" +msgstr "" + +#: shared-module/audioio/Mixer.c:91 +msgid "The sample's bits_per_sample does not match the mixer's" +msgstr "" + +#: shared-module/audioio/Mixer.c:100 +msgid "The sample's signedness does not match the mixer's" +msgstr "" + #: shared-module/audioio/WaveFile.c:61 msgid "Invalid wave file" msgstr "" @@ -2276,39 +2430,31 @@ msgstr "" msgid "Invalid file" msgstr "" -#: shared-module/audioio/WaveFile.c:117 -msgid "Couldn't allocate first buffer" -msgstr "" - -#: shared-module/audioio/WaveFile.c:123 -msgid "Couldn't allocate second buffer" -msgstr "" - #: shared-module/bitbangio/I2C.c:58 msgid "Clock stretch too long" msgstr "" -#: shared-module/bitbangio/SPI.c:45 +#: shared-module/bitbangio/SPI.c:44 msgid "Clock pin init failed." msgstr "" -#: shared-module/bitbangio/SPI.c:51 +#: shared-module/bitbangio/SPI.c:50 msgid "MOSI pin init failed." msgstr "" -#: shared-module/bitbangio/SPI.c:62 +#: shared-module/bitbangio/SPI.c:61 msgid "MISO pin init failed." msgstr "" -#: shared-module/bitbangio/SPI.c:122 +#: shared-module/bitbangio/SPI.c:121 msgid "Cannot write without MOSI pin." msgstr "" -#: shared-module/bitbangio/SPI.c:177 +#: shared-module/bitbangio/SPI.c:176 msgid "Cannot read without MISO pin." msgstr "" -#: shared-module/bitbangio/SPI.c:241 +#: shared-module/bitbangio/SPI.c:240 msgid "Cannot transfer without MOSI and MISO pins." msgstr "" @@ -2342,6 +2488,10 @@ msgstr "" msgid "Only true color (24 bpp or higher) BMP supported %x" msgstr "" +#: shared-module/storage/__init__.c:155 +msgid "Cannot remount '/' when USB is active." +msgstr "" + #: shared-module/struct/__init__.c:39 msgid "'S' and 'O' are not supported format types" msgstr "" @@ -2349,3 +2499,16 @@ msgstr "" #: shared-module/struct/__init__.c:83 msgid "too many arguments provided with the given format" msgstr "" + +#: shared-module/usb_hid/Device.c:45 +#, c-format +msgid "Buffer incorrect size. Should be %d bytes." +msgstr "" + +#: shared-module/usb_hid/Device.c:53 +msgid "USB Busy" +msgstr "" + +#: shared-module/usb_hid/Device.c:59 +msgid "USB Error" +msgstr "" diff --git a/locale/de_DE.po b/locale/de_DE.po index 72f7b254d..7451d9b2a 100644 --- a/locale/de_DE.po +++ b/locale/de_DE.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-09-21 12:23-0400\n" +"POT-Creation-Date: 2018-11-09 16:20-0800\n" "PO-Revision-Date: 2018-07-27 11:55-0700\n" "Last-Translator: Sebastian Plamauer\n" "Language-Team: \n" @@ -93,7 +93,7 @@ msgstr "struct: index außerhalb gültigen Bereichs" #: extmod/moduheapq.c:38 msgid "heap must be a list" -msgstr "heap muss eine list sein" +msgstr "heap muss eine Liste sein" #: extmod/moduheapq.c:86 extmod/modutimeq.c:147 extmod/modutimeq.c:172 msgid "empty heap" @@ -147,15 +147,15 @@ msgstr "abort() wurde aufgerufen" msgid "invalid arguments" msgstr "ungültige argumente" -#: lib/utils/pyexec.c:97 py/builtinimport.c:253 +#: lib/utils/pyexec.c:97 py/builtinimport.c:251 msgid "script compilation not supported" msgstr "kompilieren von Skripten ist nicht unterstützt" -#: main.c:143 +#: main.c:154 msgid " output:\n" msgstr " Ausgabe:\n" -#: main.c:157 main.c:230 +#: main.c:168 main.c:241 msgid "" "Auto-reload is on. Simply save files over USB to run them or enter REPL to " "disable.\n" @@ -163,45 +163,45 @@ msgstr "" "Automatisches Neuladen ist aktiv. Speichere Dateien über USB um sie " "auszuführen oder verbinde dich mit der REPL um zu deaktivieren.\n" -#: main.c:159 +#: main.c:170 msgid "Running in safe mode! Auto-reload is off.\n" msgstr "Sicherheitsmodus aktiv! Automatisches Neuladen ist deaktiviert.\n" -#: main.c:161 main.c:232 +#: main.c:172 main.c:243 msgid "Auto-reload is off.\n" msgstr "Automatisches Neuladen ist deaktiviert.\n" -#: main.c:175 +#: main.c:186 msgid "Running in safe mode! Not running saved code.\n" msgstr "Sicherheitsmodus aktiv! Gespeicherter Code wird nicht ausgeführt\n" -#: main.c:191 +#: main.c:202 msgid "WARNING: Your code filename has two extensions\n" msgstr "WARNUNG: Der Dateiname deines codes hat zwei Dateityperweiterungen\n" -#: main.c:239 +#: main.c:250 msgid "You requested starting safe mode by " msgstr "Du hast das Starten im Sicherheitsmodus ausgelöst durch " -#: main.c:242 +#: main.c:253 msgid "To exit, please reset the board without " -msgstr "Zum beenden bitte resete das board ohne " +msgstr "Zum beenden bitte resette das board ohne " -#: main.c:249 +#: main.c:260 msgid "" "You are running in safe mode which means something really bad happened.\n" -msgstr "Sicherheitsmodus aktive, etwas wirklich schlechtes ist passiert.\n" +msgstr "Sicherheitsmodus aktiv, etwas wirklich schlechtes ist passiert.\n" -#: main.c:251 +#: main.c:262 msgid "Looks like our core CircuitPython code crashed hard. Whoops!\n" msgstr "CircuitPython ist abgestürzt. Ups!\n" -#: main.c:252 +#: main.c:263 msgid "Please file an issue here with the contents of your CIRCUITPY drive:\n" msgstr "" "Bitte erstelle ein issue hier mit dem Inhalt deines CIRCUITPY-speichers:\n" -#: main.c:255 +#: main.c:266 msgid "" "The microcontroller's power dipped. Please make sure your power supply " "provides\n" @@ -209,25 +209,25 @@ msgstr "" "Die Stromversorgung des Mikrocontrollers ist eingebrochen. Stelle sicher," "dass deine Stromversorgung\n" -#: main.c:256 +#: main.c:267 msgid "" "enough power for the whole circuit and press reset (after ejecting " "CIRCUITPY).\n" msgstr "" -"genug Strom für den ganzen Schaltkreis liefert und drücke reset (nach " -"demsicheren Auswerfen von CIRCUITPY.)\n" +"genug Strom für den ganzen Schaltkreis liefert und drücke reset (nach dem " +"sicheren Auswerfen von CIRCUITPY.)\n" -#: main.c:260 +#: main.c:271 msgid "Press any key to enter the REPL. Use CTRL-D to reload." msgstr "" "Drücke eine Taste um dich mit der REPL zu verbinden. Drücke Strg-D zum neu " "laden" -#: main.c:416 +#: main.c:429 msgid "soft reboot\n" -msgstr "weicher reboot\n" +msgstr "soft reboot\n" -#: ports/atmel-samd/audio_dma.c:285 +#: ports/atmel-samd/audio_dma.c:209 #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c:361 msgid "All sync event channels in use" msgstr "Alle sync event Kanäle werden benutzt" @@ -268,7 +268,7 @@ msgstr "AnalogOut ist an diesem Pin nicht unterstützt" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:147 #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:150 msgid "Invalid bit clock pin" -msgstr "Ungülgites bit clock pin" +msgstr "Ungültiges bit clock pin" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:153 msgid "Bit clock and word select must share a clock unit" @@ -284,7 +284,7 @@ msgstr "Ungültiger data pin" #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c:145 #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c:150 msgid "Serializer in use" -msgstr "Serilaizer wird benutzt" +msgstr "Serializer wird benutzt" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:230 msgid "Clock unit in use" @@ -300,12 +300,12 @@ msgid "Too many channels in sample." msgstr "Zu viele Kanäle im sample" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:305 -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:339 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:417 msgid "No DMA channel found" msgstr "Kein DMA Kanal gefunden" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:308 -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:341 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:419 msgid "Unable to allocate buffers for signed conversion" msgstr "Konnte keine Buffer für Vorzeichenumwandlung allozieren" @@ -321,43 +321,44 @@ msgstr "Nur 8 oder 16 bit mono mit " msgid "sampling rate out of range" msgstr "Abtastrate außerhalb der Reichweite" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:69 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:132 msgid "DAC already in use" msgstr "DAC wird schon benutzt" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:73 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:136 msgid "Right channel unsupported" msgstr "Rechter Kanal wird nicht unterstützt" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:76 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:139 #: ports/atmel-samd/common-hal/pulseio/PWMOut.c:116 #: ports/atmel-samd/common-hal/touchio/TouchIn.c:65 msgid "Invalid pin" msgstr "Ungültiger Pin" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:84 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:147 msgid "Invalid pin for left channel" msgstr "Ungültiger Pin für linken Kanal" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:88 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:151 msgid "Invalid pin for right channel" msgstr "Ungültiger Pin für rechten Kanal" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:91 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:154 msgid "Cannot output both channels on the same pin" msgstr "Kann nicht beite Kanäle auf dem gleichen Pin ausgeben" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:176 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:243 #: ports/atmel-samd/common-hal/pulseio/PWMOut.c:189 #: ports/atmel-samd/common-hal/pulseio/PulseOut.c:110 +#: ports/nrf/common-hal/pulseio/PulseOut.c:107 msgid "All timers in use" msgstr "Alle timer werden benutzt" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:218 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:285 msgid "All event channels in use" -msgstr "Alle event Kanälre werden benutzt" +msgstr "Alle event Kanäle werden benutzt" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:297 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:375 #, c-format msgid "Sample rate too high. It must be less than %d" msgstr "" @@ -367,10 +368,10 @@ msgid "Not enough pins available" msgstr "Nicht genug Pins vorhanden" #: ports/atmel-samd/common-hal/busio/I2C.c:78 -#: ports/atmel-samd/common-hal/busio/SPI.c:132 +#: ports/atmel-samd/common-hal/busio/SPI.c:171 #: ports/atmel-samd/common-hal/busio/UART.c:119 #: ports/atmel-samd/common-hal/i2cslave/I2CSlave.c:45 -#: ports/nrf/common-hal/busio/I2C.c:77 +#: ports/nrf/common-hal/busio/I2C.c:82 msgid "Invalid pins" msgstr "Ungültige Pins" @@ -380,17 +381,19 @@ msgstr "SDA oder SCL brauchen pull up" #: ports/atmel-samd/common-hal/busio/I2C.c:121 msgid "Unsupported baudrate" -msgstr "Baudrate wird nicht unterstütz" +msgstr "Baudrate wird nicht unterstützt" #: ports/atmel-samd/common-hal/busio/UART.c:66 msgid "bytes > 8 bits not supported" msgstr "bytes mit merh als 8 bits werden nicht unterstützt" #: ports/atmel-samd/common-hal/busio/UART.c:72 +#: ports/nrf/common-hal/busio/UART.c:82 msgid "tx and rx cannot both be None" msgstr "tx und rx können nicht beide None sein" #: ports/atmel-samd/common-hal/busio/UART.c:145 +#: ports/nrf/common-hal/busio/UART.c:115 msgid "Failed to allocate RX buffer" msgstr "Konnte keinen RX Buffer allozieren" @@ -399,15 +402,17 @@ msgid "Could not initialize UART" msgstr "Konnte UART nicht initialisieren" #: ports/atmel-samd/common-hal/busio/UART.c:240 +#: ports/nrf/common-hal/busio/UART.c:149 msgid "No RX pin" msgstr "Kein RX Pin" #: ports/atmel-samd/common-hal/busio/UART.c:294 +#: ports/nrf/common-hal/busio/UART.c:195 msgid "No TX pin" msgstr "Kein TX Pin" #: ports/atmel-samd/common-hal/digitalio/DigitalInOut.c:170 -#: ports/nrf/common-hal/digitalio/DigitalInOut.c:142 +#: ports/nrf/common-hal/digitalio/DigitalInOut.c:147 msgid "Cannot get pull while in output mode" msgstr "Pull up im Ausgabemodus nicht möglich" @@ -418,7 +423,8 @@ msgstr "Reset zum bootloader nicht möglich da bootloader nicht vorhanden" #: ports/atmel-samd/common-hal/pulseio/PWMOut.c:120 #: ports/atmel-samd/common-hal/pulseio/PWMOut.c:369 -#: ports/nrf/common-hal/pulseio/PWMOut.c:227 +#: ports/nrf/common-hal/pulseio/PWMOut.c:119 +#: ports/nrf/common-hal/pulseio/PWMOut.c:233 msgid "Invalid PWM frequency" msgstr "Ungültige PWM Frequenz" @@ -466,30 +472,10 @@ msgstr "Ein Hardware Interrupt Kanal wird schon benutzt" msgid "calibration value out of range +/-127" msgstr "Kalibrierwert nicht im Bereich von +/-127" -#: ports/atmel-samd/common-hal/storage/__init__.c:48 -msgid "Cannot remount '/' when USB is active." -msgstr "Kann '/' nicht remounten when USB aktiv ist" - #: ports/atmel-samd/common-hal/touchio/TouchIn.c:75 msgid "No free GCLKs" msgstr "Keine freien GCLKs" -#: ports/atmel-samd/common-hal/usb_hid/Device.c:78 -#: ports/nrf/common-hal/usb_hid/Device.c:45 -#, c-format -msgid "Buffer incorrect size. Should be %d bytes." -msgstr "Buffergröße falsch, sollte %d bytes sein." - -#: ports/atmel-samd/common-hal/usb_hid/Device.c:82 -#: ports/nrf/common-hal/usb_hid/Device.c:53 -msgid "USB Busy" -msgstr "USB beschäftigt" - -#: ports/atmel-samd/common-hal/usb_hid/Device.c:82 -#: ports/nrf/common-hal/usb_hid/Device.c:59 -msgid "USB Error" -msgstr "USB Fehler" - #: ports/esp8266/common-hal/analogio/AnalogIn.c:43 msgid "Pin %q does not have ADC capabilities" msgstr "Pin %q hat keine ADC Funktion" @@ -541,23 +527,25 @@ msgstr "Minimale PWM Frequenz ist %dHz" #, c-format msgid "Multiple PWM frequencies not supported. PWM already set to %dhz." msgstr "" +"Mehrere PWM Frequenzen nicht unterstützt. PWM bereits auf %dHz gesetzt." #: ports/esp8266/common-hal/pulseio/PWMOut.c:77 ports/esp8266/machine_pwm.c:70 #, c-format msgid "PWM not supported on pin %d" -msgstr "" +msgstr "PWM nicht unterstützt an Pin %d" #: ports/esp8266/common-hal/pulseio/PulseIn.c:78 msgid "No PulseIn support for %q" -msgstr "" +msgstr "Keine PulseIn Unterstützung für %q" #: ports/esp8266/common-hal/storage/__init__.c:34 msgid "Unable to remount filesystem" -msgstr "" +msgstr "Dateisystem kann nicht wieder gemounted werden." #: ports/esp8266/common-hal/storage/__init__.c:38 msgid "Use esptool to erase flash and re-upload Python instead" msgstr "" +"Benutze esptool um den flash zu löschen und stattdessen Python hochzuladen" #: ports/esp8266/esp_mphal.c:154 msgid "C-level assert" @@ -566,102 +554,103 @@ msgstr "" #: ports/esp8266/machine_adc.c:57 #, c-format msgid "not a valid ADC Channel: %d" -msgstr "" +msgstr "Kein gültiger ADC Kanal: %d" #: ports/esp8266/machine_hspi.c:131 ports/esp8266/machine_hspi.c:137 msgid "impossible baudrate" -msgstr "" +msgstr "Unmögliche Baudrate" #: ports/esp8266/machine_pin.c:129 msgid "expecting a pin" -msgstr "" +msgstr "Ein Pin wird erwartet" #: ports/esp8266/machine_pin.c:284 msgid "Pin(16) doesn't support pull" -msgstr "" +msgstr "Pin(16) unterstützt kein pull" #: ports/esp8266/machine_pin.c:323 msgid "invalid pin" -msgstr "" +msgstr "Ungültiger Pin" #: ports/esp8266/machine_pin.c:389 msgid "pin does not have IRQ capabilities" -msgstr "" +msgstr "Pin hat keine IRQ Fähigkeiten" #: ports/esp8266/machine_rtc.c:185 msgid "buffer too long" -msgstr "" +msgstr "Buffer zu lang" #: ports/esp8266/machine_rtc.c:209 ports/esp8266/machine_rtc.c:223 #: ports/esp8266/machine_rtc.c:246 msgid "invalid alarm" -msgstr "" +msgstr "Ungültiger Alarm" #: ports/esp8266/machine_uart.c:169 #, c-format msgid "UART(%d) does not exist" -msgstr "" +msgstr "UART(%d) existiert nicht" #: ports/esp8266/machine_uart.c:219 msgid "UART(1) can't read" -msgstr "" +msgstr "UART(1) kann nicht lesen" #: ports/esp8266/modesp.c:119 msgid "len must be multiple of 4" -msgstr "" +msgstr "len muss ein vielfaches von 4 sein" #: ports/esp8266/modesp.c:274 #, c-format msgid "memory allocation failed, allocating %u bytes for native code" msgstr "" +"Speicherallozierung fehlgeschlagen, alloziere %u Bytes für nativen Code" #: ports/esp8266/modesp.c:317 msgid "flash location must be below 1MByte" -msgstr "" +msgstr "flash location muss unter 1MByte sein" #: ports/esp8266/modmachine.c:63 msgid "frequency can only be either 80Mhz or 160MHz" -msgstr "" +msgstr "Die Frequenz kann nur 80Mhz oder 160Mhz sein" #: ports/esp8266/modnetwork.c:61 msgid "AP required" -msgstr "" +msgstr "AP erforderlich" #: ports/esp8266/modnetwork.c:61 msgid "STA required" -msgstr "" +msgstr "STA erforderlich" #: ports/esp8266/modnetwork.c:87 msgid "Cannot update i/f status" -msgstr "" +msgstr "Kann i/f Status nicht updaten" #: ports/esp8266/modnetwork.c:142 msgid "Cannot set STA config" -msgstr "" +msgstr "Kann STA Konfiguration nicht setzen" #: ports/esp8266/modnetwork.c:144 msgid "Cannot connect to AP" -msgstr "" +msgstr "Kann nicht zu AP verbinden" #: ports/esp8266/modnetwork.c:152 msgid "Cannot disconnect from AP" -msgstr "" +msgstr "Kann nicht trennen von AP" #: ports/esp8266/modnetwork.c:173 msgid "unknown status param" -msgstr "" +msgstr "Unbekannter Statusparameter" #: ports/esp8266/modnetwork.c:222 msgid "STA must be active" -msgstr "" +msgstr "STA muss aktiv sein" #: ports/esp8266/modnetwork.c:239 msgid "scan failed" -msgstr "" +msgstr "Scan fehlgeschlagen" #: ports/esp8266/modnetwork.c:306 msgid "wifi_set_ip_info() failed" -msgstr "" +msgstr "wifi_set_ip_info() fehlgeschlagen" #: ports/esp8266/modnetwork.c:319 msgid "either pos or kw args are allowed" @@ -699,141 +688,180 @@ msgstr "" msgid "AnalogOut functionality not supported" msgstr "" -#: ports/nrf/common-hal/busio/I2C.c:91 -#, fuzzy -msgid "All I2C peripherals are in use" -msgstr "Alle timer werden benutzt" - -#: ports/nrf/common-hal/busio/SPI.c:109 -#, fuzzy -msgid "All SPI peripherals are in use" -msgstr "Alle timer werden benutzt" - -#: ports/nrf/common-hal/busio/SPI.c:170 -msgid "Baud rate too high for this SPI peripheral" -msgstr "" - -#: ports/nrf/common-hal/busio/UART.c:43 ports/nrf/common-hal/busio/UART.c:47 -#: ports/nrf/common-hal/busio/UART.c:51 ports/nrf/common-hal/busio/UART.c:60 -#: ports/nrf/common-hal/busio/UART.c:66 ports/nrf/common-hal/busio/UART.c:71 -#: ports/nrf/common-hal/busio/UART.c:76 ports/nrf/common-hal/busio/UART.c:81 -#: ports/nrf/common-hal/busio/UART.c:86 ports/nrf/common-hal/busio/UART.c:90 -msgid "busio.UART not yet implemented" -msgstr "" - -#: ports/nrf/common-hal/microcontroller/Processor.c:49 +#: ports/nrf/common-hal/bleio/Adapter.c:41 #, c-format -msgid "Can not get temperature. status: 0x%02x" +msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:199 -msgid "Cannot apply GAP parameters." +#: ports/nrf/common-hal/bleio/Adapter.c:125 +#, c-format +msgid "Failed to change softdevice state, error: 0x%08lX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:213 -msgid "Cannot set PPCP parameters." +#: ports/nrf/common-hal/bleio/Adapter.c:135 +#, c-format +msgid "Failed to get softdevice state, error: 0x%08lX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:245 -msgid "Can not query for the device address." +#: ports/nrf/common-hal/bleio/Adapter.c:155 +#, c-format +msgid "Failed to get local address, error: 0x%08lX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:264 -msgid "Can not add Vendor Specific 128-bit UUID." -msgstr "" +#: ports/nrf/common-hal/bleio/Characteristic.c:52 +#, fuzzy, c-format +msgid "Failed to write gatts value, status: 0x%08lX" +msgstr "Kann den Attributwert nicht schreiben. Status: 0x%02x" -#: ports/nrf/drivers/bluetooth/ble_drv.c:284 -#: ports/nrf/drivers/bluetooth/ble_drv.c:298 -msgid "Can not add Service." -msgstr "" +#: ports/nrf/common-hal/bleio/Characteristic.c:76 +#, fuzzy, c-format +msgid "Failed to notify attribute value, status: 0x%08lX" +msgstr "Kann den Attributwert nicht mitteilen. Status: 0x%02x" -#: ports/nrf/drivers/bluetooth/ble_drv.c:373 -msgid "Can not add Characteristic." -msgstr "" +#: ports/nrf/common-hal/bleio/Characteristic.c:91 +#, fuzzy, c-format +msgid "Failed to read attribute value, status: 0x%08lX" +msgstr "Kann den Attributwert nicht lesen. Status: 0x%02x" -#: ports/nrf/drivers/bluetooth/ble_drv.c:400 -msgid "Can not apply device name in the stack." +#: ports/nrf/common-hal/bleio/Characteristic.c:119 +#: ports/nrf/common-hal/bleio/Device.c:272 +#: ports/nrf/common-hal/bleio/Device.c:307 +#, c-format +msgid "Failed to acquire mutex, status: 0x%08lX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:464 -#: ports/nrf/drivers/bluetooth/ble_drv.c:514 -msgid "Can not encode UUID, to check length." -msgstr "" +#: ports/nrf/common-hal/bleio/Characteristic.c:126 +#, fuzzy, c-format +msgid "Failed to write attribute value, status: 0x%08lX" +msgstr "Kann den Attributwert nicht schreiben. Status: 0x%02x" -#: ports/nrf/drivers/bluetooth/ble_drv.c:470 -#: ports/nrf/drivers/bluetooth/ble_drv.c:520 -msgid "Can encode UUID into the advertisment packet." +#: ports/nrf/common-hal/bleio/Characteristic.c:138 +#: ports/nrf/common-hal/bleio/Device.c:284 +#: ports/nrf/common-hal/bleio/Device.c:319 +#: ports/nrf/common-hal/bleio/Device.c:354 +#: ports/nrf/common-hal/bleio/Device.c:391 +#, c-format +msgid "Failed to release mutex, status: 0x%08lX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:545 -msgid "Can not fit data into the advertisment packet." -msgstr "" +#: ports/nrf/common-hal/bleio/Device.c:81 +#: ports/nrf/common-hal/bleio/Device.c:114 +#, fuzzy +msgid "Can not fit data into the advertisment packet" +msgstr "Daten können nicht in das advertisement packet eingefügt werden." -#: ports/nrf/drivers/bluetooth/ble_drv.c:558 -#: ports/nrf/drivers/bluetooth/ble_drv.c:604 +#: ports/nrf/common-hal/bleio/Device.c:266 #, c-format -msgid "Can not apply advertisment data. status: 0x%02x" -msgstr "" - -#: ports/nrf/drivers/bluetooth/ble_drv.c:614 +msgid "Failed to discover serivices, status: 0x%08lX" +msgstr "" + +#: ports/nrf/common-hal/bleio/Device.c:403 +#: ports/nrf/common-hal/bleio/Scanner.c:76 +#, fuzzy, c-format +msgid "Failed to continue scanning, status: 0x%0xlX" +msgstr "Der Scanvorgang kann nicht gestartet werden. Status: 0x%02x" + +#: ports/nrf/common-hal/bleio/Device.c:436 +#, fuzzy, c-format +msgid "Failed to connect, status: 0x%08lX" +msgstr "Kann nicht verbinden. Status: 0x%02x" + +#: ports/nrf/common-hal/bleio/Device.c:513 +#, fuzzy, c-format +msgid "Failed to add service, status: 0x%08lX" +msgstr "Kann advertisement nicht stoppen. Status: 0x%02x" + +#: ports/nrf/common-hal/bleio/Device.c:531 +#, fuzzy, c-format +msgid "Failed to start advertisment, status: 0x%08lX" +msgstr "Kann advertisement nicht starten. Status: 0x%02x" + +#: ports/nrf/common-hal/bleio/Device.c:549 +#, fuzzy, c-format +msgid "Failed to stop advertisment, status: 0x%08lX" +msgstr "Kann advertisement nicht stoppen. Status: 0x%02x" + +#: ports/nrf/common-hal/bleio/Device.c:575 +#: ports/nrf/common-hal/bleio/Scanner.c:103 +#, fuzzy, c-format +msgid "Failed to start scanning, status: 0x%0xlX" +msgstr "Der Scanvorgang kann nicht gestartet werden. Status: 0x%02x" + +#: ports/nrf/common-hal/bleio/Device.c:592 +#, fuzzy, c-format +msgid "Failed to create mutex, status: 0x%0xlX" +msgstr "Kann den Attributwert nicht lesen. Status: 0x%02x" + +#: ports/nrf/common-hal/bleio/Service.c:83 #, c-format -msgid "Can not start advertisment. status: 0x%02x" +msgid "Failed to add characteristic, status: 0x%08lX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:631 -#, c-format -msgid "Can not stop advertisment. status: 0x%02x" -msgstr "" +#: ports/nrf/common-hal/bleio/UUID.c:97 +#, fuzzy, c-format +msgid "Failed to add Vendor Specific UUID, status: 0x%08lX" +msgstr "Kann keine herstellerspezifische 128-Bit-UUID hinzufügen." -#: ports/nrf/drivers/bluetooth/ble_drv.c:650 -#: ports/nrf/drivers/bluetooth/ble_drv.c:726 -#, c-format -msgid "Can not read attribute value. status: 0x%02x" -msgstr "" +#: ports/nrf/common-hal/bleio/UUID.c:102 +msgid "Invalid UUID string length" +msgstr "Ungültige UUID-Stringlänge" -#: ports/nrf/drivers/bluetooth/ble_drv.c:667 -#: ports/nrf/drivers/bluetooth/ble_drv.c:756 -#, c-format -msgid "Can not write attribute value. status: 0x%02x" -msgstr "" +#: ports/nrf/common-hal/bleio/UUID.c:109 +#: shared-bindings/bleio/Characteristic.c:125 +#: shared-bindings/bleio/Service.c:105 +msgid "Invalid UUID parameter" +msgstr "Ungültiger UUID-Parameter" -#: ports/nrf/drivers/bluetooth/ble_drv.c:691 -#, c-format -msgid "Can not notify attribute value. status: 0x%02x" -msgstr "" +#: ports/nrf/common-hal/busio/I2C.c:96 +#, fuzzy +msgid "All I2C peripherals are in use" +msgstr "Alle timer werden benutzt" -#: ports/nrf/drivers/bluetooth/ble_drv.c:784 -#, c-format -msgid "Can not start scanning. status: 0x%02x" -msgstr "" +#: ports/nrf/common-hal/busio/SPI.c:133 +#, fuzzy +msgid "All SPI peripherals are in use" +msgstr "Alle timer werden benutzt" -#: ports/nrf/drivers/bluetooth/ble_drv.c:829 +#: ports/nrf/common-hal/busio/UART.c:48 #, c-format -msgid "Can not connect. status: 0x%02x" +msgid "error = 0x%08lX" msgstr "" -#: ports/nrf/modules/ubluepy/ubluepy_characteristic.c:68 -#: ports/nrf/modules/ubluepy/ubluepy_service.c:80 -#: ports/nrf/modules/ubluepy/ubluepy_service.c:132 -#: ports/nrf/modules/ubluepy/ubluepy_uuid.c:137 -msgid "Invalid UUID parameter" -msgstr "" +#: ports/nrf/common-hal/busio/UART.c:86 +#, fuzzy +msgid "Invalid buffer size" +msgstr "ungültiger dupterm index" -#: ports/nrf/modules/ubluepy/ubluepy_service.c:73 -msgid "Invalid Service type" +#: ports/nrf/common-hal/busio/UART.c:90 +#, fuzzy +msgid "Odd parity is not supported" +msgstr "bytes mit merh als 8 bits werden nicht unterstützt" + +#: ports/nrf/common-hal/busio/UART.c:322 ports/nrf/common-hal/busio/UART.c:326 +#: ports/nrf/common-hal/busio/UART.c:331 ports/nrf/common-hal/busio/UART.c:336 +#: ports/nrf/common-hal/busio/UART.c:342 ports/nrf/common-hal/busio/UART.c:347 +#: ports/nrf/common-hal/busio/UART.c:352 ports/nrf/common-hal/busio/UART.c:356 +#: ports/nrf/common-hal/busio/UART.c:364 +msgid "busio.UART not available" msgstr "" -#: ports/nrf/modules/ubluepy/ubluepy_uuid.c:127 -msgid "Invalid UUID string length" +#: ports/nrf/common-hal/microcontroller/Processor.c:49 +#, c-format +msgid "Can not get temperature. status: 0x%02x" msgstr "" +#: ports/nrf/common-hal/pulseio/PWMOut.c:161 +#, fuzzy +msgid "All PWM peripherals are in use" +msgstr "Alle timer werden benutzt" + #: ports/unix/modffi.c:138 msgid "Unknown type" -msgstr "" +msgstr "Unbekannter Typ" #: ports/unix/modffi.c:207 ports/unix/modffi.c:265 msgid "Error in ffi_prep_cif" -msgstr "" +msgstr "Fehler in ffi_prep_cif" #: ports/unix/modffi.c:270 msgid "ffi_prep_closure_loc" @@ -928,19 +956,34 @@ msgstr "" msgid "bad compile mode" msgstr "" -#: py/builtinimport.c:338 +#: py/builtinhelp.c:137 +#, fuzzy +msgid "Plus any modules on the filesystem\n" +msgstr "Dateisystem kann nicht wieder gemounted werden." + +#: py/builtinhelp.c:183 +#, c-format +msgid "" +"Welcome to Adafruit CircuitPython %s!\n" +"\n" +"Please visit learn.adafruit.com/category/circuitpython for project guides.\n" +"\n" +"To list built-in modules please do `help(\"modules\")`.\n" +msgstr "" + +#: py/builtinimport.c:336 msgid "cannot perform relative import" msgstr "" -#: py/builtinimport.c:422 py/builtinimport.c:534 +#: py/builtinimport.c:420 py/builtinimport.c:532 msgid "module not found" msgstr "" -#: py/builtinimport.c:425 py/builtinimport.c:537 +#: py/builtinimport.c:423 py/builtinimport.c:535 msgid "no module named '%q'" msgstr "" -#: py/builtinimport.c:512 +#: py/builtinimport.c:510 msgid "relative import" msgstr "" @@ -1089,38 +1132,86 @@ msgstr "" msgid "'data' requires integer arguments" msgstr "" -#: py/emitinlinextensa.c:86 -msgid "can only have up to 4 parameters to Xtensa assembly" +#: py/emitinlinethumb.c:102 +msgid "can only have up to 4 parameters to Thumb assembly" msgstr "" -#: py/emitinlinextensa.c:91 py/emitinlinextensa.c:96 -msgid "parameters must be registers in sequence a2 to a5" +#: py/emitinlinethumb.c:107 py/emitinlinethumb.c:112 +msgid "parameters must be registers in sequence r0 to r3" +msgstr "" + +#: py/emitinlinethumb.c:188 py/emitinlinethumb.c:230 +#, c-format +msgid "'%s' expects at most r%d" msgstr "" -#: py/emitinlinextensa.c:162 +#: py/emitinlinethumb.c:197 py/emitinlinextensa.c:162 #, c-format msgid "'%s' expects a register" msgstr "" -#: py/emitinlinextensa.c:169 +#: py/emitinlinethumb.c:211 +#, c-format +msgid "'%s' expects a special register" +msgstr "" + +#: py/emitinlinethumb.c:239 +#, c-format +msgid "'%s' expects an FPU register" +msgstr "" + +#: py/emitinlinethumb.c:292 +#, c-format +msgid "'%s' expects {r0, r1, ...}" +msgstr "" + +#: py/emitinlinethumb.c:299 py/emitinlinextensa.c:169 #, c-format msgid "'%s' expects an integer" msgstr "" -#: py/emitinlinextensa.c:174 +#: py/emitinlinethumb.c:304 #, c-format -msgid "'%s' integer %d is not within range %d..%d" +msgid "'%s' integer 0x%x does not fit in mask 0x%x" +msgstr "" + +#: py/emitinlinethumb.c:328 +#, c-format +msgid "'%s' expects an address of the form [a, b]" msgstr "" -#: py/emitinlinextensa.c:182 +#: py/emitinlinethumb.c:334 py/emitinlinextensa.c:182 #, c-format msgid "'%s' expects a label" msgstr "" -#: py/emitinlinextensa.c:193 +#: py/emitinlinethumb.c:345 py/emitinlinextensa.c:193 msgid "label '%q' not defined" msgstr "" +#: py/emitinlinethumb.c:806 +#, c-format +msgid "unsupported Thumb instruction '%s' with %d arguments" +msgstr "" + +#: py/emitinlinethumb.c:810 +#, fuzzy +msgid "branch not in range" +msgstr "Kalibrierung ist außerhalb der Reichweite" + +#: py/emitinlinextensa.c:86 +msgid "can only have up to 4 parameters to Xtensa assembly" +msgstr "" + +#: py/emitinlinextensa.c:91 py/emitinlinextensa.c:96 +msgid "parameters must be registers in sequence a2 to a5" +msgstr "" + +#: py/emitinlinextensa.c:174 +#, c-format +msgid "'%s' integer %d is not within range %d..%d" +msgstr "" + #: py/emitinlinextensa.c:327 #, c-format msgid "unsupported Xtensa instruction '%s' with %d arguments" @@ -1940,7 +2031,7 @@ msgid "AnalogOut is only 16 bits. Value must be less than 65536." msgstr "" #: shared-bindings/audiobusio/I2SOut.c:225 -#: shared-bindings/audioio/AudioOut.c:223 +#: shared-bindings/audioio/AudioOut.c:226 msgid "Not playing" msgstr "" @@ -1977,6 +2068,25 @@ msgid "" "destination buffer must be a bytearray or array of type 'B' for bit_depth = 8" msgstr "" +#: shared-bindings/audioio/Mixer.c:94 +#, fuzzy +msgid "Invalid voice count" +msgstr "Ungültiger clock pin" + +#: shared-bindings/audioio/Mixer.c:99 +#, fuzzy +msgid "Invalid channel count" +msgstr "Ungültiger clock pin" + +#: shared-bindings/audioio/Mixer.c:103 +msgid "Sample rate must be positive" +msgstr "" + +#: shared-bindings/audioio/Mixer.c:107 +#, fuzzy +msgid "bits_per_sample must be 8 or 16" +msgstr "bits müssen 8 sein" + #: shared-bindings/audioio/RawSample.c:98 msgid "" "sample_source buffer must be a bytearray or array of type 'h', 'H', 'b' or " @@ -2001,22 +2111,46 @@ msgstr "" msgid "Buffer must be at least length 1" msgstr "" -#: shared-bindings/bitbangio/SPI.c:151 shared-bindings/busio/SPI.c:168 +#: shared-bindings/bitbangio/SPI.c:151 shared-bindings/busio/SPI.c:175 msgid "Invalid polarity" msgstr "" -#: shared-bindings/bitbangio/SPI.c:155 shared-bindings/busio/SPI.c:172 +#: shared-bindings/bitbangio/SPI.c:155 shared-bindings/busio/SPI.c:179 msgid "Invalid phase" msgstr "" -#: shared-bindings/bitbangio/SPI.c:159 shared-bindings/busio/SPI.c:176 +#: shared-bindings/bitbangio/SPI.c:159 shared-bindings/busio/SPI.c:183 msgid "Invalid number of bits" msgstr "" -#: shared-bindings/bitbangio/SPI.c:284 shared-bindings/busio/SPI.c:341 +#: shared-bindings/bitbangio/SPI.c:284 shared-bindings/busio/SPI.c:348 msgid "buffer slices must be of equal length" msgstr "" +#: shared-bindings/bleio/Address.c:101 +msgid "Wrong address length" +msgstr "" + +#: shared-bindings/bleio/Address.c:107 +msgid "Wrong number of bytes provided" +msgstr "" + +#: shared-bindings/bleio/Device.c:210 +msgid "Can't add services in Central mode" +msgstr "" + +#: shared-bindings/bleio/Device.c:226 +msgid "Can't connect in Peripheral mode" +msgstr "" + +#: shared-bindings/bleio/Device.c:256 +msgid "Can't change the name in Central mode" +msgstr "" + +#: shared-bindings/bleio/Device.c:277 shared-bindings/bleio/Device.c:313 +msgid "Can't advertise in Central mode" +msgstr "" + #: shared-bindings/busio/I2C.c:120 msgid "Function requires lock." msgstr "" @@ -2132,7 +2266,7 @@ msgstr "" #: shared-bindings/microcontroller/Pin.c:89 #: shared-bindings/neopixel_write/__init__.c:67 -#: shared-bindings/pulseio/PulseOut.c:75 +#: shared-bindings/pulseio/PulseOut.c:76 msgid "Expected a %q" msgstr "" @@ -2175,7 +2309,7 @@ msgstr "" #: shared-bindings/pulseio/PWMOut.c:195 msgid "" -"PWM frequency not writeable when variable_frequency is False on construction." +"PWM frequency not writable when variable_frequency is False on construction." msgstr "" #: shared-bindings/pulseio/PulseIn.c:275 @@ -2194,7 +2328,7 @@ msgstr "" msgid "Read-only" msgstr "" -#: shared-bindings/pulseio/PulseOut.c:134 +#: shared-bindings/pulseio/PulseOut.c:135 msgid "Array must contain halfwords (type 'H')" msgstr "" @@ -2223,6 +2357,10 @@ msgstr "" msgid "RTC calibration is not supported on this board" msgstr "" +#: shared-bindings/socket/__init__.c:516 shared-module/network/__init__.c:81 +msgid "no available NIC" +msgstr "" + #: shared-bindings/storage/__init__.c:77 msgid "filesystem must provide mount method" msgstr "" @@ -2247,15 +2385,15 @@ msgstr "" msgid "time.struct_time() takes a 9-sequence" msgstr "" -#: shared-bindings/time/__init__.c:169 shared-bindings/time/__init__.c:250 +#: shared-bindings/time/__init__.c:169 shared-bindings/time/__init__.c:264 msgid "Tuple or struct_time argument required" msgstr "" -#: shared-bindings/time/__init__.c:174 shared-bindings/time/__init__.c:255 +#: shared-bindings/time/__init__.c:174 shared-bindings/time/__init__.c:269 msgid "function takes exactly 9 arguments" msgstr "" -#: shared-bindings/time/__init__.c:226 shared-bindings/time/__init__.c:259 +#: shared-bindings/time/__init__.c:240 shared-bindings/time/__init__.c:273 msgid "timestamp out of range for platform time_t" msgstr "" @@ -2268,6 +2406,34 @@ msgid "" "Object has been deinitialized and can no longer be used. Create a new object." msgstr "" +#: shared-module/audioio/Mixer.c:47 shared-module/audioio/WaveFile.c:117 +msgid "Couldn't allocate first buffer" +msgstr "" + +#: shared-module/audioio/Mixer.c:53 shared-module/audioio/WaveFile.c:123 +msgid "Couldn't allocate second buffer" +msgstr "" + +#: shared-module/audioio/Mixer.c:82 +msgid "Voice index too high" +msgstr "" + +#: shared-module/audioio/Mixer.c:85 +msgid "The sample's sample rate does not match the mixer's" +msgstr "" + +#: shared-module/audioio/Mixer.c:88 +msgid "The sample's channel count does not match the mixer's" +msgstr "" + +#: shared-module/audioio/Mixer.c:91 +msgid "The sample's bits_per_sample does not match the mixer's" +msgstr "" + +#: shared-module/audioio/Mixer.c:100 +msgid "The sample's signedness does not match the mixer's" +msgstr "" + #: shared-module/audioio/WaveFile.c:61 msgid "Invalid wave file" msgstr "" @@ -2288,39 +2454,31 @@ msgstr "" msgid "Invalid file" msgstr "" -#: shared-module/audioio/WaveFile.c:117 -msgid "Couldn't allocate first buffer" -msgstr "" - -#: shared-module/audioio/WaveFile.c:123 -msgid "Couldn't allocate second buffer" -msgstr "" - #: shared-module/bitbangio/I2C.c:58 msgid "Clock stretch too long" msgstr "" -#: shared-module/bitbangio/SPI.c:45 +#: shared-module/bitbangio/SPI.c:44 msgid "Clock pin init failed." msgstr "" -#: shared-module/bitbangio/SPI.c:51 +#: shared-module/bitbangio/SPI.c:50 msgid "MOSI pin init failed." msgstr "" -#: shared-module/bitbangio/SPI.c:62 +#: shared-module/bitbangio/SPI.c:61 msgid "MISO pin init failed." msgstr "" -#: shared-module/bitbangio/SPI.c:122 +#: shared-module/bitbangio/SPI.c:121 msgid "Cannot write without MOSI pin." msgstr "" -#: shared-module/bitbangio/SPI.c:177 +#: shared-module/bitbangio/SPI.c:176 msgid "Cannot read without MISO pin." msgstr "" -#: shared-module/bitbangio/SPI.c:241 +#: shared-module/bitbangio/SPI.c:240 msgid "Cannot transfer without MOSI and MISO pins." msgstr "" @@ -2355,6 +2513,10 @@ msgstr "" msgid "Only true color (24 bpp or higher) BMP supported %x" msgstr "" +#: shared-module/storage/__init__.c:155 +msgid "Cannot remount '/' when USB is active." +msgstr "Kann '/' nicht remounten when USB aktiv ist" + #: shared-module/struct/__init__.c:39 msgid "'S' and 'O' are not supported format types" msgstr "" @@ -2362,3 +2524,46 @@ msgstr "" #: shared-module/struct/__init__.c:83 msgid "too many arguments provided with the given format" msgstr "" + +#: shared-module/usb_hid/Device.c:45 +#, c-format +msgid "Buffer incorrect size. Should be %d bytes." +msgstr "Buffergröße falsch, sollte %d bytes sein." + +#: shared-module/usb_hid/Device.c:53 +msgid "USB Busy" +msgstr "USB beschäftigt" + +#: shared-module/usb_hid/Device.c:59 +msgid "USB Error" +msgstr "USB Fehler" + +#~ msgid "Invalid Service type" +#~ msgstr "Ungültiger Diensttyp" + +#~ msgid "Can not query for the device address." +#~ msgstr "Kann nicht nach der Geräteadresse suchen." + +#~ msgid "Cannot set PPCP parameters." +#~ msgstr "Kann PPCP Parameter nicht setzen." + +#~ msgid "Cannot apply GAP parameters." +#~ msgstr "Kann GAP Parameter nicht anwenden." + +#~ msgid "Can not encode UUID, to check length." +#~ msgstr "Kann UUID nicht kodieren, um die Länge zu überprüfen." + +#~ msgid "Can encode UUID into the advertisement packet." +#~ msgstr "Kann UUID in das advertisement packet kodieren." + +#~ msgid "Can not apply device name in the stack." +#~ msgstr "Der Gerätename kann nicht im Stack verwendet werden." + +#~ msgid "Can not apply advertisement data. status: 0x%02x" +#~ msgstr "Kann advertisement data nicht anwenden. Status: 0x%02x" + +#~ msgid "Can not add Service." +#~ msgstr "Kann den Dienst nicht hinzufügen." + +#~ msgid "Can not add Characteristic." +#~ msgstr "Kann das Merkmal nicht hinzufügen." diff --git a/locale/en_US.po b/locale/en_US.po index 63ae50ba5..e7bcf1c08 100644 --- a/locale/en_US.po +++ b/locale/en_US.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-09-21 12:23-0400\n" +"POT-Creation-Date: 2018-11-09 15:57-0800\n" "PO-Revision-Date: 2018-07-27 11:55-0700\n" "Last-Translator: \n" "Language-Team: \n" @@ -147,78 +147,78 @@ msgstr "" msgid "invalid arguments" msgstr "" -#: lib/utils/pyexec.c:97 py/builtinimport.c:253 +#: lib/utils/pyexec.c:97 py/builtinimport.c:251 msgid "script compilation not supported" msgstr "" -#: main.c:143 +#: main.c:154 msgid " output:\n" msgstr "" -#: main.c:157 main.c:230 +#: main.c:168 main.c:241 msgid "" "Auto-reload is on. Simply save files over USB to run them or enter REPL to " "disable.\n" msgstr "" -#: main.c:159 +#: main.c:170 msgid "Running in safe mode! Auto-reload is off.\n" msgstr "" -#: main.c:161 main.c:232 +#: main.c:172 main.c:243 msgid "Auto-reload is off.\n" msgstr "" -#: main.c:175 +#: main.c:186 msgid "Running in safe mode! Not running saved code.\n" msgstr "" -#: main.c:191 +#: main.c:202 msgid "WARNING: Your code filename has two extensions\n" msgstr "" -#: main.c:239 +#: main.c:250 msgid "You requested starting safe mode by " msgstr "" -#: main.c:242 +#: main.c:253 msgid "To exit, please reset the board without " msgstr "" -#: main.c:249 +#: main.c:260 msgid "" "You are running in safe mode which means something really bad happened.\n" msgstr "" -#: main.c:251 +#: main.c:262 msgid "Looks like our core CircuitPython code crashed hard. Whoops!\n" msgstr "" -#: main.c:252 +#: main.c:263 msgid "Please file an issue here with the contents of your CIRCUITPY drive:\n" msgstr "" -#: main.c:255 +#: main.c:266 msgid "" "The microcontroller's power dipped. Please make sure your power supply " "provides\n" msgstr "" -#: main.c:256 +#: main.c:267 msgid "" "enough power for the whole circuit and press reset (after ejecting " "CIRCUITPY).\n" msgstr "" -#: main.c:260 +#: main.c:271 msgid "Press any key to enter the REPL. Use CTRL-D to reload." msgstr "" -#: main.c:416 +#: main.c:429 msgid "soft reboot\n" msgstr "" -#: ports/atmel-samd/audio_dma.c:285 +#: ports/atmel-samd/audio_dma.c:209 #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c:361 msgid "All sync event channels in use" msgstr "" @@ -291,12 +291,12 @@ msgid "Too many channels in sample." msgstr "" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:305 -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:339 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:417 msgid "No DMA channel found" msgstr "" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:308 -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:341 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:419 msgid "Unable to allocate buffers for signed conversion" msgstr "" @@ -312,43 +312,44 @@ msgstr "" msgid "sampling rate out of range" msgstr "" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:69 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:132 msgid "DAC already in use" msgstr "" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:73 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:136 msgid "Right channel unsupported" msgstr "" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:76 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:139 #: ports/atmel-samd/common-hal/pulseio/PWMOut.c:116 #: ports/atmel-samd/common-hal/touchio/TouchIn.c:65 msgid "Invalid pin" msgstr "" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:84 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:147 msgid "Invalid pin for left channel" msgstr "" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:88 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:151 msgid "Invalid pin for right channel" msgstr "" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:91 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:154 msgid "Cannot output both channels on the same pin" msgstr "" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:176 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:243 #: ports/atmel-samd/common-hal/pulseio/PWMOut.c:189 #: ports/atmel-samd/common-hal/pulseio/PulseOut.c:110 +#: ports/nrf/common-hal/pulseio/PulseOut.c:107 msgid "All timers in use" msgstr "" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:218 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:285 msgid "All event channels in use" msgstr "" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:297 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:375 #, c-format msgid "Sample rate too high. It must be less than %d" msgstr "" @@ -358,10 +359,10 @@ msgid "Not enough pins available" msgstr "" #: ports/atmel-samd/common-hal/busio/I2C.c:78 -#: ports/atmel-samd/common-hal/busio/SPI.c:132 +#: ports/atmel-samd/common-hal/busio/SPI.c:171 #: ports/atmel-samd/common-hal/busio/UART.c:119 #: ports/atmel-samd/common-hal/i2cslave/I2CSlave.c:45 -#: ports/nrf/common-hal/busio/I2C.c:77 +#: ports/nrf/common-hal/busio/I2C.c:82 msgid "Invalid pins" msgstr "" @@ -378,10 +379,12 @@ msgid "bytes > 8 bits not supported" msgstr "" #: ports/atmel-samd/common-hal/busio/UART.c:72 +#: ports/nrf/common-hal/busio/UART.c:82 msgid "tx and rx cannot both be None" msgstr "" #: ports/atmel-samd/common-hal/busio/UART.c:145 +#: ports/nrf/common-hal/busio/UART.c:115 msgid "Failed to allocate RX buffer" msgstr "" @@ -390,15 +393,17 @@ msgid "Could not initialize UART" msgstr "" #: ports/atmel-samd/common-hal/busio/UART.c:240 +#: ports/nrf/common-hal/busio/UART.c:149 msgid "No RX pin" msgstr "" #: ports/atmel-samd/common-hal/busio/UART.c:294 +#: ports/nrf/common-hal/busio/UART.c:195 msgid "No TX pin" msgstr "" #: ports/atmel-samd/common-hal/digitalio/DigitalInOut.c:170 -#: ports/nrf/common-hal/digitalio/DigitalInOut.c:142 +#: ports/nrf/common-hal/digitalio/DigitalInOut.c:147 msgid "Cannot get pull while in output mode" msgstr "" @@ -409,7 +414,8 @@ msgstr "" #: ports/atmel-samd/common-hal/pulseio/PWMOut.c:120 #: ports/atmel-samd/common-hal/pulseio/PWMOut.c:369 -#: ports/nrf/common-hal/pulseio/PWMOut.c:227 +#: ports/nrf/common-hal/pulseio/PWMOut.c:119 +#: ports/nrf/common-hal/pulseio/PWMOut.c:233 msgid "Invalid PWM frequency" msgstr "" @@ -457,30 +463,10 @@ msgstr "" msgid "calibration value out of range +/-127" msgstr "" -#: ports/atmel-samd/common-hal/storage/__init__.c:48 -msgid "Cannot remount '/' when USB is active." -msgstr "" - #: ports/atmel-samd/common-hal/touchio/TouchIn.c:75 msgid "No free GCLKs" msgstr "" -#: ports/atmel-samd/common-hal/usb_hid/Device.c:78 -#: ports/nrf/common-hal/usb_hid/Device.c:45 -#, c-format -msgid "Buffer incorrect size. Should be %d bytes." -msgstr "" - -#: ports/atmel-samd/common-hal/usb_hid/Device.c:82 -#: ports/nrf/common-hal/usb_hid/Device.c:53 -msgid "USB Busy" -msgstr "" - -#: ports/atmel-samd/common-hal/usb_hid/Device.c:82 -#: ports/nrf/common-hal/usb_hid/Device.c:59 -msgid "USB Error" -msgstr "" - #: ports/esp8266/common-hal/analogio/AnalogIn.c:43 msgid "Pin %q does not have ADC capabilities" msgstr "" @@ -690,130 +676,165 @@ msgstr "" msgid "AnalogOut functionality not supported" msgstr "" -#: ports/nrf/common-hal/busio/I2C.c:91 -msgid "All I2C peripherals are in use" +#: ports/nrf/common-hal/bleio/Adapter.c:41 +#, c-format +msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX" msgstr "" -#: ports/nrf/common-hal/busio/SPI.c:109 -msgid "All SPI peripherals are in use" +#: ports/nrf/common-hal/bleio/Adapter.c:125 +#, c-format +msgid "Failed to change softdevice state, error: 0x%08lX" msgstr "" -#: ports/nrf/common-hal/busio/SPI.c:170 -msgid "Baud rate too high for this SPI peripheral" +#: ports/nrf/common-hal/bleio/Adapter.c:135 +#, c-format +msgid "Failed to get softdevice state, error: 0x%08lX" msgstr "" -#: ports/nrf/common-hal/busio/UART.c:43 ports/nrf/common-hal/busio/UART.c:47 -#: ports/nrf/common-hal/busio/UART.c:51 ports/nrf/common-hal/busio/UART.c:60 -#: ports/nrf/common-hal/busio/UART.c:66 ports/nrf/common-hal/busio/UART.c:71 -#: ports/nrf/common-hal/busio/UART.c:76 ports/nrf/common-hal/busio/UART.c:81 -#: ports/nrf/common-hal/busio/UART.c:86 ports/nrf/common-hal/busio/UART.c:90 -msgid "busio.UART not yet implemented" +#: ports/nrf/common-hal/bleio/Adapter.c:155 +#, c-format +msgid "Failed to get local address, error: 0x%08lX" msgstr "" -#: ports/nrf/common-hal/microcontroller/Processor.c:49 +#: ports/nrf/common-hal/bleio/Characteristic.c:52 #, c-format -msgid "Can not get temperature. status: 0x%02x" +msgid "Failed to write gatts value, status: 0x%08lX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:199 -msgid "Cannot apply GAP parameters." +#: ports/nrf/common-hal/bleio/Characteristic.c:76 +#, c-format +msgid "Failed to notify attribute value, status: 0x%08lX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:213 -msgid "Cannot set PPCP parameters." +#: ports/nrf/common-hal/bleio/Characteristic.c:91 +#, c-format +msgid "Failed to read attribute value, status: 0x%08lX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:245 -msgid "Can not query for the device address." +#: ports/nrf/common-hal/bleio/Characteristic.c:119 +#: ports/nrf/common-hal/bleio/Device.c:272 +#: ports/nrf/common-hal/bleio/Device.c:307 +#, c-format +msgid "Failed to acquire mutex, status: 0x%08lX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:264 -msgid "Can not add Vendor Specific 128-bit UUID." +#: ports/nrf/common-hal/bleio/Characteristic.c:126 +#, c-format +msgid "Failed to write attribute value, status: 0x%08lX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:284 -#: ports/nrf/drivers/bluetooth/ble_drv.c:298 -msgid "Can not add Service." +#: ports/nrf/common-hal/bleio/Characteristic.c:138 +#: ports/nrf/common-hal/bleio/Device.c:284 +#: ports/nrf/common-hal/bleio/Device.c:319 +#: ports/nrf/common-hal/bleio/Device.c:354 +#: ports/nrf/common-hal/bleio/Device.c:391 +#, c-format +msgid "Failed to release mutex, status: 0x%08lX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:373 -msgid "Can not add Characteristic." +#: ports/nrf/common-hal/bleio/Device.c:81 +#: ports/nrf/common-hal/bleio/Device.c:114 +msgid "Can not fit data into the advertisment packet" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:400 -msgid "Can not apply device name in the stack." +#: ports/nrf/common-hal/bleio/Device.c:266 +#, c-format +msgid "Failed to discover serivices, status: 0x%08lX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:464 -#: ports/nrf/drivers/bluetooth/ble_drv.c:514 -msgid "Can not encode UUID, to check length." +#: ports/nrf/common-hal/bleio/Device.c:403 +#: ports/nrf/common-hal/bleio/Scanner.c:76 +#, c-format +msgid "Failed to continue scanning, status: 0x%0xlX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:470 -#: ports/nrf/drivers/bluetooth/ble_drv.c:520 -msgid "Can encode UUID into the advertisment packet." +#: ports/nrf/common-hal/bleio/Device.c:436 +#, c-format +msgid "Failed to connect, status: 0x%08lX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:545 -msgid "Can not fit data into the advertisment packet." +#: ports/nrf/common-hal/bleio/Device.c:513 +#, c-format +msgid "Failed to add service, status: 0x%08lX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:558 -#: ports/nrf/drivers/bluetooth/ble_drv.c:604 +#: ports/nrf/common-hal/bleio/Device.c:531 #, c-format -msgid "Can not apply advertisment data. status: 0x%02x" +msgid "Failed to start advertisment, status: 0x%08lX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:614 +#: ports/nrf/common-hal/bleio/Device.c:549 #, c-format -msgid "Can not start advertisment. status: 0x%02x" +msgid "Failed to stop advertisment, status: 0x%08lX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:631 +#: ports/nrf/common-hal/bleio/Device.c:575 +#: ports/nrf/common-hal/bleio/Scanner.c:103 #, c-format -msgid "Can not stop advertisment. status: 0x%02x" +msgid "Failed to start scanning, status: 0x%0xlX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:650 -#: ports/nrf/drivers/bluetooth/ble_drv.c:726 +#: ports/nrf/common-hal/bleio/Device.c:592 #, c-format -msgid "Can not read attribute value. status: 0x%02x" +msgid "Failed to create mutex, status: 0x%0xlX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:667 -#: ports/nrf/drivers/bluetooth/ble_drv.c:756 +#: ports/nrf/common-hal/bleio/Service.c:83 #, c-format -msgid "Can not write attribute value. status: 0x%02x" +msgid "Failed to add characteristic, status: 0x%08lX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:691 +#: ports/nrf/common-hal/bleio/UUID.c:97 #, c-format -msgid "Can not notify attribute value. status: 0x%02x" +msgid "Failed to add Vendor Specific UUID, status: 0x%08lX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:784 -#, c-format -msgid "Can not start scanning. status: 0x%02x" +#: ports/nrf/common-hal/bleio/UUID.c:102 +msgid "Invalid UUID string length" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:829 +#: ports/nrf/common-hal/bleio/UUID.c:109 +#: shared-bindings/bleio/Characteristic.c:125 +#: shared-bindings/bleio/Service.c:105 +msgid "Invalid UUID parameter" +msgstr "" + +#: ports/nrf/common-hal/busio/I2C.c:96 +msgid "All I2C peripherals are in use" +msgstr "" + +#: ports/nrf/common-hal/busio/SPI.c:133 +msgid "All SPI peripherals are in use" +msgstr "" + +#: ports/nrf/common-hal/busio/UART.c:48 #, c-format -msgid "Can not connect. status: 0x%02x" +msgid "error = 0x%08lX" msgstr "" -#: ports/nrf/modules/ubluepy/ubluepy_characteristic.c:68 -#: ports/nrf/modules/ubluepy/ubluepy_service.c:80 -#: ports/nrf/modules/ubluepy/ubluepy_service.c:132 -#: ports/nrf/modules/ubluepy/ubluepy_uuid.c:137 -msgid "Invalid UUID parameter" +#: ports/nrf/common-hal/busio/UART.c:86 +msgid "Invalid buffer size" msgstr "" -#: ports/nrf/modules/ubluepy/ubluepy_service.c:73 -msgid "Invalid Service type" +#: ports/nrf/common-hal/busio/UART.c:90 +msgid "Odd parity is not supported" msgstr "" -#: ports/nrf/modules/ubluepy/ubluepy_uuid.c:127 -msgid "Invalid UUID string length" +#: ports/nrf/common-hal/busio/UART.c:322 ports/nrf/common-hal/busio/UART.c:326 +#: ports/nrf/common-hal/busio/UART.c:331 ports/nrf/common-hal/busio/UART.c:336 +#: ports/nrf/common-hal/busio/UART.c:342 ports/nrf/common-hal/busio/UART.c:347 +#: ports/nrf/common-hal/busio/UART.c:352 ports/nrf/common-hal/busio/UART.c:356 +#: ports/nrf/common-hal/busio/UART.c:364 +msgid "busio.UART not available" +msgstr "" + +#: ports/nrf/common-hal/microcontroller/Processor.c:49 +#, c-format +msgid "Can not get temperature. status: 0x%02x" +msgstr "" + +#: ports/nrf/common-hal/pulseio/PWMOut.c:161 +msgid "All PWM peripherals are in use" msgstr "" #: ports/unix/modffi.c:138 @@ -917,19 +938,33 @@ msgstr "" msgid "bad compile mode" msgstr "" -#: py/builtinimport.c:338 +#: py/builtinhelp.c:137 +msgid "Plus any modules on the filesystem\n" +msgstr "" + +#: py/builtinhelp.c:183 +#, c-format +msgid "" +"Welcome to Adafruit CircuitPython %s!\n" +"\n" +"Please visit learn.adafruit.com/category/circuitpython for project guides.\n" +"\n" +"To list built-in modules please do `help(\"modules\")`.\n" +msgstr "" + +#: py/builtinimport.c:336 msgid "cannot perform relative import" msgstr "" -#: py/builtinimport.c:422 py/builtinimport.c:534 +#: py/builtinimport.c:420 py/builtinimport.c:532 msgid "module not found" msgstr "" -#: py/builtinimport.c:425 py/builtinimport.c:537 +#: py/builtinimport.c:423 py/builtinimport.c:535 msgid "no module named '%q'" msgstr "" -#: py/builtinimport.c:512 +#: py/builtinimport.c:510 msgid "relative import" msgstr "" @@ -1078,38 +1113,85 @@ msgstr "" msgid "'data' requires integer arguments" msgstr "" -#: py/emitinlinextensa.c:86 -msgid "can only have up to 4 parameters to Xtensa assembly" +#: py/emitinlinethumb.c:102 +msgid "can only have up to 4 parameters to Thumb assembly" msgstr "" -#: py/emitinlinextensa.c:91 py/emitinlinextensa.c:96 -msgid "parameters must be registers in sequence a2 to a5" +#: py/emitinlinethumb.c:107 py/emitinlinethumb.c:112 +msgid "parameters must be registers in sequence r0 to r3" +msgstr "" + +#: py/emitinlinethumb.c:188 py/emitinlinethumb.c:230 +#, c-format +msgid "'%s' expects at most r%d" msgstr "" -#: py/emitinlinextensa.c:162 +#: py/emitinlinethumb.c:197 py/emitinlinextensa.c:162 #, c-format msgid "'%s' expects a register" msgstr "" -#: py/emitinlinextensa.c:169 +#: py/emitinlinethumb.c:211 +#, c-format +msgid "'%s' expects a special register" +msgstr "" + +#: py/emitinlinethumb.c:239 +#, c-format +msgid "'%s' expects an FPU register" +msgstr "" + +#: py/emitinlinethumb.c:292 +#, c-format +msgid "'%s' expects {r0, r1, ...}" +msgstr "" + +#: py/emitinlinethumb.c:299 py/emitinlinextensa.c:169 #, c-format msgid "'%s' expects an integer" msgstr "" -#: py/emitinlinextensa.c:174 +#: py/emitinlinethumb.c:304 #, c-format -msgid "'%s' integer %d is not within range %d..%d" +msgid "'%s' integer 0x%x does not fit in mask 0x%x" +msgstr "" + +#: py/emitinlinethumb.c:328 +#, c-format +msgid "'%s' expects an address of the form [a, b]" msgstr "" -#: py/emitinlinextensa.c:182 +#: py/emitinlinethumb.c:334 py/emitinlinextensa.c:182 #, c-format msgid "'%s' expects a label" msgstr "" -#: py/emitinlinextensa.c:193 +#: py/emitinlinethumb.c:345 py/emitinlinextensa.c:193 msgid "label '%q' not defined" msgstr "" +#: py/emitinlinethumb.c:806 +#, c-format +msgid "unsupported Thumb instruction '%s' with %d arguments" +msgstr "" + +#: py/emitinlinethumb.c:810 +msgid "branch not in range" +msgstr "" + +#: py/emitinlinextensa.c:86 +msgid "can only have up to 4 parameters to Xtensa assembly" +msgstr "" + +#: py/emitinlinextensa.c:91 py/emitinlinextensa.c:96 +msgid "parameters must be registers in sequence a2 to a5" +msgstr "" + +#: py/emitinlinextensa.c:174 +#, c-format +msgid "'%s' integer %d is not within range %d..%d" +msgstr "" + #: py/emitinlinextensa.c:327 #, c-format msgid "unsupported Xtensa instruction '%s' with %d arguments" @@ -1929,7 +2011,7 @@ msgid "AnalogOut is only 16 bits. Value must be less than 65536." msgstr "" #: shared-bindings/audiobusio/I2SOut.c:225 -#: shared-bindings/audioio/AudioOut.c:223 +#: shared-bindings/audioio/AudioOut.c:226 msgid "Not playing" msgstr "" @@ -1966,6 +2048,22 @@ msgid "" "destination buffer must be a bytearray or array of type 'B' for bit_depth = 8" msgstr "" +#: shared-bindings/audioio/Mixer.c:94 +msgid "Invalid voice count" +msgstr "" + +#: shared-bindings/audioio/Mixer.c:99 +msgid "Invalid channel count" +msgstr "" + +#: shared-bindings/audioio/Mixer.c:103 +msgid "Sample rate must be positive" +msgstr "" + +#: shared-bindings/audioio/Mixer.c:107 +msgid "bits_per_sample must be 8 or 16" +msgstr "" + #: shared-bindings/audioio/RawSample.c:98 msgid "" "sample_source buffer must be a bytearray or array of type 'h', 'H', 'b' or " @@ -1990,22 +2088,46 @@ msgstr "" msgid "Buffer must be at least length 1" msgstr "" -#: shared-bindings/bitbangio/SPI.c:151 shared-bindings/busio/SPI.c:168 +#: shared-bindings/bitbangio/SPI.c:151 shared-bindings/busio/SPI.c:175 msgid "Invalid polarity" msgstr "" -#: shared-bindings/bitbangio/SPI.c:155 shared-bindings/busio/SPI.c:172 +#: shared-bindings/bitbangio/SPI.c:155 shared-bindings/busio/SPI.c:179 msgid "Invalid phase" msgstr "" -#: shared-bindings/bitbangio/SPI.c:159 shared-bindings/busio/SPI.c:176 +#: shared-bindings/bitbangio/SPI.c:159 shared-bindings/busio/SPI.c:183 msgid "Invalid number of bits" msgstr "" -#: shared-bindings/bitbangio/SPI.c:284 shared-bindings/busio/SPI.c:341 +#: shared-bindings/bitbangio/SPI.c:284 shared-bindings/busio/SPI.c:348 msgid "buffer slices must be of equal length" msgstr "" +#: shared-bindings/bleio/Address.c:101 +msgid "Wrong address length" +msgstr "" + +#: shared-bindings/bleio/Address.c:107 +msgid "Wrong number of bytes provided" +msgstr "" + +#: shared-bindings/bleio/Device.c:210 +msgid "Can't add services in Central mode" +msgstr "" + +#: shared-bindings/bleio/Device.c:226 +msgid "Can't connect in Peripheral mode" +msgstr "" + +#: shared-bindings/bleio/Device.c:256 +msgid "Can't change the name in Central mode" +msgstr "" + +#: shared-bindings/bleio/Device.c:277 shared-bindings/bleio/Device.c:313 +msgid "Can't advertise in Central mode" +msgstr "" + #: shared-bindings/busio/I2C.c:120 msgid "Function requires lock." msgstr "" @@ -2120,7 +2242,7 @@ msgstr "" #: shared-bindings/microcontroller/Pin.c:89 #: shared-bindings/neopixel_write/__init__.c:67 -#: shared-bindings/pulseio/PulseOut.c:75 +#: shared-bindings/pulseio/PulseOut.c:76 msgid "Expected a %q" msgstr "" @@ -2163,7 +2285,7 @@ msgstr "" #: shared-bindings/pulseio/PWMOut.c:195 msgid "" -"PWM frequency not writeable when variable_frequency is False on construction." +"PWM frequency not writable when variable_frequency is False on construction." msgstr "" #: shared-bindings/pulseio/PulseIn.c:275 @@ -2182,7 +2304,7 @@ msgstr "" msgid "Read-only" msgstr "" -#: shared-bindings/pulseio/PulseOut.c:134 +#: shared-bindings/pulseio/PulseOut.c:135 msgid "Array must contain halfwords (type 'H')" msgstr "" @@ -2211,6 +2333,10 @@ msgstr "" msgid "RTC calibration is not supported on this board" msgstr "" +#: shared-bindings/socket/__init__.c:516 shared-module/network/__init__.c:81 +msgid "no available NIC" +msgstr "" + #: shared-bindings/storage/__init__.c:77 msgid "filesystem must provide mount method" msgstr "" @@ -2235,15 +2361,15 @@ msgstr "" msgid "time.struct_time() takes a 9-sequence" msgstr "" -#: shared-bindings/time/__init__.c:169 shared-bindings/time/__init__.c:250 +#: shared-bindings/time/__init__.c:169 shared-bindings/time/__init__.c:264 msgid "Tuple or struct_time argument required" msgstr "" -#: shared-bindings/time/__init__.c:174 shared-bindings/time/__init__.c:255 +#: shared-bindings/time/__init__.c:174 shared-bindings/time/__init__.c:269 msgid "function takes exactly 9 arguments" msgstr "" -#: shared-bindings/time/__init__.c:226 shared-bindings/time/__init__.c:259 +#: shared-bindings/time/__init__.c:240 shared-bindings/time/__init__.c:273 msgid "timestamp out of range for platform time_t" msgstr "" @@ -2256,6 +2382,34 @@ msgid "" "Object has been deinitialized and can no longer be used. Create a new object." msgstr "" +#: shared-module/audioio/Mixer.c:47 shared-module/audioio/WaveFile.c:117 +msgid "Couldn't allocate first buffer" +msgstr "" + +#: shared-module/audioio/Mixer.c:53 shared-module/audioio/WaveFile.c:123 +msgid "Couldn't allocate second buffer" +msgstr "" + +#: shared-module/audioio/Mixer.c:82 +msgid "Voice index too high" +msgstr "" + +#: shared-module/audioio/Mixer.c:85 +msgid "The sample's sample rate does not match the mixer's" +msgstr "" + +#: shared-module/audioio/Mixer.c:88 +msgid "The sample's channel count does not match the mixer's" +msgstr "" + +#: shared-module/audioio/Mixer.c:91 +msgid "The sample's bits_per_sample does not match the mixer's" +msgstr "" + +#: shared-module/audioio/Mixer.c:100 +msgid "The sample's signedness does not match the mixer's" +msgstr "" + #: shared-module/audioio/WaveFile.c:61 msgid "Invalid wave file" msgstr "" @@ -2276,39 +2430,31 @@ msgstr "" msgid "Invalid file" msgstr "" -#: shared-module/audioio/WaveFile.c:117 -msgid "Couldn't allocate first buffer" -msgstr "" - -#: shared-module/audioio/WaveFile.c:123 -msgid "Couldn't allocate second buffer" -msgstr "" - #: shared-module/bitbangio/I2C.c:58 msgid "Clock stretch too long" msgstr "" -#: shared-module/bitbangio/SPI.c:45 +#: shared-module/bitbangio/SPI.c:44 msgid "Clock pin init failed." msgstr "" -#: shared-module/bitbangio/SPI.c:51 +#: shared-module/bitbangio/SPI.c:50 msgid "MOSI pin init failed." msgstr "" -#: shared-module/bitbangio/SPI.c:62 +#: shared-module/bitbangio/SPI.c:61 msgid "MISO pin init failed." msgstr "" -#: shared-module/bitbangio/SPI.c:122 +#: shared-module/bitbangio/SPI.c:121 msgid "Cannot write without MOSI pin." msgstr "" -#: shared-module/bitbangio/SPI.c:177 +#: shared-module/bitbangio/SPI.c:176 msgid "Cannot read without MISO pin." msgstr "" -#: shared-module/bitbangio/SPI.c:241 +#: shared-module/bitbangio/SPI.c:240 msgid "Cannot transfer without MOSI and MISO pins." msgstr "" @@ -2342,6 +2488,10 @@ msgstr "" msgid "Only true color (24 bpp or higher) BMP supported %x" msgstr "" +#: shared-module/storage/__init__.c:155 +msgid "Cannot remount '/' when USB is active." +msgstr "" + #: shared-module/struct/__init__.c:39 msgid "'S' and 'O' are not supported format types" msgstr "" @@ -2349,3 +2499,16 @@ msgstr "" #: shared-module/struct/__init__.c:83 msgid "too many arguments provided with the given format" msgstr "" + +#: shared-module/usb_hid/Device.c:45 +#, c-format +msgid "Buffer incorrect size. Should be %d bytes." +msgstr "" + +#: shared-module/usb_hid/Device.c:53 +msgid "USB Busy" +msgstr "" + +#: shared-module/usb_hid/Device.c:59 +msgid "USB Error" +msgstr "" diff --git a/locale/es.po b/locale/es.po index 48cfdcda8..e9e97842a 100644 --- a/locale/es.po +++ b/locale/es.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-09-21 12:23-0400\n" +"POT-Creation-Date: 2018-11-09 16:20-0800\n" "PO-Revision-Date: 2018-08-24 22:56-0500\n" "Last-Translator: \n" "Language-Team: \n" @@ -65,7 +65,7 @@ msgstr "string de longitud impar" #: extmod/modubinascii.c:101 msgid "non-hex digit found" -msgstr "se encontró un digito no hexadecimal" +msgstr "se encontró un digito non-hex" #: extmod/modubinascii.c:169 msgid "incorrect padding" @@ -81,7 +81,7 @@ msgstr "No se puede obtener inequívocamente sizeof escalar" #: extmod/moductypes.c:397 msgid "struct: no fields" -msgstr "struct: no fields" +msgstr "struct: sin campos" #: extmod/moductypes.c:530 msgid "struct: cannot index" @@ -121,7 +121,7 @@ msgstr "certificado inválido" #: extmod/modutimeq.c:131 msgid "queue overflow" -msgstr "desborde de queue" +msgstr "desbordamiento de queue" #: extmod/moduzlib.c:98 msgid "compression header" @@ -132,16 +132,14 @@ msgid "invalid dupterm index" msgstr "index dupterm inválido" #: extmod/vfs_fat.c:426 py/moduerrno.c:150 -#, fuzzy msgid "Read-only filesystem" -msgstr "sistema de archivos de Solo-Lectura" +msgstr "Sistema de archivos de solo-Lectura" #: extmod/vfs_posix_file.c:48 ports/unix/file.c:50 py/objstringio.c:43 msgid "I/O operation on closed file" msgstr "Operación I/O en archivo cerrado" #: lib/embed/abort_.c:8 -#, fuzzy msgid "abort() called" msgstr "se llamó abort()" @@ -149,91 +147,90 @@ msgstr "se llamó abort()" msgid "invalid arguments" msgstr "argumentos inválidos" -#: lib/utils/pyexec.c:97 py/builtinimport.c:253 +#: lib/utils/pyexec.c:97 py/builtinimport.c:251 msgid "script compilation not supported" msgstr "script de compilación no soportado" -#: main.c:143 +#: main.c:154 msgid " output:\n" msgstr " salida:\n" -#: main.c:157 main.c:230 -#, fuzzy +#: main.c:168 main.c:241 msgid "" "Auto-reload is on. Simply save files over USB to run them or enter REPL to " "disable.\n" msgstr "" "Auto-reload habilitado. Simplemente guarda los archivos via USB para " -"ejecutarlos o entra REPL para desabilitarlos.\n" +"ejecutarlos o entra al REPL para desabilitarlos.\n" -#: main.c:159 +#: main.c:170 msgid "Running in safe mode! Auto-reload is off.\n" -msgstr "Ejecutando en modo seguro! Auto-recarga esta deshabilitado.\n" +msgstr "Ejecutando en modo seguro! La auto-recarga esta deshabilitada.\n" -#: main.c:161 main.c:232 +#: main.c:172 main.c:243 msgid "Auto-reload is off.\n" -msgstr "Auto-reload deshabilitado.\n" +msgstr "Auto-recarga deshabilitada.\n" -#: main.c:175 +#: main.c:186 msgid "Running in safe mode! Not running saved code.\n" msgstr "Ejecutando en modo seguro! No se esta ejecutando el código guardado.\n" -#: main.c:191 +#: main.c:202 msgid "WARNING: Your code filename has two extensions\n" msgstr "ADVERTENCIA: El nombre de archivo de tu código tiene dos extensiones\n" -#: main.c:239 +#: main.c:250 msgid "You requested starting safe mode by " -msgstr "Solicitaste iniciar en modo seguro con " +msgstr "Solicitaste iniciar en modo seguro por " -#: main.c:242 +#: main.c:253 msgid "To exit, please reset the board without " msgstr "Para salir, por favor reinicia la tarjeta sin " -#: main.c:249 +#: main.c:260 msgid "" "You are running in safe mode which means something really bad happened.\n" msgstr "" "Estás ejecutando en modo seguro, lo cual significa que algo realmente malo " "ha sucedido.\n" -#: main.c:251 +#: main.c:262 msgid "Looks like our core CircuitPython code crashed hard. Whoops!\n" -msgstr "" -"Parece que nuestro código del núcleo CircuitPython dejó de funcionar. " -"Whoops!\n" +msgstr "Parece que nuestro código CircuitPython dejó de funcionar. Whoops!\n" -#: main.c:252 +#: main.c:263 #, fuzzy msgid "Please file an issue here with the contents of your CIRCUITPY drive:\n" msgstr "" -"Por favor registra un problema aquí con los contenidos de tu unidad de " -"almacenamiento CIRCUITPY:\n" +"Por favor registra un issue en el siguiente URL con los contenidos de tu " +"unidad de almacenamiento CIRCUITPY:\n" -#: main.c:255 +#: main.c:266 msgid "" "The microcontroller's power dipped. Please make sure your power supply " "provides\n" msgstr "" +"La alimentación del microcontrolador cayó. Por favor asegurate de que tu " +"fuente de alimentación provee\n" -#: main.c:256 +#: main.c:267 msgid "" "enough power for the whole circuit and press reset (after ejecting " "CIRCUITPY).\n" msgstr "" -"suficiente poder para todo el circuito y pulsa reset (después de expulsar " +"suficiente poder para todo el circuito y presiona reset (después de expulsar " "CIRCUITPY).\n" -#: main.c:260 +#: main.c:271 msgid "Press any key to enter the REPL. Use CTRL-D to reload." msgstr "" "Presiona cualquier tecla para entrar al REPL. Usa CTRL-D para recargar." -#: main.c:416 +#: main.c:429 msgid "soft reboot\n" msgstr "reinicio suave\n" -#: ports/atmel-samd/audio_dma.c:285 +#: ports/atmel-samd/audio_dma.c:209 #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c:361 msgid "All sync event channels in use" msgstr "Todos los sync event channels están siendo utilizados" @@ -261,7 +258,7 @@ msgstr "Sin bus UART por default" #: ports/atmel-samd/common-hal/analogio/AnalogIn.c:63 #: ports/nrf/common-hal/analogio/AnalogIn.c:39 msgid "Pin does not have ADC capabilities" -msgstr "pin no tiene capacidades ADC" +msgstr "Pin no tiene capacidad ADC" #: ports/atmel-samd/common-hal/analogio/AnalogOut.c:49 msgid "No DAC on chip" @@ -278,7 +275,7 @@ msgstr "Pin bit clock inválido" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:153 msgid "Bit clock and word select must share a clock unit" -msgstr "Bit clock y Word select deben compartir la unidad de reloj" +msgstr "Bit clock y word select deben compartir una unidad de reloj" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:156 #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c:130 @@ -299,19 +296,19 @@ msgstr "Clock unit está siendo utilizado" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:240 #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c:172 msgid "Unable to find free GCLK" -msgstr "No se pudo encontrar un GCLK disponible" +msgstr "No se pudo encontrar un GCLK libre" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:254 msgid "Too many channels in sample." -msgstr "Demasiados canales en sample" +msgstr "Demasiados canales en sample." #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:305 -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:339 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:417 msgid "No DMA channel found" msgstr "No se encontró el canal DMA" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:308 -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:341 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:419 msgid "Unable to allocate buffers for signed conversion" msgstr "No se pudieron asignar buffers para la conversión con signo" @@ -321,112 +318,118 @@ msgstr "Pin clock inválido" #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c:134 msgid "Only 8 or 16 bit mono with " -msgstr "Solo mono de 8 o 16 bit con" +msgstr "Solo mono de 8 o 16 bit con " #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c:167 msgid "sampling rate out of range" -msgstr "velocidad de muestreo fuera de rango" +msgstr "frecuencia de muestreo fuera de rango" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:69 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:132 msgid "DAC already in use" msgstr "DAC ya está siendo utilizado" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:73 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:136 msgid "Right channel unsupported" -msgstr "El canal derecho no tiene soporte" +msgstr "Canal derecho no soportado" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:76 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:139 #: ports/atmel-samd/common-hal/pulseio/PWMOut.c:116 #: ports/atmel-samd/common-hal/touchio/TouchIn.c:65 msgid "Invalid pin" -msgstr "pin inválido" +msgstr "Pin inválido" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:84 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:147 msgid "Invalid pin for left channel" -msgstr "" +msgstr "Pin inválido para canal izquierdo" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:88 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:151 msgid "Invalid pin for right channel" -msgstr "" +msgstr "Pin inválido para canal derecho" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:91 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:154 msgid "Cannot output both channels on the same pin" -msgstr "No es posible utilizar el mismo pin para ambos canales" +msgstr "No se puede tener ambos canales en el mismo pin" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:176 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:243 #: ports/atmel-samd/common-hal/pulseio/PWMOut.c:189 #: ports/atmel-samd/common-hal/pulseio/PulseOut.c:110 +#: ports/nrf/common-hal/pulseio/PulseOut.c:107 msgid "All timers in use" -msgstr "Todos los timers están siendo utilizados" +msgstr "Todos los timers en uso" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:218 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:285 msgid "All event channels in use" -msgstr "Todos los canales de eventos están siendo utilizados" +msgstr "Todos los event channels en uso" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:297 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:375 #, c-format msgid "Sample rate too high. It must be less than %d" -msgstr "" +msgstr "Frecuencia de muestreo demasiado alta. Debe ser menor a %d" #: ports/atmel-samd/common-hal/busio/I2C.c:71 msgid "Not enough pins available" msgstr "No hay suficientes pines disponibles" #: ports/atmel-samd/common-hal/busio/I2C.c:78 -#: ports/atmel-samd/common-hal/busio/SPI.c:132 +#: ports/atmel-samd/common-hal/busio/SPI.c:171 #: ports/atmel-samd/common-hal/busio/UART.c:119 #: ports/atmel-samd/common-hal/i2cslave/I2CSlave.c:45 -#: ports/nrf/common-hal/busio/I2C.c:77 +#: ports/nrf/common-hal/busio/I2C.c:82 msgid "Invalid pins" msgstr "pines inválidos" #: ports/atmel-samd/common-hal/busio/I2C.c:101 msgid "SDA or SCL needs a pull up" -msgstr "" +msgstr "SDA o SCL necesitan una pull up" #: ports/atmel-samd/common-hal/busio/I2C.c:121 msgid "Unsupported baudrate" -msgstr "" +msgstr "Baudrate no soportado" #: ports/atmel-samd/common-hal/busio/UART.c:66 msgid "bytes > 8 bits not supported" -msgstr "bytes > 8 bits no son soportados" +msgstr "bytes > 8 bits no soportados" #: ports/atmel-samd/common-hal/busio/UART.c:72 +#: ports/nrf/common-hal/busio/UART.c:82 msgid "tx and rx cannot both be None" -msgstr "tx y rx no pueden ser ambos None" +msgstr "Ambos tx y rx no pueden ser None" #: ports/atmel-samd/common-hal/busio/UART.c:145 +#: ports/nrf/common-hal/busio/UART.c:115 msgid "Failed to allocate RX buffer" -msgstr "Fallo la asignación del buffer RX" +msgstr "Ha fallado la asignación del buffer RX" #: ports/atmel-samd/common-hal/busio/UART.c:153 msgid "Could not initialize UART" -msgstr "" +msgstr "No se puede inicializar la UART" #: ports/atmel-samd/common-hal/busio/UART.c:240 +#: ports/nrf/common-hal/busio/UART.c:149 msgid "No RX pin" -msgstr "" +msgstr "Sin pin RX" #: ports/atmel-samd/common-hal/busio/UART.c:294 +#: ports/nrf/common-hal/busio/UART.c:195 msgid "No TX pin" -msgstr "" +msgstr "Sin pin TX" #: ports/atmel-samd/common-hal/digitalio/DigitalInOut.c:170 -#: ports/nrf/common-hal/digitalio/DigitalInOut.c:142 +#: ports/nrf/common-hal/digitalio/DigitalInOut.c:147 msgid "Cannot get pull while in output mode" -msgstr "" +msgstr "No puede ser pull mientras este en modo de salida" #: ports/atmel-samd/common-hal/microcontroller/__init__.c:74 #: ports/esp8266/common-hal/microcontroller/__init__.c:64 msgid "Cannot reset into bootloader because no bootloader is present." -msgstr "" +msgstr "No se puede reiniciar a bootloader porque no hay bootloader presente." #: ports/atmel-samd/common-hal/pulseio/PWMOut.c:120 #: ports/atmel-samd/common-hal/pulseio/PWMOut.c:369 -#: ports/nrf/common-hal/pulseio/PWMOut.c:227 +#: ports/nrf/common-hal/pulseio/PWMOut.c:119 +#: ports/nrf/common-hal/pulseio/PWMOut.c:233 msgid "Invalid PWM frequency" -msgstr "" +msgstr "Frecuencia PWM inválida" #: ports/atmel-samd/common-hal/pulseio/PWMOut.c:187 msgid "All timers for this pin are in use" @@ -434,7 +437,7 @@ msgstr "Todos los timers para este pin están siendo utilizados" #: ports/atmel-samd/common-hal/pulseio/PulseIn.c:110 msgid "No hardware support on pin" -msgstr "" +msgstr "Sin soporte de hardware en pin" #: ports/atmel-samd/common-hal/pulseio/PulseIn.c:113 msgid "EXTINT channel already in use" @@ -444,21 +447,21 @@ msgstr "El canal EXTINT ya está siendo utilizado" #: ports/esp8266/common-hal/pulseio/PulseIn.c:86 #, c-format msgid "Failed to allocate RX buffer of %d bytes" -msgstr "Fallo la asignación del buffer RX de %d bytes" +msgstr "Falló la asignación del buffer RX de %d bytes" #: ports/atmel-samd/common-hal/pulseio/PulseIn.c:205 #: ports/esp8266/common-hal/pulseio/PulseIn.c:151 msgid "pop from an empty PulseIn" -msgstr "" +msgstr "pop de un PulseIn vacío" #: ports/atmel-samd/common-hal/pulseio/PulseIn.c:237 #: ports/esp8266/common-hal/pulseio/PulseIn.c:182 py/obj.c:420 msgid "index out of range" -msgstr "" +msgstr "index fuera de rango" #: ports/atmel-samd/common-hal/pulseio/PulseOut.c:178 msgid "Another send is already active" -msgstr "" +msgstr "Otro envío ya está activo" #: ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.c:38 msgid "Both pins must support hardware interrupts" @@ -470,59 +473,39 @@ msgstr "El canal EXTINT ya está siendo utilizado" #: ports/atmel-samd/common-hal/rtc/RTC.c:101 msgid "calibration value out of range +/-127" -msgstr "Valor de calibración fuera de rango +/-127" - -#: ports/atmel-samd/common-hal/storage/__init__.c:48 -msgid "Cannot remount '/' when USB is active." -msgstr "" +msgstr "Valor de calibración fuera del rango +/-127" #: ports/atmel-samd/common-hal/touchio/TouchIn.c:75 msgid "No free GCLKs" -msgstr "" - -#: ports/atmel-samd/common-hal/usb_hid/Device.c:78 -#: ports/nrf/common-hal/usb_hid/Device.c:45 -#, c-format -msgid "Buffer incorrect size. Should be %d bytes." -msgstr "Tamaño de buffer incorrecto. Debe ser de %d bytes." - -#: ports/atmel-samd/common-hal/usb_hid/Device.c:82 -#: ports/nrf/common-hal/usb_hid/Device.c:53 -msgid "USB Busy" -msgstr "" - -#: ports/atmel-samd/common-hal/usb_hid/Device.c:82 -#: ports/nrf/common-hal/usb_hid/Device.c:59 -msgid "USB Error" -msgstr "" +msgstr "Sin GCLKs libres" #: ports/esp8266/common-hal/analogio/AnalogIn.c:43 msgid "Pin %q does not have ADC capabilities" -msgstr "" +msgstr "Pin %q no tiene capacidades de ADC" #: ports/esp8266/common-hal/analogio/AnalogOut.c:39 msgid "No hardware support for analog out." -msgstr "" +msgstr "Sin soporte de hardware para analog out" #: ports/esp8266/common-hal/busio/SPI.c:72 msgid "Pins not valid for SPI" -msgstr "" +msgstr "Pines no válidos para SPI" #: ports/esp8266/common-hal/busio/UART.c:45 msgid "Only tx supported on UART1 (GPIO2)." -msgstr "" +msgstr "Solo tx soportada en UART1 (GPIO2)" #: ports/esp8266/common-hal/busio/UART.c:67 ports/esp8266/machine_uart.c:108 msgid "invalid data bits" -msgstr "" +msgstr "data bits inválidos" #: ports/esp8266/common-hal/busio/UART.c:91 ports/esp8266/machine_uart.c:144 msgid "invalid stop bits" -msgstr "" +msgstr "stop bits inválidos" #: ports/esp8266/common-hal/digitalio/DigitalInOut.c:200 msgid "ESP8266 does not support pull down." -msgstr "" +msgstr "ESP8266 no soporta pull down." #: ports/esp8266/common-hal/digitalio/DigitalInOut.c:210 msgid "GPIO16 does not support pull up." @@ -530,13 +513,13 @@ msgstr "GPIO16 no soporta pull up." #: ports/esp8266/common-hal/microcontroller/__init__.c:66 msgid "ESP8226 does not support safe mode." -msgstr "ESP8226 no soporta modo seguro" +msgstr "ESP8226 no soporta modo seguro." #: ports/esp8266/common-hal/pulseio/PWMOut.c:54 #: ports/esp8266/common-hal/pulseio/PWMOut.c:113 #, c-format msgid "Maximum PWM frequency is %dhz." -msgstr "La frecuencia máxima del PWM es %dhz" +msgstr "La frecuencia máxima del PWM es %dhz." #: ports/esp8266/common-hal/pulseio/PWMOut.c:57 #: ports/esp8266/common-hal/pulseio/PWMOut.c:116 @@ -547,7 +530,7 @@ msgstr "La frecuencia mínima del PWM es 1hz" #, c-format msgid "Multiple PWM frequencies not supported. PWM already set to %dhz." msgstr "" -"PWM de múltiples frecuencias no tiene soporte. El PWM ya se estableció a %dhz" +"PWM de múltiples frecuencias no soportado. El PWM ya se estableció a %dhz" #: ports/esp8266/common-hal/pulseio/PWMOut.c:77 ports/esp8266/machine_pwm.c:70 #, c-format @@ -556,293 +539,329 @@ msgstr "El pin %d no soporta PWM" #: ports/esp8266/common-hal/pulseio/PulseIn.c:78 msgid "No PulseIn support for %q" -msgstr "%q no tiene soporte para PulseIn" +msgstr "Sin soporte PulseIn para %q" #: ports/esp8266/common-hal/storage/__init__.c:34 msgid "Unable to remount filesystem" -msgstr "No se pudo montar de nuevo el sistema de archivos" +msgstr "Incapaz de montar de nuevo el sistema de archivos" #: ports/esp8266/common-hal/storage/__init__.c:38 msgid "Use esptool to erase flash and re-upload Python instead" -msgstr "" +msgstr "Usa esptool para borrar la flash y vuelve a cargar Python en su lugar" #: ports/esp8266/esp_mphal.c:154 msgid "C-level assert" -msgstr "" +msgstr "C-level assert" #: ports/esp8266/machine_adc.c:57 #, c-format msgid "not a valid ADC Channel: %d" -msgstr "" +msgstr "no es un canal ADC válido: %d" #: ports/esp8266/machine_hspi.c:131 ports/esp8266/machine_hspi.c:137 msgid "impossible baudrate" -msgstr "" +msgstr "baudrate imposible" #: ports/esp8266/machine_pin.c:129 msgid "expecting a pin" -msgstr "" +msgstr "esperando un pin" #: ports/esp8266/machine_pin.c:284 msgid "Pin(16) doesn't support pull" -msgstr "" +msgstr "Pin(16) no soporta para pull" #: ports/esp8266/machine_pin.c:323 msgid "invalid pin" -msgstr "" +msgstr "pin inválido" #: ports/esp8266/machine_pin.c:389 msgid "pin does not have IRQ capabilities" -msgstr "" +msgstr "pin sin capacidades IRQ" #: ports/esp8266/machine_rtc.c:185 msgid "buffer too long" -msgstr "" +msgstr "buffer demasiado largo" #: ports/esp8266/machine_rtc.c:209 ports/esp8266/machine_rtc.c:223 #: ports/esp8266/machine_rtc.c:246 msgid "invalid alarm" -msgstr "" +msgstr "alarma inválida" #: ports/esp8266/machine_uart.c:169 #, c-format msgid "UART(%d) does not exist" -msgstr "" +msgstr "UART(%d) no existe" #: ports/esp8266/machine_uart.c:219 msgid "UART(1) can't read" -msgstr "" +msgstr "UART(1) no puede leer" #: ports/esp8266/modesp.c:119 msgid "len must be multiple of 4" -msgstr "" +msgstr "len debe de ser múltiple de 4" #: ports/esp8266/modesp.c:274 #, c-format msgid "memory allocation failed, allocating %u bytes for native code" -msgstr "" +msgstr "falló la asignación de memoria, asignando %u bytes para código nativo" #: ports/esp8266/modesp.c:317 msgid "flash location must be below 1MByte" -msgstr "" +msgstr "la ubicación de la flash debe estar debajo de 1MByte" #: ports/esp8266/modmachine.c:63 msgid "frequency can only be either 80Mhz or 160MHz" -msgstr "" +msgstr "la frecuencia solo puede ser 80MHz o 160MHz" #: ports/esp8266/modnetwork.c:61 msgid "AP required" -msgstr "" +msgstr "AP requerido" #: ports/esp8266/modnetwork.c:61 msgid "STA required" -msgstr "" +msgstr "STA requerido" #: ports/esp8266/modnetwork.c:87 msgid "Cannot update i/f status" -msgstr "" +msgstr "No se puede actualizar i/f status" #: ports/esp8266/modnetwork.c:142 msgid "Cannot set STA config" -msgstr "" +msgstr "No se puede establecer STA config" #: ports/esp8266/modnetwork.c:144 msgid "Cannot connect to AP" -msgstr "" +msgstr "No se puede conectar a AP" #: ports/esp8266/modnetwork.c:152 msgid "Cannot disconnect from AP" -msgstr "" +msgstr "No se puede desconectar de AP" #: ports/esp8266/modnetwork.c:173 msgid "unknown status param" -msgstr "" +msgstr "status param desconocido" #: ports/esp8266/modnetwork.c:222 msgid "STA must be active" -msgstr "" +msgstr "STA debe estar activo" #: ports/esp8266/modnetwork.c:239 msgid "scan failed" -msgstr "" +msgstr "scan ha fallado" #: ports/esp8266/modnetwork.c:306 msgid "wifi_set_ip_info() failed" -msgstr "" +msgstr "wifi_set_ip_info() ha fallado" #: ports/esp8266/modnetwork.c:319 msgid "either pos or kw args are allowed" -msgstr "" +msgstr "ya sea pos o kw args son permitidos" #: ports/esp8266/modnetwork.c:329 msgid "can't get STA config" -msgstr "" +msgstr "no se puede obtener STA config" #: ports/esp8266/modnetwork.c:331 msgid "can't get AP config" -msgstr "" +msgstr "no se puede obtener AP config" #: ports/esp8266/modnetwork.c:346 msgid "invalid buffer length" -msgstr "" +msgstr "longitud de buffer inválida" #: ports/esp8266/modnetwork.c:405 msgid "can't set STA config" -msgstr "" +msgstr "no se puede establecer STA config" #: ports/esp8266/modnetwork.c:407 msgid "can't set AP config" -msgstr "" +msgstr "no se puede establecer AP config" #: ports/esp8266/modnetwork.c:416 msgid "can query only one param" -msgstr "" +msgstr "puede consultar solo un param" #: ports/esp8266/modnetwork.c:469 msgid "unknown config param" -msgstr "" +msgstr "parámetro config desconocido" #: ports/nrf/common-hal/analogio/AnalogOut.c:37 msgid "AnalogOut functionality not supported" -msgstr "" - -#: ports/nrf/common-hal/busio/I2C.c:91 -msgid "All I2C peripherals are in use" -msgstr "Todos los timers están siendo utilizados" - -#: ports/nrf/common-hal/busio/SPI.c:109 -msgid "All SPI peripherals are in use" -msgstr "Todos los timers están siendo utilizados" - -#: ports/nrf/common-hal/busio/SPI.c:170 -msgid "Baud rate too high for this SPI peripheral" -msgstr "" - -#: ports/nrf/common-hal/busio/UART.c:43 ports/nrf/common-hal/busio/UART.c:47 -#: ports/nrf/common-hal/busio/UART.c:51 ports/nrf/common-hal/busio/UART.c:60 -#: ports/nrf/common-hal/busio/UART.c:66 ports/nrf/common-hal/busio/UART.c:71 -#: ports/nrf/common-hal/busio/UART.c:76 ports/nrf/common-hal/busio/UART.c:81 -#: ports/nrf/common-hal/busio/UART.c:86 ports/nrf/common-hal/busio/UART.c:90 -msgid "busio.UART not yet implemented" -msgstr "" +msgstr "Funcionalidad AnalogOut no soportada" -#: ports/nrf/common-hal/microcontroller/Processor.c:49 +#: ports/nrf/common-hal/bleio/Adapter.c:41 #, c-format -msgid "Can not get temperature. status: 0x%02x" +msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:199 -msgid "Cannot apply GAP parameters." +#: ports/nrf/common-hal/bleio/Adapter.c:125 +#, c-format +msgid "Failed to change softdevice state, error: 0x%08lX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:213 -msgid "Cannot set PPCP parameters." +#: ports/nrf/common-hal/bleio/Adapter.c:135 +#, c-format +msgid "Failed to get softdevice state, error: 0x%08lX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:245 -msgid "Can not query for the device address." +#: ports/nrf/common-hal/bleio/Adapter.c:155 +#, c-format +msgid "Failed to get local address, error: 0x%08lX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:264 -msgid "Can not add Vendor Specific 128-bit UUID." -msgstr "" +#: ports/nrf/common-hal/bleio/Characteristic.c:52 +#, fuzzy, c-format +msgid "Failed to write gatts value, status: 0x%08lX" +msgstr "No se puede escribir el valor del atributo. status: 0x%02x" -#: ports/nrf/drivers/bluetooth/ble_drv.c:284 -#: ports/nrf/drivers/bluetooth/ble_drv.c:298 -msgid "Can not add Service." -msgstr "" +#: ports/nrf/common-hal/bleio/Characteristic.c:76 +#, fuzzy, c-format +msgid "Failed to notify attribute value, status: 0x%08lX" +msgstr "No se puede notificar el valor del anuncio. status: 0x%02x" -#: ports/nrf/drivers/bluetooth/ble_drv.c:373 -msgid "Can not add Characteristic." -msgstr "" +#: ports/nrf/common-hal/bleio/Characteristic.c:91 +#, fuzzy, c-format +msgid "Failed to read attribute value, status: 0x%08lX" +msgstr "No se puede leer el valor del atributo. status 0x%02x" -#: ports/nrf/drivers/bluetooth/ble_drv.c:400 -msgid "Can not apply device name in the stack." +#: ports/nrf/common-hal/bleio/Characteristic.c:119 +#: ports/nrf/common-hal/bleio/Device.c:272 +#: ports/nrf/common-hal/bleio/Device.c:307 +#, c-format +msgid "Failed to acquire mutex, status: 0x%08lX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:464 -#: ports/nrf/drivers/bluetooth/ble_drv.c:514 -msgid "Can not encode UUID, to check length." -msgstr "" +#: ports/nrf/common-hal/bleio/Characteristic.c:126 +#, fuzzy, c-format +msgid "Failed to write attribute value, status: 0x%08lX" +msgstr "No se puede escribir el valor del atributo. status: 0x%02x" -#: ports/nrf/drivers/bluetooth/ble_drv.c:470 -#: ports/nrf/drivers/bluetooth/ble_drv.c:520 -msgid "Can encode UUID into the advertisment packet." +#: ports/nrf/common-hal/bleio/Characteristic.c:138 +#: ports/nrf/common-hal/bleio/Device.c:284 +#: ports/nrf/common-hal/bleio/Device.c:319 +#: ports/nrf/common-hal/bleio/Device.c:354 +#: ports/nrf/common-hal/bleio/Device.c:391 +#, c-format +msgid "Failed to release mutex, status: 0x%08lX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:545 -msgid "Can not fit data into the advertisment packet." -msgstr "" +#: ports/nrf/common-hal/bleio/Device.c:81 +#: ports/nrf/common-hal/bleio/Device.c:114 +#, fuzzy +msgid "Can not fit data into the advertisment packet" +msgstr "Los datos no caben en el paquete de anuncio." -#: ports/nrf/drivers/bluetooth/ble_drv.c:558 -#: ports/nrf/drivers/bluetooth/ble_drv.c:604 +#: ports/nrf/common-hal/bleio/Device.c:266 #, c-format -msgid "Can not apply advertisment data. status: 0x%02x" -msgstr "" - -#: ports/nrf/drivers/bluetooth/ble_drv.c:614 +msgid "Failed to discover serivices, status: 0x%08lX" +msgstr "" + +#: ports/nrf/common-hal/bleio/Device.c:403 +#: ports/nrf/common-hal/bleio/Scanner.c:76 +#, fuzzy, c-format +msgid "Failed to continue scanning, status: 0x%0xlX" +msgstr "No se puede iniciar el escaneo. status: 0x%02x" + +#: ports/nrf/common-hal/bleio/Device.c:436 +#, fuzzy, c-format +msgid "Failed to connect, status: 0x%08lX" +msgstr "No se puede conectar. status: 0x%02x" + +#: ports/nrf/common-hal/bleio/Device.c:513 +#, fuzzy, c-format +msgid "Failed to add service, status: 0x%08lX" +msgstr "No se puede detener el anuncio. status: 0x%02x" + +#: ports/nrf/common-hal/bleio/Device.c:531 +#, fuzzy, c-format +msgid "Failed to start advertisment, status: 0x%08lX" +msgstr "No se puede inicar el anuncio. status: 0x%02x" + +#: ports/nrf/common-hal/bleio/Device.c:549 +#, fuzzy, c-format +msgid "Failed to stop advertisment, status: 0x%08lX" +msgstr "No se puede detener el anuncio. status: 0x%02x" + +#: ports/nrf/common-hal/bleio/Device.c:575 +#: ports/nrf/common-hal/bleio/Scanner.c:103 +#, fuzzy, c-format +msgid "Failed to start scanning, status: 0x%0xlX" +msgstr "No se puede iniciar el escaneo. status: 0x%02x" + +#: ports/nrf/common-hal/bleio/Device.c:592 +#, fuzzy, c-format +msgid "Failed to create mutex, status: 0x%0xlX" +msgstr "No se puede leer el valor del atributo. status 0x%02x" + +#: ports/nrf/common-hal/bleio/Service.c:83 #, c-format -msgid "Can not start advertisment. status: 0x%02x" +msgid "Failed to add characteristic, status: 0x%08lX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:631 -#, c-format -msgid "Can not stop advertisment. status: 0x%02x" -msgstr "" +#: ports/nrf/common-hal/bleio/UUID.c:97 +#, fuzzy, c-format +msgid "Failed to add Vendor Specific UUID, status: 0x%08lX" +msgstr "No se puede agregar el Vendor Specific 128-bit UUID." -#: ports/nrf/drivers/bluetooth/ble_drv.c:650 -#: ports/nrf/drivers/bluetooth/ble_drv.c:726 -#, c-format -msgid "Can not read attribute value. status: 0x%02x" -msgstr "" +#: ports/nrf/common-hal/bleio/UUID.c:102 +msgid "Invalid UUID string length" +msgstr "Longitud de string UUID inválida" -#: ports/nrf/drivers/bluetooth/ble_drv.c:667 -#: ports/nrf/drivers/bluetooth/ble_drv.c:756 -#, c-format -msgid "Can not write attribute value. status: 0x%02x" -msgstr "" +#: ports/nrf/common-hal/bleio/UUID.c:109 +#: shared-bindings/bleio/Characteristic.c:125 +#: shared-bindings/bleio/Service.c:105 +msgid "Invalid UUID parameter" +msgstr "Parámetro UUID inválido" -#: ports/nrf/drivers/bluetooth/ble_drv.c:691 -#, c-format -msgid "Can not notify attribute value. status: 0x%02x" -msgstr "" +#: ports/nrf/common-hal/busio/I2C.c:96 +msgid "All I2C peripherals are in use" +msgstr "Todos los timers están siendo usados" -#: ports/nrf/drivers/bluetooth/ble_drv.c:784 -#, c-format -msgid "Can not start scanning. status: 0x%02x" -msgstr "" +#: ports/nrf/common-hal/busio/SPI.c:133 +msgid "All SPI peripherals are in use" +msgstr "Todos los timers están siendo usados" -#: ports/nrf/drivers/bluetooth/ble_drv.c:829 +#: ports/nrf/common-hal/busio/UART.c:48 #, c-format -msgid "Can not connect. status: 0x%02x" -msgstr "" +msgid "error = 0x%08lX" +msgstr "error = 0x%08lx" -#: ports/nrf/modules/ubluepy/ubluepy_characteristic.c:68 -#: ports/nrf/modules/ubluepy/ubluepy_service.c:80 -#: ports/nrf/modules/ubluepy/ubluepy_service.c:132 -#: ports/nrf/modules/ubluepy/ubluepy_uuid.c:137 -msgid "Invalid UUID parameter" -msgstr "" +#: ports/nrf/common-hal/busio/UART.c:86 +msgid "Invalid buffer size" +msgstr "Tamaño de buffer inválido" -#: ports/nrf/modules/ubluepy/ubluepy_service.c:73 -msgid "Invalid Service type" -msgstr "" +#: ports/nrf/common-hal/busio/UART.c:90 +msgid "Odd parity is not supported" +msgstr "Paridad impar no soportada" -#: ports/nrf/modules/ubluepy/ubluepy_uuid.c:127 -msgid "Invalid UUID string length" -msgstr "" +#: ports/nrf/common-hal/busio/UART.c:322 ports/nrf/common-hal/busio/UART.c:326 +#: ports/nrf/common-hal/busio/UART.c:331 ports/nrf/common-hal/busio/UART.c:336 +#: ports/nrf/common-hal/busio/UART.c:342 ports/nrf/common-hal/busio/UART.c:347 +#: ports/nrf/common-hal/busio/UART.c:352 ports/nrf/common-hal/busio/UART.c:356 +#: ports/nrf/common-hal/busio/UART.c:364 +msgid "busio.UART not available" +msgstr "busio.UART no disponible" + +#: ports/nrf/common-hal/microcontroller/Processor.c:49 +#, c-format +msgid "Can not get temperature. status: 0x%02x" +msgstr "No se puede obtener la temperatura. status: 0x%02x" + +#: ports/nrf/common-hal/pulseio/PWMOut.c:161 +msgid "All PWM peripherals are in use" +msgstr "Todos los periféricos PWM en uso" #: ports/unix/modffi.c:138 msgid "Unknown type" -msgstr "" +msgstr "Tipo desconocido" #: ports/unix/modffi.c:207 ports/unix/modffi.c:265 msgid "Error in ffi_prep_cif" -msgstr "" +msgstr "Error en ffi_prep_cif" #: ports/unix/modffi.c:270 msgid "ffi_prep_closure_loc" -msgstr "" +msgstr "ffi_prep_closure_loc" #: ports/unix/modffi.c:413 msgid "Don't know how to pass object to native function" @@ -851,30 +870,30 @@ msgstr "" #: ports/unix/modusocket.c:474 #, c-format msgid "[addrinfo error %d]" -msgstr "" +msgstr "[addrinfo error %d]" #: py/argcheck.c:44 msgid "function does not take keyword arguments" -msgstr "" +msgstr "la función no tiene argumentos por palabra clave" #: py/argcheck.c:54 py/bc.c:85 py/objnamedtuple.c:104 #, c-format msgid "function takes %d positional arguments but %d were given" -msgstr "" +msgstr "la función toma %d argumentos posicionales pero le fueron dados %d" #: py/argcheck.c:64 #, c-format msgid "function missing %d required positional arguments" -msgstr "" +msgstr "a la función le hacen falta %d argumentos posicionales requeridos" #: py/argcheck.c:72 #, c-format msgid "function expected at most %d arguments, got %d" -msgstr "" +msgstr "la función esperaba a lo sumo %d argumentos, tiene %d" #: py/argcheck.c:97 msgid "'%q' argument required" -msgstr "" +msgstr "argumento '%q' requerido" #: py/argcheck.c:122 msgid "extra positional arguments given" @@ -898,11 +917,11 @@ msgstr "" #: py/bc.c:197 py/bc.c:215 msgid "unexpected keyword argument" -msgstr "" +msgstr "argumento por palabra clave inesperado" #: py/bc.c:199 msgid "keywords must be strings" -msgstr "" +msgstr "palabras clave deben ser strings" #: py/bc.c:206 py/objnamedtuple.c:138 msgid "function got multiple values for argument '%q'" @@ -933,19 +952,34 @@ msgstr "" msgid "bad compile mode" msgstr "" -#: py/builtinimport.c:338 +#: py/builtinhelp.c:137 +#, fuzzy +msgid "Plus any modules on the filesystem\n" +msgstr "Incapaz de montar de nuevo el sistema de archivos" + +#: py/builtinhelp.c:183 +#, c-format +msgid "" +"Welcome to Adafruit CircuitPython %s!\n" +"\n" +"Please visit learn.adafruit.com/category/circuitpython for project guides.\n" +"\n" +"To list built-in modules please do `help(\"modules\")`.\n" +msgstr "" + +#: py/builtinimport.c:336 msgid "cannot perform relative import" msgstr "" -#: py/builtinimport.c:422 py/builtinimport.c:534 +#: py/builtinimport.c:420 py/builtinimport.c:532 msgid "module not found" msgstr "módulo no encontrado" -#: py/builtinimport.c:425 py/builtinimport.c:537 +#: py/builtinimport.c:423 py/builtinimport.c:535 msgid "no module named '%q'" msgstr "ningún módulo se llama '%q'" -#: py/builtinimport.c:512 +#: py/builtinimport.c:510 msgid "relative import" msgstr "import relativo" @@ -1095,38 +1129,85 @@ msgstr "" msgid "'data' requires integer arguments" msgstr "" -#: py/emitinlinextensa.c:86 -msgid "can only have up to 4 parameters to Xtensa assembly" +#: py/emitinlinethumb.c:102 +msgid "can only have up to 4 parameters to Thumb assembly" msgstr "" -#: py/emitinlinextensa.c:91 py/emitinlinextensa.c:96 -msgid "parameters must be registers in sequence a2 to a5" +#: py/emitinlinethumb.c:107 py/emitinlinethumb.c:112 +msgid "parameters must be registers in sequence r0 to r3" +msgstr "" + +#: py/emitinlinethumb.c:188 py/emitinlinethumb.c:230 +#, c-format +msgid "'%s' expects at most r%d" msgstr "" -#: py/emitinlinextensa.c:162 +#: py/emitinlinethumb.c:197 py/emitinlinextensa.c:162 #, c-format msgid "'%s' expects a register" msgstr "" -#: py/emitinlinextensa.c:169 +#: py/emitinlinethumb.c:211 +#, c-format +msgid "'%s' expects a special register" +msgstr "ord espera un carácter" + +#: py/emitinlinethumb.c:239 +#, c-format +msgid "'%s' expects an FPU register" +msgstr "" + +#: py/emitinlinethumb.c:292 +#, c-format +msgid "'%s' expects {r0, r1, ...}" +msgstr "" + +#: py/emitinlinethumb.c:299 py/emitinlinextensa.c:169 #, c-format msgid "'%s' expects an integer" msgstr "" -#: py/emitinlinextensa.c:174 +#: py/emitinlinethumb.c:304 #, c-format -msgid "'%s' integer %d is not within range %d..%d" +msgid "'%s' integer 0x%x does not fit in mask 0x%x" msgstr "" -#: py/emitinlinextensa.c:182 +#: py/emitinlinethumb.c:328 +#, c-format +msgid "'%s' expects an address of the form [a, b]" +msgstr "" + +#: py/emitinlinethumb.c:334 py/emitinlinextensa.c:182 #, c-format msgid "'%s' expects a label" msgstr "" -#: py/emitinlinextensa.c:193 +#: py/emitinlinethumb.c:345 py/emitinlinextensa.c:193 msgid "label '%q' not defined" msgstr "" +#: py/emitinlinethumb.c:806 +#, c-format +msgid "unsupported Thumb instruction '%s' with %d arguments" +msgstr "" + +#: py/emitinlinethumb.c:810 +msgid "branch not in range" +msgstr "El argumento de chr() no esta en el rango(256)" + +#: py/emitinlinextensa.c:86 +msgid "can only have up to 4 parameters to Xtensa assembly" +msgstr "" + +#: py/emitinlinextensa.c:91 py/emitinlinextensa.c:96 +msgid "parameters must be registers in sequence a2 to a5" +msgstr "" + +#: py/emitinlinextensa.c:174 +#, c-format +msgid "'%s' integer %d is not within range %d..%d" +msgstr "" + #: py/emitinlinextensa.c:327 #, c-format msgid "unsupported Xtensa instruction '%s' with %d arguments" @@ -1277,14 +1358,12 @@ msgid "File exists" msgstr "" #: py/moduerrno.c:148 -#, fuzzy msgid "Unsupported operation" -msgstr "El pin %d no soporta PWM" +msgstr "Operacion no soportada" #: py/moduerrno.c:149 -#, fuzzy msgid "Invalid argument" -msgstr "argumentos inválidos" +msgstr "Argumento inválido" #: py/obj.c:90 msgid "Traceback (most recent call last):\n" @@ -1356,9 +1435,8 @@ msgid "%q indices must be integers, not %s" msgstr "" #: py/obj.c:423 -#, fuzzy msgid "%q index out of range" -msgstr "struct: index fuera de rango" +msgstr "%w index fuera de rango" #: py/obj.c:455 msgid "object has no len" @@ -1370,9 +1448,8 @@ msgid "object of type '%s' has no len()" msgstr "" #: py/obj.c:496 -#, fuzzy msgid "object does not support item deletion" -msgstr "ESP8226 no soporta modo seguro" +msgstr "object no soporta supresión de item" #: py/obj.c:499 #, c-format @@ -1431,9 +1508,8 @@ msgid "full" msgstr "" #: py/objdeque.c:127 -#, fuzzy msgid "empty" -msgstr "heap vacío" +msgstr "vacío" #: py/objdict.c:314 msgid "popitem(): dictionary is empty" @@ -1444,9 +1520,8 @@ msgid "dict update sequence has wrong length" msgstr "" #: py/objfloat.c:308 py/parsenum.c:331 -#, fuzzy msgid "complex values not supported" -msgstr "script de compilación no soportado" +msgstr "valores complejos no soportados" #: py/objgenerator.c:108 msgid "can't send non-None value to a just-started generator" @@ -1477,9 +1552,8 @@ msgid "float too big" msgstr "" #: py/objint.c:328 -#, fuzzy msgid "long int not supported in this build" -msgstr "AnalogOut no es soportado por el pin dado" +msgstr "long int no soportado en esta compilación" #: py/objint.c:334 py/objint.c:340 py/objint.c:350 py/objint.c:358 msgid "small int overflow" @@ -1518,9 +1592,8 @@ msgid "can't set attribute" msgstr "" #: py/objobject.c:55 -#, fuzzy msgid "__new__ arg must be a user-type" -msgstr "heap debe ser una lista" +msgstr "__new__ arg debe ser un user-type" #: py/objrange.c:110 msgid "zero step" @@ -1531,9 +1604,8 @@ msgid "pop from an empty set" msgstr "" #: py/objslice.c:66 -#, fuzzy msgid "Length must be an int" -msgstr "heap debe ser una lista" +msgstr "Length debe ser un int" #: py/objslice.c:71 msgid "Length must be non-negative" @@ -1548,9 +1620,8 @@ msgid "Cannot subclass slice" msgstr "" #: py/objstr.c:261 -#, fuzzy msgid "bytes value out of range" -msgstr "Valor de calibración fuera de rango +/-127" +msgstr "valor de bytes fuera de rango" #: py/objstr.c:270 msgid "wrong number of arguments" @@ -1561,18 +1632,16 @@ msgid "join expects a list of str/bytes objects consistent with self object" msgstr "" #: py/objstr.c:542 py/objstr.c:647 py/objstr.c:1744 -#, fuzzy msgid "empty separator" -msgstr "heap vacío" +msgstr "separator vacío" #: py/objstr.c:641 msgid "rsplit(None,n)" msgstr "" #: py/objstr.c:713 -#, fuzzy msgid "substring not found" -msgstr "módulo no encontrado" +msgstr "substring no encontrado" #: py/objstr.c:770 msgid "start/end indices" @@ -1613,14 +1682,12 @@ msgid "" msgstr "" #: py/objstr.c:1055 py/objstr.c:1083 -#, fuzzy msgid "tuple index out of range" -msgstr "struct: index fuera de rango" +msgstr "tuple index fuera de rango" #: py/objstr.c:1071 -#, fuzzy msgid "attributes not supported yet" -msgstr "bytes > 8 bits no son soportados" +msgstr "atributos aún no soportados" #: py/objstr.c:1079 msgid "" @@ -1628,9 +1695,8 @@ msgid "" msgstr "" #: py/objstr.c:1171 -#, fuzzy msgid "invalid format specifier" -msgstr "formato inválido" +msgstr "especificador de formato inválido" #: py/objstr.c:1192 msgid "sign not allowed in string format specifier" @@ -1668,9 +1734,8 @@ msgid "incomplete format key" msgstr "" #: py/objstr.c:1482 -#, fuzzy msgid "incomplete format" -msgstr "formato inválido" +msgstr "formato incompleto" #: py/objstr.c:1490 msgid "not enough arguments for format string" @@ -1708,9 +1773,8 @@ msgid "string indices must be integers, not %s" msgstr "" #: py/objstrunicode.c:145 py/objstrunicode.c:164 -#, fuzzy msgid "string index out of range" -msgstr "struct: index fuera de rango" +msgstr "string index fuera de rango" #: py/objtype.c:358 msgid "__init__() should return None" @@ -1759,9 +1823,8 @@ msgid "type '%q' is not an acceptable base type" msgstr "" #: py/objtype.c:1137 -#, fuzzy msgid "multiple inheritance not supported" -msgstr "operación I2C no soportada" +msgstr "herencia multiple no soportada" #: py/objtype.c:1164 msgid "multiple bases have instance lay-out conflict" @@ -1780,14 +1843,12 @@ msgid "issubclass() arg 1 must be a class" msgstr "" #: py/parse.c:726 -#, fuzzy msgid "constant must be an integer" -msgstr "heap debe ser una lista" +msgstr "constant debe ser un entero" #: py/parse.c:868 -#, fuzzy msgid "Unable to init parser" -msgstr "No se pudo encontrar un GCLK disponible" +msgstr "Incapaz de inicializar el parser" #: py/parse.c:1170 msgid "unexpected indent" @@ -1802,9 +1863,8 @@ msgid "int() arg 2 must be >= 2 and <= 36" msgstr "" #: py/parsenum.c:151 -#, fuzzy msgid "invalid syntax for integer" -msgstr "formato inválido" +msgstr "sintaxis inválido para entero" #: py/parsenum.c:155 #, c-format @@ -1812,14 +1872,12 @@ msgid "invalid syntax for integer with base %d" msgstr "" #: py/parsenum.c:339 -#, fuzzy msgid "invalid syntax for number" -msgstr "argumentos inválidos" +msgstr "sintaxis inválido para número" #: py/parsenum.c:342 -#, fuzzy msgid "decimal numbers not supported" -msgstr "bytes > 8 bits no son soportados" +msgstr "números decimales no soportados" #: py/persistentcode.c:223 msgid "" @@ -1832,9 +1890,8 @@ msgid "can only save bytecode" msgstr "" #: py/runtime.c:206 -#, fuzzy msgid "name not defined" -msgstr "módulo no encontrado" +msgstr "name no definido" #: py/runtime.c:209 msgid "name '%q' is not defined" @@ -1909,9 +1966,8 @@ msgid "exceptions must derive from BaseException" msgstr "" #: py/runtime.c:1430 -#, fuzzy msgid "cannot import name %q" -msgstr "ningún módulo se llama '%q'" +msgstr "no se puede importar name '%q'" #: py/runtime.c:1535 msgid "memory allocation failed, heap is locked" @@ -1931,9 +1987,8 @@ msgid "object not in sequence" msgstr "" #: py/stream.c:96 -#, fuzzy msgid "stream operation not supported" -msgstr "operación I2C no soportada" +msgstr "operación stream no soportada" #: py/vm.c:255 msgid "local variable referenced before assignment" @@ -1972,7 +2027,7 @@ msgid "AnalogOut is only 16 bits. Value must be less than 65536." msgstr "" #: shared-bindings/audiobusio/I2SOut.c:225 -#: shared-bindings/audioio/AudioOut.c:223 +#: shared-bindings/audioio/AudioOut.c:226 msgid "Not playing" msgstr "" @@ -2009,15 +2064,33 @@ msgid "" "destination buffer must be a bytearray or array of type 'B' for bit_depth = 8" msgstr "" +#: shared-bindings/audioio/Mixer.c:94 +msgid "Invalid voice count" +msgstr "Cuenta de voces inválida" + +#: shared-bindings/audioio/Mixer.c:99 +msgid "Invalid channel count" +msgstr "Cuenta de canales inválida" + +#: shared-bindings/audioio/Mixer.c:103 +msgid "Sample rate must be positive" +msgstr "Sample rate debe ser positivo" + +#: shared-bindings/audioio/Mixer.c:107 +msgid "bits_per_sample must be 8 or 16" +msgstr "bits_per_sample debe ser 8 o 16" + #: shared-bindings/audioio/RawSample.c:98 msgid "" "sample_source buffer must be a bytearray or array of type 'h', 'H', 'b' or " "'B'" msgstr "" +"sample_source buffer debe ser un bytearray o un array de tipo 'h', 'H', 'b' " +"o'B'" #: shared-bindings/audioio/RawSample.c:104 msgid "buffer must be a bytes-like object" -msgstr "" +msgstr "buffer debe de ser un objeto bytes-like" #: shared-bindings/audioio/WaveFile.c:78 #: shared-bindings/displayio/OnDiskBitmap.c:85 @@ -2033,22 +2106,46 @@ msgstr "" msgid "Buffer must be at least length 1" msgstr "" -#: shared-bindings/bitbangio/SPI.c:151 shared-bindings/busio/SPI.c:168 +#: shared-bindings/bitbangio/SPI.c:151 shared-bindings/busio/SPI.c:175 msgid "Invalid polarity" msgstr "" -#: shared-bindings/bitbangio/SPI.c:155 shared-bindings/busio/SPI.c:172 +#: shared-bindings/bitbangio/SPI.c:155 shared-bindings/busio/SPI.c:179 msgid "Invalid phase" msgstr "" -#: shared-bindings/bitbangio/SPI.c:159 shared-bindings/busio/SPI.c:176 +#: shared-bindings/bitbangio/SPI.c:159 shared-bindings/busio/SPI.c:183 msgid "Invalid number of bits" msgstr "" -#: shared-bindings/bitbangio/SPI.c:284 shared-bindings/busio/SPI.c:341 +#: shared-bindings/bitbangio/SPI.c:284 shared-bindings/busio/SPI.c:348 msgid "buffer slices must be of equal length" msgstr "" +#: shared-bindings/bleio/Address.c:101 +msgid "Wrong address length" +msgstr "" + +#: shared-bindings/bleio/Address.c:107 +msgid "Wrong number of bytes provided" +msgstr "" + +#: shared-bindings/bleio/Device.c:210 +msgid "Can't add services in Central mode" +msgstr "" + +#: shared-bindings/bleio/Device.c:226 +msgid "Can't connect in Peripheral mode" +msgstr "" + +#: shared-bindings/bleio/Device.c:256 +msgid "Can't change the name in Central mode" +msgstr "" + +#: shared-bindings/bleio/Device.c:277 shared-bindings/bleio/Device.c:313 +msgid "Can't advertise in Central mode" +msgstr "" + #: shared-bindings/busio/I2C.c:120 msgid "Function requires lock." msgstr "" @@ -2062,7 +2159,6 @@ msgid "stop must be 1 or 2" msgstr "" #: shared-bindings/digitalio/DigitalInOut.c:211 -#, fuzzy msgid "Invalid direction." msgstr "Dirección inválida." @@ -2164,7 +2260,7 @@ msgstr "" #: shared-bindings/microcontroller/Pin.c:89 #: shared-bindings/neopixel_write/__init__.c:67 -#: shared-bindings/pulseio/PulseOut.c:75 +#: shared-bindings/pulseio/PulseOut.c:76 msgid "Expected a %q" msgstr "" @@ -2207,7 +2303,7 @@ msgstr "" #: shared-bindings/pulseio/PWMOut.c:195 msgid "" -"PWM frequency not writeable when variable_frequency is False on construction." +"PWM frequency not writable when variable_frequency is False on construction." msgstr "" #: shared-bindings/pulseio/PulseIn.c:275 @@ -2223,11 +2319,10 @@ msgid "index must be int" msgstr "" #: shared-bindings/pulseio/PulseIn.c:293 -#, fuzzy msgid "Read-only" -msgstr "Solo lectura" +msgstr "Solo-lectura" -#: shared-bindings/pulseio/PulseOut.c:134 +#: shared-bindings/pulseio/PulseOut.c:135 msgid "Array must contain halfwords (type 'H')" msgstr "" @@ -2256,6 +2351,10 @@ msgstr "" msgid "RTC calibration is not supported on this board" msgstr "" +#: shared-bindings/socket/__init__.c:516 shared-module/network/__init__.c:81 +msgid "no available NIC" +msgstr "" + #: shared-bindings/storage/__init__.c:77 msgid "filesystem must provide mount method" msgstr "" @@ -2280,15 +2379,15 @@ msgstr "" msgid "time.struct_time() takes a 9-sequence" msgstr "" -#: shared-bindings/time/__init__.c:169 shared-bindings/time/__init__.c:250 +#: shared-bindings/time/__init__.c:169 shared-bindings/time/__init__.c:264 msgid "Tuple or struct_time argument required" msgstr "" -#: shared-bindings/time/__init__.c:174 shared-bindings/time/__init__.c:255 +#: shared-bindings/time/__init__.c:174 shared-bindings/time/__init__.c:269 msgid "function takes exactly 9 arguments" msgstr "" -#: shared-bindings/time/__init__.c:226 shared-bindings/time/__init__.c:259 +#: shared-bindings/time/__init__.c:240 shared-bindings/time/__init__.c:273 msgid "timestamp out of range for platform time_t" msgstr "" @@ -2301,6 +2400,34 @@ msgid "" "Object has been deinitialized and can no longer be used. Create a new object." msgstr "" +#: shared-module/audioio/Mixer.c:47 shared-module/audioio/WaveFile.c:117 +msgid "Couldn't allocate first buffer" +msgstr "No se pudo asignar el primer buffer" + +#: shared-module/audioio/Mixer.c:53 shared-module/audioio/WaveFile.c:123 +msgid "Couldn't allocate second buffer" +msgstr "No se pudo asignar el segundo buffer" + +#: shared-module/audioio/Mixer.c:82 +msgid "Voice index too high" +msgstr "Index de voz demasiado alto" + +#: shared-module/audioio/Mixer.c:85 +msgid "The sample's sample rate does not match the mixer's" +msgstr "El sample rate del sample no iguala al del mixer" + +#: shared-module/audioio/Mixer.c:88 +msgid "The sample's channel count does not match the mixer's" +msgstr "La cuenta de canales del sample no iguala a las del mixer" + +#: shared-module/audioio/Mixer.c:91 +msgid "The sample's bits_per_sample does not match the mixer's" +msgstr "Los bits_per_sample del sample no igualan a los del mixer" + +#: shared-module/audioio/Mixer.c:100 +msgid "The sample's signedness does not match the mixer's" +msgstr "El signo del sample no iguala al del mixer" + #: shared-module/audioio/WaveFile.c:61 msgid "Invalid wave file" msgstr "" @@ -2321,39 +2448,31 @@ msgstr "" msgid "Invalid file" msgstr "" -#: shared-module/audioio/WaveFile.c:117 -msgid "Couldn't allocate first buffer" -msgstr "" - -#: shared-module/audioio/WaveFile.c:123 -msgid "Couldn't allocate second buffer" -msgstr "" - #: shared-module/bitbangio/I2C.c:58 msgid "Clock stretch too long" msgstr "" -#: shared-module/bitbangio/SPI.c:45 +#: shared-module/bitbangio/SPI.c:44 msgid "Clock pin init failed." msgstr "" -#: shared-module/bitbangio/SPI.c:51 +#: shared-module/bitbangio/SPI.c:50 msgid "MOSI pin init failed." msgstr "" -#: shared-module/bitbangio/SPI.c:62 +#: shared-module/bitbangio/SPI.c:61 msgid "MISO pin init failed." msgstr "" -#: shared-module/bitbangio/SPI.c:122 +#: shared-module/bitbangio/SPI.c:121 msgid "Cannot write without MOSI pin." msgstr "" -#: shared-module/bitbangio/SPI.c:177 +#: shared-module/bitbangio/SPI.c:176 msgid "Cannot read without MISO pin." msgstr "" -#: shared-module/bitbangio/SPI.c:241 +#: shared-module/bitbangio/SPI.c:240 msgid "Cannot transfer without MOSI and MISO pins." msgstr "" @@ -2370,14 +2489,12 @@ msgid "Group full" msgstr "" #: shared-module/displayio/Group.c:48 -#, fuzzy msgid "Group empty" -msgstr "heap vacío" +msgstr "Group vacío" #: shared-module/displayio/OnDiskBitmap.c:49 -#, fuzzy msgid "Invalid BMP file" -msgstr "pin inválido" +msgstr "Archivo BMP inválido" #: shared-module/displayio/OnDiskBitmap.c:59 #, c-format @@ -2389,6 +2506,10 @@ msgstr "" msgid "Only true color (24 bpp or higher) BMP supported %x" msgstr "" +#: shared-module/storage/__init__.c:155 +msgid "Cannot remount '/' when USB is active." +msgstr "No se puede volver a montar '/' cuando el USB esta activo." + #: shared-module/struct/__init__.c:39 msgid "'S' and 'O' are not supported format types" msgstr "" @@ -2396,3 +2517,49 @@ msgstr "" #: shared-module/struct/__init__.c:83 msgid "too many arguments provided with the given format" msgstr "" + +#: shared-module/usb_hid/Device.c:45 +#, c-format +msgid "Buffer incorrect size. Should be %d bytes." +msgstr "Tamaño de buffer incorrecto. Debe ser de %d bytes." + +#: shared-module/usb_hid/Device.c:53 +msgid "USB Busy" +msgstr "USB ocupado" + +#: shared-module/usb_hid/Device.c:59 +msgid "USB Error" +msgstr "Error USB" + +#~ msgid "Baud rate too high for this SPI peripheral" +#~ msgstr "Baud rate demasiado alto para este periférico SPI" + +#~ msgid "Invalid Service type" +#~ msgstr "Tipo de Servicio inválido" + +#~ msgid "Can encode UUID into the advertisement packet." +#~ msgstr "Se puede codificar el UUID en el paquete de anuncio." + +#~ msgid "Can not encode UUID, to check length." +#~ msgstr "No se puede codificar el UUID, para revisar la longitud." + +#~ msgid "Can not query for the device address." +#~ msgstr "No se puede consultar la dirección del dispositivo." + +#~ msgid "Can not apply advertisement data. status: 0x%02x" +#~ msgstr "No se puede aplicar los datos de anuncio. status: 0x%02x" + +#~ msgid "Can not apply device name in the stack." +#~ msgstr "No se puede aplicar el nombre del dispositivo en el stack." + +#~ msgid "Can not add Characteristic." +#~ msgstr "No se puede agregar la Característica." + +#~ msgid "Cannot apply GAP parameters." +#~ msgstr "No se pueden aplicar los parámetros GAP." + +#~ msgid "Cannot set PPCP parameters." +#~ msgstr "No se pueden establecer los parámetros PPCP." + +#~ msgid "Can not add Service." +#~ msgstr "No se puede agregar el Servicio." diff --git a/locale/fil.po b/locale/fil.po index ad6252a21..1dc5c1ca4 100644 --- a/locale/fil.po +++ b/locale/fil.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-09-21 12:23-0400\n" +"POT-Creation-Date: 2018-11-09 16:20-0800\n" "PO-Revision-Date: 2018-08-30 23:04-0700\n" "Last-Translator: Timothy <me@timothygarcia.ca>\n" "Language-Team: fil\n" @@ -147,15 +147,15 @@ msgstr "abort() tinawag" msgid "invalid arguments" msgstr "mali ang mga argumento" -#: lib/utils/pyexec.c:97 py/builtinimport.c:253 +#: lib/utils/pyexec.c:97 py/builtinimport.c:251 msgid "script compilation not supported" msgstr "script kompilasyon hindi supportado" -#: main.c:143 +#: main.c:154 msgid " output:\n" msgstr " output:\n" -#: main.c:157 main.c:230 +#: main.c:168 main.c:241 msgid "" "Auto-reload is on. Simply save files over USB to run them or enter REPL to " "disable.\n" @@ -163,48 +163,48 @@ msgstr "" "Ang awtomatikong pag re-reload ay ON. i-save lamang ang mga files sa USB " "para patakbuhin sila o pasukin ang REPL para i-disable ito.\n" -#: main.c:159 +#: main.c:170 msgid "Running in safe mode! Auto-reload is off.\n" msgstr "Tumatakbo sa safe mode! Awtomatikong pag re-reload ay OFF.\n" -#: main.c:161 main.c:232 +#: main.c:172 main.c:243 msgid "Auto-reload is off.\n" msgstr "Awtomatikong pag re-reload ay OFF.\n" -#: main.c:175 +#: main.c:186 msgid "Running in safe mode! Not running saved code.\n" msgstr "Tumatakbo sa safe mode! Hindi tumatakbo ang nai-save na code.\n" -#: main.c:191 +#: main.c:202 msgid "WARNING: Your code filename has two extensions\n" msgstr "BABALA: Ang pangalan ng file ay may dalawang extension\n" -#: main.c:239 +#: main.c:250 msgid "You requested starting safe mode by " msgstr "Ikaw ang humiling sa safe mode sa pamamagitan ng " -#: main.c:242 +#: main.c:253 msgid "To exit, please reset the board without " msgstr "Para lumabas, paki-reset ang board na wala ang " -#: main.c:249 +#: main.c:260 msgid "" "You are running in safe mode which means something really bad happened.\n" msgstr "" "Ikaw ay tumatakbo sa safe mode, ang ibig sabihin nito ay may masamang " "nangyari.\n" -#: main.c:251 +#: main.c:262 msgid "Looks like our core CircuitPython code crashed hard. Whoops!\n" msgstr "Mukhang ang core CircuitPython code ay nag-crash ng malakas. Aray!\n" -#: main.c:252 +#: main.c:263 msgid "Please file an issue here with the contents of your CIRCUITPY drive:\n" msgstr "" "Mag-file ng isang isyu dito gamit ang mga nilalaman ng iyong CIRCUITPY " "drive:\n" -#: main.c:255 +#: main.c:266 msgid "" "The microcontroller's power dipped. Please make sure your power supply " "provides\n" @@ -212,7 +212,7 @@ msgstr "" "Ang kapangyarihan ng mikrokontroller ay bumaba. Mangyaring suriin ang power " "supply \n" -#: main.c:256 +#: main.c:267 msgid "" "enough power for the whole circuit and press reset (after ejecting " "CIRCUITPY).\n" @@ -220,17 +220,17 @@ msgstr "" "ay nagbibigay ng sapat na power para sa buong circuit at i-press ang reset " "(pagkatapos i-eject ang CIRCUITPY).\n" -#: main.c:260 +#: main.c:271 msgid "Press any key to enter the REPL. Use CTRL-D to reload." msgstr "" "Pindutin ang anumang key upang ipasok ang REPL. Gamitin ang CTRL-D upang i-" "reload." -#: main.c:416 +#: main.c:429 msgid "soft reboot\n" msgstr "malambot na reboot\n" -#: ports/atmel-samd/audio_dma.c:285 +#: ports/atmel-samd/audio_dma.c:209 #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c:361 msgid "All sync event channels in use" msgstr "Lahat ng sync event channels ay ginagamit" @@ -303,12 +303,12 @@ msgid "Too many channels in sample." msgstr "Sobra ang channels sa sample." #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:305 -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:339 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:417 msgid "No DMA channel found" msgstr "Walang DMA channel na mahanap" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:308 -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:341 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:419 msgid "Unable to allocate buffers for signed conversion" msgstr "Hindi ma-allocate ang buffers para sa naka-sign na conversion" @@ -324,43 +324,44 @@ msgstr "Tanging 8 o 16 na bit mono na may " msgid "sampling rate out of range" msgstr "pagpili ng rate wala sa sakop" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:69 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:132 msgid "DAC already in use" msgstr "Ginagamit na ang DAC" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:73 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:136 msgid "Right channel unsupported" msgstr "Hindi supportado ang kanang channel" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:76 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:139 #: ports/atmel-samd/common-hal/pulseio/PWMOut.c:116 #: ports/atmel-samd/common-hal/touchio/TouchIn.c:65 msgid "Invalid pin" msgstr "Mali ang pin" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:84 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:147 msgid "Invalid pin for left channel" msgstr "Mali ang pin para sa kaliwang channel" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:88 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:151 msgid "Invalid pin for right channel" msgstr "Mali ang pin para sa kanang channel" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:91 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:154 msgid "Cannot output both channels on the same pin" msgstr "Hindi maaaring output ang mga parehong channel sa parehong pin" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:176 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:243 #: ports/atmel-samd/common-hal/pulseio/PWMOut.c:189 #: ports/atmel-samd/common-hal/pulseio/PulseOut.c:110 +#: ports/nrf/common-hal/pulseio/PulseOut.c:107 msgid "All timers in use" msgstr "Lahat ng timer ginagamit" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:218 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:285 msgid "All event channels in use" msgstr "Lahat ng event channels ginagamit" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:297 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:375 #, c-format msgid "Sample rate too high. It must be less than %d" msgstr "" @@ -370,10 +371,10 @@ msgid "Not enough pins available" msgstr "Hindi sapat ang magagamit na pins" #: ports/atmel-samd/common-hal/busio/I2C.c:78 -#: ports/atmel-samd/common-hal/busio/SPI.c:132 +#: ports/atmel-samd/common-hal/busio/SPI.c:171 #: ports/atmel-samd/common-hal/busio/UART.c:119 #: ports/atmel-samd/common-hal/i2cslave/I2CSlave.c:45 -#: ports/nrf/common-hal/busio/I2C.c:77 +#: ports/nrf/common-hal/busio/I2C.c:82 msgid "Invalid pins" msgstr "Mali ang pins" @@ -390,10 +391,12 @@ msgid "bytes > 8 bits not supported" msgstr "hindi sinusuportahan ang bytes > 8 bits" #: ports/atmel-samd/common-hal/busio/UART.c:72 +#: ports/nrf/common-hal/busio/UART.c:82 msgid "tx and rx cannot both be None" msgstr "tx at rx hindi pwedeng parehas na None" #: ports/atmel-samd/common-hal/busio/UART.c:145 +#: ports/nrf/common-hal/busio/UART.c:115 msgid "Failed to allocate RX buffer" msgstr "Nabigong ilaan ang RX buffer" @@ -402,15 +405,17 @@ msgid "Could not initialize UART" msgstr "Hindi ma-initialize ang UART" #: ports/atmel-samd/common-hal/busio/UART.c:240 +#: ports/nrf/common-hal/busio/UART.c:149 msgid "No RX pin" msgstr "Walang RX pin" #: ports/atmel-samd/common-hal/busio/UART.c:294 +#: ports/nrf/common-hal/busio/UART.c:195 msgid "No TX pin" msgstr "Walang TX pin" #: ports/atmel-samd/common-hal/digitalio/DigitalInOut.c:170 -#: ports/nrf/common-hal/digitalio/DigitalInOut.c:142 +#: ports/nrf/common-hal/digitalio/DigitalInOut.c:147 msgid "Cannot get pull while in output mode" msgstr "Hindi makakakuha ng pull habang nasa output mode" @@ -421,7 +426,8 @@ msgstr "Hindi ma-reset sa bootloader dahil walang bootloader." #: ports/atmel-samd/common-hal/pulseio/PWMOut.c:120 #: ports/atmel-samd/common-hal/pulseio/PWMOut.c:369 -#: ports/nrf/common-hal/pulseio/PWMOut.c:227 +#: ports/nrf/common-hal/pulseio/PWMOut.c:119 +#: ports/nrf/common-hal/pulseio/PWMOut.c:233 msgid "Invalid PWM frequency" msgstr "Mali ang PWM frequency" @@ -469,30 +475,10 @@ msgstr "Isang channel ng hardware interrupt ay ginagamit na" msgid "calibration value out of range +/-127" msgstr "ang halaga ng pagkakalibrate ay wala sa sakop +/-127" -#: ports/atmel-samd/common-hal/storage/__init__.c:48 -msgid "Cannot remount '/' when USB is active." -msgstr "Hindi ma-remount '/' kapag aktibo ang USB." - #: ports/atmel-samd/common-hal/touchio/TouchIn.c:75 msgid "No free GCLKs" msgstr "Walang libreng GCLKs" -#: ports/atmel-samd/common-hal/usb_hid/Device.c:78 -#: ports/nrf/common-hal/usb_hid/Device.c:45 -#, c-format -msgid "Buffer incorrect size. Should be %d bytes." -msgstr "Mali ang size ng buffer. Dapat %d bytes." - -#: ports/atmel-samd/common-hal/usb_hid/Device.c:82 -#: ports/nrf/common-hal/usb_hid/Device.c:53 -msgid "USB Busy" -msgstr "Busy ang USB" - -#: ports/atmel-samd/common-hal/usb_hid/Device.c:82 -#: ports/nrf/common-hal/usb_hid/Device.c:59 -msgid "USB Error" -msgstr "May pagkakamali ang USB" - #: ports/esp8266/common-hal/analogio/AnalogIn.c:43 msgid "Pin %q does not have ADC capabilities" msgstr "Walang kakayahang ADC ang pin %q" @@ -705,133 +691,172 @@ msgstr "hindi alam na config param" msgid "AnalogOut functionality not supported" msgstr "Hindi supportado ang AnalogOut" -#: ports/nrf/common-hal/busio/I2C.c:91 -#, fuzzy -msgid "All I2C peripherals are in use" -msgstr "Lahat ng timer ginagamit" - -#: ports/nrf/common-hal/busio/SPI.c:109 -#, fuzzy -msgid "All SPI peripherals are in use" -msgstr "Lahat ng timer ginagamit" +#: ports/nrf/common-hal/bleio/Adapter.c:41 +#, c-format +msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX" +msgstr "" -#: ports/nrf/common-hal/busio/SPI.c:170 -msgid "Baud rate too high for this SPI peripheral" +#: ports/nrf/common-hal/bleio/Adapter.c:125 +#, c-format +msgid "Failed to change softdevice state, error: 0x%08lX" msgstr "" -#: ports/nrf/common-hal/busio/UART.c:43 ports/nrf/common-hal/busio/UART.c:47 -#: ports/nrf/common-hal/busio/UART.c:51 ports/nrf/common-hal/busio/UART.c:60 -#: ports/nrf/common-hal/busio/UART.c:66 ports/nrf/common-hal/busio/UART.c:71 -#: ports/nrf/common-hal/busio/UART.c:76 ports/nrf/common-hal/busio/UART.c:81 -#: ports/nrf/common-hal/busio/UART.c:86 ports/nrf/common-hal/busio/UART.c:90 -msgid "busio.UART not yet implemented" -msgstr "hindi pa implemented ang busio.UART" +#: ports/nrf/common-hal/bleio/Adapter.c:135 +#, c-format +msgid "Failed to get softdevice state, error: 0x%08lX" +msgstr "" -#: ports/nrf/common-hal/microcontroller/Processor.c:49 +#: ports/nrf/common-hal/bleio/Adapter.c:155 #, c-format -msgid "Can not get temperature. status: 0x%02x" -msgstr "Hindi makuha ang temperatura. status 0x%02x" +msgid "Failed to get local address, error: 0x%08lX" +msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:199 -msgid "Cannot apply GAP parameters." -msgstr "Hindi ma-apply ang GAP parameters." +#: ports/nrf/common-hal/bleio/Characteristic.c:52 +#, fuzzy, c-format +msgid "Failed to write gatts value, status: 0x%08lX" +msgstr "Hindi maisulat ang attribute value. status: 0x%02x" -#: ports/nrf/drivers/bluetooth/ble_drv.c:213 -msgid "Cannot set PPCP parameters." -msgstr "Hindi ma-set ang PPCP parameters." +#: ports/nrf/common-hal/bleio/Characteristic.c:76 +#, fuzzy, c-format +msgid "Failed to notify attribute value, status: 0x%08lX" +msgstr "Hindi mabalitaan ang attribute value. status: 0x%02x" -#: ports/nrf/drivers/bluetooth/ble_drv.c:245 -msgid "Can not query for the device address." -msgstr "Hindi maaaring mag-query para sa address ng device." +#: ports/nrf/common-hal/bleio/Characteristic.c:91 +#, fuzzy, c-format +msgid "Failed to read attribute value, status: 0x%08lX" +msgstr "Hindi mabasa ang value ng attribute. status: 0x%02x" -#: ports/nrf/drivers/bluetooth/ble_drv.c:264 -msgid "Can not add Vendor Specific 128-bit UUID." -msgstr "Hindi maaaring magdagdag ng Vendor Specific na 128-bit UUID." +#: ports/nrf/common-hal/bleio/Characteristic.c:119 +#: ports/nrf/common-hal/bleio/Device.c:272 +#: ports/nrf/common-hal/bleio/Device.c:307 +#, c-format +msgid "Failed to acquire mutex, status: 0x%08lX" +msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:284 -#: ports/nrf/drivers/bluetooth/ble_drv.c:298 -msgid "Can not add Service." -msgstr "Hindi maidaragdag ang serbisyo." +#: ports/nrf/common-hal/bleio/Characteristic.c:126 +#, fuzzy, c-format +msgid "Failed to write attribute value, status: 0x%08lX" +msgstr "Hindi maisulat ang attribute value. status: 0x%02x" -#: ports/nrf/drivers/bluetooth/ble_drv.c:373 -msgid "Can not add Characteristic." -msgstr "Hindi mabasa and Characteristic." +#: ports/nrf/common-hal/bleio/Characteristic.c:138 +#: ports/nrf/common-hal/bleio/Device.c:284 +#: ports/nrf/common-hal/bleio/Device.c:319 +#: ports/nrf/common-hal/bleio/Device.c:354 +#: ports/nrf/common-hal/bleio/Device.c:391 +#, c-format +msgid "Failed to release mutex, status: 0x%08lX" +msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:400 -msgid "Can not apply device name in the stack." -msgstr "Hindi maaaring ma-aplay ang device name sa stack." +#: ports/nrf/common-hal/bleio/Device.c:81 +#: ports/nrf/common-hal/bleio/Device.c:114 +#, fuzzy +msgid "Can not fit data into the advertisment packet" +msgstr "Hindi makasya ang data sa loob ng advertisement packet." -#: ports/nrf/drivers/bluetooth/ble_drv.c:464 -#: ports/nrf/drivers/bluetooth/ble_drv.c:514 -msgid "Can not encode UUID, to check length." -msgstr "Hindi ma-encode UUID, para suriin ang haba." +#: ports/nrf/common-hal/bleio/Device.c:266 +#, c-format +msgid "Failed to discover serivices, status: 0x%08lX" +msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:470 -#: ports/nrf/drivers/bluetooth/ble_drv.c:520 -msgid "Can encode UUID into the advertisment packet." -msgstr "Maaring i-encode ang UUID sa advertisement packet." +#: ports/nrf/common-hal/bleio/Device.c:403 +#: ports/nrf/common-hal/bleio/Scanner.c:76 +#, fuzzy, c-format +msgid "Failed to continue scanning, status: 0x%0xlX" +msgstr "Hindi masimulaan mag i-scan. status: 0x%02x" -#: ports/nrf/drivers/bluetooth/ble_drv.c:545 -msgid "Can not fit data into the advertisment packet." -msgstr "Hindi makasya ang data sa loob ng advertisement packet." +#: ports/nrf/common-hal/bleio/Device.c:436 +#, fuzzy, c-format +msgid "Failed to connect, status: 0x%08lX" +msgstr "Hindi makaconnect. status: 0x%02x" -#: ports/nrf/drivers/bluetooth/ble_drv.c:558 -#: ports/nrf/drivers/bluetooth/ble_drv.c:604 -#, c-format -msgid "Can not apply advertisment data. status: 0x%02x" -msgstr "Hindi ma i-apply ang advertisment data. status: 0x%02x" +#: ports/nrf/common-hal/bleio/Device.c:513 +#, fuzzy, c-format +msgid "Failed to add service, status: 0x%08lX" +msgstr "Hindi mahinto ang advertisement. status: 0x%02x" -#: ports/nrf/drivers/bluetooth/ble_drv.c:614 -#, c-format -msgid "Can not start advertisment. status: 0x%02x" +#: ports/nrf/common-hal/bleio/Device.c:531 +#, fuzzy, c-format +msgid "Failed to start advertisment, status: 0x%08lX" msgstr "Hindi masimulaan ang advertisement. status 0x%02x" -#: ports/nrf/drivers/bluetooth/ble_drv.c:631 -#, c-format -msgid "Can not stop advertisment. status: 0x%02x" -msgstr "Hindi mahinto ang advertisment. status: 0x%02x" +#: ports/nrf/common-hal/bleio/Device.c:549 +#, fuzzy, c-format +msgid "Failed to stop advertisment, status: 0x%08lX" +msgstr "Hindi mahinto ang advertisement. status: 0x%02x" -#: ports/nrf/drivers/bluetooth/ble_drv.c:650 -#: ports/nrf/drivers/bluetooth/ble_drv.c:726 -#, c-format -msgid "Can not read attribute value. status: 0x%02x" -msgstr "Hindi mabasa ang value ng attribute. status: 0x%02x" +#: ports/nrf/common-hal/bleio/Device.c:575 +#: ports/nrf/common-hal/bleio/Scanner.c:103 +#, fuzzy, c-format +msgid "Failed to start scanning, status: 0x%0xlX" +msgstr "Hindi masimulaan mag i-scan. status: 0x%02x" -#: ports/nrf/drivers/bluetooth/ble_drv.c:667 -#: ports/nrf/drivers/bluetooth/ble_drv.c:756 -#, c-format -msgid "Can not write attribute value. status: 0x%02x" -msgstr "Hindi maisulat ang attribute value. status: 0x%02x" +#: ports/nrf/common-hal/bleio/Device.c:592 +#, fuzzy, c-format +msgid "Failed to create mutex, status: 0x%0xlX" +msgstr "Hindi mabasa ang value ng attribute. status: 0x%02x" -#: ports/nrf/drivers/bluetooth/ble_drv.c:691 +#: ports/nrf/common-hal/bleio/Service.c:83 #, c-format -msgid "Can not notify attribute value. status: 0x%02x" -msgstr "Hindi mabalitaan ang attribute value. status: 0x%02x" +msgid "Failed to add characteristic, status: 0x%08lX" +msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:784 -#, c-format -msgid "Can not start scanning. status: 0x%02x" -msgstr "Hindi masimulaan mag i-scan. status: 0x%02x" +#: ports/nrf/common-hal/bleio/UUID.c:97 +#, fuzzy, c-format +msgid "Failed to add Vendor Specific UUID, status: 0x%08lX" +msgstr "Hindi maaaring magdagdag ng Vendor Specific na 128-bit UUID." -#: ports/nrf/drivers/bluetooth/ble_drv.c:829 -#, c-format -msgid "Can not connect. status: 0x%02x" -msgstr "Hindi makaconnect. status: 0x%02x" +#: ports/nrf/common-hal/bleio/UUID.c:102 +msgid "Invalid UUID string length" +msgstr "Mali ang UUID string length" -#: ports/nrf/modules/ubluepy/ubluepy_characteristic.c:68 -#: ports/nrf/modules/ubluepy/ubluepy_service.c:80 -#: ports/nrf/modules/ubluepy/ubluepy_service.c:132 -#: ports/nrf/modules/ubluepy/ubluepy_uuid.c:137 +#: ports/nrf/common-hal/bleio/UUID.c:109 +#: shared-bindings/bleio/Characteristic.c:125 +#: shared-bindings/bleio/Service.c:105 msgid "Invalid UUID parameter" msgstr "Mali ang UUID parameter" -#: ports/nrf/modules/ubluepy/ubluepy_service.c:73 -msgid "Invalid Service type" -msgstr "Mali ang tipo ng serbisyo" +#: ports/nrf/common-hal/busio/I2C.c:96 +#, fuzzy +msgid "All I2C peripherals are in use" +msgstr "Lahat ng timer ginagamit" -#: ports/nrf/modules/ubluepy/ubluepy_uuid.c:127 -msgid "Invalid UUID string length" -msgstr "Mali ang UUID string length" +#: ports/nrf/common-hal/busio/SPI.c:133 +#, fuzzy +msgid "All SPI peripherals are in use" +msgstr "Lahat ng timer ginagamit" + +#: ports/nrf/common-hal/busio/UART.c:48 +#, c-format +msgid "error = 0x%08lX" +msgstr "" + +#: ports/nrf/common-hal/busio/UART.c:86 +#, fuzzy +msgid "Invalid buffer size" +msgstr "mali ang buffer length" + +#: ports/nrf/common-hal/busio/UART.c:90 +#, fuzzy +msgid "Odd parity is not supported" +msgstr "hindi sinusuportahan ang bytes > 8 bits" + +#: ports/nrf/common-hal/busio/UART.c:322 ports/nrf/common-hal/busio/UART.c:326 +#: ports/nrf/common-hal/busio/UART.c:331 ports/nrf/common-hal/busio/UART.c:336 +#: ports/nrf/common-hal/busio/UART.c:342 ports/nrf/common-hal/busio/UART.c:347 +#: ports/nrf/common-hal/busio/UART.c:352 ports/nrf/common-hal/busio/UART.c:356 +#: ports/nrf/common-hal/busio/UART.c:364 +msgid "busio.UART not available" +msgstr "" + +#: ports/nrf/common-hal/microcontroller/Processor.c:49 +#, c-format +msgid "Can not get temperature. status: 0x%02x" +msgstr "Hindi makuha ang temperatura. status 0x%02x" + +#: ports/nrf/common-hal/pulseio/PWMOut.c:161 +#, fuzzy +msgid "All PWM peripherals are in use" +msgstr "Lahat ng timer ginagamit" #: ports/unix/modffi.c:138 msgid "Unknown type" @@ -938,19 +963,34 @@ msgstr "masamang typecode" msgid "bad compile mode" msgstr "masamang mode ng compile" -#: py/builtinimport.c:338 +#: py/builtinhelp.c:137 +#, fuzzy +msgid "Plus any modules on the filesystem\n" +msgstr "Hindi ma-remount ang filesystem" + +#: py/builtinhelp.c:183 +#, c-format +msgid "" +"Welcome to Adafruit CircuitPython %s!\n" +"\n" +"Please visit learn.adafruit.com/category/circuitpython for project guides.\n" +"\n" +"To list built-in modules please do `help(\"modules\")`.\n" +msgstr "" + +#: py/builtinimport.c:336 msgid "cannot perform relative import" msgstr "hindi maaring isagawa ang relative import" -#: py/builtinimport.c:422 py/builtinimport.c:534 +#: py/builtinimport.c:420 py/builtinimport.c:532 msgid "module not found" msgstr "module hindi nakita" -#: py/builtinimport.c:425 py/builtinimport.c:537 +#: py/builtinimport.c:423 py/builtinimport.c:535 msgid "no module named '%q'" msgstr "walang module na '%q'" -#: py/builtinimport.c:512 +#: py/builtinimport.c:510 msgid "relative import" msgstr "relative import" @@ -1099,38 +1139,88 @@ msgstr "'data' kailangan ng hindi bababa sa 2 argument" msgid "'data' requires integer arguments" msgstr "'data' kailangan ng integer arguments" -#: py/emitinlinextensa.c:86 -msgid "can only have up to 4 parameters to Xtensa assembly" +#: py/emitinlinethumb.c:102 +#, fuzzy +msgid "can only have up to 4 parameters to Thumb assembly" msgstr "maaari lamang magkaroon ng hanggang 4 na parameter sa Xtensa assembly" -#: py/emitinlinextensa.c:91 py/emitinlinextensa.c:96 -msgid "parameters must be registers in sequence a2 to a5" +#: py/emitinlinethumb.c:107 py/emitinlinethumb.c:112 +#, fuzzy +msgid "parameters must be registers in sequence r0 to r3" msgstr "ang mga parameter ay dapat na nagrerehistro sa sequence a2 hanggang a5" -#: py/emitinlinextensa.c:162 +#: py/emitinlinethumb.c:188 py/emitinlinethumb.c:230 +#, fuzzy, c-format +msgid "'%s' expects at most r%d" +msgstr "Inaasahan ng '%s' ang isang rehistro" + +#: py/emitinlinethumb.c:197 py/emitinlinextensa.c:162 #, c-format msgid "'%s' expects a register" msgstr "Inaasahan ng '%s' ang isang rehistro" -#: py/emitinlinextensa.c:169 +#: py/emitinlinethumb.c:211 +#, fuzzy, c-format +msgid "'%s' expects a special register" +msgstr "Inaasahan ng '%s' ang isang rehistro" + +#: py/emitinlinethumb.c:239 +#, fuzzy, c-format +msgid "'%s' expects an FPU register" +msgstr "Inaasahan ng '%s' ang isang rehistro" + +#: py/emitinlinethumb.c:292 +#, fuzzy, c-format +msgid "'%s' expects {r0, r1, ...}" +msgstr "Inaasahan ng '%s' ang isang rehistro" + +#: py/emitinlinethumb.c:299 py/emitinlinextensa.c:169 #, c-format msgid "'%s' expects an integer" msgstr "Inaasahan ng '%s' ang isang integer" -#: py/emitinlinextensa.c:174 -#, c-format -msgid "'%s' integer %d is not within range %d..%d" +#: py/emitinlinethumb.c:304 +#, fuzzy, c-format +msgid "'%s' integer 0x%x does not fit in mask 0x%x" msgstr "'%s' integer %d ay wala sa sakop ng %d..%d" -#: py/emitinlinextensa.c:182 +#: py/emitinlinethumb.c:328 +#, fuzzy, c-format +msgid "'%s' expects an address of the form [a, b]" +msgstr "Inaasahan ng '%s' ang isang rehistro" + +#: py/emitinlinethumb.c:334 py/emitinlinextensa.c:182 #, c-format msgid "'%s' expects a label" msgstr "'%s' umaasa ng label" -#: py/emitinlinextensa.c:193 +#: py/emitinlinethumb.c:345 py/emitinlinextensa.c:193 msgid "label '%q' not defined" msgstr "label '%d' kailangan na i-define" +#: py/emitinlinethumb.c:806 +#, fuzzy, c-format +msgid "unsupported Thumb instruction '%s' with %d arguments" +msgstr "hindi sinusuportahan ang instruction ng Xtensa '%s' sa %d argumento" + +#: py/emitinlinethumb.c:810 +#, fuzzy +msgid "branch not in range" +msgstr "chr() arg wala sa sakop ng range(256)" + +#: py/emitinlinextensa.c:86 +msgid "can only have up to 4 parameters to Xtensa assembly" +msgstr "maaari lamang magkaroon ng hanggang 4 na parameter sa Xtensa assembly" + +#: py/emitinlinextensa.c:91 py/emitinlinextensa.c:96 +msgid "parameters must be registers in sequence a2 to a5" +msgstr "ang mga parameter ay dapat na nagrerehistro sa sequence a2 hanggang a5" + +#: py/emitinlinextensa.c:174 +#, c-format +msgid "'%s' integer %d is not within range %d..%d" +msgstr "'%s' integer %d ay wala sa sakop ng %d..%d" + #: py/emitinlinextensa.c:327 #, c-format msgid "unsupported Xtensa instruction '%s' with %d arguments" @@ -1962,7 +2052,7 @@ msgid "AnalogOut is only 16 bits. Value must be less than 65536." msgstr "AnalogOut ay 16 bits. Value ay dapat hindi hihigit pa sa 65536." #: shared-bindings/audiobusio/I2SOut.c:225 -#: shared-bindings/audioio/AudioOut.c:223 +#: shared-bindings/audioio/AudioOut.c:226 msgid "Not playing" msgstr "Hindi playing" @@ -2004,6 +2094,26 @@ msgstr "" "ang destination buffer ay dapat na isang bytearray o array ng uri na 'B' " "para sa bit_depth = 8" +#: shared-bindings/audioio/Mixer.c:94 +#, fuzzy +msgid "Invalid voice count" +msgstr "Mali ang tipo ng serbisyo" + +#: shared-bindings/audioio/Mixer.c:99 +#, fuzzy +msgid "Invalid channel count" +msgstr "Maling argumento" + +#: shared-bindings/audioio/Mixer.c:103 +#, fuzzy +msgid "Sample rate must be positive" +msgstr "Dapat aktibo ang STA" + +#: shared-bindings/audioio/Mixer.c:107 +#, fuzzy +msgid "bits_per_sample must be 8 or 16" +msgstr "bits ay dapat 7, 8 o 9" + #: shared-bindings/audioio/RawSample.c:98 msgid "" "sample_source buffer must be a bytearray or array of type 'h', 'H', 'b' or " @@ -2030,22 +2140,47 @@ msgstr "Function nangangailangan ng lock" msgid "Buffer must be at least length 1" msgstr "Buffer dapat ay hindi baba sa 1 na haba" -#: shared-bindings/bitbangio/SPI.c:151 shared-bindings/busio/SPI.c:168 +#: shared-bindings/bitbangio/SPI.c:151 shared-bindings/busio/SPI.c:175 msgid "Invalid polarity" msgstr "Mali ang polarity" -#: shared-bindings/bitbangio/SPI.c:155 shared-bindings/busio/SPI.c:172 +#: shared-bindings/bitbangio/SPI.c:155 shared-bindings/busio/SPI.c:179 msgid "Invalid phase" msgstr "Mali ang phase" -#: shared-bindings/bitbangio/SPI.c:159 shared-bindings/busio/SPI.c:176 +#: shared-bindings/bitbangio/SPI.c:159 shared-bindings/busio/SPI.c:183 msgid "Invalid number of bits" msgstr "Mali ang bilang ng bits" -#: shared-bindings/bitbangio/SPI.c:284 shared-bindings/busio/SPI.c:341 +#: shared-bindings/bitbangio/SPI.c:284 shared-bindings/busio/SPI.c:348 msgid "buffer slices must be of equal length" msgstr "aarehas na haba dapat ang buffer slices" +#: shared-bindings/bleio/Address.c:101 +msgid "Wrong address length" +msgstr "" + +#: shared-bindings/bleio/Address.c:107 +#, fuzzy +msgid "Wrong number of bytes provided" +msgstr "mali ang bilang ng argumento" + +#: shared-bindings/bleio/Device.c:210 +msgid "Can't add services in Central mode" +msgstr "" + +#: shared-bindings/bleio/Device.c:226 +msgid "Can't connect in Peripheral mode" +msgstr "" + +#: shared-bindings/bleio/Device.c:256 +msgid "Can't change the name in Central mode" +msgstr "" + +#: shared-bindings/bleio/Device.c:277 shared-bindings/bleio/Device.c:313 +msgid "Can't advertise in Central mode" +msgstr "" + #: shared-bindings/busio/I2C.c:120 msgid "Function requires lock." msgstr "Kailangan ng lock ang function." @@ -2174,7 +2309,7 @@ msgstr "walang laman ang address" #: shared-bindings/microcontroller/Pin.c:89 #: shared-bindings/neopixel_write/__init__.c:67 -#: shared-bindings/pulseio/PulseOut.c:75 +#: shared-bindings/pulseio/PulseOut.c:76 msgid "Expected a %q" msgstr "Umasa ng %q" @@ -2216,8 +2351,9 @@ msgid "" msgstr "PWM duty_cycle ay dapat sa loob ng 0 at 65535 (16 bit resolution)" #: shared-bindings/pulseio/PWMOut.c:195 +#, fuzzy msgid "" -"PWM frequency not writeable when variable_frequency is False on construction." +"PWM frequency not writable when variable_frequency is False on construction." msgstr "" "PWM frequency hindi maisulat kapag variable_frequency ay False sa pag buo." @@ -2237,7 +2373,7 @@ msgstr "index ay dapat int" msgid "Read-only" msgstr "Basahin-lamang" -#: shared-bindings/pulseio/PulseOut.c:134 +#: shared-bindings/pulseio/PulseOut.c:135 msgid "Array must contain halfwords (type 'H')" msgstr "May halfwords (type 'H') dapat ang array" @@ -2266,6 +2402,10 @@ msgstr "Hindi supportado ang RTC sa board na ito" msgid "RTC calibration is not supported on this board" msgstr "RTC calibration ay hindi supportado ng board na ito" +#: shared-bindings/socket/__init__.c:516 shared-module/network/__init__.c:81 +msgid "no available NIC" +msgstr "" + #: shared-bindings/storage/__init__.c:77 msgid "filesystem must provide mount method" msgstr "ang filesystem dapat mag bigay ng mount method" @@ -2290,15 +2430,15 @@ msgstr "time.struct_time() kumukuha ng 1 argument" msgid "time.struct_time() takes a 9-sequence" msgstr "time.struct_time() kumukuha ng 9-sequence" -#: shared-bindings/time/__init__.c:169 shared-bindings/time/__init__.c:250 +#: shared-bindings/time/__init__.c:169 shared-bindings/time/__init__.c:264 msgid "Tuple or struct_time argument required" msgstr "Tuple o struct_time argument kailangan" -#: shared-bindings/time/__init__.c:174 shared-bindings/time/__init__.c:255 +#: shared-bindings/time/__init__.c:174 shared-bindings/time/__init__.c:269 msgid "function takes exactly 9 arguments" msgstr "function kumukuha ng 9 arguments" -#: shared-bindings/time/__init__.c:226 shared-bindings/time/__init__.c:259 +#: shared-bindings/time/__init__.c:240 shared-bindings/time/__init__.c:273 msgid "timestamp out of range for platform time_t" msgstr "wala sa sakop ng timestamp ang platform time_t" @@ -2313,6 +2453,34 @@ msgstr "" "Object ay deinitialized at hindi na magagamit. Lumikha ng isang bagong " "Object." +#: shared-module/audioio/Mixer.c:47 shared-module/audioio/WaveFile.c:117 +msgid "Couldn't allocate first buffer" +msgstr "Hindi ma-iallocate ang first buffer" + +#: shared-module/audioio/Mixer.c:53 shared-module/audioio/WaveFile.c:123 +msgid "Couldn't allocate second buffer" +msgstr "Hindi ma-iallocate ang second buffer" + +#: shared-module/audioio/Mixer.c:82 +msgid "Voice index too high" +msgstr "" + +#: shared-module/audioio/Mixer.c:85 +msgid "The sample's sample rate does not match the mixer's" +msgstr "" + +#: shared-module/audioio/Mixer.c:88 +msgid "The sample's channel count does not match the mixer's" +msgstr "" + +#: shared-module/audioio/Mixer.c:91 +msgid "The sample's bits_per_sample does not match the mixer's" +msgstr "" + +#: shared-module/audioio/Mixer.c:100 +msgid "The sample's signedness does not match the mixer's" +msgstr "" + #: shared-module/audioio/WaveFile.c:61 msgid "Invalid wave file" msgstr "May hindi tama sa wave file" @@ -2333,39 +2501,31 @@ msgstr "Dapat sunurin ng Data chunk ang fmt chunk" msgid "Invalid file" msgstr "Mali ang file" -#: shared-module/audioio/WaveFile.c:117 -msgid "Couldn't allocate first buffer" -msgstr "Hindi ma-iallocate ang first buffer" - -#: shared-module/audioio/WaveFile.c:123 -msgid "Couldn't allocate second buffer" -msgstr "Hindi ma-iallocate ang second buffer" - #: shared-module/bitbangio/I2C.c:58 msgid "Clock stretch too long" msgstr "Masyadong mahaba ang Clock stretch" -#: shared-module/bitbangio/SPI.c:45 +#: shared-module/bitbangio/SPI.c:44 msgid "Clock pin init failed." msgstr "Nabigo sa pag init ng Clock pin." -#: shared-module/bitbangio/SPI.c:51 +#: shared-module/bitbangio/SPI.c:50 msgid "MOSI pin init failed." msgstr "Hindi ma-initialize ang MOSI pin." -#: shared-module/bitbangio/SPI.c:62 +#: shared-module/bitbangio/SPI.c:61 msgid "MISO pin init failed." msgstr "Hindi ma-initialize ang MISO pin." -#: shared-module/bitbangio/SPI.c:122 +#: shared-module/bitbangio/SPI.c:121 msgid "Cannot write without MOSI pin." msgstr "Hindi maaring isulat kapag walang MOSI pin." -#: shared-module/bitbangio/SPI.c:177 +#: shared-module/bitbangio/SPI.c:176 msgid "Cannot read without MISO pin." msgstr "Hindi maaring mabasa kapag walang MISO pin." -#: shared-module/bitbangio/SPI.c:241 +#: shared-module/bitbangio/SPI.c:240 msgid "Cannot transfer without MOSI and MISO pins." msgstr "Hindi maaaring ilipat kapag walang MOSI at MISO pin." @@ -2401,6 +2561,10 @@ msgstr "" msgid "Only true color (24 bpp or higher) BMP supported %x" msgstr "" +#: shared-module/storage/__init__.c:155 +msgid "Cannot remount '/' when USB is active." +msgstr "Hindi ma-remount '/' kapag aktibo ang USB." + #: shared-module/struct/__init__.c:39 msgid "'S' and 'O' are not supported format types" msgstr "Ang 'S' at 'O' ay hindi suportadong uri ng format" @@ -2409,6 +2573,49 @@ msgstr "Ang 'S' at 'O' ay hindi suportadong uri ng format" msgid "too many arguments provided with the given format" msgstr "masyadong maraming mga argumento na ibinigay sa ibinigay na format" +#: shared-module/usb_hid/Device.c:45 +#, c-format +msgid "Buffer incorrect size. Should be %d bytes." +msgstr "Mali ang size ng buffer. Dapat %d bytes." + +#: shared-module/usb_hid/Device.c:53 +msgid "USB Busy" +msgstr "Busy ang USB" + +#: shared-module/usb_hid/Device.c:59 +msgid "USB Error" +msgstr "May pagkakamali ang USB" + #, fuzzy #~ msgid "palette must be displayio.Palette" #~ msgstr "ang palette ay dapat 32 bytes ang haba" + +#~ msgid "Invalid Service type" +#~ msgstr "Mali ang tipo ng serbisyo" + +#~ msgid "Can encode UUID into the advertisement packet." +#~ msgstr "Maaring i-encode ang UUID sa advertisement packet." + +#~ msgid "Can not encode UUID, to check length." +#~ msgstr "Hindi ma-encode UUID, para suriin ang haba." + +#~ msgid "Can not query for the device address." +#~ msgstr "Hindi maaaring mag-query para sa address ng device." + +#~ msgid "Can not apply advertisement data. status: 0x%02x" +#~ msgstr "Hindi ma i-apply ang advertisement data. status: 0x%02x" + +#~ msgid "Can not apply device name in the stack." +#~ msgstr "Hindi maaaring ma-aplay ang device name sa stack." + +#~ msgid "Can not add Characteristic." +#~ msgstr "Hindi mabasa and Characteristic." + +#~ msgid "Cannot apply GAP parameters." +#~ msgstr "Hindi ma-apply ang GAP parameters." + +#~ msgid "Cannot set PPCP parameters." +#~ msgstr "Hindi ma-set ang PPCP parameters." + +#~ msgid "Can not add Service." +#~ msgstr "Hindi maidaragdag ang serbisyo." diff --git a/locale/fr.po b/locale/fr.po index d6d7b6087..71962f610 100644 --- a/locale/fr.po +++ b/locale/fr.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-09-21 12:23-0400\n" +"POT-Creation-Date: 2018-11-09 16:20-0800\n" "PO-Revision-Date: 2018-08-14 11:01+0200\n" "Last-Translator: Pierrick Couturier <arofarn@arofarn.info>\n" "Language-Team: fr\n" @@ -146,15 +146,15 @@ msgstr "abort() appelé" msgid "invalid arguments" msgstr "arguments invalides" -#: lib/utils/pyexec.c:97 py/builtinimport.c:253 +#: lib/utils/pyexec.c:97 py/builtinimport.c:251 msgid "script compilation not supported" msgstr "compilation du script non supporté" -#: main.c:143 +#: main.c:154 msgid " output:\n" msgstr " sortie:\n" -#: main.c:157 main.c:230 +#: main.c:168 main.c:241 msgid "" "Auto-reload is on. Simply save files over USB to run them or enter REPL to " "disable.\n" @@ -162,46 +162,46 @@ msgstr "" "Auto-chargement activé. Copiez simplement les fichiers en USB pour les " "lancer ou entrez sur REPL pour le désactiver.\n" -#: main.c:159 +#: main.c:170 msgid "Running in safe mode! Auto-reload is off.\n" msgstr "Mode sans-échec. Auto-rechargement désactivé.\n" -#: main.c:161 main.c:232 +#: main.c:172 main.c:243 msgid "Auto-reload is off.\n" msgstr "Auto-rechargement désactivé.\n" -#: main.c:175 +#: main.c:186 msgid "Running in safe mode! Not running saved code.\n" msgstr "Mode sans-échec! Le code sauvegardé ne s'éxecute pas.\n" -#: main.c:191 +#: main.c:202 msgid "WARNING: Your code filename has two extensions\n" msgstr "ATTENTION: le nom de fichier de votre code a deux extensions\n" -#: main.c:239 +#: main.c:250 msgid "You requested starting safe mode by " msgstr "Vous avez demandé à démarrer en mode sans-échec par " -#: main.c:242 +#: main.c:253 msgid "To exit, please reset the board without " msgstr "Pour quitter, redémarrez la carte SVP sans " -#: main.c:249 +#: main.c:260 msgid "" "You are running in safe mode which means something really bad happened.\n" msgstr "" "Vous êtes en mode sans-échec ce qui signifie que quelque chose demauvais est " "arrivé.\n" -#: main.c:251 +#: main.c:262 msgid "Looks like our core CircuitPython code crashed hard. Whoops!\n" msgstr "Il semblerait que votre code CircuitPython a durement planté. Oups!\n" -#: main.c:252 +#: main.c:263 msgid "Please file an issue here with the contents of your CIRCUITPY drive:\n" msgstr "SVP, remontez le problème là avec le contenu du lecteur CIRCUITPY:\n" -#: main.c:255 +#: main.c:266 msgid "" "The microcontroller's power dipped. Please make sure your power supply " "provides\n" @@ -209,7 +209,7 @@ msgstr "" "L'alimentation du microcontroleur a chuté. Merci de vérifier que votre " "alimentation fournit\n" -#: main.c:256 +#: main.c:267 msgid "" "enough power for the whole circuit and press reset (after ejecting " "CIRCUITPY).\n" @@ -217,15 +217,15 @@ msgstr "" "assez de puissance pour l'ensemble du circuit et appuyez sur 'reset' (après " "avoir éjecter CIRCUITPY).\n" -#: main.c:260 +#: main.c:271 msgid "Press any key to enter the REPL. Use CTRL-D to reload." msgstr "Appuyez sur une touche pour entrer sur REPL ou CTRL-D pour recharger." -#: main.c:416 +#: main.c:429 msgid "soft reboot\n" msgstr "redémarrage logiciel\n" -#: ports/atmel-samd/audio_dma.c:285 +#: ports/atmel-samd/audio_dma.c:209 #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c:361 msgid "All sync event channels in use" msgstr "Tous les canaux d'événements de synchro sont utilisés" @@ -298,12 +298,12 @@ msgid "Too many channels in sample." msgstr "Trop de canaux dans l'échantillon." #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:305 -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:339 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:417 msgid "No DMA channel found" msgstr "Aucun canal DMA trouvé" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:308 -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:341 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:419 msgid "Unable to allocate buffers for signed conversion" msgstr "Impossible d'allouer des tampons pour une conversion signée" @@ -319,43 +319,44 @@ msgstr "Uniquement 8 ou 16 bit mono avec " msgid "sampling rate out of range" msgstr "taux d'échantillonage hors gamme" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:69 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:132 msgid "DAC already in use" msgstr "DAC déjà utilisé" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:73 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:136 msgid "Right channel unsupported" msgstr "Canal droit non supporté" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:76 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:139 #: ports/atmel-samd/common-hal/pulseio/PWMOut.c:116 #: ports/atmel-samd/common-hal/touchio/TouchIn.c:65 msgid "Invalid pin" msgstr "Broche invalide" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:84 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:147 msgid "Invalid pin for left channel" msgstr "Broche invalide pour le canal gauche" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:88 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:151 msgid "Invalid pin for right channel" msgstr "Broche invalide pour le canal droit" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:91 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:154 msgid "Cannot output both channels on the same pin" msgstr "On ne peut mettre les deux canaux sur la même broche" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:176 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:243 #: ports/atmel-samd/common-hal/pulseio/PWMOut.c:189 #: ports/atmel-samd/common-hal/pulseio/PulseOut.c:110 +#: ports/nrf/common-hal/pulseio/PulseOut.c:107 msgid "All timers in use" msgstr "Tous les timers sont utilisés" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:218 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:285 msgid "All event channels in use" msgstr "Tous les canaux d'événements sont utilisés" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c:297 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:375 #, c-format msgid "Sample rate too high. It must be less than %d" msgstr "" @@ -365,10 +366,10 @@ msgid "Not enough pins available" msgstr "Pas assez de broches disponibles" #: ports/atmel-samd/common-hal/busio/I2C.c:78 -#: ports/atmel-samd/common-hal/busio/SPI.c:132 +#: ports/atmel-samd/common-hal/busio/SPI.c:171 #: ports/atmel-samd/common-hal/busio/UART.c:119 #: ports/atmel-samd/common-hal/i2cslave/I2CSlave.c:45 -#: ports/nrf/common-hal/busio/I2C.c:77 +#: ports/nrf/common-hal/busio/I2C.c:82 msgid "Invalid pins" msgstr "Broche invalide" @@ -385,10 +386,12 @@ msgid "bytes > 8 bits not supported" msgstr "octets > 8 bits non supporté" #: ports/atmel-samd/common-hal/busio/UART.c:72 +#: ports/nrf/common-hal/busio/UART.c:82 msgid "tx and rx cannot both be None" msgstr "TX et RX ne peuvent être None tous les deux" #: ports/atmel-samd/common-hal/busio/UART.c:145 +#: ports/nrf/common-hal/busio/UART.c:115 msgid "Failed to allocate RX buffer" msgstr "Echec de l'allocation du tampon RX" @@ -397,15 +400,17 @@ msgid "Could not initialize UART" msgstr "L'UART n'a pu être initialisé" #: ports/atmel-samd/common-hal/busio/UART.c:240 +#: ports/nrf/common-hal/busio/UART.c:149 msgid "No RX pin" msgstr "Pas de broche RX" #: ports/atmel-samd/common-hal/busio/UART.c:294 +#: ports/nrf/common-hal/busio/UART.c:195 msgid "No TX pin" msgstr "Pas de broche TX" #: ports/atmel-samd/common-hal/digitalio/DigitalInOut.c:170 -#: ports/nrf/common-hal/digitalio/DigitalInOut.c:142 +#: ports/nrf/common-hal/digitalio/DigitalInOut.c:147 msgid "Cannot get pull while in output mode" msgstr "Ne peux être tirer ('pull') en mode 'output'" @@ -417,7 +422,8 @@ msgstr "" #: ports/atmel-samd/common-hal/pulseio/PWMOut.c:120 #: ports/atmel-samd/common-hal/pulseio/PWMOut.c:369 -#: ports/nrf/common-hal/pulseio/PWMOut.c:227 +#: ports/nrf/common-hal/pulseio/PWMOut.c:119 +#: ports/nrf/common-hal/pulseio/PWMOut.c:233 msgid "Invalid PWM frequency" msgstr "Fréquence de PWM invalide" @@ -465,30 +471,10 @@ msgstr "Un canal d'interruptions est déjà utilisé" msgid "calibration value out of range +/-127" msgstr "valeur de calibration hors gamme +/-127" -#: ports/atmel-samd/common-hal/storage/__init__.c:48 -msgid "Cannot remount '/' when USB is active." -msgstr "'/' ne peut être remonté quand l'USB est actif." - #: ports/atmel-samd/common-hal/touchio/TouchIn.c:75 msgid "No free GCLKs" msgstr "Pas de GCLK libre" -#: ports/atmel-samd/common-hal/usb_hid/Device.c:78 -#: ports/nrf/common-hal/usb_hid/Device.c:45 -#, c-format -msgid "Buffer incorrect size. Should be %d bytes." -msgstr "Tampon de taille incorrect. Devrait être de %d octets." - -#: ports/atmel-samd/common-hal/usb_hid/Device.c:82 -#: ports/nrf/common-hal/usb_hid/Device.c:53 -msgid "USB Busy" -msgstr "USB occupé" - -#: ports/atmel-samd/common-hal/usb_hid/Device.c:82 -#: ports/nrf/common-hal/usb_hid/Device.c:59 -msgid "USB Error" -msgstr "Erreur USB" - #: ports/esp8266/common-hal/analogio/AnalogIn.c:43 msgid "Pin %q does not have ADC capabilities" msgstr "La broche %q n'a pas de convertisseur analogique-digital" @@ -701,133 +687,172 @@ msgstr "paramètre de config. inconnu" msgid "AnalogOut functionality not supported" msgstr "AnalogOut non supporté" -#: ports/nrf/common-hal/busio/I2C.c:91 -#, fuzzy -msgid "All I2C peripherals are in use" -msgstr "Tous les timers sont utilisés" - -#: ports/nrf/common-hal/busio/SPI.c:109 -#, fuzzy -msgid "All SPI peripherals are in use" -msgstr "Tous les timers sont utilisés" - -#: ports/nrf/common-hal/busio/SPI.c:170 -msgid "Baud rate too high for this SPI peripheral" +#: ports/nrf/common-hal/bleio/Adapter.c:41 +#, c-format +msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX" msgstr "" -#: ports/nrf/common-hal/busio/UART.c:43 ports/nrf/common-hal/busio/UART.c:47 -#: ports/nrf/common-hal/busio/UART.c:51 ports/nrf/common-hal/busio/UART.c:60 -#: ports/nrf/common-hal/busio/UART.c:66 ports/nrf/common-hal/busio/UART.c:71 -#: ports/nrf/common-hal/busio/UART.c:76 ports/nrf/common-hal/busio/UART.c:81 -#: ports/nrf/common-hal/busio/UART.c:86 ports/nrf/common-hal/busio/UART.c:90 -msgid "busio.UART not yet implemented" -msgstr "busio.UART pas encore implémenté" - -#: ports/nrf/common-hal/microcontroller/Processor.c:49 +#: ports/nrf/common-hal/bleio/Adapter.c:125 #, c-format -msgid "Can not get temperature. status: 0x%02x" -msgstr "Impossible de lire la température. status: 0x%02x" - -#: ports/nrf/drivers/bluetooth/ble_drv.c:199 -msgid "Cannot apply GAP parameters." -msgstr "Impossible d'appliquer les paramètres GAP" +msgid "Failed to change softdevice state, error: 0x%08lX" +msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:213 -msgid "Cannot set PPCP parameters." -msgstr "Impossible d'appliquer les paramètres PPCP" +#: ports/nrf/common-hal/bleio/Adapter.c:135 +#, c-format +msgid "Failed to get softdevice state, error: 0x%08lX" +msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:245 -msgid "Can not query for the device address." -msgstr "Impossible d'obtenir l'adresse du périphérique" +#: ports/nrf/common-hal/bleio/Adapter.c:155 +#, c-format +msgid "Failed to get local address, error: 0x%08lX" +msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:264 -msgid "Can not add Vendor Specific 128-bit UUID." -msgstr "Impossible d'ajouter l'UUID 128bits Vendor Specific" +#: ports/nrf/common-hal/bleio/Characteristic.c:52 +#, fuzzy, c-format +msgid "Failed to write gatts value, status: 0x%08lX" +msgstr "Impossible d'écrire la valeur de l'attribut. status: 0x%02x" -#: ports/nrf/drivers/bluetooth/ble_drv.c:284 -#: ports/nrf/drivers/bluetooth/ble_drv.c:298 -msgid "Can not add Service." -msgstr "Impossible d'ajouter le Service" +#: ports/nrf/common-hal/bleio/Characteristic.c:76 +#, fuzzy, c-format +msgid "Failed to notify attribute value, status: 0x%08lX" +msgstr "Impossible de notifier la valeur de l'attribut. status: 0x%02x" -#: ports/nrf/drivers/bluetooth/ble_drv.c:373 -msgid "Can not add Characteristic." -msgstr "Impossible d'ajouter la Characteristic." +#: ports/nrf/common-hal/bleio/Characteristic.c:91 +#, fuzzy, c-format +msgid "Failed to read attribute value, status: 0x%08lX" +msgstr "Impossible de lire la valeur de l'attribut. status: 0x%02x" -#: ports/nrf/drivers/bluetooth/ble_drv.c:400 -msgid "Can not apply device name in the stack." -msgstr "Impossible d'appliquer le nom de périphérique dans la pile" +#: ports/nrf/common-hal/bleio/Characteristic.c:119 +#: ports/nrf/common-hal/bleio/Device.c:272 +#: ports/nrf/common-hal/bleio/Device.c:307 +#, c-format +msgid "Failed to acquire mutex, status: 0x%08lX" +msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:464 -#: ports/nrf/drivers/bluetooth/ble_drv.c:514 -msgid "Can not encode UUID, to check length." -msgstr "Impossible d'encoder l'UUID pour vérifier la longueur." +#: ports/nrf/common-hal/bleio/Characteristic.c:126 +#, fuzzy, c-format +msgid "Failed to write attribute value, status: 0x%08lX" +msgstr "Impossible d'écrire la valeur de l'attribut. status: 0x%02x" -#: ports/nrf/drivers/bluetooth/ble_drv.c:470 -#: ports/nrf/drivers/bluetooth/ble_drv.c:520 -msgid "Can encode UUID into the advertisment packet." +#: ports/nrf/common-hal/bleio/Characteristic.c:138 +#: ports/nrf/common-hal/bleio/Device.c:284 +#: ports/nrf/common-hal/bleio/Device.c:319 +#: ports/nrf/common-hal/bleio/Device.c:354 +#: ports/nrf/common-hal/bleio/Device.c:391 +#, c-format +msgid "Failed to release mutex, status: 0x%08lX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:545 -msgid "Can not fit data into the advertisment packet." +#: ports/nrf/common-hal/bleio/Device.c:81 +#: ports/nrf/common-hal/bleio/Device.c:114 +msgid "Can not fit data into the advertisment packet" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:558 -#: ports/nrf/drivers/bluetooth/ble_drv.c:604 +#: ports/nrf/common-hal/bleio/Device.c:266 #, c-format -msgid "Can not apply advertisment data. status: 0x%02x" +msgid "Failed to discover serivices, status: 0x%08lX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:614 +#: ports/nrf/common-hal/bleio/Device.c:403 +#: ports/nrf/common-hal/bleio/Scanner.c:76 +#, fuzzy, c-format +msgid "Failed to continue scanning, status: 0x%0xlX" +msgstr "Impossible de commencer à scanner. status: 0x%02x" + +#: ports/nrf/common-hal/bleio/Device.c:436 +#, fuzzy, c-format +msgid "Failed to connect, status: 0x%08lX" +msgstr "Connection impossible. status: 0x%02x" + +#: ports/nrf/common-hal/bleio/Device.c:513 #, c-format -msgid "Can not start advertisment. status: 0x%02x" +msgid "Failed to add service, status: 0x%08lX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:631 +#: ports/nrf/common-hal/bleio/Device.c:531 +#, fuzzy, c-format +msgid "Failed to start advertisment, status: 0x%08lX" +msgstr "Impossible de commencer à scanner. status: 0x%02x" + +#: ports/nrf/common-hal/bleio/Device.c:549 #, c-format -msgid "Can not stop advertisment. status: 0x%02x" +msgid "Failed to stop advertisment, status: 0x%08lX" msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:650 -#: ports/nrf/drivers/bluetooth/ble_drv.c:726 -#, c-format -msgid "Can not read attribute value. status: 0x%02x" -msgstr "Impossible de lire la valeur de l'attribut. status: 0x%02x" +#: ports/nrf/common-hal/bleio/Device.c:575 +#: ports/nrf/common-hal/bleio/Scanner.c:103 +#, fuzzy, c-format +msgid "Failed to start scanning, status: 0x%0xlX" +msgstr "Impossible de commencer à scanner. status: 0x%02x" -#: ports/nrf/drivers/bluetooth/ble_drv.c:667 -#: ports/nrf/drivers/bluetooth/ble_drv.c:756 -#, c-format -msgid "Can not write attribute value. status: 0x%02x" -msgstr "Impossible d'écrire la valeur de l'attribut. status: 0x%02x" +#: ports/nrf/common-hal/bleio/Device.c:592 +#, fuzzy, c-format +msgid "Failed to create mutex, status: 0x%0xlX" +msgstr "Impossible de lire la valeur de l'attribut. status: 0x%02x" -#: ports/nrf/drivers/bluetooth/ble_drv.c:691 +#: ports/nrf/common-hal/bleio/Service.c:83 #, c-format -msgid "Can not notify attribute value. status: 0x%02x" -msgstr "Impossible de notifier la valeur de l'attribut. status: 0x%02x" +msgid "Failed to add characteristic, status: 0x%08lX" +msgstr "" -#: ports/nrf/drivers/bluetooth/ble_drv.c:784 -#, c-format -msgid "Can not start scanning. status: 0x%02x" -msgstr "Impossible de commencer à scanner. status: 0x%02x" +#: ports/nrf/common-hal/bleio/UUID.c:97 +#, fuzzy, c-format +msgid "Failed to add Vendor Specific UUID, status: 0x%08lX" +msgstr "Impossible d'ajouter l'UUID 128bits Vendor Specific" -#: ports/nrf/drivers/bluetooth/ble_drv.c:829 -#, c-format -msgid "Can not connect. status: 0x%02x" -msgstr "Connection impossible. status: 0x%02x" +#: ports/nrf/common-hal/bleio/UUID.c:102 +msgid "Invalid UUID string length" +msgstr "Longeur de chaîne UUID invalide" -#: ports/nrf/modules/ubluepy/ubluepy_characteristic.c:68 -#: ports/nrf/modules/ubluepy/ubluepy_service.c:80 -#: ports/nrf/modules/ubluepy/ubluepy_service.c:132 -#: ports/nrf/modules/ubluepy/ubluepy_uuid.c:137 +#: ports/nrf/common-hal/bleio/UUID.c:109 +#: shared-bindings/bleio/Characteristic.c:125 +#: shared-bindings/bleio/Service.c:105 msgid "Invalid UUID parameter" msgstr "Paramètre UUID invalide" -#: ports/nrf/modules/ubluepy/ubluepy_service.c:73 -msgid "Invalid Service type" -msgstr "Type de service invalide" +#: ports/nrf/common-hal/busio/I2C.c:96 +#, fuzzy +msgid "All I2C peripherals are in use" +msgstr "Tous les timers sont utilisés" -#: ports/nrf/modules/ubluepy/ubluepy_uuid.c:127 -msgid "Invalid UUID string length" -msgstr "Longeur de chaîne UUID invalide" +#: ports/nrf/common-hal/busio/SPI.c:133 +#, fuzzy +msgid "All SPI peripherals are in use" +msgstr "Tous les timers sont utilisés" + +#: ports/nrf/common-hal/busio/UART.c:48 +#, c-format +msgid "error = 0x%08lX" +msgstr "" + +#: ports/nrf/common-hal/busio/UART.c:86 +#, fuzzy +msgid "Invalid buffer size" +msgstr "longueur de tampon invalide" + +#: ports/nrf/common-hal/busio/UART.c:90 +#, fuzzy +msgid "Odd parity is not supported" +msgstr "octets > 8 bits non supporté" + +#: ports/nrf/common-hal/busio/UART.c:322 ports/nrf/common-hal/busio/UART.c:326 +#: ports/nrf/common-hal/busio/UART.c:331 ports/nrf/common-hal/busio/UART.c:336 +#: ports/nrf/common-hal/busio/UART.c:342 ports/nrf/common-hal/busio/UART.c:347 +#: ports/nrf/common-hal/busio/UART.c:352 ports/nrf/common-hal/busio/UART.c:356 +#: ports/nrf/common-hal/busio/UART.c:364 +#, fuzzy +msgid "busio.UART not available" +msgstr "busio.UART n'est pas disponible" + +#: ports/nrf/common-hal/microcontroller/Processor.c:49 +#, c-format +msgid "Can not get temperature. status: 0x%02x" +msgstr "Impossible de lire la température. status: 0x%02x" + +#: ports/nrf/common-hal/pulseio/PWMOut.c:161 +#, fuzzy +msgid "All PWM peripherals are in use" +msgstr "Tous les timers sont utilisés" #: ports/unix/modffi.c:138 msgid "Unknown type" @@ -931,19 +956,34 @@ msgstr "mauvais code type" msgid "bad compile mode" msgstr "mauvais mode de compilation" -#: py/builtinimport.c:338 +#: py/builtinhelp.c:137 +#, fuzzy +msgid "Plus any modules on the filesystem\n" +msgstr "Impossible de remonter le système de fichiers" + +#: py/builtinhelp.c:183 +#, c-format +msgid "" +"Welcome to Adafruit CircuitPython %s!\n" +"\n" +"Please visit learn.adafruit.com/category/circuitpython for project guides.\n" +"\n" +"To list built-in modules please do `help(\"modules\")`.\n" +msgstr "" + +#: py/builtinimport.c:336 msgid "cannot perform relative import" msgstr "ne peut pas réaliser un import relatif" -#: py/builtinimport.c:422 py/builtinimport.c:534 +#: py/builtinimport.c:420 py/builtinimport.c:532 msgid "module not found" msgstr "module introuvable" -#: py/builtinimport.c:425 py/builtinimport.c:537 +#: py/builtinimport.c:423 py/builtinimport.c:535 msgid "no module named '%q'" msgstr "pas de module '%q'" -#: py/builtinimport.c:512 +#: py/builtinimport.c:510 msgid "relative import" msgstr "import relatif" @@ -1092,38 +1132,87 @@ msgstr "'data' nécessite au moins 2 arguments" msgid "'data' requires integer arguments" msgstr "'data' nécessite des arguments entiers" -#: py/emitinlinextensa.c:86 -msgid "can only have up to 4 parameters to Xtensa assembly" +#: py/emitinlinethumb.c:102 +msgid "can only have up to 4 parameters to Thumb assembly" msgstr "" -#: py/emitinlinextensa.c:91 py/emitinlinextensa.c:96 -msgid "parameters must be registers in sequence a2 to a5" +#: py/emitinlinethumb.c:107 py/emitinlinethumb.c:112 +#, fuzzy +msgid "parameters must be registers in sequence r0 to r3" msgstr "les paramètres doivent être des registres dans la séquence a2 à a5" -#: py/emitinlinextensa.c:162 +#: py/emitinlinethumb.c:188 py/emitinlinethumb.c:230 +#, fuzzy, c-format +msgid "'%s' expects at most r%d" +msgstr "'%s' attend un registre" + +#: py/emitinlinethumb.c:197 py/emitinlinextensa.c:162 #, c-format msgid "'%s' expects a register" msgstr "'%s' attend un registre" -#: py/emitinlinextensa.c:169 +#: py/emitinlinethumb.c:211 +#, fuzzy, c-format +msgid "'%s' expects a special register" +msgstr "'%s' attend un registre" + +#: py/emitinlinethumb.c:239 +#, fuzzy, c-format +msgid "'%s' expects an FPU register" +msgstr "'%s' attend un registre" + +#: py/emitinlinethumb.c:292 +#, fuzzy, c-format +msgid "'%s' expects {r0, r1, ...}" +msgstr "'%s' attend un registre" + +#: py/emitinlinethumb.c:299 py/emitinlinextensa.c:169 #, c-format msgid "'%s' expects an integer" msgstr "'%s' attend un entier" -#: py/emitinlinextensa.c:174 -#, c-format -msgid "'%s' integer %d is not within range %d..%d" +#: py/emitinlinethumb.c:304 +#, fuzzy, c-format +msgid "'%s' integer 0x%x does not fit in mask 0x%x" msgstr "'%s' l'entier %d n'est pas dans la gamme %d..%d" -#: py/emitinlinextensa.c:182 +#: py/emitinlinethumb.c:328 +#, fuzzy, c-format +msgid "'%s' expects an address of the form [a, b]" +msgstr "'%s' attend un registre" + +#: py/emitinlinethumb.c:334 py/emitinlinextensa.c:182 #, c-format msgid "'%s' expects a label" msgstr "'%s' attend un label" -#: py/emitinlinextensa.c:193 +#: py/emitinlinethumb.c:345 py/emitinlinextensa.c:193 msgid "label '%q' not defined" msgstr "label '%q' non supporté" +#: py/emitinlinethumb.c:806 +#, fuzzy, c-format +msgid "unsupported Thumb instruction '%s' with %d arguments" +msgstr "instruction Xtensa '%s' non supportée avec %d arguments" + +#: py/emitinlinethumb.c:810 +#, fuzzy +msgid "branch not in range" +msgstr "argument de chr() hors de la gamme range(256)" + +#: py/emitinlinextensa.c:86 +msgid "can only have up to 4 parameters to Xtensa assembly" +msgstr "" + +#: py/emitinlinextensa.c:91 py/emitinlinextensa.c:96 +msgid "parameters must be registers in sequence a2 to a5" +msgstr "les paramètres doivent être des registres dans la séquence a2 à a5" + +#: py/emitinlinextensa.c:174 +#, c-format +msgid "'%s' integer %d is not within range %d..%d" +msgstr "'%s' l'entier %d n'est pas dans la gamme %d..%d" + #: py/emitinlinextensa.c:327 #, c-format msgid "unsupported Xtensa instruction '%s' with %d arguments" @@ -1956,7 +2045,7 @@ msgstr "" "65536." #: shared-bindings/audiobusio/I2SOut.c:225 -#: shared-bindings/audioio/AudioOut.c:223 +#: shared-bindings/audioio/AudioOut.c:226 msgid "Not playing" msgstr "En pause" @@ -1995,6 +2084,26 @@ msgid "" msgstr "" "le tampon de destination doit être un tableau de type 'B' pour bit_depth = 8" +#: shared-bindings/audioio/Mixer.c:94 +#, fuzzy +msgid "Invalid voice count" +msgstr "Type de service invalide" + +#: shared-bindings/audioio/Mixer.c:99 +#, fuzzy +msgid "Invalid channel count" +msgstr "Argument invalide" + +#: shared-bindings/audioio/Mixer.c:103 +#, fuzzy +msgid "Sample rate must be positive" +msgstr "'STA' doit être actif" + +#: shared-bindings/audioio/Mixer.c:107 +#, fuzzy +msgid "bits_per_sample must be 8 or 16" +msgstr "bits doivent être 7, 8 ou 9" + #: shared-bindings/audioio/RawSample.c:98 msgid "" "sample_source buffer must be a bytearray or array of type 'h', 'H', 'b' or " @@ -2021,22 +2130,47 @@ msgstr "La fonction nécessite un verrou" msgid "Buffer must be at least length 1" msgstr "Le tampon doit être de longueur au moins 1" -#: shared-bindings/bitbangio/SPI.c:151 shared-bindings/busio/SPI.c:168 +#: shared-bindings/bitbangio/SPI.c:151 shared-bindings/busio/SPI.c:175 msgid "Invalid polarity" msgstr "Polarité invalide" -#: shared-bindings/bitbangio/SPI.c:155 shared-bindings/busio/SPI.c:172 +#: shared-bindings/bitbangio/SPI.c:155 shared-bindings/busio/SPI.c:179 msgid "Invalid phase" msgstr "Phase invalide" -#: shared-bindings/bitbangio/SPI.c:159 shared-bindings/busio/SPI.c:176 +#: shared-bindings/bitbangio/SPI.c:159 shared-bindings/busio/SPI.c:183 msgid "Invalid number of bits" msgstr "Nombre de bits invalide" -#: shared-bindings/bitbangio/SPI.c:284 shared-bindings/busio/SPI.c:341 +#: shared-bindings/bitbangio/SPI.c:284 shared-bindings/busio/SPI.c:348 msgid "buffer slices must be of equal length" msgstr "les slices de tampon doivent être de longueurs égales" +#: shared-bindings/bleio/Address.c:101 +msgid "Wrong address length" +msgstr "" + +#: shared-bindings/bleio/Address.c:107 +#, fuzzy +msgid "Wrong number of bytes provided" +msgstr "mauvais nombres d'arguments" + +#: shared-bindings/bleio/Device.c:210 +msgid "Can't add services in Central mode" +msgstr "" + +#: shared-bindings/bleio/Device.c:226 +msgid "Can't connect in Peripheral mode" +msgstr "" + +#: shared-bindings/bleio/Device.c:256 +msgid "Can't change the name in Central mode" +msgstr "" + +#: shared-bindings/bleio/Device.c:277 shared-bindings/bleio/Device.c:313 +msgid "Can't advertise in Central mode" +msgstr "" + #: shared-bindings/busio/I2C.c:120 msgid "Function requires lock." msgstr "La fonction nécessite un verrou." @@ -2096,7 +2230,7 @@ msgstr "La longueur doit être entière" #: shared-bindings/displayio/FourWire.c:55 #: shared-bindings/displayio/FourWire.c:64 msgid "displayio is a work in progress" -msgstr "" +msgstr "displayio est en cours de développement" #: shared-bindings/displayio/Group.c:65 #, fuzzy @@ -2113,6 +2247,8 @@ msgstr "" #: shared-bindings/displayio/Palette.c:102 msgid "color buffer must be 3 bytes (RGB) or 4 bytes (RGB + pad byte)" msgstr "" +"Le tampon couleur doit avoir 3 octets (RVB) ou 4 octets (RVB + octet de " +"padding)" #: shared-bindings/displayio/Palette.c:106 #, fuzzy @@ -2159,15 +2295,15 @@ msgstr "ne peut convertir %s en entier int" #: shared-bindings/i2cslave/I2CSlave.c:101 msgid "address out of bounds" -msgstr "" +msgstr "Adresse hors limite" #: shared-bindings/i2cslave/I2CSlave.c:107 msgid "addresses is empty" -msgstr "" +msgstr "Adresses est vide" #: shared-bindings/microcontroller/Pin.c:89 #: shared-bindings/neopixel_write/__init__.c:67 -#: shared-bindings/pulseio/PulseOut.c:75 +#: shared-bindings/pulseio/PulseOut.c:76 msgid "Expected a %q" msgstr "Attendu : %q" @@ -2211,8 +2347,9 @@ msgstr "" "bits)" #: shared-bindings/pulseio/PWMOut.c:195 +#, fuzzy msgid "" -"PWM frequency not writeable when variable_frequency is False on construction." +"PWM frequency not writable when variable_frequency is False on construction." msgstr "" "La fréquence de PWM n'est pas modifiable quand variable_frequency est False " "à laconstruction." @@ -2233,7 +2370,7 @@ msgstr "l'index doit être un entier" msgid "Read-only" msgstr "Lecture seule" -#: shared-bindings/pulseio/PulseOut.c:134 +#: shared-bindings/pulseio/PulseOut.c:135 msgid "Array must contain halfwords (type 'H')" msgstr "Le tableau doit contenir des halfwords (type 'H')" @@ -2262,6 +2399,11 @@ msgstr "RTC non supportée sur cette carte" msgid "RTC calibration is not supported on this board" msgstr "calibration de la RTC non supportée sur cette carte" +#: shared-bindings/socket/__init__.c:516 shared-module/network/__init__.c:81 +#, fuzzy +msgid "no available NIC" +msgstr "NIC non disponible" + #: shared-bindings/storage/__init__.c:77 msgid "filesystem must provide mount method" msgstr "le system de fichier doit fournir une méthode 'mount'" @@ -2286,15 +2428,15 @@ msgstr "time.struct_time() prend exactement 1 argument" msgid "time.struct_time() takes a 9-sequence" msgstr "time.struct_time() prend une séquence de longueur 9" -#: shared-bindings/time/__init__.c:169 shared-bindings/time/__init__.c:250 +#: shared-bindings/time/__init__.c:169 shared-bindings/time/__init__.c:264 msgid "Tuple or struct_time argument required" msgstr "Argument de type tuple ou struct_time nécessaire" -#: shared-bindings/time/__init__.c:174 shared-bindings/time/__init__.c:255 +#: shared-bindings/time/__init__.c:174 shared-bindings/time/__init__.c:269 msgid "function takes exactly 9 arguments" msgstr "la fonction prend exactement 9 arguments" -#: shared-bindings/time/__init__.c:226 shared-bindings/time/__init__.c:259 +#: shared-bindings/time/__init__.c:240 shared-bindings/time/__init__.c:273 msgid "timestamp out of range for platform time_t" msgstr "timestamp hors gamme pour la plateforme time_t" @@ -2309,6 +2451,34 @@ msgstr "" "L'objet a été désinitialisé et ne peut plus être utilisé. Créez un nouvel " "objet." +#: shared-module/audioio/Mixer.c:47 shared-module/audioio/WaveFile.c:117 +msgid "Couldn't allocate first buffer" +msgstr "Impossible d'allouer le 1er tampon" + +#: shared-module/audioio/Mixer.c:53 shared-module/audioio/WaveFile.c:123 +msgid "Couldn't allocate second buffer" +msgstr "Impossible d'allouer le 2e tampon" + +#: shared-module/audioio/Mixer.c:82 +msgid "Voice index too high" +msgstr "Index de la voix trop grand" + +#: shared-module/audioio/Mixer.c:85 +msgid "The sample's sample rate does not match the mixer's" +msgstr "" + +#: shared-module/audioio/Mixer.c:88 +msgid "The sample's channel count does not match the mixer's" +msgstr "" + +#: shared-module/audioio/Mixer.c:91 +msgid "The sample's bits_per_sample does not match the mixer's" +msgstr "Le bits_per_sample de l'échantillon ne correspond pas au mixer" + +#: shared-module/audioio/Mixer.c:100 +msgid "The sample's signedness does not match the mixer's" +msgstr "L'échantillon non signé ne correspond pas au mixer" + #: shared-module/audioio/WaveFile.c:61 msgid "Invalid wave file" msgstr "Fichier WAVE invalide" @@ -2329,45 +2499,37 @@ msgstr "Un bloc de données doit suivre un bloc de format" msgid "Invalid file" msgstr "Fichier invalide" -#: shared-module/audioio/WaveFile.c:117 -msgid "Couldn't allocate first buffer" -msgstr "Impossible d'allouer le 1er tampon" - -#: shared-module/audioio/WaveFile.c:123 -msgid "Couldn't allocate second buffer" -msgstr "Impossible d'allouer le 2e tampon" - #: shared-module/bitbangio/I2C.c:58 msgid "Clock stretch too long" msgstr "Période de l'horloge trop longue" -#: shared-module/bitbangio/SPI.c:45 +#: shared-module/bitbangio/SPI.c:44 msgid "Clock pin init failed." msgstr "Echec de l'init. de la broche d'horloge" -#: shared-module/bitbangio/SPI.c:51 +#: shared-module/bitbangio/SPI.c:50 msgid "MOSI pin init failed." msgstr "Echec de l'init. de la broche MOSI" -#: shared-module/bitbangio/SPI.c:62 +#: shared-module/bitbangio/SPI.c:61 msgid "MISO pin init failed." msgstr "Echec de l'init. de la broche MISO" -#: shared-module/bitbangio/SPI.c:122 +#: shared-module/bitbangio/SPI.c:121 msgid "Cannot write without MOSI pin." msgstr "Impossible d'écrire sans broche MOSI." -#: shared-module/bitbangio/SPI.c:177 +#: shared-module/bitbangio/SPI.c:176 msgid "Cannot read without MISO pin." msgstr "Impossible de lire sans broche MISO." -#: shared-module/bitbangio/SPI.c:241 +#: shared-module/bitbangio/SPI.c:240 msgid "Cannot transfer without MOSI and MISO pins." msgstr "Pas de transfert sans broches MOSI et MISO" #: shared-module/displayio/Bitmap.c:49 msgid "Only bit maps of 8 bit color or less are supported" -msgstr "" +msgstr "Seul les mappings en couleur 8 bits (ou moins) sont supportés" #: shared-module/displayio/Bitmap.c:69 msgid "row must be packed and word aligned" @@ -2375,12 +2537,12 @@ msgstr "" #: shared-module/displayio/Group.c:39 msgid "Group full" -msgstr "" +msgstr "Group complet" #: shared-module/displayio/Group.c:48 #, fuzzy msgid "Group empty" -msgstr "vide" +msgstr "Groupe vide" #: shared-module/displayio/OnDiskBitmap.c:49 #, fuzzy @@ -2390,12 +2552,16 @@ msgstr "Fichier invalide" #: shared-module/displayio/OnDiskBitmap.c:59 #, c-format msgid "Only Windows format, uncompressed BMP supported %d" -msgstr "" +msgstr "Seul le format Windows, BMP non compressé, est supporté %d" #: shared-module/displayio/OnDiskBitmap.c:64 #, c-format msgid "Only true color (24 bpp or higher) BMP supported %x" -msgstr "" +msgstr "Seul les BMP 'true color' (24 bpp ou plus) sont supportés %x" + +#: shared-module/storage/__init__.c:155 +msgid "Cannot remount '/' when USB is active." +msgstr "'/' ne peut être remonté quand l'USB est actif." #: shared-module/struct/__init__.c:39 msgid "'S' and 'O' are not supported format types" @@ -2405,10 +2571,47 @@ msgstr "'S' et 'O' ne sont pas des types de format supportés" msgid "too many arguments provided with the given format" msgstr "trop d'arguments fournis avec ce format" -#, fuzzy -#~ msgid "value_size must be power of two" -#~ msgstr "'len' doit être un multiple de 4" +#: shared-module/usb_hid/Device.c:45 +#, c-format +msgid "Buffer incorrect size. Should be %d bytes." +msgstr "Tampon de taille incorrect. Devrait être de %d octets." + +#: shared-module/usb_hid/Device.c:53 +msgid "USB Busy" +msgstr "USB occupé" + +#: shared-module/usb_hid/Device.c:59 +msgid "USB Error" +msgstr "Erreur USB" #, fuzzy #~ msgid "palette must be displayio.Palette" -#~ msgstr "la palette doit être longue de 32 octets" +#~ msgstr "palettre doit être displayio.Palette" + +#~ msgid "Can not query for the device address." +#~ msgstr "Impossible d'obtenir l'adresse du périphérique" + +#~ msgid "Cannot set PPCP parameters." +#~ msgstr "Impossible d'appliquer les paramètres PPCP" + +#~ msgid "Cannot apply GAP parameters." +#~ msgstr "Impossible d'appliquer les paramètres GAP" + +#~ msgid "Can not encode UUID, to check length." +#~ msgstr "Impossible d'encoder l'UUID pour vérifier la longueur." + +#~ msgid "Invalid Service type" +#~ msgstr "Type de service invalide" + +#~ msgid "Can not apply device name in the stack." +#~ msgstr "Impossible d'appliquer le nom de périphérique dans la pile" + +#, fuzzy +#~ msgid "value_size must be power of two" +#~ msgstr "value_size est une puissance de deux" + +#~ msgid "Can not add Service." +#~ msgstr "Impossible d'ajouter le Service" + +#~ msgid "Can not add Characteristic." +#~ msgstr "Impossible d'ajouter la Characteristic." diff --git a/locale/it_IT.po b/locale/it_IT.po new file mode 100644 index 000000000..4acdb39f7 --- /dev/null +++ b/locale/it_IT.po @@ -0,0 +1,2602 @@ +# Italian translation. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# Enrico Paganin <enrico.paganin@mail.com>, 2018 +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-11-09 16:20-0800\n" +"PO-Revision-Date: 2018-10-02 16:27+0200\n" +"Last-Translator: Enrico Paganin <enrico.paganin@mail.com>\n" +"Language-Team: \n" +"Language: it_IT\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: extmod/machine_i2c.c:299 +msgid "invalid I2C peripheral" +msgstr "periferica I2C invalida" + +#: extmod/machine_i2c.c:340 extmod/machine_i2c.c:354 extmod/machine_i2c.c:368 +#: extmod/machine_i2c.c:392 +msgid "I2C operation not supported" +msgstr "operazione I2C non supportata" + +#: extmod/machine_mem.c:45 ports/unix/modmachine.c:53 +#, c-format +msgid "address %08x is not aligned to %d bytes" +msgstr "l'indirizzo %08x non è allineato a %d bytes" + +#: extmod/machine_spi.c:57 +msgid "invalid SPI peripheral" +msgstr "periferica SPI invalida" + +#: extmod/machine_spi.c:124 +msgid "buffers must be the same length" +msgstr "i buffer devono essere della stessa lunghezza" + +#: extmod/machine_spi.c:207 +msgid "bits must be 8" +msgstr "i bit devono essere 8" + +#: extmod/machine_spi.c:210 +msgid "firstbit must be MSB" +msgstr "il primo bit deve essere il più significativo (MSB)" + +#: extmod/machine_spi.c:215 +msgid "must specify all of sck/mosi/miso" +msgstr "è necessario specificare tutte le sck/mosi/miso" + +#: extmod/modframebuf.c:299 +msgid "invalid format" +msgstr "formato non valido" + +#: extmod/modubinascii.c:38 extmod/moduhashlib.c:102 +msgid "a bytes-like object is required" +msgstr "un oggetto byte-like è richiesto" + +#: extmod/modubinascii.c:90 +msgid "odd-length string" +msgstr "stringa di lunghezza dispari" + +#: extmod/modubinascii.c:101 +msgid "non-hex digit found" +msgstr "trovata cifra non esadecimale" + +#: extmod/modubinascii.c:169 +msgid "incorrect padding" +msgstr "padding incorretto" + +#: extmod/moductypes.c:122 +msgid "syntax error in uctypes descriptor" +msgstr "errore di sintassi nel descrittore uctypes" + +#: extmod/moductypes.c:219 +msgid "Cannot unambiguously get sizeof scalar" +msgstr "Impossibile ricavare la grandezza scalare di sizeof inequivocabilmente" + +#: extmod/moductypes.c:397 +msgid "struct: no fields" +msgstr "struct: nessun campo" + +#: extmod/moductypes.c:530 +msgid "struct: cannot index" +msgstr "struct: impossibile indicizzare" + +#: extmod/moductypes.c:544 +msgid "struct: index out of range" +msgstr "struct: indice fuori intervallo" + +#: extmod/moduheapq.c:38 +msgid "heap must be a list" +msgstr "l'heap deve essere una lista" + +#: extmod/moduheapq.c:86 extmod/modutimeq.c:147 extmod/modutimeq.c:172 +msgid "empty heap" +msgstr "heap vuoto" + +#: extmod/modujson.c:281 +msgid "syntax error in JSON" +msgstr "errore di sintassi nel JSON" + +#: extmod/modure.c:161 +msgid "Splitting with sub-captures" +msgstr "Suddivisione con sotto-catture" + +#: extmod/modure.c:207 +msgid "Error in regex" +msgstr "Errore nella regex" + +#: extmod/modussl_axtls.c:81 +msgid "invalid key" +msgstr "chiave non valida" + +#: extmod/modussl_axtls.c:87 +msgid "invalid cert" +msgstr "certificato non valido" + +#: extmod/modutimeq.c:131 +msgid "queue overflow" +msgstr "overflow della coda" + +#: extmod/moduzlib.c:98 +msgid "compression header" +msgstr "compressione dell'header" + +#: extmod/uos_dupterm.c:120 +msgid "invalid dupterm index" +msgstr "indice dupterm non valido" + +#: extmod/vfs_fat.c:426 py/moduerrno.c:150 +msgid "Read-only filesystem" +msgstr "Filesystem in sola lettura" + +#: extmod/vfs_posix_file.c:48 ports/unix/file.c:50 py/objstringio.c:43 +msgid "I/O operation on closed file" +msgstr "operazione I/O su file chiuso" + +#: lib/embed/abort_.c:8 +msgid "abort() called" +msgstr "abort() chiamato" + +#: lib/netutils/netutils.c:83 +msgid "invalid arguments" +msgstr "argomenti non validi" + +#: lib/utils/pyexec.c:97 py/builtinimport.c:251 +msgid "script compilation not supported" +msgstr "compilazione dello scrip non suportata" + +#: main.c:154 +msgid " output:\n" +msgstr " output:\n" + +#: main.c:168 main.c:241 +msgid "" +"Auto-reload is on. Simply save files over USB to run them or enter REPL to " +"disable.\n" +msgstr "" +"L'auto-reload è attivo. Salva i file su USB per eseguirli o entra nel REPL " +"per disabilitarlo.\n" + +#: main.c:170 +msgid "Running in safe mode! Auto-reload is off.\n" +msgstr "Modalità sicura in esecuzione! Auto-reload disattivato.\n" + +#: main.c:172 main.c:243 +msgid "Auto-reload is off.\n" +msgstr "Auto-reload disattivato.\n" + +#: main.c:186 +msgid "Running in safe mode! Not running saved code.\n" +msgstr "Modalità sicura in esecuzione! Codice salvato non in esecuzione.\n" + +#: main.c:202 +msgid "WARNING: Your code filename has two extensions\n" +msgstr "ATTENZIONE: Il nome del sorgente ha due estensioni\n" + +#: main.c:250 +msgid "You requested starting safe mode by " +msgstr "È stato richiesto l'avvio in modalità sicura da " + +#: main.c:253 +msgid "To exit, please reset the board without " +msgstr "Per uscire resettare la scheda senza " + +#: main.c:260 +msgid "" +"You are running in safe mode which means something really bad happened.\n" +msgstr "" +"Sei nella modalità sicura che significa che qualcosa di molto brutto è " +"successo.\n" + +#: main.c:262 +msgid "Looks like our core CircuitPython code crashed hard. Whoops!\n" +msgstr "" +"Sembra che il codice del core di CircuitPython sia crashato malamente. " +"Whoops!\n" + +#: main.c:263 +msgid "Please file an issue here with the contents of your CIRCUITPY drive:\n" +msgstr "" +"Ti preghiamo di compilare una issue con il contenuto del tuo drie " +"CIRCUITPY:\n" + +#: main.c:266 +msgid "" +"The microcontroller's power dipped. Please make sure your power supply " +"provides\n" +msgstr "" +"La potenza del microcontrollore è calata. Assicurati che l'alimentazione sia " +"attaccata correttamente\n" + +#: main.c:267 +msgid "" +"enough power for the whole circuit and press reset (after ejecting " +"CIRCUITPY).\n" +msgstr "" +"abbastanza potenza per l'intero circuito e premere reset (dopo aver espulso " +"CIRCUITPY).\n" + +#: main.c:271 +msgid "Press any key to enter the REPL. Use CTRL-D to reload." +msgstr "" +"Premi un qualunque tasto per entrare nel REPL. Usa CTRL-D per ricaricare." + +#: main.c:429 +msgid "soft reboot\n" +msgstr "soft reboot\n" + +#: ports/atmel-samd/audio_dma.c:209 +#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c:361 +msgid "All sync event channels in use" +msgstr "Tutti i canali di eventi sincronizzati in uso" + +#: ports/atmel-samd/bindings/samd/Clock.c:135 +msgid "calibration is read only" +msgstr "la calibrazione è in sola lettura" + +#: ports/atmel-samd/bindings/samd/Clock.c:137 +msgid "calibration is out of range" +msgstr "la calibrazione è fuori intervallo" + +#: ports/atmel-samd/board_busses.c:59 ports/nrf/board_busses.c:39 +msgid "No default I2C bus" +msgstr "Nessun bus I2C predefinito" + +#: ports/atmel-samd/board_busses.c:85 ports/nrf/board_busses.c:64 +msgid "No default SPI bus" +msgstr "Nessun bus SPI predefinito" + +#: ports/atmel-samd/board_busses.c:112 ports/nrf/board_busses.c:91 +msgid "No default UART bus" +msgstr "Nessun bus UART predefinito" + +#: ports/atmel-samd/common-hal/analogio/AnalogIn.c:63 +#: ports/nrf/common-hal/analogio/AnalogIn.c:39 +msgid "Pin does not have ADC capabilities" +msgstr "Il pin non ha capacità di ADC" + +#: ports/atmel-samd/common-hal/analogio/AnalogOut.c:49 +msgid "No DAC on chip" +msgstr "Nessun DAC sul chip" + +#: ports/atmel-samd/common-hal/analogio/AnalogOut.c:56 +msgid "AnalogOut not supported on given pin" +msgstr "AnalogOut non supportato sul pin scelto" + +#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:147 +#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:150 +msgid "Invalid bit clock pin" +msgstr "Pin del clock di bit non valido" + +#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:153 +msgid "Bit clock and word select must share a clock unit" +msgstr "" +"Clock di bit e selezione parola devono condividere la stessa unità di clock" + +#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:156 +#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c:130 +msgid "Invalid data pin" +msgstr "Pin dati non valido" + +#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:169 +#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:174 +#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c:145 +#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c:150 +msgid "Serializer in use" +msgstr "Serializer in uso" + +#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:230 +msgid "Clock unit in use" +msgstr "Unità di clock in uso" + +#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:240 +#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c:172 +msgid "Unable to find free GCLK" +msgstr "Impossibile trovare un GCLK libero" + +#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:254 +msgid "Too many channels in sample." +msgstr "" + +#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:305 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:417 +msgid "No DMA channel found" +msgstr "Nessun canale DMA trovato" + +#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:308 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:419 +msgid "Unable to allocate buffers for signed conversion" +msgstr "Ipossibilitato ad allocare buffer per la conversione con segno" + +#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c:109 +msgid "Invalid clock pin" +msgstr "Pin di clock non valido" + +#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c:134 +msgid "Only 8 or 16 bit mono with " +msgstr "" + +#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c:167 +msgid "sampling rate out of range" +msgstr "frequenza di campionamento fuori intervallo" + +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:132 +msgid "DAC already in use" +msgstr "DAC già in uso" + +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:136 +msgid "Right channel unsupported" +msgstr "Canale destro non supportato" + +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:139 +#: ports/atmel-samd/common-hal/pulseio/PWMOut.c:116 +#: ports/atmel-samd/common-hal/touchio/TouchIn.c:65 +msgid "Invalid pin" +msgstr "Pin non valido" + +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:147 +msgid "Invalid pin for left channel" +msgstr "Pin non valido per il canale sinistro" + +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:151 +msgid "Invalid pin for right channel" +msgstr "Pin non valido per il canale destro" + +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:154 +msgid "Cannot output both channels on the same pin" +msgstr "Impossibile dare in output entrambi i canal sullo stesso pin" + +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:243 +#: ports/atmel-samd/common-hal/pulseio/PWMOut.c:189 +#: ports/atmel-samd/common-hal/pulseio/PulseOut.c:110 +#: ports/nrf/common-hal/pulseio/PulseOut.c:107 +msgid "All timers in use" +msgstr "Tutti i timer utilizzati" + +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:285 +msgid "All event channels in use" +msgstr "Tutti i canali eventi utilizati" + +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:375 +#, c-format +msgid "Sample rate too high. It must be less than %d" +msgstr "" +"Frequenza di campionamento troppo alta. Il valore deve essere inferiore a %d" + +#: ports/atmel-samd/common-hal/busio/I2C.c:71 +msgid "Not enough pins available" +msgstr "Non sono presenti abbastanza pin" + +#: ports/atmel-samd/common-hal/busio/I2C.c:78 +#: ports/atmel-samd/common-hal/busio/SPI.c:171 +#: ports/atmel-samd/common-hal/busio/UART.c:119 +#: ports/atmel-samd/common-hal/i2cslave/I2CSlave.c:45 +#: ports/nrf/common-hal/busio/I2C.c:82 +msgid "Invalid pins" +msgstr "Pin non validi" + +#: ports/atmel-samd/common-hal/busio/I2C.c:101 +msgid "SDA or SCL needs a pull up" +msgstr "SDA o SCL necessitano un pull-up" + +#: ports/atmel-samd/common-hal/busio/I2C.c:121 +msgid "Unsupported baudrate" +msgstr "baudrate non supportato" + +#: ports/atmel-samd/common-hal/busio/UART.c:66 +msgid "bytes > 8 bits not supported" +msgstr "byte > 8 bit non supportati" + +#: ports/atmel-samd/common-hal/busio/UART.c:72 +#: ports/nrf/common-hal/busio/UART.c:82 +msgid "tx and rx cannot both be None" +msgstr "tx e rx non possono essere entrambi None" + +#: ports/atmel-samd/common-hal/busio/UART.c:145 +#: ports/nrf/common-hal/busio/UART.c:115 +msgid "Failed to allocate RX buffer" +msgstr "Impossibile allocare buffer RX" + +#: ports/atmel-samd/common-hal/busio/UART.c:153 +msgid "Could not initialize UART" +msgstr "Impossibile inizializzare l'UART" + +#: ports/atmel-samd/common-hal/busio/UART.c:240 +#: ports/nrf/common-hal/busio/UART.c:149 +msgid "No RX pin" +msgstr "Nessun pin RX" + +#: ports/atmel-samd/common-hal/busio/UART.c:294 +#: ports/nrf/common-hal/busio/UART.c:195 +msgid "No TX pin" +msgstr "Nessun pin TX" + +#: ports/atmel-samd/common-hal/digitalio/DigitalInOut.c:170 +#: ports/nrf/common-hal/digitalio/DigitalInOut.c:147 +msgid "Cannot get pull while in output mode" +msgstr "" + +#: ports/atmel-samd/common-hal/microcontroller/__init__.c:74 +#: ports/esp8266/common-hal/microcontroller/__init__.c:64 +msgid "Cannot reset into bootloader because no bootloader is present." +msgstr "" +"Impossibile resettare nel bootloader poiché nessun bootloader è presente." + +#: ports/atmel-samd/common-hal/pulseio/PWMOut.c:120 +#: ports/atmel-samd/common-hal/pulseio/PWMOut.c:369 +#: ports/nrf/common-hal/pulseio/PWMOut.c:119 +#: ports/nrf/common-hal/pulseio/PWMOut.c:233 +msgid "Invalid PWM frequency" +msgstr "Frequenza PWM non valida" + +#: ports/atmel-samd/common-hal/pulseio/PWMOut.c:187 +msgid "All timers for this pin are in use" +msgstr "Tutti i timer per questo pin sono in uso" + +#: ports/atmel-samd/common-hal/pulseio/PulseIn.c:110 +msgid "No hardware support on pin" +msgstr "Nessun supporto hardware sul pin" + +#: ports/atmel-samd/common-hal/pulseio/PulseIn.c:113 +msgid "EXTINT channel already in use" +msgstr "Canale EXTINT già in uso" + +#: ports/atmel-samd/common-hal/pulseio/PulseIn.c:118 +#: ports/esp8266/common-hal/pulseio/PulseIn.c:86 +#, c-format +msgid "Failed to allocate RX buffer of %d bytes" +msgstr "Fallita allocazione del buffer RX di %d byte" + +#: ports/atmel-samd/common-hal/pulseio/PulseIn.c:205 +#: ports/esp8266/common-hal/pulseio/PulseIn.c:151 +msgid "pop from an empty PulseIn" +msgstr "pop sun un PulseIn vuoto" + +#: ports/atmel-samd/common-hal/pulseio/PulseIn.c:237 +#: ports/esp8266/common-hal/pulseio/PulseIn.c:182 py/obj.c:420 +msgid "index out of range" +msgstr "indice fuori intervallo" + +#: ports/atmel-samd/common-hal/pulseio/PulseOut.c:178 +msgid "Another send is already active" +msgstr "" + +#: ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.c:38 +msgid "Both pins must support hardware interrupts" +msgstr "Entrambi i pin devono supportare gli interrupt hardware" + +#: ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.c:46 +msgid "A hardware interrupt channel is already in use" +msgstr "Un canale di interrupt hardware è già in uso" + +#: ports/atmel-samd/common-hal/rtc/RTC.c:101 +msgid "calibration value out of range +/-127" +msgstr "valore di calibrazione fuori intervallo +/-127" + +#: ports/atmel-samd/common-hal/touchio/TouchIn.c:75 +msgid "No free GCLKs" +msgstr "Nessun GCLK libero" + +#: ports/esp8266/common-hal/analogio/AnalogIn.c:43 +msgid "Pin %q does not have ADC capabilities" +msgstr "Il pin %q non ha capacità ADC" + +#: ports/esp8266/common-hal/analogio/AnalogOut.c:39 +msgid "No hardware support for analog out." +msgstr "Nessun supporto hardware per l'uscita analogica." + +#: ports/esp8266/common-hal/busio/SPI.c:72 +msgid "Pins not valid for SPI" +msgstr "Pin non validi per SPI" + +#: ports/esp8266/common-hal/busio/UART.c:45 +msgid "Only tx supported on UART1 (GPIO2)." +msgstr "Solo tx supportato su UART1 (GPIO2)." + +#: ports/esp8266/common-hal/busio/UART.c:67 ports/esp8266/machine_uart.c:108 +msgid "invalid data bits" +msgstr "bit dati invalidi" + +#: ports/esp8266/common-hal/busio/UART.c:91 ports/esp8266/machine_uart.c:144 +msgid "invalid stop bits" +msgstr "bit di stop invalidi" + +#: ports/esp8266/common-hal/digitalio/DigitalInOut.c:200 +msgid "ESP8266 does not support pull down." +msgstr "ESP8266 non supporta pull-down" + +#: ports/esp8266/common-hal/digitalio/DigitalInOut.c:210 +msgid "GPIO16 does not support pull up." +msgstr "GPIO16 non supporta pull-up" + +#: ports/esp8266/common-hal/microcontroller/__init__.c:66 +msgid "ESP8226 does not support safe mode." +msgstr "ESP8266 non supporta la modalità sicura." + +#: ports/esp8266/common-hal/pulseio/PWMOut.c:54 +#: ports/esp8266/common-hal/pulseio/PWMOut.c:113 +#, c-format +msgid "Maximum PWM frequency is %dhz." +msgstr "Frequenza massima su PWM è %dhz" + +#: ports/esp8266/common-hal/pulseio/PWMOut.c:57 +#: ports/esp8266/common-hal/pulseio/PWMOut.c:116 +msgid "Minimum PWM frequency is 1hz." +msgstr "Frequenza minima su PWM è 1hz" + +#: ports/esp8266/common-hal/pulseio/PWMOut.c:68 +#, c-format +msgid "Multiple PWM frequencies not supported. PWM already set to %dhz." +msgstr "Frequenze PWM multiple non supportate. PWM già impostato a %shz." + +#: ports/esp8266/common-hal/pulseio/PWMOut.c:77 ports/esp8266/machine_pwm.c:70 +#, c-format +msgid "PWM not supported on pin %d" +msgstr "PWM non è supportato sul pin %d" + +#: ports/esp8266/common-hal/pulseio/PulseIn.c:78 +msgid "No PulseIn support for %q" +msgstr "Nessun supporto per PulseIn per %q" + +#: ports/esp8266/common-hal/storage/__init__.c:34 +msgid "Unable to remount filesystem" +msgstr "Imposssibile rimontare il filesystem" + +#: ports/esp8266/common-hal/storage/__init__.c:38 +msgid "Use esptool to erase flash and re-upload Python instead" +msgstr "Usa esptool per cancellare la flash e ricaricare Python invece" + +#: ports/esp8266/esp_mphal.c:154 +msgid "C-level assert" +msgstr "assert a livello C" + +#: ports/esp8266/machine_adc.c:57 +#, c-format +msgid "not a valid ADC Channel: %d" +msgstr "canale ADC non valido: %d" + +#: ports/esp8266/machine_hspi.c:131 ports/esp8266/machine_hspi.c:137 +msgid "impossible baudrate" +msgstr "baudrate impossibile" + +#: ports/esp8266/machine_pin.c:129 +msgid "expecting a pin" +msgstr "pin atteso" + +#: ports/esp8266/machine_pin.c:284 +msgid "Pin(16) doesn't support pull" +msgstr "Pin(16) non supporta pull" + +#: ports/esp8266/machine_pin.c:323 +msgid "invalid pin" +msgstr "pin non valido" + +#: ports/esp8266/machine_pin.c:389 +msgid "pin does not have IRQ capabilities" +msgstr "il pin non implementa IRQ" + +#: ports/esp8266/machine_rtc.c:185 +msgid "buffer too long" +msgstr "buffer troppo lungo" + +#: ports/esp8266/machine_rtc.c:209 ports/esp8266/machine_rtc.c:223 +#: ports/esp8266/machine_rtc.c:246 +msgid "invalid alarm" +msgstr "alarm non valido" + +#: ports/esp8266/machine_uart.c:169 +#, c-format +msgid "UART(%d) does not exist" +msgstr "UART(%d) non esistente" + +#: ports/esp8266/machine_uart.c:219 +msgid "UART(1) can't read" +msgstr "UART(1) non leggibile" + +#: ports/esp8266/modesp.c:119 +msgid "len must be multiple of 4" +msgstr "len deve essere multiplo di 4" + +#: ports/esp8266/modesp.c:274 +#, c-format +msgid "memory allocation failed, allocating %u bytes for native code" +msgstr "" +"allocazione di memoria fallita, allocazione di %d byte per codice nativo" + +#: ports/esp8266/modesp.c:317 +msgid "flash location must be below 1MByte" +msgstr "Locazione della flash deve essere inferiore a 1mb" + +#: ports/esp8266/modmachine.c:63 +msgid "frequency can only be either 80Mhz or 160MHz" +msgstr "la frequenza può essere o 80Mhz o 160Mhz" + +#: ports/esp8266/modnetwork.c:61 +msgid "AP required" +msgstr "AP richiesto" + +#: ports/esp8266/modnetwork.c:61 +msgid "STA required" +msgstr "STA richiesta" + +#: ports/esp8266/modnetwork.c:87 +msgid "Cannot update i/f status" +msgstr "Impossibile aggiornare status di i/f" + +#: ports/esp8266/modnetwork.c:142 +msgid "Cannot set STA config" +msgstr "Impossibile impostare la configurazione della STA" + +#: ports/esp8266/modnetwork.c:144 +msgid "Cannot connect to AP" +msgstr "Impossible connettersi all'AP" + +#: ports/esp8266/modnetwork.c:152 +msgid "Cannot disconnect from AP" +msgstr "Impossible disconnettersi all'AP" + +#: ports/esp8266/modnetwork.c:173 +msgid "unknown status param" +msgstr "prametro di stato sconosciuto" + +#: ports/esp8266/modnetwork.c:222 +msgid "STA must be active" +msgstr "STA deve essere attiva" + +#: ports/esp8266/modnetwork.c:239 +msgid "scan failed" +msgstr "scansione fallita" + +#: ports/esp8266/modnetwork.c:306 +msgid "wifi_set_ip_info() failed" +msgstr "wifi_set_ip_info() faillito" + +#: ports/esp8266/modnetwork.c:319 +msgid "either pos or kw args are allowed" +msgstr "sono permesse solo gli argomenti pos o kw" + +#: ports/esp8266/modnetwork.c:329 +msgid "can't get STA config" +msgstr "impossibile recuperare la configurazione della STA" + +#: ports/esp8266/modnetwork.c:331 +msgid "can't get AP config" +msgstr "impossibile recuperare le configurazioni dell'AP" + +#: ports/esp8266/modnetwork.c:346 +msgid "invalid buffer length" +msgstr "lunghezza del buffer non valida" + +#: ports/esp8266/modnetwork.c:405 +msgid "can't set STA config" +msgstr "impossibile impostare le configurazioni della STA" + +#: ports/esp8266/modnetwork.c:407 +msgid "can't set AP config" +msgstr "impossibile impostare le configurazioni dell'AP" + +#: ports/esp8266/modnetwork.c:416 +msgid "can query only one param" +msgstr "è possibile interrogare solo un parametro" + +#: ports/esp8266/modnetwork.c:469 +msgid "unknown config param" +msgstr "parametro di configurazione sconosciuto" + +#: ports/nrf/common-hal/analogio/AnalogOut.c:37 +msgid "AnalogOut functionality not supported" +msgstr "funzionalità AnalogOut non supportata" + +#: ports/nrf/common-hal/bleio/Adapter.c:41 +#, c-format +msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX" +msgstr "" + +#: ports/nrf/common-hal/bleio/Adapter.c:125 +#, c-format +msgid "Failed to change softdevice state, error: 0x%08lX" +msgstr "" + +#: ports/nrf/common-hal/bleio/Adapter.c:135 +#, c-format +msgid "Failed to get softdevice state, error: 0x%08lX" +msgstr "" + +#: ports/nrf/common-hal/bleio/Adapter.c:155 +#, c-format +msgid "Failed to get local address, error: 0x%08lX" +msgstr "" + +#: ports/nrf/common-hal/bleio/Characteristic.c:52 +#, fuzzy, c-format +msgid "Failed to write gatts value, status: 0x%08lX" +msgstr "Impossibile scrivere valore dell'attributo. status: 0x%02x" + +#: ports/nrf/common-hal/bleio/Characteristic.c:76 +#, fuzzy, c-format +msgid "Failed to notify attribute value, status: 0x%08lX" +msgstr "Impossibile notificare valore dell'attributo. status: 0x%02x" + +#: ports/nrf/common-hal/bleio/Characteristic.c:91 +#, fuzzy, c-format +msgid "Failed to read attribute value, status: 0x%08lX" +msgstr "Impossibile leggere valore dell'attributo. status: 0x%02x" + +#: ports/nrf/common-hal/bleio/Characteristic.c:119 +#: ports/nrf/common-hal/bleio/Device.c:272 +#: ports/nrf/common-hal/bleio/Device.c:307 +#, c-format +msgid "Failed to acquire mutex, status: 0x%08lX" +msgstr "" + +#: ports/nrf/common-hal/bleio/Characteristic.c:126 +#, fuzzy, c-format +msgid "Failed to write attribute value, status: 0x%08lX" +msgstr "Impossibile scrivere valore dell'attributo. status: 0x%02x" + +#: ports/nrf/common-hal/bleio/Characteristic.c:138 +#: ports/nrf/common-hal/bleio/Device.c:284 +#: ports/nrf/common-hal/bleio/Device.c:319 +#: ports/nrf/common-hal/bleio/Device.c:354 +#: ports/nrf/common-hal/bleio/Device.c:391 +#, c-format +msgid "Failed to release mutex, status: 0x%08lX" +msgstr "" + +#: ports/nrf/common-hal/bleio/Device.c:81 +#: ports/nrf/common-hal/bleio/Device.c:114 +#, fuzzy +msgid "Can not fit data into the advertisment packet" +msgstr "Impossibile inserire dati nel pacchetto di advertisement." + +#: ports/nrf/common-hal/bleio/Device.c:266 +#, c-format +msgid "Failed to discover serivices, status: 0x%08lX" +msgstr "" + +#: ports/nrf/common-hal/bleio/Device.c:403 +#: ports/nrf/common-hal/bleio/Scanner.c:76 +#, fuzzy, c-format +msgid "Failed to continue scanning, status: 0x%0xlX" +msgstr "Impossible iniziare la scansione. status: 0x%02x" + +#: ports/nrf/common-hal/bleio/Device.c:436 +#, fuzzy, c-format +msgid "Failed to connect, status: 0x%08lX" +msgstr "Impossibile connettersi. status: 0x%02x" + +#: ports/nrf/common-hal/bleio/Device.c:513 +#, fuzzy, c-format +msgid "Failed to add service, status: 0x%08lX" +msgstr "Impossibile fermare advertisement. status: 0x%02x" + +#: ports/nrf/common-hal/bleio/Device.c:531 +#, fuzzy, c-format +msgid "Failed to start advertisment, status: 0x%08lX" +msgstr "Impossibile avviare advertisement. status: 0x%02x" + +#: ports/nrf/common-hal/bleio/Device.c:549 +#, fuzzy, c-format +msgid "Failed to stop advertisment, status: 0x%08lX" +msgstr "Impossibile fermare advertisement. status: 0x%02x" + +#: ports/nrf/common-hal/bleio/Device.c:575 +#: ports/nrf/common-hal/bleio/Scanner.c:103 +#, fuzzy, c-format +msgid "Failed to start scanning, status: 0x%0xlX" +msgstr "Impossible iniziare la scansione. status: 0x%02x" + +#: ports/nrf/common-hal/bleio/Device.c:592 +#, fuzzy, c-format +msgid "Failed to create mutex, status: 0x%0xlX" +msgstr "Impossibile leggere valore dell'attributo. status: 0x%02x" + +#: ports/nrf/common-hal/bleio/Service.c:83 +#, c-format +msgid "Failed to add characteristic, status: 0x%08lX" +msgstr "" + +#: ports/nrf/common-hal/bleio/UUID.c:97 +#, fuzzy, c-format +msgid "Failed to add Vendor Specific UUID, status: 0x%08lX" +msgstr "Non è possibile aggiungere l'UUID del vendor specifico da 128-bit" + +#: ports/nrf/common-hal/bleio/UUID.c:102 +msgid "Invalid UUID string length" +msgstr "Lunghezza della stringa UUID non valida" + +#: ports/nrf/common-hal/bleio/UUID.c:109 +#: shared-bindings/bleio/Characteristic.c:125 +#: shared-bindings/bleio/Service.c:105 +msgid "Invalid UUID parameter" +msgstr "Parametro UUID non valido" + +#: ports/nrf/common-hal/busio/I2C.c:96 +msgid "All I2C peripherals are in use" +msgstr "Tutte le periferiche I2C sono in uso" + +#: ports/nrf/common-hal/busio/SPI.c:133 +msgid "All SPI peripherals are in use" +msgstr "Tutte le periferiche SPI sono in uso" + +#: ports/nrf/common-hal/busio/UART.c:48 +#, c-format +msgid "error = 0x%08lX" +msgstr "" + +#: ports/nrf/common-hal/busio/UART.c:86 +#, fuzzy +msgid "Invalid buffer size" +msgstr "lunghezza del buffer non valida" + +#: ports/nrf/common-hal/busio/UART.c:90 +#, fuzzy +msgid "Odd parity is not supported" +msgstr "operazione I2C non supportata" + +#: ports/nrf/common-hal/busio/UART.c:322 ports/nrf/common-hal/busio/UART.c:326 +#: ports/nrf/common-hal/busio/UART.c:331 ports/nrf/common-hal/busio/UART.c:336 +#: ports/nrf/common-hal/busio/UART.c:342 ports/nrf/common-hal/busio/UART.c:347 +#: ports/nrf/common-hal/busio/UART.c:352 ports/nrf/common-hal/busio/UART.c:356 +#: ports/nrf/common-hal/busio/UART.c:364 +#, fuzzy +msgid "busio.UART not available" +msgstr "busio.UART non ancora implementato" + +#: ports/nrf/common-hal/microcontroller/Processor.c:49 +#, c-format +msgid "Can not get temperature. status: 0x%02x" +msgstr "Impossibile leggere la temperatura. status: 0x%02x" + +#: ports/nrf/common-hal/pulseio/PWMOut.c:161 +#, fuzzy +msgid "All PWM peripherals are in use" +msgstr "Tutte le periferiche SPI sono in uso" + +#: ports/unix/modffi.c:138 +msgid "Unknown type" +msgstr "Tipo sconosciuto" + +#: ports/unix/modffi.c:207 ports/unix/modffi.c:265 +msgid "Error in ffi_prep_cif" +msgstr "Errore in ffi_prep_cif" + +#: ports/unix/modffi.c:270 +msgid "ffi_prep_closure_loc" +msgstr "ffi_prep_closure_loc" + +#: ports/unix/modffi.c:413 +msgid "Don't know how to pass object to native function" +msgstr "Non so come passare l'oggetto alla funzione nativa" + +#: ports/unix/modusocket.c:474 +#, c-format +msgid "[addrinfo error %d]" +msgstr "[errore addrinfo %d]" + +#: py/argcheck.c:44 +msgid "function does not take keyword arguments" +msgstr "la funzione non prende argomenti nominati" + +#: py/argcheck.c:54 py/bc.c:85 py/objnamedtuple.c:104 +#, c-format +msgid "function takes %d positional arguments but %d were given" +msgstr "" +"la funzione prende %d argomenti posizionali ma ne sono stati forniti %d" + +#: py/argcheck.c:64 +#, c-format +msgid "function missing %d required positional arguments" +msgstr "mancano %d argomenti posizionali obbligatori alla funzione" + +#: py/argcheck.c:72 +#, c-format +msgid "function expected at most %d arguments, got %d" +msgstr "la funzione prevede al massimo %d argmoneti, ma ne ha ricevuti %d" + +#: py/argcheck.c:97 +msgid "'%q' argument required" +msgstr "'%q' argomento richiesto" + +#: py/argcheck.c:122 +msgid "extra positional arguments given" +msgstr "argomenti posizonali extra dati" + +#: py/argcheck.c:130 +msgid "extra keyword arguments given" +msgstr "argomento nominato aggiuntivo fornito" + +#: py/argcheck.c:142 +msgid "argument num/types mismatch" +msgstr "discrepanza di numero/tipo di argomenti" + +#: py/argcheck.c:147 +msgid "keyword argument(s) not yet implemented - use normal args instead" +msgstr "" +"argomento(i) nominati non ancora implementati - usare invece argomenti " +"normali" + +#: py/bc.c:88 py/objnamedtuple.c:108 +msgid "%q() takes %d positional arguments but %d were given" +msgstr "%q() prende %d argomenti posizionali ma ne sono stati forniti %d" + +#: py/bc.c:197 py/bc.c:215 +msgid "unexpected keyword argument" +msgstr "argomento nominato inaspettato" + +#: py/bc.c:199 +msgid "keywords must be strings" +msgstr "argomenti nominati devono essere stringhe" + +#: py/bc.c:206 py/objnamedtuple.c:138 +msgid "function got multiple values for argument '%q'" +msgstr "la funzione ha ricevuto valori multipli per l'argomento '%q'" + +#: py/bc.c:218 py/objnamedtuple.c:130 +msgid "unexpected keyword argument '%q'" +msgstr "argomento nominato '%q' inaspettato" + +#: py/bc.c:244 +#, c-format +msgid "function missing required positional argument #%d" +msgstr "mancante il #%d argomento posizonale obbligatorio della funzione" + +#: py/bc.c:260 +msgid "function missing required keyword argument '%q'" +msgstr "argomento nominato '%q' mancante alla funzione" + +#: py/bc.c:269 +msgid "function missing keyword-only argument" +msgstr "argomento nominato mancante alla funzione" + +#: py/binary.c:112 +msgid "bad typecode" +msgstr "" + +#: py/builtinevex.c:99 +msgid "bad compile mode" +msgstr "" + +#: py/builtinhelp.c:137 +#, fuzzy +msgid "Plus any modules on the filesystem\n" +msgstr "Imposssibile rimontare il filesystem" + +#: py/builtinhelp.c:183 +#, c-format +msgid "" +"Welcome to Adafruit CircuitPython %s!\n" +"\n" +"Please visit learn.adafruit.com/category/circuitpython for project guides.\n" +"\n" +"To list built-in modules please do `help(\"modules\")`.\n" +msgstr "" + +#: py/builtinimport.c:336 +msgid "cannot perform relative import" +msgstr "impossibile effettuare l'importazione relativa" + +#: py/builtinimport.c:420 py/builtinimport.c:532 +msgid "module not found" +msgstr "modulo non trovato" + +#: py/builtinimport.c:423 py/builtinimport.c:535 +msgid "no module named '%q'" +msgstr "nessun modulo chiamato '%q'" + +#: py/builtinimport.c:510 +msgid "relative import" +msgstr "importazione relativa" + +#: py/compile.c:397 py/compile.c:542 +msgid "can't assign to expression" +msgstr "impossibile assegnare all'espressione" + +#: py/compile.c:416 +msgid "multiple *x in assignment" +msgstr "*x multipli nell'assegnamento" + +#: py/compile.c:642 +msgid "non-default argument follows default argument" +msgstr "argomento non predefinito segue argmoento predfinito" + +#: py/compile.c:771 py/compile.c:789 +msgid "invalid micropython decorator" +msgstr "decoratore non valido in micropython" + +#: py/compile.c:943 +msgid "can't delete expression" +msgstr "impossibile cancellare l'espessione" + +#: py/compile.c:955 +msgid "'break' outside loop" +msgstr "'break' al di fuori del ciclo" + +#: py/compile.c:958 +msgid "'continue' outside loop" +msgstr "'continue' al di fuori del ciclo" + +#: py/compile.c:969 +msgid "'return' outside function" +msgstr "'return' al di fuori della funzione" + +#: py/compile.c:1169 +msgid "identifier redefined as global" +msgstr "identificatore ridefinito come globale" + +#: py/compile.c:1185 +msgid "no binding for nonlocal found" +msgstr "nessun binding per nonlocal trovato" + +#: py/compile.c:1188 +msgid "identifier redefined as nonlocal" +msgstr "identificatore ridefinito come nonlocal" + +#: py/compile.c:1197 +msgid "can't declare nonlocal in outer code" +msgstr "impossibile dichiarare nonlocal nel codice esterno" + +#: py/compile.c:1542 +msgid "default 'except' must be last" +msgstr "'except' predefinito deve essere ultimo" + +#: py/compile.c:2095 +msgid "*x must be assignment target" +msgstr "" + +#: py/compile.c:2193 +msgid "super() can't find self" +msgstr "" + +#: py/compile.c:2256 +msgid "can't have multiple *x" +msgstr "impossibile usare *x multipli" + +#: py/compile.c:2263 +msgid "can't have multiple **x" +msgstr "impossibile usare **x multipli" + +#: py/compile.c:2271 +msgid "LHS of keyword arg must be an id" +msgstr "" + +#: py/compile.c:2287 +msgid "non-keyword arg after */**" +msgstr "argomento non nominato dopo */**" + +#: py/compile.c:2291 +msgid "non-keyword arg after keyword arg" +msgstr "argomento non nominato seguito da argomento nominato" + +#: py/compile.c:2463 py/compile.c:2473 py/compile.c:2712 py/compile.c:2742 +#: py/parse.c:1176 +msgid "invalid syntax" +msgstr "sintassi non valida" + +#: py/compile.c:2465 +msgid "expecting key:value for dict" +msgstr "chiave:valore atteso per dict" + +#: py/compile.c:2475 +msgid "expecting just a value for set" +msgstr "un solo valore atteso per set" + +#: py/compile.c:2600 +msgid "'yield' outside function" +msgstr "'yield' al di fuori della funzione" + +#: py/compile.c:2619 +msgid "'await' outside function" +msgstr "'await' al di fuori della funzione" + +#: py/compile.c:2774 +msgid "name reused for argument" +msgstr "nome riutilizzato come argomento" + +#: py/compile.c:2827 +msgid "parameter annotation must be an identifier" +msgstr "" + +#: py/compile.c:2969 py/compile.c:3137 +msgid "return annotation must be an identifier" +msgstr "" + +#: py/compile.c:3097 +msgid "inline assembler must be a function" +msgstr "inline assembler deve essere una funzione" + +#: py/compile.c:3134 +msgid "unknown type" +msgstr "tipo sconosciuto" + +#: py/compile.c:3154 +msgid "expecting an assembler instruction" +msgstr "istruzione assembler attesa" + +#: py/compile.c:3184 +msgid "'label' requires 1 argument" +msgstr "'label' richiede 1 argomento" + +#: py/compile.c:3190 +msgid "label redefined" +msgstr "etichetta ridefinita" + +#: py/compile.c:3196 +msgid "'align' requires 1 argument" +msgstr "'align' richiede 1 argomento" + +#: py/compile.c:3205 +msgid "'data' requires at least 2 arguments" +msgstr "'data' richiede almeno 2 argomento" + +#: py/compile.c:3212 +msgid "'data' requires integer arguments" +msgstr "'data' richiede argomenti interi" + +#: py/emitinlinethumb.c:102 +#, fuzzy +msgid "can only have up to 4 parameters to Thumb assembly" +msgstr "sono disponibili fino a 4 parametri per il Xtensa assembly" + +#: py/emitinlinethumb.c:107 py/emitinlinethumb.c:112 +#, fuzzy +msgid "parameters must be registers in sequence r0 to r3" +msgstr "parametri devono essere i registri in sequenza da a2 a a5" + +#: py/emitinlinethumb.c:188 py/emitinlinethumb.c:230 +#, fuzzy, c-format +msgid "'%s' expects at most r%d" +msgstr "'%s' aspetta un registro" + +#: py/emitinlinethumb.c:197 py/emitinlinextensa.c:162 +#, c-format +msgid "'%s' expects a register" +msgstr "'%s' aspetta un registro" + +#: py/emitinlinethumb.c:211 +#, fuzzy, c-format +msgid "'%s' expects a special register" +msgstr "'%s' aspetta un registro" + +#: py/emitinlinethumb.c:239 +#, fuzzy, c-format +msgid "'%s' expects an FPU register" +msgstr "'%s' aspetta un registro" + +#: py/emitinlinethumb.c:292 +#, fuzzy, c-format +msgid "'%s' expects {r0, r1, ...}" +msgstr "'%s' aspetta un registro" + +#: py/emitinlinethumb.c:299 py/emitinlinextensa.c:169 +#, c-format +msgid "'%s' expects an integer" +msgstr "'%s' aspetta un intero" + +#: py/emitinlinethumb.c:304 +#, fuzzy, c-format +msgid "'%s' integer 0x%x does not fit in mask 0x%x" +msgstr "intero '%s' non è nell'intervallo %d..%d" + +#: py/emitinlinethumb.c:328 +#, fuzzy, c-format +msgid "'%s' expects an address of the form [a, b]" +msgstr "'%s' aspetta un registro" + +#: py/emitinlinethumb.c:334 py/emitinlinextensa.c:182 +#, c-format +msgid "'%s' expects a label" +msgstr "'%s' aspetta una etichetta" + +#: py/emitinlinethumb.c:345 py/emitinlinextensa.c:193 +msgid "label '%q' not defined" +msgstr "etichetta '%q' non definita" + +#: py/emitinlinethumb.c:806 +#, fuzzy, c-format +msgid "unsupported Thumb instruction '%s' with %d arguments" +msgstr "istruzione '%s' Xtensa non supportata con %d argomenti" + +#: py/emitinlinethumb.c:810 +#, fuzzy +msgid "branch not in range" +msgstr "argomento di chr() non è in range(256)" + +#: py/emitinlinextensa.c:86 +msgid "can only have up to 4 parameters to Xtensa assembly" +msgstr "sono disponibili fino a 4 parametri per il Xtensa assembly" + +#: py/emitinlinextensa.c:91 py/emitinlinextensa.c:96 +msgid "parameters must be registers in sequence a2 to a5" +msgstr "parametri devono essere i registri in sequenza da a2 a a5" + +#: py/emitinlinextensa.c:174 +#, c-format +msgid "'%s' integer %d is not within range %d..%d" +msgstr "intero '%s' non è nell'intervallo %d..%d" + +#: py/emitinlinextensa.c:327 +#, c-format +msgid "unsupported Xtensa instruction '%s' with %d arguments" +msgstr "istruzione '%s' Xtensa non supportata con %d argomenti" + +#: py/emitnative.c:183 +msgid "unknown type '%q'" +msgstr "tipo '%q' sconosciuto" + +#: py/emitnative.c:260 +msgid "Viper functions don't currently support more than 4 arguments" +msgstr "Le funzioni Viper non supportano più di 4 argomenti al momento" + +#: py/emitnative.c:742 +msgid "conversion to object" +msgstr "conversione in oggetto" + +#: py/emitnative.c:921 +msgid "local '%q' used before type known" +msgstr "locla '%q' utilizzato prima che il tipo fosse noto" + +#: py/emitnative.c:1118 py/emitnative.c:1156 +msgid "can't load from '%q'" +msgstr "impossibile caricare da '%q'" + +#: py/emitnative.c:1128 +msgid "can't load with '%q' index" +msgstr "impossibile caricare con indice '%q'" + +#: py/emitnative.c:1188 +msgid "local '%q' has type '%q' but source is '%q'" +msgstr "local '%q' ha tipo '%q' ma sorgente è '%q'" + +#: py/emitnative.c:1289 py/emitnative.c:1379 +msgid "can't store '%q'" +msgstr "impossibile memorizzare '%q'" + +#: py/emitnative.c:1358 py/emitnative.c:1419 +msgid "can't store to '%q'" +msgstr "impossibile memorizzare in '%q'" + +#: py/emitnative.c:1369 +msgid "can't store with '%q' index" +msgstr "impossibile memorizzare con indice '%q'" + +#: py/emitnative.c:1540 +msgid "can't implicitly convert '%q' to 'bool'" +msgstr "non è possibile convertire implicitamente '%q' in 'bool'" + +#: py/emitnative.c:1774 +msgid "unary op %q not implemented" +msgstr "operazione unaria %q non implementata" + +#: py/emitnative.c:1930 +msgid "binary op %q not implemented" +msgstr "operazione binaria %q non implementata" + +#: py/emitnative.c:1951 +msgid "can't do binary op between '%q' and '%q'" +msgstr "impossibile eseguire operazione binaria tra '%q' e '%q'" + +#: py/emitnative.c:2126 +msgid "casting" +msgstr "casting" + +#: py/emitnative.c:2173 +msgid "return expected '%q' but got '%q'" +msgstr "return aspettava '%q' ma ha ottenuto '%q'" + +#: py/emitnative.c:2191 +msgid "must raise an object" +msgstr "deve lanciare un oggetto" + +#: py/emitnative.c:2201 +msgid "native yield" +msgstr "yield nativo" + +#: py/lexer.c:345 +msgid "unicode name escapes" +msgstr "" + +#: py/modbuiltins.c:162 +msgid "chr() arg not in range(0x110000)" +msgstr "argomento di chr() non è in range(0x110000)" + +#: py/modbuiltins.c:171 +msgid "chr() arg not in range(256)" +msgstr "argomento di chr() non è in range(256)" + +#: py/modbuiltins.c:285 +msgid "arg is an empty sequence" +msgstr "l'argomento è una sequenza vuota" + +#: py/modbuiltins.c:350 +msgid "ord expects a character" +msgstr "ord() aspetta un carattere" + +#: py/modbuiltins.c:353 +#, c-format +msgid "ord() expected a character, but string of length %d found" +msgstr "" +"ord() aspettava un carattere, ma ha ricevuto una stringa di lunghezza %d" + +#: py/modbuiltins.c:363 +msgid "3-arg pow() not supported" +msgstr "pow() con tre argmomenti non supportata" + +#: py/modbuiltins.c:517 +msgid "must use keyword argument for key function" +msgstr "" + +#: py/modmath.c:41 shared-bindings/math/__init__.c:53 +msgid "math domain error" +msgstr "errore di dominio matematico" + +#: py/modmath.c:196 py/objfloat.c:270 py/objint_longlong.c:222 +#: py/objint_mpz.c:230 py/runtime.c:619 shared-bindings/math/__init__.c:346 +msgid "division by zero" +msgstr "divisione per zero" + +#: py/modmicropython.c:155 +msgid "schedule stack full" +msgstr "" + +#: py/modstruct.c:145 py/modstruct.c:153 py/modstruct.c:234 py/modstruct.c:244 +#: shared-bindings/struct/__init__.c:103 shared-bindings/struct/__init__.c:145 +#: shared-module/struct/__init__.c:91 shared-module/struct/__init__.c:175 +msgid "buffer too small" +msgstr "buffer troppo piccolo" + +#: py/modthread.c:240 +msgid "expecting a dict for keyword args" +msgstr "argomenti nominati necessitano un dizionario" + +#: py/moduerrno.c:143 py/moduerrno.c:146 +msgid "Permission denied" +msgstr "Permesso negato" + +#: py/moduerrno.c:144 +msgid "No such file/directory" +msgstr "Nessun file/directory esistente" + +#: py/moduerrno.c:145 +msgid "Input/output error" +msgstr "Errore input/output" + +#: py/moduerrno.c:147 +msgid "File exists" +msgstr "File esistente" + +#: py/moduerrno.c:148 +msgid "Unsupported operation" +msgstr "Operazione non supportata" + +#: py/moduerrno.c:149 +msgid "Invalid argument" +msgstr "Argomento non valido" + +#: py/obj.c:90 +msgid "Traceback (most recent call last):\n" +msgstr "Traceback (chiamata più recente per ultima):\n" + +#: py/obj.c:94 +msgid " File \"%q\", line %d" +msgstr " File \"%q\", riga %d" + +#: py/obj.c:96 +msgid " File \"%q\"" +msgstr " File \"%q\"" + +#: py/obj.c:100 +msgid ", in %q\n" +msgstr ", in %q\n" + +#: py/obj.c:257 +msgid "can't convert to int" +msgstr "non è possibile convertire a int" + +#: py/obj.c:260 +#, c-format +msgid "can't convert %s to int" +msgstr "non è possibile convertire %s a int" + +#: py/obj.c:320 +msgid "can't convert to float" +msgstr "non è possibile convertire a float" + +#: py/obj.c:323 +#, c-format +msgid "can't convert %s to float" +msgstr "non è possibile convertire %s a float" + +#: py/obj.c:353 +msgid "can't convert to complex" +msgstr "non è possibile convertire a complex" + +#: py/obj.c:356 +#, c-format +msgid "can't convert %s to complex" +msgstr "non è possibile convertire a complex" + +#: py/obj.c:371 +msgid "expected tuple/list" +msgstr "lista/tupla prevista" + +#: py/obj.c:374 +#, c-format +msgid "object '%s' is not a tuple or list" +msgstr "oggetto '%s' non è una tupla o una lista" + +#: py/obj.c:385 +msgid "tuple/list has wrong length" +msgstr "tupla/lista ha la lunghezza sbagliata" + +#: py/obj.c:387 +#, c-format +msgid "requested length %d but object has length %d" +msgstr "lunghezza %d richiesta ma l'oggetto ha lunghezza %d" + +#: py/obj.c:400 +msgid "indices must be integers" +msgstr "gli indici devono essere interi" + +#: py/obj.c:403 +msgid "%q indices must be integers, not %s" +msgstr "gli indici %q devono essere interi, non %s" + +#: py/obj.c:423 +msgid "%q index out of range" +msgstr "indice %q fuori intervallo" + +#: py/obj.c:455 +msgid "object has no len" +msgstr "l'oggetto non ha lunghezza" + +#: py/obj.c:458 +#, c-format +msgid "object of type '%s' has no len()" +msgstr "l'oggetto di tipo '%s' non implementa len()" + +#: py/obj.c:496 +msgid "object does not support item deletion" +msgstr "" + +#: py/obj.c:499 +#, c-format +msgid "'%s' object does not support item deletion" +msgstr "" + +#: py/obj.c:503 +msgid "object is not subscriptable" +msgstr "" + +#: py/obj.c:506 +#, c-format +msgid "'%s' object is not subscriptable" +msgstr "" + +#: py/obj.c:510 +msgid "object does not support item assignment" +msgstr "" + +#: py/obj.c:513 +#, c-format +msgid "'%s' object does not support item assignment" +msgstr "" + +#: py/obj.c:544 +msgid "object with buffer protocol required" +msgstr "" + +#: py/objarray.c:413 py/objstr.c:427 py/objstrunicode.c:191 py/objtuple.c:187 +#: shared-bindings/nvm/ByteArray.c:85 +msgid "only slices with step=1 (aka None) are supported" +msgstr "solo slice con step=1 (aka None) sono supportate" + +#: py/objarray.c:426 +msgid "lhs and rhs should be compatible" +msgstr "lhs e rhs devono essere compatibili" + +#: py/objarray.c:444 shared-bindings/nvm/ByteArray.c:107 +msgid "array/bytes required on right side" +msgstr "" + +#: py/objcomplex.c:203 +msgid "can't do truncated division of a complex number" +msgstr "impossibile fare il modulo di un numero complesso" + +#: py/objcomplex.c:209 +msgid "complex division by zero" +msgstr "complex divisione per zero" + +#: py/objcomplex.c:237 +msgid "0.0 to a complex power" +msgstr "0.0 elevato alla potenza di un numero complesso" + +#: py/objdeque.c:107 +msgid "full" +msgstr "pieno" + +#: py/objdeque.c:127 +msgid "empty" +msgstr "vuoto" + +#: py/objdict.c:314 +msgid "popitem(): dictionary is empty" +msgstr "popitem(): il dizionario è vuoto" + +#: py/objdict.c:357 +msgid "dict update sequence has wrong length" +msgstr "sequanza di aggiornamento del dizionario ha la lunghezza errata" + +#: py/objfloat.c:308 py/parsenum.c:331 +msgid "complex values not supported" +msgstr "valori complessi non supportai" + +#: py/objgenerator.c:108 +msgid "can't send non-None value to a just-started generator" +msgstr "" + +#: py/objgenerator.c:126 +msgid "generator already executing" +msgstr "" + +#: py/objgenerator.c:229 +msgid "generator ignored GeneratorExit" +msgstr "" + +#: py/objgenerator.c:251 +msgid "can't pend throw to just-started generator" +msgstr "" + +#: py/objint.c:144 +msgid "can't convert inf to int" +msgstr "impossibile convertire inf in int" + +#: py/objint.c:146 +msgid "can't convert NaN to int" +msgstr "impossibile convertire NaN in int" + +#: py/objint.c:163 +msgid "float too big" +msgstr "float troppo grande" + +#: py/objint.c:328 +msgid "long int not supported in this build" +msgstr "long int non supportata in questa build" + +#: py/objint.c:334 py/objint.c:340 py/objint.c:350 py/objint.c:358 +msgid "small int overflow" +msgstr "small int overflow" + +#: py/objint_longlong.c:189 py/objint_mpz.c:283 py/runtime.c:486 +msgid "negative power with no float support" +msgstr "potenza negativa senza supporto per float" + +#: py/objint_longlong.c:251 +msgid "ulonglong too large" +msgstr "ulonglong troppo grande" + +#: py/objint_mpz.c:267 py/runtime.c:396 py/runtime.c:411 +msgid "negative shift count" +msgstr "" + +#: py/objint_mpz.c:336 +msgid "pow() with 3 arguments requires integers" +msgstr "pow() con 3 argomenti richiede interi" + +#: py/objint_mpz.c:347 +msgid "pow() 3rd argument cannot be 0" +msgstr "il terzo argomento di pow() non può essere 0" + +#: py/objint_mpz.c:415 +msgid "overflow converting long int to machine word" +msgstr "overflow convertendo long int in parola" + +#: py/objlist.c:273 +msgid "pop from empty list" +msgstr "pop da una lista vuota" + +#: py/objnamedtuple.c:92 +msgid "can't set attribute" +msgstr "impossibile impostare attributo" + +#: py/objobject.c:55 +msgid "__new__ arg must be a user-type" +msgstr "" + +#: py/objrange.c:110 +msgid "zero step" +msgstr "zero step" + +#: py/objset.c:371 +msgid "pop from an empty set" +msgstr "pop da un set vuoto" + +#: py/objslice.c:66 +msgid "Length must be an int" +msgstr "Length deve essere un intero" + +#: py/objslice.c:71 +msgid "Length must be non-negative" +msgstr "Length deve essere non negativo" + +#: py/objslice.c:86 py/sequence.c:57 +msgid "slice step cannot be zero" +msgstr "la step della slice non può essere zero" + +#: py/objslice.c:159 +msgid "Cannot subclass slice" +msgstr "Impossibile subclasare slice" + +#: py/objstr.c:261 +msgid "bytes value out of range" +msgstr "valore byte fuori intervallo" + +#: py/objstr.c:270 +msgid "wrong number of arguments" +msgstr "numero di argomenti errato" + +#: py/objstr.c:467 +msgid "join expects a list of str/bytes objects consistent with self object" +msgstr "" +"join prende una lista di oggetti str/byte consistenti con l'oggetto stesso" + +#: py/objstr.c:542 py/objstr.c:647 py/objstr.c:1744 +msgid "empty separator" +msgstr "separatore vuoto" + +#: py/objstr.c:641 +msgid "rsplit(None,n)" +msgstr "" + +#: py/objstr.c:713 +msgid "substring not found" +msgstr "sottostringa non trovata" + +#: py/objstr.c:770 +msgid "start/end indices" +msgstr "" + +#: py/objstr.c:931 +msgid "bad format string" +msgstr "stringa di formattazione scorretta" + +#: py/objstr.c:953 +msgid "single '}' encountered in format string" +msgstr "'}' singolo presente nella stringa di formattazione" + +#: py/objstr.c:992 +msgid "bad conversion specifier" +msgstr "specificatore di conversione scorretto" + +#: py/objstr.c:996 +msgid "end of format while looking for conversion specifier" +msgstr "" + +#: py/objstr.c:998 +#, c-format +msgid "unknown conversion specifier %c" +msgstr "specificatore di conversione %s sconosciuto" + +#: py/objstr.c:1029 +msgid "unmatched '{' in format" +msgstr "'{' spaiato nella stringa di formattazione" + +#: py/objstr.c:1036 +msgid "expected ':' after format specifier" +msgstr "':' atteso dopo lo specificatore di formato" + +#: py/objstr.c:1050 +msgid "" +"can't switch from automatic field numbering to manual field specification" +msgstr "" + +#: py/objstr.c:1055 py/objstr.c:1083 +msgid "tuple index out of range" +msgstr "indice della tupla fuori intervallo" + +#: py/objstr.c:1071 +msgid "attributes not supported yet" +msgstr "attributi non ancora supportati" + +#: py/objstr.c:1079 +msgid "" +"can't switch from manual field specification to automatic field numbering" +msgstr "" + +#: py/objstr.c:1171 +msgid "invalid format specifier" +msgstr "specificatore di formato non valido" + +#: py/objstr.c:1192 +msgid "sign not allowed in string format specifier" +msgstr "segno non permesso nello spcificatore di formato della stringa" + +#: py/objstr.c:1200 +msgid "sign not allowed with integer format specifier 'c'" +msgstr "segno non permesso nello spcificatore di formato 'c' della stringa" + +#: py/objstr.c:1259 +#, c-format +msgid "unknown format code '%c' for object of type '%s'" +msgstr "codice di formattaione '%c' sconosciuto per oggetto di tipo '%s'" + +#: py/objstr.c:1331 +#, c-format +msgid "unknown format code '%c' for object of type 'float'" +msgstr "codice di formattazione '%c' sconosciuto per oggetto di tipo 'float'" + +#: py/objstr.c:1343 +msgid "'=' alignment not allowed in string format specifier" +msgstr "" + +#: py/objstr.c:1367 +#, c-format +msgid "unknown format code '%c' for object of type 'str'" +msgstr "codice di formattazione '%c' sconosciuto per oggetto di tipo 'str'" + +#: py/objstr.c:1415 +msgid "format requires a dict" +msgstr "la formattazione richiede un dict" + +#: py/objstr.c:1424 +msgid "incomplete format key" +msgstr "" + +#: py/objstr.c:1482 +msgid "incomplete format" +msgstr "formato incompleto" + +#: py/objstr.c:1490 +msgid "not enough arguments for format string" +msgstr "argomenti non sufficienti per la stringa di formattazione" + +#: py/objstr.c:1500 +#, c-format +msgid "%%c requires int or char" +msgstr "%%c necessita di int o char" + +#: py/objstr.c:1507 +msgid "integer required" +msgstr "intero richiesto" + +#: py/objstr.c:1570 +#, c-format +msgid "unsupported format character '%c' (0x%x) at index %d" +msgstr "carattere di formattazione '%c' (0x%x) non supportato all indice %d" + +#: py/objstr.c:1577 +msgid "not all arguments converted during string formatting" +msgstr "" +"non tutti gli argomenti sono stati convertiti durante la formatazione in " +"stringhe" + +#: py/objstr.c:2102 +msgid "can't convert to str implicitly" +msgstr "impossibile convertire a stringa implicitamente" + +#: py/objstr.c:2106 +msgid "can't convert '%q' object to %q implicitly" +msgstr "impossibile convertire l'oggetto '%q' implicitamente in %q" + +#: py/objstrunicode.c:134 +#, c-format +msgid "string indices must be integers, not %s" +msgstr "indici della stringa devono essere interi, non %s" + +#: py/objstrunicode.c:145 py/objstrunicode.c:164 +msgid "string index out of range" +msgstr "indice della stringa fuori intervallo" + +#: py/objtype.c:358 +msgid "__init__() should return None" +msgstr "__init__() deve ritornare None" + +#: py/objtype.c:360 +#, c-format +msgid "__init__() should return None, not '%s'" +msgstr "__init__() deve ritornare None, non '%s'" + +#: py/objtype.c:623 py/objtype.c:1275 py/runtime.c:1065 +msgid "unreadable attribute" +msgstr "attributo non leggibile" + +#: py/objtype.c:868 py/runtime.c:653 +msgid "object not callable" +msgstr "" + +#: py/objtype.c:870 py/runtime.c:655 +#, c-format +msgid "'%s' object is not callable" +msgstr "" + +#: py/objtype.c:978 +msgid "type takes 1 or 3 arguments" +msgstr "tipo prende 1 o 3 argomenti" + +#: py/objtype.c:989 +msgid "cannot create instance" +msgstr "impossibile creare un istanza" + +#: py/objtype.c:991 +msgid "cannot create '%q' instances" +msgstr "creare '%q' istanze" + +#: py/objtype.c:1047 +msgid "can't add special method to already-subclassed class" +msgstr "" + +#: py/objtype.c:1091 py/objtype.c:1097 +msgid "type is not an acceptable base type" +msgstr "il tipo non è un tipo di base accettabile" + +#: py/objtype.c:1100 +msgid "type '%q' is not an acceptable base type" +msgstr "il tipo '%q' non è un tipo di base accettabile" + +#: py/objtype.c:1137 +msgid "multiple inheritance not supported" +msgstr "ereditarietà multipla non supportata" + +#: py/objtype.c:1164 +msgid "multiple bases have instance lay-out conflict" +msgstr "" + +#: py/objtype.c:1205 +msgid "first argument to super() must be type" +msgstr "" + +#: py/objtype.c:1370 +msgid "issubclass() arg 2 must be a class or a tuple of classes" +msgstr "" +"il secondo argomento di issubclass() deve essere una classe o una tupla di " +"classi" + +#: py/objtype.c:1384 +msgid "issubclass() arg 1 must be a class" +msgstr "il primo argomento di issubclass() deve essere una classe" + +#: py/parse.c:726 +msgid "constant must be an integer" +msgstr "la costante deve essere un intero" + +#: py/parse.c:868 +msgid "Unable to init parser" +msgstr "Inizilizzazione del parser non possibile" + +#: py/parse.c:1170 +msgid "unexpected indent" +msgstr "indentazione inaspettata" + +#: py/parse.c:1173 +msgid "unindent does not match any outer indentation level" +msgstr "" + +#: py/parsenum.c:60 +msgid "int() arg 2 must be >= 2 and <= 36" +msgstr "il secondo argomanto di int() deve essere >= 2 e <= 36" + +#: py/parsenum.c:151 +msgid "invalid syntax for integer" +msgstr "sintassi invalida per l'intero" + +#: py/parsenum.c:155 +#, c-format +msgid "invalid syntax for integer with base %d" +msgstr "sintassi invalida per l'intero con base %d" + +#: py/parsenum.c:339 +msgid "invalid syntax for number" +msgstr "sintassi invalida per il numero" + +#: py/parsenum.c:342 +msgid "decimal numbers not supported" +msgstr "numeri decimali non supportati" + +#: py/persistentcode.c:223 +msgid "" +"Incompatible .mpy file. Please update all .mpy files. See http://adafru.it/" +"mpy-update for more info." +msgstr "" +"File .mpy incompatibile. Aggiorna tutti i file .mpy. Vedi http://adafru.it/" +"mpy-update per più informazioni." + +#: py/persistentcode.c:326 +msgid "can only save bytecode" +msgstr "È possibile salvare solo bytecode" + +#: py/runtime.c:206 +msgid "name not defined" +msgstr "nome non definito" + +#: py/runtime.c:209 +msgid "name '%q' is not defined" +msgstr "nome '%q'non definito" + +#: py/runtime.c:304 py/runtime.c:611 +msgid "unsupported type for operator" +msgstr "tipo non supportato per l'operando" + +#: py/runtime.c:307 +msgid "unsupported type for %q: '%s'" +msgstr "tipo non supportato per %q: '%s'" + +#: py/runtime.c:614 +msgid "unsupported types for %q: '%s', '%s'" +msgstr "tipi non supportati per %q: '%s', '%s'" + +#: py/runtime.c:881 py/runtime.c:888 py/runtime.c:945 +msgid "wrong number of values to unpack" +msgstr "numero di valori da scompattare non corretto" + +#: py/runtime.c:883 py/runtime.c:947 +#, c-format +msgid "need more than %d values to unpack" +msgstr "necessari più di %d valori da scompattare" + +#: py/runtime.c:890 +#, c-format +msgid "too many values to unpack (expected %d)" +msgstr "troppi valori da scompattare (%d attesi)" + +#: py/runtime.c:984 +msgid "argument has wrong type" +msgstr "il tipo dell'argomento è errato" + +#: py/runtime.c:986 +msgid "argument should be a '%q' not a '%q'" +msgstr "l'argomento dovrebbe essere un '%q' e non un '%q'" + +#: py/runtime.c:1123 py/runtime.c:1197 +msgid "no such attribute" +msgstr "attributo inesistente" + +#: py/runtime.c:1128 +msgid "type object '%q' has no attribute '%q'" +msgstr "l'oggetto di tipo '%q' non ha l'attributo '%q'" + +#: py/runtime.c:1132 py/runtime.c:1200 +msgid "'%s' object has no attribute '%q'" +msgstr "l'oggetto '%s' non ha l'attributo '%q'" + +#: py/runtime.c:1238 +msgid "object not iterable" +msgstr "oggetto non iterabile" + +#: py/runtime.c:1241 +#, c-format +msgid "'%s' object is not iterable" +msgstr "l'oggetto '%s' non è iterabile" + +#: py/runtime.c:1260 py/runtime.c:1296 +msgid "object not an iterator" +msgstr "l'oggetto non è un iteratore" + +#: py/runtime.c:1262 py/runtime.c:1298 +#, c-format +msgid "'%s' object is not an iterator" +msgstr "l'oggetto '%s' non è un iteratore" + +#: py/runtime.c:1401 +msgid "exceptions must derive from BaseException" +msgstr "le eccezioni devono derivare da BaseException" + +#: py/runtime.c:1430 +msgid "cannot import name %q" +msgstr "impossibile imporate il nome %q" + +#: py/runtime.c:1535 +msgid "memory allocation failed, heap is locked" +msgstr "allocazione di memoria fallita, l'heap è bloccato" + +#: py/runtime.c:1539 +#, c-format +msgid "memory allocation failed, allocating %u bytes" +msgstr "allocazione di memoria fallita, allocando %u byte" + +#: py/runtime.c:1609 +msgid "maximum recursion depth exceeded" +msgstr "profondità massima di ricorsione superata" + +#: py/sequence.c:264 +msgid "object not in sequence" +msgstr "oggetto non in sequenza" + +#: py/stream.c:96 +msgid "stream operation not supported" +msgstr "operazione di stream non supportata" + +#: py/vm.c:255 +msgid "local variable referenced before assignment" +msgstr "variabile locale richiamata prima di un assegnamento" + +#: py/vm.c:1142 +msgid "no active exception to reraise" +msgstr "nessuna eccezione attiva da rilanciare" + +#: py/vm.c:1284 +msgid "byte code not implemented" +msgstr "byte code non implementato" + +#: shared-bindings/_stage/Layer.c:71 +msgid "graphic must be 2048 bytes long" +msgstr "graphic deve essere lunga 2048 byte" + +#: shared-bindings/_stage/Layer.c:77 shared-bindings/_stage/Text.c:75 +msgid "palette must be 32 bytes long" +msgstr "la palette deve essere lunga 32 byte" + +#: shared-bindings/_stage/Layer.c:84 +msgid "map buffer too small" +msgstr "map buffer troppo piccolo" + +#: shared-bindings/_stage/Text.c:69 +msgid "font must be 2048 bytes long" +msgstr "il font deve essere lungo 2048 byte" + +#: shared-bindings/_stage/Text.c:81 +msgid "chars buffer too small" +msgstr "buffer dei caratteri troppo piccolo" + +#: shared-bindings/analogio/AnalogOut.c:118 +msgid "AnalogOut is only 16 bits. Value must be less than 65536." +msgstr "AnalogOut ha solo 16 bit. Il valore deve essere meno di 65536." + +#: shared-bindings/audiobusio/I2SOut.c:225 +#: shared-bindings/audioio/AudioOut.c:226 +msgid "Not playing" +msgstr "In pausa" + +#: shared-bindings/audiobusio/PDMIn.c:124 +msgid "Bit depth must be multiple of 8." +msgstr "La profondità di bit deve essere multipla di 8." + +#: shared-bindings/audiobusio/PDMIn.c:128 +msgid "Oversample must be multiple of 8." +msgstr "L'oversampling deve essere multiplo di 8." + +#: shared-bindings/audiobusio/PDMIn.c:136 +msgid "Microphone startup delay must be in range 0.0 to 1.0" +msgstr "" +"Il ritardo di avvio del microfono deve essere nell'intervallo tra 0.0 e 1.0" + +#: shared-bindings/audiobusio/PDMIn.c:193 +msgid "destination_length must be an int >= 0" +msgstr "destination_length deve essere un int >= 0" + +#: shared-bindings/audiobusio/PDMIn.c:199 +msgid "Cannot record to a file" +msgstr "Impossibile registrare in un file" + +#: shared-bindings/audiobusio/PDMIn.c:202 +msgid "Destination capacity is smaller than destination_length." +msgstr "La capacità di destinazione è più piccola di destination_length." + +#: shared-bindings/audiobusio/PDMIn.c:206 +msgid "destination buffer must be an array of type 'H' for bit_depth = 16" +msgstr "" +"il buffer di destinazione deve essere un array di tipo 'H' con bit_depth = 16" + +#: shared-bindings/audiobusio/PDMIn.c:208 +msgid "" +"destination buffer must be a bytearray or array of type 'B' for bit_depth = 8" +msgstr "" +"il buffer di destinazione deve essere un bytearray o un array di tipo 'B' " +"con bit_depth = 8" + +#: shared-bindings/audioio/Mixer.c:94 +#, fuzzy +msgid "Invalid voice count" +msgstr "Tipo di servizio non valido" + +#: shared-bindings/audioio/Mixer.c:99 +#, fuzzy +msgid "Invalid channel count" +msgstr "Argomento non valido" + +#: shared-bindings/audioio/Mixer.c:103 +#, fuzzy +msgid "Sample rate must be positive" +msgstr "STA deve essere attiva" + +#: shared-bindings/audioio/Mixer.c:107 +#, fuzzy +msgid "bits_per_sample must be 8 or 16" +msgstr "i bit devono essere 7, 8 o 9" + +#: shared-bindings/audioio/RawSample.c:98 +msgid "" +"sample_source buffer must be a bytearray or array of type 'h', 'H', 'b' or " +"'B'" +msgstr "" +"il buffer sample_source deve essere un bytearray o un array di tipo 'h', " +"'H', 'b' o 'B'" + +#: shared-bindings/audioio/RawSample.c:104 +msgid "buffer must be a bytes-like object" +msgstr "" + +#: shared-bindings/audioio/WaveFile.c:78 +#: shared-bindings/displayio/OnDiskBitmap.c:85 +msgid "file must be a file opened in byte mode" +msgstr "" + +#: shared-bindings/bitbangio/I2C.c:111 shared-bindings/bitbangio/SPI.c:121 +#: shared-bindings/busio/SPI.c:133 +msgid "Function requires lock" +msgstr "" + +#: shared-bindings/bitbangio/I2C.c:195 shared-bindings/busio/I2C.c:210 +msgid "Buffer must be at least length 1" +msgstr "Il buffer deve essere lungo almeno 1" + +#: shared-bindings/bitbangio/SPI.c:151 shared-bindings/busio/SPI.c:175 +msgid "Invalid polarity" +msgstr "Polarità non valida" + +#: shared-bindings/bitbangio/SPI.c:155 shared-bindings/busio/SPI.c:179 +msgid "Invalid phase" +msgstr "Fase non valida" + +#: shared-bindings/bitbangio/SPI.c:159 shared-bindings/busio/SPI.c:183 +msgid "Invalid number of bits" +msgstr "Numero di bit non valido" + +#: shared-bindings/bitbangio/SPI.c:284 shared-bindings/busio/SPI.c:348 +msgid "buffer slices must be of equal length" +msgstr "slice del buffer devono essere della stessa lunghezza" + +#: shared-bindings/bleio/Address.c:101 +msgid "Wrong address length" +msgstr "" + +#: shared-bindings/bleio/Address.c:107 +#, fuzzy +msgid "Wrong number of bytes provided" +msgstr "numero di argomenti errato" + +#: shared-bindings/bleio/Device.c:210 +msgid "Can't add services in Central mode" +msgstr "" + +#: shared-bindings/bleio/Device.c:226 +msgid "Can't connect in Peripheral mode" +msgstr "" + +#: shared-bindings/bleio/Device.c:256 +msgid "Can't change the name in Central mode" +msgstr "" + +#: shared-bindings/bleio/Device.c:277 shared-bindings/bleio/Device.c:313 +msgid "Can't advertise in Central mode" +msgstr "" + +#: shared-bindings/busio/I2C.c:120 +msgid "Function requires lock." +msgstr "" + +#: shared-bindings/busio/UART.c:102 +msgid "bits must be 7, 8 or 9" +msgstr "i bit devono essere 7, 8 o 9" + +#: shared-bindings/busio/UART.c:114 +msgid "stop must be 1 or 2" +msgstr "" + +#: shared-bindings/digitalio/DigitalInOut.c:211 +msgid "Invalid direction." +msgstr "Direzione non valida." + +#: shared-bindings/digitalio/DigitalInOut.c:240 +msgid "Cannot set value when direction is input." +msgstr "" + +#: shared-bindings/digitalio/DigitalInOut.c:266 +#: shared-bindings/digitalio/DigitalInOut.c:281 +msgid "Drive mode not used when direction is input." +msgstr "" + +#: shared-bindings/digitalio/DigitalInOut.c:314 +#: shared-bindings/digitalio/DigitalInOut.c:331 +msgid "Pull not used when direction is output." +msgstr "" + +#: shared-bindings/digitalio/DigitalInOut.c:340 +msgid "Unsupported pull value." +msgstr "Valore di pull non supportato." + +#: shared-bindings/displayio/Bitmap.c:84 +msgid "y should be an int" +msgstr "y dovrebbe essere un int" + +#: shared-bindings/displayio/Bitmap.c:89 +msgid "row buffer must be a bytearray or array of type 'b' or 'B'" +msgstr "buffer di riga deve essere un bytearray o un array di tipo 'b' o 'B'" + +#: shared-bindings/displayio/Bitmap.c:94 +msgid "row data must be a buffer" +msgstr "valori della riga devono essere un buffer" + +#: shared-bindings/displayio/ColorConverter.c:72 +msgid "color should be an int" +msgstr "il colore deve essere un int" + +#: shared-bindings/displayio/FourWire.c:55 +#: shared-bindings/displayio/FourWire.c:64 +msgid "displayio is a work in progress" +msgstr "" + +#: shared-bindings/displayio/Group.c:65 +msgid "Group must have size at least 1" +msgstr "Il gruppo deve avere dimensione almeno 1" + +#: shared-bindings/displayio/Palette.c:96 +msgid "color buffer must be a bytearray or array of type 'b' or 'B'" +msgstr "" +"buffer del colore deve essere un bytearray o un array di tipo 'b' o 'B'" + +#: shared-bindings/displayio/Palette.c:102 +msgid "color buffer must be 3 bytes (RGB) or 4 bytes (RGB + pad byte)" +msgstr "" +"il buffer del colore deve esseer di 3 byte (RGB) o 4 byte (RGB + pad byte)" + +#: shared-bindings/displayio/Palette.c:106 +msgid "color must be between 0x000000 and 0xffffff" +msgstr "il colore deve essere compreso tra 0x000000 e 0xffffff" + +#: shared-bindings/displayio/Palette.c:110 +msgid "color buffer must be a buffer or int" +msgstr "il buffer del colore deve essere un buffer o un int" + +#: shared-bindings/displayio/Palette.c:123 +#: shared-bindings/displayio/Palette.c:137 +msgid "palette_index should be an int" +msgstr "palette_index deve essere un int" + +#: shared-bindings/displayio/Sprite.c:48 +msgid "position must be 2-tuple" +msgstr "position deve essere una 2-tuple" + +#: shared-bindings/displayio/Sprite.c:97 +msgid "unsupported bitmap type" +msgstr "tipo di bitmap non supportato" + +#: shared-bindings/displayio/Sprite.c:162 +msgid "pixel_shader must be displayio.Palette or displayio.ColorConverter" +msgstr "pixel_shader deve essere displayio.Palette o displayio.ColorConverter" + +#: shared-bindings/gamepad/GamePad.c:100 +msgid "too many arguments" +msgstr "troppi argomenti" + +#: shared-bindings/gamepad/GamePad.c:104 +msgid "expected a DigitalInOut" +msgstr "DigitalInOut atteso" + +#: shared-bindings/i2cslave/I2CSlave.c:98 +msgid "can't convert address to int" +msgstr "impossible convertire indirizzo in int" + +#: shared-bindings/i2cslave/I2CSlave.c:101 +msgid "address out of bounds" +msgstr "indirizzo fuori limite" + +#: shared-bindings/i2cslave/I2CSlave.c:107 +msgid "addresses is empty" +msgstr "gli indirizzi sono vuoti" + +#: shared-bindings/microcontroller/Pin.c:89 +#: shared-bindings/neopixel_write/__init__.c:67 +#: shared-bindings/pulseio/PulseOut.c:76 +msgid "Expected a %q" +msgstr "Atteso un %q" + +#: shared-bindings/microcontroller/Pin.c:100 +msgid "%q in use" +msgstr "%q in uso" + +#: shared-bindings/microcontroller/__init__.c:126 +msgid "Invalid run mode." +msgstr "Modalità di esecuzione non valida." + +#: shared-bindings/multiterminal/__init__.c:68 +msgid "Stream missing readinto() or write() method." +msgstr "Metodi mancanti readinto() o write() allo stream." + +#: shared-bindings/nvm/ByteArray.c:99 +msgid "Slice and value different lengths." +msgstr "" + +#: shared-bindings/nvm/ByteArray.c:104 +msgid "Array values should be single bytes." +msgstr "" + +#: shared-bindings/nvm/ByteArray.c:111 shared-bindings/nvm/ByteArray.c:141 +msgid "Unable to write to nvm." +msgstr "Imposibile scrivere su nvm." + +#: shared-bindings/nvm/ByteArray.c:137 +msgid "Bytes must be between 0 and 255." +msgstr "I byte devono essere compresi tra 0 e 255" + +#: shared-bindings/os/__init__.c:200 +msgid "No hardware random available" +msgstr "Nessun generatore hardware di numeri casuali disponibile" + +#: shared-bindings/pulseio/PWMOut.c:164 +msgid "" +"PWM duty_cycle must be between 0 and 65535 inclusive (16 bit resolution)" +msgstr "" +"duty_cycle del PWM deve essere compresa tra 0 e 65535 inclusiva (risoluzione " +"a 16 bit)" + +#: shared-bindings/pulseio/PWMOut.c:195 +#, fuzzy +msgid "" +"PWM frequency not writable when variable_frequency is False on construction." +msgstr "" +"frequenza PWM frequency non è scrivibile quando variable_frequency è " +"impostato nel costruttore a False." + +#: shared-bindings/pulseio/PulseIn.c:275 +msgid "Cannot delete values" +msgstr "Impossibile cancellare valori" + +#: shared-bindings/pulseio/PulseIn.c:281 +msgid "Slices not supported" +msgstr "Slice non supportate" + +#: shared-bindings/pulseio/PulseIn.c:287 +msgid "index must be int" +msgstr "l'indice deve essere int" + +#: shared-bindings/pulseio/PulseIn.c:293 +msgid "Read-only" +msgstr "Sola lettura" + +#: shared-bindings/pulseio/PulseOut.c:135 +msgid "Array must contain halfwords (type 'H')" +msgstr "" + +#: shared-bindings/random/__init__.c:92 shared-bindings/random/__init__.c:100 +msgid "stop not reachable from start" +msgstr "stop non raggiungibile dall'inizio" + +#: shared-bindings/random/__init__.c:111 +msgid "step must be non-zero" +msgstr "step deve essere non zero" + +#: shared-bindings/random/__init__.c:114 +msgid "invalid step" +msgstr "step non valida" + +#: shared-bindings/random/__init__.c:146 +msgid "empty sequence" +msgstr "sequenza vuota" + +#: shared-bindings/rtc/RTC.c:40 shared-bindings/rtc/RTC.c:44 +#: shared-bindings/time/__init__.c:190 +msgid "RTC is not supported on this board" +msgstr "RTC non supportato su questa scheda" + +#: shared-bindings/rtc/RTC.c:52 +msgid "RTC calibration is not supported on this board" +msgstr "calibrazione RTC non supportata su questa scheda" + +#: shared-bindings/socket/__init__.c:516 shared-module/network/__init__.c:81 +#, fuzzy +msgid "no available NIC" +msgstr "busio.UART non ancora implementato" + +#: shared-bindings/storage/__init__.c:77 +msgid "filesystem must provide mount method" +msgstr "il filesystem deve fornire un metodo di mount" + +#: shared-bindings/supervisor/__init__.c:93 +msgid "Brightness must be between 0 and 255" +msgstr "La luminosità deve essere compreso tra 0 e 255" + +#: shared-bindings/supervisor/__init__.c:119 +msgid "Stack size must be at least 256" +msgstr "La dimensione dello stack deve essere almeno 256" + +#: shared-bindings/time/__init__.c:78 +msgid "sleep length must be non-negative" +msgstr "la lunghezza di sleed deve essere non negativa" + +#: shared-bindings/time/__init__.c:88 +msgid "time.struct_time() takes exactly 1 argument" +msgstr "time.struct_time() prende esattamente un argomento" + +#: shared-bindings/time/__init__.c:91 +msgid "time.struct_time() takes a 9-sequence" +msgstr "" + +#: shared-bindings/time/__init__.c:169 shared-bindings/time/__init__.c:264 +msgid "Tuple or struct_time argument required" +msgstr "Tupla o struct_time richiesto come argomento" + +#: shared-bindings/time/__init__.c:174 shared-bindings/time/__init__.c:269 +msgid "function takes exactly 9 arguments" +msgstr "la funzione prende esattamente 9 argomenti" + +#: shared-bindings/time/__init__.c:240 shared-bindings/time/__init__.c:273 +msgid "timestamp out of range for platform time_t" +msgstr "timestamp è fuori intervallo per il time_t della piattaforma" + +#: shared-bindings/touchio/TouchIn.c:173 +msgid "threshold must be in the range 0-65536" +msgstr "la soglia deve essere nell'intervallo 0-65536" + +#: shared-bindings/util.c:38 +msgid "" +"Object has been deinitialized and can no longer be used. Create a new object." +msgstr "" +"L'oggetto è stato deinizializzato e non può essere più usato. Crea un nuovo " +"oggetto." + +#: shared-module/audioio/Mixer.c:47 shared-module/audioio/WaveFile.c:117 +msgid "Couldn't allocate first buffer" +msgstr "Impossibile allocare il primo buffer" + +#: shared-module/audioio/Mixer.c:53 shared-module/audioio/WaveFile.c:123 +msgid "Couldn't allocate second buffer" +msgstr "Impossibile allocare il secondo buffer" + +#: shared-module/audioio/Mixer.c:82 +msgid "Voice index too high" +msgstr "" + +#: shared-module/audioio/Mixer.c:85 +msgid "The sample's sample rate does not match the mixer's" +msgstr "" + +#: shared-module/audioio/Mixer.c:88 +msgid "The sample's channel count does not match the mixer's" +msgstr "" + +#: shared-module/audioio/Mixer.c:91 +msgid "The sample's bits_per_sample does not match the mixer's" +msgstr "" + +#: shared-module/audioio/Mixer.c:100 +msgid "The sample's signedness does not match the mixer's" +msgstr "" + +#: shared-module/audioio/WaveFile.c:61 +msgid "Invalid wave file" +msgstr "File wave non valido" + +#: shared-module/audioio/WaveFile.c:69 +msgid "Invalid format chunk size" +msgstr "" + +#: shared-module/audioio/WaveFile.c:83 +msgid "Unsupported format" +msgstr "Formato non supportato" + +#: shared-module/audioio/WaveFile.c:99 +msgid "Data chunk must follow fmt chunk" +msgstr "" + +#: shared-module/audioio/WaveFile.c:107 +msgid "Invalid file" +msgstr "File non valido" + +#: shared-module/bitbangio/I2C.c:58 +msgid "Clock stretch too long" +msgstr "" + +#: shared-module/bitbangio/SPI.c:44 +msgid "Clock pin init failed." +msgstr "Inizializzazione del pin di clock fallita." + +#: shared-module/bitbangio/SPI.c:50 +msgid "MOSI pin init failed." +msgstr "inizializzazione del pin MOSI fallita." + +#: shared-module/bitbangio/SPI.c:61 +msgid "MISO pin init failed." +msgstr "inizializzazione del pin MISO fallita." + +#: shared-module/bitbangio/SPI.c:121 +msgid "Cannot write without MOSI pin." +msgstr "Impossibile scrivere senza pin MOSI." + +#: shared-module/bitbangio/SPI.c:176 +msgid "Cannot read without MISO pin." +msgstr "Impossibile leggere senza pin MISO." + +#: shared-module/bitbangio/SPI.c:240 +msgid "Cannot transfer without MOSI and MISO pins." +msgstr "Impossibile trasferire senza i pin MOSI e MISO." + +#: shared-module/displayio/Bitmap.c:49 +msgid "Only bit maps of 8 bit color or less are supported" +msgstr "Sono supportate solo bitmap con colori a 8 bit o meno" + +#: shared-module/displayio/Bitmap.c:69 +msgid "row must be packed and word aligned" +msgstr "la riga deve essere compattata e allineata alla parola" + +#: shared-module/displayio/Group.c:39 +msgid "Group full" +msgstr "Gruppo pieno" + +#: shared-module/displayio/Group.c:48 +msgid "Group empty" +msgstr "Gruppo vuoto" + +#: shared-module/displayio/OnDiskBitmap.c:49 +msgid "Invalid BMP file" +msgstr "File BMP non valido" + +#: shared-module/displayio/OnDiskBitmap.c:59 +#, c-format +msgid "Only Windows format, uncompressed BMP supported %d" +msgstr "Formato solo di Windows, BMP non compresso supportato %d" + +#: shared-module/displayio/OnDiskBitmap.c:64 +#, c-format +msgid "Only true color (24 bpp or higher) BMP supported %x" +msgstr "Solo BMP true color (24 bpp o superiore) sono supportati %x" + +#: shared-module/storage/__init__.c:155 +msgid "Cannot remount '/' when USB is active." +msgstr "Non è possibile rimontare '/' mentre l'USB è attiva." + +#: shared-module/struct/__init__.c:39 +msgid "'S' and 'O' are not supported format types" +msgstr "'S' e 'O' non sono formati supportati" + +#: shared-module/struct/__init__.c:83 +msgid "too many arguments provided with the given format" +msgstr "troppi argomenti forniti con il formato specificato" + +#: shared-module/usb_hid/Device.c:45 +#, c-format +msgid "Buffer incorrect size. Should be %d bytes." +msgstr "Buffer di lunghezza non valida. Dovrebbe essere di %d bytes." + +#: shared-module/usb_hid/Device.c:53 +msgid "USB Busy" +msgstr "USB occupata" + +#: shared-module/usb_hid/Device.c:59 +msgid "USB Error" +msgstr "Errore USB" + +#~ msgid "Invalid Service type" +#~ msgstr "Tipo di servizio non valido" + +#~ msgid "Can not query for the device address." +#~ msgstr "Non è possibile trovare l'indirizzo del dispositivo." + +#~ msgid "Cannot set PPCP parameters." +#~ msgstr "Impossibile impostare i parametri PPCP." + +#~ msgid "Cannot apply GAP parameters." +#~ msgstr "Impossibile applicare i parametri GAP." + +#~ msgid "Can not encode UUID, to check length." +#~ msgstr "Non è possibile codificare l'UUID, lunghezza da controllare." + +#~ msgid "Can encode UUID into the advertisement packet." +#~ msgstr "È possibile codificare l'UUID nel pacchetto di advertisement." + +#~ msgid "Can not apply device name in the stack." +#~ msgstr "Non è possibile inserire il nome del dipositivo nella lista." + +#~ msgid "Can not apply advertisement data. status: 0x%02x" +#~ msgstr "Impossible inserire dati advertisement. status: 0x%02x" + +#~ msgid "Can not add Service." +#~ msgstr "Non è possibile aggiungere Service." + +#~ msgid "Can not add Characteristic." +#~ msgstr "Non è possibile aggiungere Characteristic." diff --git a/locale/pt_BR.po b/locale/pt_BR.po new file mode 100644 index 000000000..2400b6a13 --- /dev/null +++ b/locale/pt_BR.po @@ -0,0 +1,2554 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-11-09 16:20-0800\n" +"PO-Revision-Date: 2018-10-02 21:14-0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"Language: pt_BR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: extmod/machine_i2c.c:299 +msgid "invalid I2C peripheral" +msgstr "periférico I2C inválido" + +#: extmod/machine_i2c.c:340 extmod/machine_i2c.c:354 extmod/machine_i2c.c:368 +#: extmod/machine_i2c.c:392 +msgid "I2C operation not supported" +msgstr "I2C operação não suportada" + +#: extmod/machine_mem.c:45 ports/unix/modmachine.c:53 +#, c-format +msgid "address %08x is not aligned to %d bytes" +msgstr "endereço %08x não está alinhado com %d bytes" + +#: extmod/machine_spi.c:57 +msgid "invalid SPI peripheral" +msgstr "periférico SPI inválido" + +#: extmod/machine_spi.c:124 +msgid "buffers must be the same length" +msgstr "buffers devem ser o mesmo tamanho" + +#: extmod/machine_spi.c:207 +msgid "bits must be 8" +msgstr "bits devem ser 8" + +#: extmod/machine_spi.c:210 +msgid "firstbit must be MSB" +msgstr "firstbit devem ser MSB" + +#: extmod/machine_spi.c:215 +msgid "must specify all of sck/mosi/miso" +msgstr "deve especificar todos sck/mosi/miso" + +#: extmod/modframebuf.c:299 +msgid "invalid format" +msgstr "formato inválido" + +#: extmod/modubinascii.c:38 extmod/moduhashlib.c:102 +msgid "a bytes-like object is required" +msgstr "" + +#: extmod/modubinascii.c:90 +msgid "odd-length string" +msgstr "" + +#: extmod/modubinascii.c:101 +msgid "non-hex digit found" +msgstr "" + +#: extmod/modubinascii.c:169 +msgid "incorrect padding" +msgstr "preenchimento incorreto" + +#: extmod/moductypes.c:122 +msgid "syntax error in uctypes descriptor" +msgstr "" + +#: extmod/moductypes.c:219 +msgid "Cannot unambiguously get sizeof scalar" +msgstr "" + +#: extmod/moductypes.c:397 +msgid "struct: no fields" +msgstr "struct: sem campos" + +#: extmod/moductypes.c:530 +msgid "struct: cannot index" +msgstr "struct: não pode indexar" + +#: extmod/moductypes.c:544 +msgid "struct: index out of range" +msgstr "struct: índice fora do intervalo" + +#: extmod/moduheapq.c:38 +msgid "heap must be a list" +msgstr "heap deve ser uma lista" + +#: extmod/moduheapq.c:86 extmod/modutimeq.c:147 extmod/modutimeq.c:172 +msgid "empty heap" +msgstr "heap vazia" + +#: extmod/modujson.c:281 +msgid "syntax error in JSON" +msgstr "erro de sintaxe no JSON" + +#: extmod/modure.c:161 +msgid "Splitting with sub-captures" +msgstr "" + +#: extmod/modure.c:207 +msgid "Error in regex" +msgstr "Erro no regex" + +#: extmod/modussl_axtls.c:81 +msgid "invalid key" +msgstr "chave inválida" + +#: extmod/modussl_axtls.c:87 +msgid "invalid cert" +msgstr "certificado inválido" + +#: extmod/modutimeq.c:131 +msgid "queue overflow" +msgstr "estouro de fila" + +#: extmod/moduzlib.c:98 +msgid "compression header" +msgstr "" + +#: extmod/uos_dupterm.c:120 +msgid "invalid dupterm index" +msgstr "Índice de dupterm inválido" + +#: extmod/vfs_fat.c:426 py/moduerrno.c:150 +msgid "Read-only filesystem" +msgstr "Sistema de arquivos somente leitura" + +#: extmod/vfs_posix_file.c:48 ports/unix/file.c:50 py/objstringio.c:43 +msgid "I/O operation on closed file" +msgstr "Operação I/O no arquivo fechado" + +#: lib/embed/abort_.c:8 +msgid "abort() called" +msgstr "abort() chamado" + +#: lib/netutils/netutils.c:83 +msgid "invalid arguments" +msgstr "argumentos inválidos" + +#: lib/utils/pyexec.c:97 py/builtinimport.c:251 +msgid "script compilation not supported" +msgstr "compilação de script não suportada" + +#: main.c:154 +msgid " output:\n" +msgstr " saída:\n" + +#: main.c:168 main.c:241 +msgid "" +"Auto-reload is on. Simply save files over USB to run them or enter REPL to " +"disable.\n" +msgstr "" + +#: main.c:170 +msgid "Running in safe mode! Auto-reload is off.\n" +msgstr "Rodando em modo seguro! Atualização automática está desligada.\n" + +#: main.c:172 main.c:243 +msgid "Auto-reload is off.\n" +msgstr "A atualização automática está desligada.\n" + +#: main.c:186 +msgid "Running in safe mode! Not running saved code.\n" +msgstr "Rodando em modo seguro! Não está executando o código salvo.\n" + +#: main.c:202 +msgid "WARNING: Your code filename has two extensions\n" +msgstr "AVISO: Seu arquivo de código tem duas extensões\n" + +#: main.c:250 +msgid "You requested starting safe mode by " +msgstr "Você solicitou o início do modo de segurança" + +#: main.c:253 +msgid "To exit, please reset the board without " +msgstr "Para sair, por favor, reinicie a placa sem " + +#: main.c:260 +msgid "" +"You are running in safe mode which means something really bad happened.\n" +msgstr "" + +#: main.c:262 +msgid "Looks like our core CircuitPython code crashed hard. Whoops!\n" +msgstr "" + +#: main.c:263 +msgid "Please file an issue here with the contents of your CIRCUITPY drive:\n" +msgstr "" + +#: main.c:266 +msgid "" +"The microcontroller's power dipped. Please make sure your power supply " +"provides\n" +msgstr "" + +#: main.c:267 +msgid "" +"enough power for the whole circuit and press reset (after ejecting " +"CIRCUITPY).\n" +msgstr "" + +#: main.c:271 +msgid "Press any key to enter the REPL. Use CTRL-D to reload." +msgstr "" + +#: main.c:429 +msgid "soft reboot\n" +msgstr "" + +#: ports/atmel-samd/audio_dma.c:209 +#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c:361 +msgid "All sync event channels in use" +msgstr "" + +#: ports/atmel-samd/bindings/samd/Clock.c:135 +msgid "calibration is read only" +msgstr "Calibração é somente leitura" + +#: ports/atmel-samd/bindings/samd/Clock.c:137 +msgid "calibration is out of range" +msgstr "Calibração está fora do intervalo" + +#: ports/atmel-samd/board_busses.c:59 ports/nrf/board_busses.c:39 +msgid "No default I2C bus" +msgstr "Nenhum barramento I2C padrão" + +#: ports/atmel-samd/board_busses.c:85 ports/nrf/board_busses.c:64 +msgid "No default SPI bus" +msgstr "Nenhum barramento SPI padrão" + +#: ports/atmel-samd/board_busses.c:112 ports/nrf/board_busses.c:91 +msgid "No default UART bus" +msgstr "Nenhum barramento UART padrão" + +#: ports/atmel-samd/common-hal/analogio/AnalogIn.c:63 +#: ports/nrf/common-hal/analogio/AnalogIn.c:39 +msgid "Pin does not have ADC capabilities" +msgstr "O pino não tem recursos de ADC" + +#: ports/atmel-samd/common-hal/analogio/AnalogOut.c:49 +msgid "No DAC on chip" +msgstr "Nenhum DAC no chip" + +#: ports/atmel-samd/common-hal/analogio/AnalogOut.c:56 +msgid "AnalogOut not supported on given pin" +msgstr "Saída analógica não suportada no pino fornecido" + +#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:147 +#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:150 +msgid "Invalid bit clock pin" +msgstr "Pino de bit clock inválido" + +#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:153 +msgid "Bit clock and word select must share a clock unit" +msgstr "" + +#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:156 +#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c:130 +msgid "Invalid data pin" +msgstr "Pino de dados inválido" + +#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:169 +#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:174 +#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c:145 +#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c:150 +msgid "Serializer in use" +msgstr "Serializer em uso" + +#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:230 +msgid "Clock unit in use" +msgstr "Unidade de Clock em uso" + +#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:240 +#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c:172 +msgid "Unable to find free GCLK" +msgstr "Não é possível encontrar GCLK livre" + +#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:254 +msgid "Too many channels in sample." +msgstr "Muitos canais na amostra." + +#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:305 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:417 +msgid "No DMA channel found" +msgstr "Nenhum canal DMA encontrado" + +#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c:308 +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:419 +msgid "Unable to allocate buffers for signed conversion" +msgstr "Não é possível alocar buffers para conversão assinada" + +#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c:109 +msgid "Invalid clock pin" +msgstr "Pino do Clock inválido" + +#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c:134 +msgid "Only 8 or 16 bit mono with " +msgstr "" + +#: ports/atmel-samd/common-hal/audiobusio/PDMIn.c:167 +msgid "sampling rate out of range" +msgstr "Taxa de amostragem fora do intervalo" + +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:132 +msgid "DAC already in use" +msgstr "DAC em uso" + +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:136 +msgid "Right channel unsupported" +msgstr "Canal direito não suportado" + +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:139 +#: ports/atmel-samd/common-hal/pulseio/PWMOut.c:116 +#: ports/atmel-samd/common-hal/touchio/TouchIn.c:65 +msgid "Invalid pin" +msgstr "Pino inválido" + +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:147 +msgid "Invalid pin for left channel" +msgstr "Pino inválido para canal esquerdo" + +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:151 +msgid "Invalid pin for right channel" +msgstr "Pino inválido para canal direito" + +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:154 +msgid "Cannot output both channels on the same pin" +msgstr "" + +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:243 +#: ports/atmel-samd/common-hal/pulseio/PWMOut.c:189 +#: ports/atmel-samd/common-hal/pulseio/PulseOut.c:110 +#: ports/nrf/common-hal/pulseio/PulseOut.c:107 +msgid "All timers in use" +msgstr "Todos os temporizadores em uso" + +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:285 +msgid "All event channels in use" +msgstr "Todos os canais de eventos em uso" + +#: ports/atmel-samd/common-hal/audioio/AudioOut.c:375 +#, c-format +msgid "Sample rate too high. It must be less than %d" +msgstr "Taxa de amostragem muito alta. Deve ser menor que %d" + +#: ports/atmel-samd/common-hal/busio/I2C.c:71 +msgid "Not enough pins available" +msgstr "Não há pinos suficientes disponíveis" + +#: ports/atmel-samd/common-hal/busio/I2C.c:78 +#: ports/atmel-samd/common-hal/busio/SPI.c:171 +#: ports/atmel-samd/common-hal/busio/UART.c:119 +#: ports/atmel-samd/common-hal/i2cslave/I2CSlave.c:45 +#: ports/nrf/common-hal/busio/I2C.c:82 +msgid "Invalid pins" +msgstr "Pinos inválidos" + +#: ports/atmel-samd/common-hal/busio/I2C.c:101 +msgid "SDA or SCL needs a pull up" +msgstr "SDA ou SCL precisa de um pull up" + +#: ports/atmel-samd/common-hal/busio/I2C.c:121 +msgid "Unsupported baudrate" +msgstr "Taxa de transmissão não suportada" + +#: ports/atmel-samd/common-hal/busio/UART.c:66 +msgid "bytes > 8 bits not supported" +msgstr "bytes > 8 bits não suportado" + +#: ports/atmel-samd/common-hal/busio/UART.c:72 +#: ports/nrf/common-hal/busio/UART.c:82 +msgid "tx and rx cannot both be None" +msgstr "TX e RX não podem ser ambos" + +#: ports/atmel-samd/common-hal/busio/UART.c:145 +#: ports/nrf/common-hal/busio/UART.c:115 +msgid "Failed to allocate RX buffer" +msgstr "Falha ao alocar buffer RX" + +#: ports/atmel-samd/common-hal/busio/UART.c:153 +msgid "Could not initialize UART" +msgstr "Não foi possível inicializar o UART" + +#: ports/atmel-samd/common-hal/busio/UART.c:240 +#: ports/nrf/common-hal/busio/UART.c:149 +msgid "No RX pin" +msgstr "Nenhum pino RX" + +#: ports/atmel-samd/common-hal/busio/UART.c:294 +#: ports/nrf/common-hal/busio/UART.c:195 +msgid "No TX pin" +msgstr "Nenhum pino TX" + +#: ports/atmel-samd/common-hal/digitalio/DigitalInOut.c:170 +#: ports/nrf/common-hal/digitalio/DigitalInOut.c:147 +msgid "Cannot get pull while in output mode" +msgstr "" + +#: ports/atmel-samd/common-hal/microcontroller/__init__.c:74 +#: ports/esp8266/common-hal/microcontroller/__init__.c:64 +msgid "Cannot reset into bootloader because no bootloader is present." +msgstr "" + +#: ports/atmel-samd/common-hal/pulseio/PWMOut.c:120 +#: ports/atmel-samd/common-hal/pulseio/PWMOut.c:369 +#: ports/nrf/common-hal/pulseio/PWMOut.c:119 +#: ports/nrf/common-hal/pulseio/PWMOut.c:233 +msgid "Invalid PWM frequency" +msgstr "Frequência PWM inválida" + +#: ports/atmel-samd/common-hal/pulseio/PWMOut.c:187 +msgid "All timers for this pin are in use" +msgstr "Todos os temporizadores para este pino estão em uso" + +#: ports/atmel-samd/common-hal/pulseio/PulseIn.c:110 +msgid "No hardware support on pin" +msgstr "Nenhum suporte de hardware no pino" + +#: ports/atmel-samd/common-hal/pulseio/PulseIn.c:113 +msgid "EXTINT channel already in use" +msgstr "Canal EXTINT em uso" + +#: ports/atmel-samd/common-hal/pulseio/PulseIn.c:118 +#: ports/esp8266/common-hal/pulseio/PulseIn.c:86 +#, c-format +msgid "Failed to allocate RX buffer of %d bytes" +msgstr "Falha ao alocar buffer RX de %d bytes" + +#: ports/atmel-samd/common-hal/pulseio/PulseIn.c:205 +#: ports/esp8266/common-hal/pulseio/PulseIn.c:151 +msgid "pop from an empty PulseIn" +msgstr "" + +#: ports/atmel-samd/common-hal/pulseio/PulseIn.c:237 +#: ports/esp8266/common-hal/pulseio/PulseIn.c:182 py/obj.c:420 +msgid "index out of range" +msgstr "Índice fora do intervalo" + +#: ports/atmel-samd/common-hal/pulseio/PulseOut.c:178 +msgid "Another send is already active" +msgstr "Outro envio já está ativo" + +#: ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.c:38 +msgid "Both pins must support hardware interrupts" +msgstr "Ambos os pinos devem suportar interrupções de hardware" + +#: ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.c:46 +msgid "A hardware interrupt channel is already in use" +msgstr "Um canal de interrupção de hardware já está em uso" + +#: ports/atmel-samd/common-hal/rtc/RTC.c:101 +msgid "calibration value out of range +/-127" +msgstr "Valor de calibração fora do intervalo +/- 127" + +#: ports/atmel-samd/common-hal/touchio/TouchIn.c:75 +msgid "No free GCLKs" +msgstr "Não há GCLKs livre" + +#: ports/esp8266/common-hal/analogio/AnalogIn.c:43 +msgid "Pin %q does not have ADC capabilities" +msgstr "Pino %q não tem recursos de ADC" + +#: ports/esp8266/common-hal/analogio/AnalogOut.c:39 +msgid "No hardware support for analog out." +msgstr "Nenhum suporte de hardware para saída analógica." + +#: ports/esp8266/common-hal/busio/SPI.c:72 +msgid "Pins not valid for SPI" +msgstr "Pinos não válidos para SPI" + +#: ports/esp8266/common-hal/busio/UART.c:45 +msgid "Only tx supported on UART1 (GPIO2)." +msgstr "Apenas TX suportado no UART1 (GPIO2)." + +#: ports/esp8266/common-hal/busio/UART.c:67 ports/esp8266/machine_uart.c:108 +msgid "invalid data bits" +msgstr "Bits de dados inválidos" + +#: ports/esp8266/common-hal/busio/UART.c:91 ports/esp8266/machine_uart.c:144 +msgid "invalid stop bits" +msgstr "Bits de parada inválidos" + +#: ports/esp8266/common-hal/digitalio/DigitalInOut.c:200 +msgid "ESP8266 does not support pull down." +msgstr "ESP8266 não suporta pull down." + +#: ports/esp8266/common-hal/digitalio/DigitalInOut.c:210 +msgid "GPIO16 does not support pull up." +msgstr "GPIO16 não suporta pull up." + +#: ports/esp8266/common-hal/microcontroller/__init__.c:66 +msgid "ESP8226 does not support safe mode." +msgstr "O ESP8226 não suporta o modo de segurança." + +#: ports/esp8266/common-hal/pulseio/PWMOut.c:54 +#: ports/esp8266/common-hal/pulseio/PWMOut.c:113 +#, c-format +msgid "Maximum PWM frequency is %dhz." +msgstr "A frequência máxima PWM é de %dhz." + +#: ports/esp8266/common-hal/pulseio/PWMOut.c:57 +#: ports/esp8266/common-hal/pulseio/PWMOut.c:116 +msgid "Minimum PWM frequency is 1hz." +msgstr "A frequência mínima PWM é de 1hz" + +#: ports/esp8266/common-hal/pulseio/PWMOut.c:68 +#, c-format +msgid "Multiple PWM frequencies not supported. PWM already set to %dhz." +msgstr "Múltiplas frequências PWM não suportadas. PWM já definido para %dhz." + +#: ports/esp8266/common-hal/pulseio/PWMOut.c:77 ports/esp8266/machine_pwm.c:70 +#, c-format +msgid "PWM not supported on pin %d" +msgstr "PWM não suportado no pino %d" + +#: ports/esp8266/common-hal/pulseio/PulseIn.c:78 +msgid "No PulseIn support for %q" +msgstr "Não há suporte para PulseIn no pino %q" + +#: ports/esp8266/common-hal/storage/__init__.c:34 +msgid "Unable to remount filesystem" +msgstr "Não é possível remontar o sistema de arquivos" + +#: ports/esp8266/common-hal/storage/__init__.c:38 +msgid "Use esptool to erase flash and re-upload Python instead" +msgstr "Use o esptool para apagar o flash e recarregar o Python" + +#: ports/esp8266/esp_mphal.c:154 +msgid "C-level assert" +msgstr "" + +#: ports/esp8266/machine_adc.c:57 +#, c-format +msgid "not a valid ADC Channel: %d" +msgstr "não é um canal ADC válido: %d" + +#: ports/esp8266/machine_hspi.c:131 ports/esp8266/machine_hspi.c:137 +msgid "impossible baudrate" +msgstr "taxa de transmissão impossível" + +#: ports/esp8266/machine_pin.c:129 +msgid "expecting a pin" +msgstr "esperando um pino" + +#: ports/esp8266/machine_pin.c:284 +msgid "Pin(16) doesn't support pull" +msgstr "Pino (16) não suporta pull" + +#: ports/esp8266/machine_pin.c:323 +msgid "invalid pin" +msgstr "Pino inválido" + +#: ports/esp8266/machine_pin.c:389 +msgid "pin does not have IRQ capabilities" +msgstr "Pino não tem recursos de IRQ" + +#: ports/esp8266/machine_rtc.c:185 +msgid "buffer too long" +msgstr "buffer muito longo" + +#: ports/esp8266/machine_rtc.c:209 ports/esp8266/machine_rtc.c:223 +#: ports/esp8266/machine_rtc.c:246 +msgid "invalid alarm" +msgstr "Alarme inválido" + +#: ports/esp8266/machine_uart.c:169 +#, c-format +msgid "UART(%d) does not exist" +msgstr "UART(%d) não existe" + +#: ports/esp8266/machine_uart.c:219 +msgid "UART(1) can't read" +msgstr "UART(1) não pode ler" + +#: ports/esp8266/modesp.c:119 +msgid "len must be multiple of 4" +msgstr "len deve ser múltiplo de 4" + +#: ports/esp8266/modesp.c:274 +#, c-format +msgid "memory allocation failed, allocating %u bytes for native code" +msgstr "alocação de memória falhou, alocando %u bytes para código nativo" + +#: ports/esp8266/modesp.c:317 +msgid "flash location must be below 1MByte" +msgstr "o local do flash deve estar abaixo de 1 MByte" + +#: ports/esp8266/modmachine.c:63 +msgid "frequency can only be either 80Mhz or 160MHz" +msgstr "A frequência só pode ser 80Mhz ou 160MHz" + +#: ports/esp8266/modnetwork.c:61 +msgid "AP required" +msgstr "AP requerido" + +#: ports/esp8266/modnetwork.c:61 +msgid "STA required" +msgstr "STA requerido" + +#: ports/esp8266/modnetwork.c:87 +msgid "Cannot update i/f status" +msgstr "Não é possível atualizar o status i/f" + +#: ports/esp8266/modnetwork.c:142 +msgid "Cannot set STA config" +msgstr "Não é possível definir a configuração STA" + +#: ports/esp8266/modnetwork.c:144 +msgid "Cannot connect to AP" +msgstr "Não é possível conectar-se ao AP" + +#: ports/esp8266/modnetwork.c:152 +msgid "Cannot disconnect from AP" +msgstr "Não é possível desconectar do AP" + +#: ports/esp8266/modnetwork.c:173 +msgid "unknown status param" +msgstr "parâmetro de status desconhecido" + +#: ports/esp8266/modnetwork.c:222 +msgid "STA must be active" +msgstr "STA deve estar ativo" + +#: ports/esp8266/modnetwork.c:239 +msgid "scan failed" +msgstr "varredura falhou" + +#: ports/esp8266/modnetwork.c:306 +msgid "wifi_set_ip_info() failed" +msgstr "wifi_set_ip_info() falhou" + +#: ports/esp8266/modnetwork.c:319 +msgid "either pos or kw args are allowed" +msgstr "pos ou kw args são permitidos" + +#: ports/esp8266/modnetwork.c:329 +msgid "can't get STA config" +msgstr "não pode obter a configuração STA" + +#: ports/esp8266/modnetwork.c:331 +msgid "can't get AP config" +msgstr "não pode obter configuração de AP" + +#: ports/esp8266/modnetwork.c:346 +msgid "invalid buffer length" +msgstr "comprimento de buffer inválido" + +#: ports/esp8266/modnetwork.c:405 +msgid "can't set STA config" +msgstr "não é possível definir a configuração STA" + +#: ports/esp8266/modnetwork.c:407 +msgid "can't set AP config" +msgstr "não é possível definir a configuração do AP" + +#: ports/esp8266/modnetwork.c:416 +msgid "can query only one param" +msgstr "pode consultar apenas um parâmetro" + +#: ports/esp8266/modnetwork.c:469 +msgid "unknown config param" +msgstr "parâmetro configuração desconhecido" + +#: ports/nrf/common-hal/analogio/AnalogOut.c:37 +msgid "AnalogOut functionality not supported" +msgstr "Funcionalidade AnalogOut não suportada" + +#: ports/nrf/common-hal/bleio/Adapter.c:41 +#, c-format +msgid "Soft device assert, id: 0x%08lX, pc: 0x%08lX" +msgstr "" + +#: ports/nrf/common-hal/bleio/Adapter.c:125 +#, c-format +msgid "Failed to change softdevice state, error: 0x%08lX" +msgstr "" + +#: ports/nrf/common-hal/bleio/Adapter.c:135 +#, c-format +msgid "Failed to get softdevice state, error: 0x%08lX" +msgstr "" + +#: ports/nrf/common-hal/bleio/Adapter.c:155 +#, c-format +msgid "Failed to get local address, error: 0x%08lX" +msgstr "" + +#: ports/nrf/common-hal/bleio/Characteristic.c:52 +#, fuzzy, c-format +msgid "Failed to write gatts value, status: 0x%08lX" +msgstr "Não é possível gravar o valor do atributo. status: 0x%02x" + +#: ports/nrf/common-hal/bleio/Characteristic.c:76 +#, fuzzy, c-format +msgid "Failed to notify attribute value, status: 0x%08lX" +msgstr "Não é possível gravar o valor do atributo. status: 0x%02x" + +#: ports/nrf/common-hal/bleio/Characteristic.c:91 +#, fuzzy, c-format +msgid "Failed to read attribute value, status: 0x%08lX" +msgstr "Não é possível ler o valor do atributo. status: 0x%02x" + +#: ports/nrf/common-hal/bleio/Characteristic.c:119 +#: ports/nrf/common-hal/bleio/Device.c:272 +#: ports/nrf/common-hal/bleio/Device.c:307 +#, c-format +msgid "Failed to acquire mutex, status: 0x%08lX" +msgstr "" + +#: ports/nrf/common-hal/bleio/Characteristic.c:126 +#, fuzzy, c-format +msgid "Failed to write attribute value, status: 0x%08lX" +msgstr "Não é possível gravar o valor do atributo. status: 0x%02x" + +#: ports/nrf/common-hal/bleio/Characteristic.c:138 +#: ports/nrf/common-hal/bleio/Device.c:284 +#: ports/nrf/common-hal/bleio/Device.c:319 +#: ports/nrf/common-hal/bleio/Device.c:354 +#: ports/nrf/common-hal/bleio/Device.c:391 +#, c-format +msgid "Failed to release mutex, status: 0x%08lX" +msgstr "" + +#: ports/nrf/common-hal/bleio/Device.c:81 +#: ports/nrf/common-hal/bleio/Device.c:114 +#, fuzzy +msgid "Can not fit data into the advertisment packet" +msgstr "Não é possível ajustar dados no pacote de anúncios." + +#: ports/nrf/common-hal/bleio/Device.c:266 +#, c-format +msgid "Failed to discover serivices, status: 0x%08lX" +msgstr "" + +#: ports/nrf/common-hal/bleio/Device.c:403 +#: ports/nrf/common-hal/bleio/Scanner.c:76 +#, c-format +msgid "Failed to continue scanning, status: 0x%0xlX" +msgstr "" + +#: ports/nrf/common-hal/bleio/Device.c:436 +#, c-format +msgid "Failed to connect, status: 0x%08lX" +msgstr "" + +#: ports/nrf/common-hal/bleio/Device.c:513 +#, fuzzy, c-format +msgid "Failed to add service, status: 0x%08lX" +msgstr "Não pode parar propaganda. status: 0x%02x" + +#: ports/nrf/common-hal/bleio/Device.c:531 +#, fuzzy, c-format +msgid "Failed to start advertisment, status: 0x%08lX" +msgstr "Não é possível iniciar o anúncio. status: 0x%02x" + +#: ports/nrf/common-hal/bleio/Device.c:549 +#, fuzzy, c-format +msgid "Failed to stop advertisment, status: 0x%08lX" +msgstr "Não pode parar propaganda. status: 0x%02x" + +#: ports/nrf/common-hal/bleio/Device.c:575 +#: ports/nrf/common-hal/bleio/Scanner.c:103 +#, fuzzy, c-format +msgid "Failed to start scanning, status: 0x%0xlX" +msgstr "Não é possível iniciar o anúncio. status: 0x%02x" + +#: ports/nrf/common-hal/bleio/Device.c:592 +#, fuzzy, c-format +msgid "Failed to create mutex, status: 0x%0xlX" +msgstr "Não é possível ler o valor do atributo. status: 0x%02x" + +#: ports/nrf/common-hal/bleio/Service.c:83 +#, c-format +msgid "Failed to add characteristic, status: 0x%08lX" +msgstr "" + +#: ports/nrf/common-hal/bleio/UUID.c:97 +#, fuzzy, c-format +msgid "Failed to add Vendor Specific UUID, status: 0x%08lX" +msgstr "Não é possível adicionar o UUID de 128 bits específico do fornecedor." + +#: ports/nrf/common-hal/bleio/UUID.c:102 +msgid "Invalid UUID string length" +msgstr "" + +#: ports/nrf/common-hal/bleio/UUID.c:109 +#: shared-bindings/bleio/Characteristic.c:125 +#: shared-bindings/bleio/Service.c:105 +msgid "Invalid UUID parameter" +msgstr "Parâmetro UUID inválido" + +#: ports/nrf/common-hal/busio/I2C.c:96 +msgid "All I2C peripherals are in use" +msgstr "Todos os periféricos I2C estão em uso" + +#: ports/nrf/common-hal/busio/SPI.c:133 +msgid "All SPI peripherals are in use" +msgstr "Todos os periféricos SPI estão em uso" + +#: ports/nrf/common-hal/busio/UART.c:48 +#, c-format +msgid "error = 0x%08lX" +msgstr "erro = 0x%08lX" + +#: ports/nrf/common-hal/busio/UART.c:86 +#, fuzzy +msgid "Invalid buffer size" +msgstr "Arquivo inválido" + +#: ports/nrf/common-hal/busio/UART.c:90 +#, fuzzy +msgid "Odd parity is not supported" +msgstr "I2C operação não suportada" + +#: ports/nrf/common-hal/busio/UART.c:322 ports/nrf/common-hal/busio/UART.c:326 +#: ports/nrf/common-hal/busio/UART.c:331 ports/nrf/common-hal/busio/UART.c:336 +#: ports/nrf/common-hal/busio/UART.c:342 ports/nrf/common-hal/busio/UART.c:347 +#: ports/nrf/common-hal/busio/UART.c:352 ports/nrf/common-hal/busio/UART.c:356 +#: ports/nrf/common-hal/busio/UART.c:364 +msgid "busio.UART not available" +msgstr "busio.UART não disponível" + +#: ports/nrf/common-hal/microcontroller/Processor.c:49 +#, c-format +msgid "Can not get temperature. status: 0x%02x" +msgstr "Não pode obter a temperatura. status: 0x%02x" + +#: ports/nrf/common-hal/pulseio/PWMOut.c:161 +#, fuzzy +msgid "All PWM peripherals are in use" +msgstr "Todos os temporizadores em uso" + +#: ports/unix/modffi.c:138 +msgid "Unknown type" +msgstr "Tipo desconhecido" + +#: ports/unix/modffi.c:207 ports/unix/modffi.c:265 +msgid "Error in ffi_prep_cif" +msgstr "Erro no ffi_prep_cif" + +#: ports/unix/modffi.c:270 +msgid "ffi_prep_closure_loc" +msgstr "ffi_prep_closure_loc" + +#: ports/unix/modffi.c:413 +msgid "Don't know how to pass object to native function" +msgstr "Não sabe como passar o objeto para a função nativa" + +#: ports/unix/modusocket.c:474 +#, c-format +msgid "[addrinfo error %d]" +msgstr "" + +#: py/argcheck.c:44 +msgid "function does not take keyword arguments" +msgstr "função não aceita argumentos de palavras-chave" + +#: py/argcheck.c:54 py/bc.c:85 py/objnamedtuple.c:104 +#, c-format +msgid "function takes %d positional arguments but %d were given" +msgstr "função leva %d argumentos posicionais, mas apenas %d foram passadas" + +#: py/argcheck.c:64 +#, c-format +msgid "function missing %d required positional arguments" +msgstr "função ausente %d requer argumentos posicionais" + +#: py/argcheck.c:72 +#, c-format +msgid "function expected at most %d arguments, got %d" +msgstr "função esperada na maioria dos %d argumentos, obteve %d" + +#: py/argcheck.c:97 +msgid "'%q' argument required" +msgstr "'%q' argumento(s) requerido(s)" + +#: py/argcheck.c:122 +msgid "extra positional arguments given" +msgstr "argumentos extra posicionais passados" + +#: py/argcheck.c:130 +msgid "extra keyword arguments given" +msgstr "argumentos extras de palavras-chave passados" + +#: py/argcheck.c:142 +msgid "argument num/types mismatch" +msgstr "" + +#: py/argcheck.c:147 +msgid "keyword argument(s) not yet implemented - use normal args instead" +msgstr "" + +#: py/bc.c:88 py/objnamedtuple.c:108 +msgid "%q() takes %d positional arguments but %d were given" +msgstr "" + +#: py/bc.c:197 py/bc.c:215 +msgid "unexpected keyword argument" +msgstr "" + +#: py/bc.c:199 +msgid "keywords must be strings" +msgstr "" + +#: py/bc.c:206 py/objnamedtuple.c:138 +msgid "function got multiple values for argument '%q'" +msgstr "" + +#: py/bc.c:218 py/objnamedtuple.c:130 +msgid "unexpected keyword argument '%q'" +msgstr "" + +#: py/bc.c:244 +#, c-format +msgid "function missing required positional argument #%d" +msgstr "" + +#: py/bc.c:260 +msgid "function missing required keyword argument '%q'" +msgstr "" + +#: py/bc.c:269 +msgid "function missing keyword-only argument" +msgstr "" + +#: py/binary.c:112 +msgid "bad typecode" +msgstr "" + +#: py/builtinevex.c:99 +msgid "bad compile mode" +msgstr "" + +#: py/builtinhelp.c:137 +#, fuzzy +msgid "Plus any modules on the filesystem\n" +msgstr "Não é possível remontar o sistema de arquivos" + +#: py/builtinhelp.c:183 +#, c-format +msgid "" +"Welcome to Adafruit CircuitPython %s!\n" +"\n" +"Please visit learn.adafruit.com/category/circuitpython for project guides.\n" +"\n" +"To list built-in modules please do `help(\"modules\")`.\n" +msgstr "" + +#: py/builtinimport.c:336 +msgid "cannot perform relative import" +msgstr "" + +#: py/builtinimport.c:420 py/builtinimport.c:532 +msgid "module not found" +msgstr "" + +#: py/builtinimport.c:423 py/builtinimport.c:535 +msgid "no module named '%q'" +msgstr "" + +#: py/builtinimport.c:510 +msgid "relative import" +msgstr "" + +#: py/compile.c:397 py/compile.c:542 +msgid "can't assign to expression" +msgstr "" + +#: py/compile.c:416 +msgid "multiple *x in assignment" +msgstr "" + +#: py/compile.c:642 +msgid "non-default argument follows default argument" +msgstr "" + +#: py/compile.c:771 py/compile.c:789 +msgid "invalid micropython decorator" +msgstr "" + +#: py/compile.c:943 +msgid "can't delete expression" +msgstr "" + +#: py/compile.c:955 +msgid "'break' outside loop" +msgstr "" + +#: py/compile.c:958 +msgid "'continue' outside loop" +msgstr "" + +#: py/compile.c:969 +msgid "'return' outside function" +msgstr "" + +#: py/compile.c:1169 +msgid "identifier redefined as global" +msgstr "" + +#: py/compile.c:1185 +msgid "no binding for nonlocal found" +msgstr "" + +#: py/compile.c:1188 +msgid "identifier redefined as nonlocal" +msgstr "" + +#: py/compile.c:1197 +msgid "can't declare nonlocal in outer code" +msgstr "" + +#: py/compile.c:1542 +msgid "default 'except' must be last" +msgstr "" + +#: py/compile.c:2095 +msgid "*x must be assignment target" +msgstr "" + +#: py/compile.c:2193 +msgid "super() can't find self" +msgstr "" + +#: py/compile.c:2256 +msgid "can't have multiple *x" +msgstr "" + +#: py/compile.c:2263 +msgid "can't have multiple **x" +msgstr "" + +#: py/compile.c:2271 +msgid "LHS of keyword arg must be an id" +msgstr "" + +#: py/compile.c:2287 +msgid "non-keyword arg after */**" +msgstr "" + +#: py/compile.c:2291 +msgid "non-keyword arg after keyword arg" +msgstr "" + +#: py/compile.c:2463 py/compile.c:2473 py/compile.c:2712 py/compile.c:2742 +#: py/parse.c:1176 +msgid "invalid syntax" +msgstr "" + +#: py/compile.c:2465 +msgid "expecting key:value for dict" +msgstr "" + +#: py/compile.c:2475 +msgid "expecting just a value for set" +msgstr "" + +#: py/compile.c:2600 +msgid "'yield' outside function" +msgstr "" + +#: py/compile.c:2619 +msgid "'await' outside function" +msgstr "" + +#: py/compile.c:2774 +msgid "name reused for argument" +msgstr "" + +#: py/compile.c:2827 +msgid "parameter annotation must be an identifier" +msgstr "" + +#: py/compile.c:2969 py/compile.c:3137 +msgid "return annotation must be an identifier" +msgstr "" + +#: py/compile.c:3097 +msgid "inline assembler must be a function" +msgstr "" + +#: py/compile.c:3134 +msgid "unknown type" +msgstr "" + +#: py/compile.c:3154 +msgid "expecting an assembler instruction" +msgstr "" + +#: py/compile.c:3184 +msgid "'label' requires 1 argument" +msgstr "" + +#: py/compile.c:3190 +msgid "label redefined" +msgstr "" + +#: py/compile.c:3196 +msgid "'align' requires 1 argument" +msgstr "" + +#: py/compile.c:3205 +msgid "'data' requires at least 2 arguments" +msgstr "" + +#: py/compile.c:3212 +msgid "'data' requires integer arguments" +msgstr "" + +#: py/emitinlinethumb.c:102 +msgid "can only have up to 4 parameters to Thumb assembly" +msgstr "" + +#: py/emitinlinethumb.c:107 py/emitinlinethumb.c:112 +msgid "parameters must be registers in sequence r0 to r3" +msgstr "" + +#: py/emitinlinethumb.c:188 py/emitinlinethumb.c:230 +#, c-format +msgid "'%s' expects at most r%d" +msgstr "" + +#: py/emitinlinethumb.c:197 py/emitinlinextensa.c:162 +#, c-format +msgid "'%s' expects a register" +msgstr "" + +#: py/emitinlinethumb.c:211 +#, c-format +msgid "'%s' expects a special register" +msgstr "" + +#: py/emitinlinethumb.c:239 +#, c-format +msgid "'%s' expects an FPU register" +msgstr "" + +#: py/emitinlinethumb.c:292 +#, c-format +msgid "'%s' expects {r0, r1, ...}" +msgstr "" + +#: py/emitinlinethumb.c:299 py/emitinlinextensa.c:169 +#, c-format +msgid "'%s' expects an integer" +msgstr "" + +#: py/emitinlinethumb.c:304 +#, c-format +msgid "'%s' integer 0x%x does not fit in mask 0x%x" +msgstr "" + +#: py/emitinlinethumb.c:328 +#, c-format +msgid "'%s' expects an address of the form [a, b]" +msgstr "" + +#: py/emitinlinethumb.c:334 py/emitinlinextensa.c:182 +#, c-format +msgid "'%s' expects a label" +msgstr "" + +#: py/emitinlinethumb.c:345 py/emitinlinextensa.c:193 +msgid "label '%q' not defined" +msgstr "" + +#: py/emitinlinethumb.c:806 +#, c-format +msgid "unsupported Thumb instruction '%s' with %d arguments" +msgstr "" + +#: py/emitinlinethumb.c:810 +#, fuzzy +msgid "branch not in range" +msgstr "Calibração está fora do intervalo" + +#: py/emitinlinextensa.c:86 +msgid "can only have up to 4 parameters to Xtensa assembly" +msgstr "" + +#: py/emitinlinextensa.c:91 py/emitinlinextensa.c:96 +msgid "parameters must be registers in sequence a2 to a5" +msgstr "" + +#: py/emitinlinextensa.c:174 +#, c-format +msgid "'%s' integer %d is not within range %d..%d" +msgstr "" + +#: py/emitinlinextensa.c:327 +#, c-format +msgid "unsupported Xtensa instruction '%s' with %d arguments" +msgstr "" + +#: py/emitnative.c:183 +msgid "unknown type '%q'" +msgstr "" + +#: py/emitnative.c:260 +msgid "Viper functions don't currently support more than 4 arguments" +msgstr "" + +#: py/emitnative.c:742 +msgid "conversion to object" +msgstr "" + +#: py/emitnative.c:921 +msgid "local '%q' used before type known" +msgstr "" + +#: py/emitnative.c:1118 py/emitnative.c:1156 +msgid "can't load from '%q'" +msgstr "" + +#: py/emitnative.c:1128 +msgid "can't load with '%q' index" +msgstr "" + +#: py/emitnative.c:1188 +msgid "local '%q' has type '%q' but source is '%q'" +msgstr "" + +#: py/emitnative.c:1289 py/emitnative.c:1379 +msgid "can't store '%q'" +msgstr "" + +#: py/emitnative.c:1358 py/emitnative.c:1419 +msgid "can't store to '%q'" +msgstr "" + +#: py/emitnative.c:1369 +msgid "can't store with '%q' index" +msgstr "" + +#: py/emitnative.c:1540 +msgid "can't implicitly convert '%q' to 'bool'" +msgstr "" + +#: py/emitnative.c:1774 +msgid "unary op %q not implemented" +msgstr "" + +#: py/emitnative.c:1930 +msgid "binary op %q not implemented" +msgstr "" + +#: py/emitnative.c:1951 +msgid "can't do binary op between '%q' and '%q'" +msgstr "" + +#: py/emitnative.c:2126 +msgid "casting" +msgstr "" + +#: py/emitnative.c:2173 +msgid "return expected '%q' but got '%q'" +msgstr "" + +#: py/emitnative.c:2191 +msgid "must raise an object" +msgstr "" + +#: py/emitnative.c:2201 +msgid "native yield" +msgstr "" + +#: py/lexer.c:345 +msgid "unicode name escapes" +msgstr "" + +#: py/modbuiltins.c:162 +msgid "chr() arg not in range(0x110000)" +msgstr "" + +#: py/modbuiltins.c:171 +msgid "chr() arg not in range(256)" +msgstr "" + +#: py/modbuiltins.c:285 +msgid "arg is an empty sequence" +msgstr "" + +#: py/modbuiltins.c:350 +msgid "ord expects a character" +msgstr "" + +#: py/modbuiltins.c:353 +#, c-format +msgid "ord() expected a character, but string of length %d found" +msgstr "" + +#: py/modbuiltins.c:363 +msgid "3-arg pow() not supported" +msgstr "" + +#: py/modbuiltins.c:517 +msgid "must use keyword argument for key function" +msgstr "" + +#: py/modmath.c:41 shared-bindings/math/__init__.c:53 +msgid "math domain error" +msgstr "" + +#: py/modmath.c:196 py/objfloat.c:270 py/objint_longlong.c:222 +#: py/objint_mpz.c:230 py/runtime.c:619 shared-bindings/math/__init__.c:346 +msgid "division by zero" +msgstr "divisão por zero" + +#: py/modmicropython.c:155 +msgid "schedule stack full" +msgstr "" + +#: py/modstruct.c:145 py/modstruct.c:153 py/modstruct.c:234 py/modstruct.c:244 +#: shared-bindings/struct/__init__.c:103 shared-bindings/struct/__init__.c:145 +#: shared-module/struct/__init__.c:91 shared-module/struct/__init__.c:175 +msgid "buffer too small" +msgstr "" + +#: py/modthread.c:240 +msgid "expecting a dict for keyword args" +msgstr "" + +#: py/moduerrno.c:143 py/moduerrno.c:146 +msgid "Permission denied" +msgstr "Permissão negada" + +#: py/moduerrno.c:144 +msgid "No such file/directory" +msgstr "" + +#: py/moduerrno.c:145 +msgid "Input/output error" +msgstr "" + +#: py/moduerrno.c:147 +msgid "File exists" +msgstr "Arquivo já existe" + +#: py/moduerrno.c:148 +msgid "Unsupported operation" +msgstr "" + +#: py/moduerrno.c:149 +msgid "Invalid argument" +msgstr "Argumento inválido" + +#: py/obj.c:90 +msgid "Traceback (most recent call last):\n" +msgstr "" + +#: py/obj.c:94 +msgid " File \"%q\", line %d" +msgstr " Arquivo \"%q\", linha %d" + +#: py/obj.c:96 +msgid " File \"%q\"" +msgstr " Arquivo \"%q\"" + +#: py/obj.c:100 +msgid ", in %q\n" +msgstr "" + +#: py/obj.c:257 +msgid "can't convert to int" +msgstr "" + +#: py/obj.c:260 +#, c-format +msgid "can't convert %s to int" +msgstr "" + +#: py/obj.c:320 +msgid "can't convert to float" +msgstr "" + +#: py/obj.c:323 +#, c-format +msgid "can't convert %s to float" +msgstr "" + +#: py/obj.c:353 +msgid "can't convert to complex" +msgstr "" + +#: py/obj.c:356 +#, c-format +msgid "can't convert %s to complex" +msgstr "" + +#: py/obj.c:371 +msgid "expected tuple/list" +msgstr "" + +#: py/obj.c:374 +#, c-format +msgid "object '%s' is not a tuple or list" +msgstr "" + +#: py/obj.c:385 +msgid "tuple/list has wrong length" +msgstr "" + +#: py/obj.c:387 +#, c-format +msgid "requested length %d but object has length %d" +msgstr "" + +#: py/obj.c:400 +msgid "indices must be integers" +msgstr "" + +#: py/obj.c:403 +msgid "%q indices must be integers, not %s" +msgstr "" + +#: py/obj.c:423 +msgid "%q index out of range" +msgstr "" + +#: py/obj.c:455 +msgid "object has no len" +msgstr "" + +#: py/obj.c:458 +#, c-format +msgid "object of type '%s' has no len()" +msgstr "" + +#: py/obj.c:496 +msgid "object does not support item deletion" +msgstr "" + +#: py/obj.c:499 +#, c-format +msgid "'%s' object does not support item deletion" +msgstr "" + +#: py/obj.c:503 +msgid "object is not subscriptable" +msgstr "" + +#: py/obj.c:506 +#, c-format +msgid "'%s' object is not subscriptable" +msgstr "" + +#: py/obj.c:510 +msgid "object does not support item assignment" +msgstr "" + +#: py/obj.c:513 +#, c-format +msgid "'%s' object does not support item assignment" +msgstr "" + +#: py/obj.c:544 +msgid "object with buffer protocol required" +msgstr "" + +#: py/objarray.c:413 py/objstr.c:427 py/objstrunicode.c:191 py/objtuple.c:187 +#: shared-bindings/nvm/ByteArray.c:85 +msgid "only slices with step=1 (aka None) are supported" +msgstr "" + +#: py/objarray.c:426 +msgid "lhs and rhs should be compatible" +msgstr "" + +#: py/objarray.c:444 shared-bindings/nvm/ByteArray.c:107 +msgid "array/bytes required on right side" +msgstr "" + +#: py/objcomplex.c:203 +msgid "can't do truncated division of a complex number" +msgstr "" + +#: py/objcomplex.c:209 +msgid "complex division by zero" +msgstr "" + +#: py/objcomplex.c:237 +msgid "0.0 to a complex power" +msgstr "" + +#: py/objdeque.c:107 +msgid "full" +msgstr "cheio" + +#: py/objdeque.c:127 +msgid "empty" +msgstr "vazio" + +#: py/objdict.c:314 +msgid "popitem(): dictionary is empty" +msgstr "" + +#: py/objdict.c:357 +msgid "dict update sequence has wrong length" +msgstr "" + +#: py/objfloat.c:308 py/parsenum.c:331 +msgid "complex values not supported" +msgstr "" + +#: py/objgenerator.c:108 +msgid "can't send non-None value to a just-started generator" +msgstr "" + +#: py/objgenerator.c:126 +msgid "generator already executing" +msgstr "" + +#: py/objgenerator.c:229 +msgid "generator ignored GeneratorExit" +msgstr "" + +#: py/objgenerator.c:251 +msgid "can't pend throw to just-started generator" +msgstr "" + +#: py/objint.c:144 +msgid "can't convert inf to int" +msgstr "" + +#: py/objint.c:146 +msgid "can't convert NaN to int" +msgstr "" + +#: py/objint.c:163 +msgid "float too big" +msgstr "float muito grande" + +#: py/objint.c:328 +msgid "long int not supported in this build" +msgstr "" + +#: py/objint.c:334 py/objint.c:340 py/objint.c:350 py/objint.c:358 +msgid "small int overflow" +msgstr "" + +#: py/objint_longlong.c:189 py/objint_mpz.c:283 py/runtime.c:486 +msgid "negative power with no float support" +msgstr "" + +#: py/objint_longlong.c:251 +msgid "ulonglong too large" +msgstr "" + +#: py/objint_mpz.c:267 py/runtime.c:396 py/runtime.c:411 +msgid "negative shift count" +msgstr "" + +#: py/objint_mpz.c:336 +msgid "pow() with 3 arguments requires integers" +msgstr "" + +#: py/objint_mpz.c:347 +msgid "pow() 3rd argument cannot be 0" +msgstr "" + +#: py/objint_mpz.c:415 +msgid "overflow converting long int to machine word" +msgstr "" + +#: py/objlist.c:273 +msgid "pop from empty list" +msgstr "" + +#: py/objnamedtuple.c:92 +msgid "can't set attribute" +msgstr "" + +#: py/objobject.c:55 +msgid "__new__ arg must be a user-type" +msgstr "" + +#: py/objrange.c:110 +msgid "zero step" +msgstr "passo zero" + +#: py/objset.c:371 +msgid "pop from an empty set" +msgstr "" + +#: py/objslice.c:66 +msgid "Length must be an int" +msgstr "Tamanho deve ser um int" + +#: py/objslice.c:71 +msgid "Length must be non-negative" +msgstr "" + +#: py/objslice.c:86 py/sequence.c:57 +msgid "slice step cannot be zero" +msgstr "" + +#: py/objslice.c:159 +msgid "Cannot subclass slice" +msgstr "" + +#: py/objstr.c:261 +msgid "bytes value out of range" +msgstr "" + +#: py/objstr.c:270 +msgid "wrong number of arguments" +msgstr "" + +#: py/objstr.c:467 +msgid "join expects a list of str/bytes objects consistent with self object" +msgstr "" + +#: py/objstr.c:542 py/objstr.c:647 py/objstr.c:1744 +msgid "empty separator" +msgstr "" + +#: py/objstr.c:641 +msgid "rsplit(None,n)" +msgstr "" + +#: py/objstr.c:713 +msgid "substring not found" +msgstr "" + +#: py/objstr.c:770 +msgid "start/end indices" +msgstr "" + +#: py/objstr.c:931 +msgid "bad format string" +msgstr "" + +#: py/objstr.c:953 +msgid "single '}' encountered in format string" +msgstr "" + +#: py/objstr.c:992 +msgid "bad conversion specifier" +msgstr "" + +#: py/objstr.c:996 +msgid "end of format while looking for conversion specifier" +msgstr "" + +#: py/objstr.c:998 +#, c-format +msgid "unknown conversion specifier %c" +msgstr "" + +#: py/objstr.c:1029 +msgid "unmatched '{' in format" +msgstr "" + +#: py/objstr.c:1036 +msgid "expected ':' after format specifier" +msgstr "" + +#: py/objstr.c:1050 +msgid "" +"can't switch from automatic field numbering to manual field specification" +msgstr "" + +#: py/objstr.c:1055 py/objstr.c:1083 +msgid "tuple index out of range" +msgstr "" + +#: py/objstr.c:1071 +msgid "attributes not supported yet" +msgstr "atributos ainda não suportados" + +#: py/objstr.c:1079 +msgid "" +"can't switch from manual field specification to automatic field numbering" +msgstr "" + +#: py/objstr.c:1171 +msgid "invalid format specifier" +msgstr "" + +#: py/objstr.c:1192 +msgid "sign not allowed in string format specifier" +msgstr "" + +#: py/objstr.c:1200 +msgid "sign not allowed with integer format specifier 'c'" +msgstr "" + +#: py/objstr.c:1259 +#, c-format +msgid "unknown format code '%c' for object of type '%s'" +msgstr "" + +#: py/objstr.c:1331 +#, c-format +msgid "unknown format code '%c' for object of type 'float'" +msgstr "" + +#: py/objstr.c:1343 +msgid "'=' alignment not allowed in string format specifier" +msgstr "" + +#: py/objstr.c:1367 +#, c-format +msgid "unknown format code '%c' for object of type 'str'" +msgstr "" + +#: py/objstr.c:1415 +msgid "format requires a dict" +msgstr "" + +#: py/objstr.c:1424 +msgid "incomplete format key" +msgstr "" + +#: py/objstr.c:1482 +msgid "incomplete format" +msgstr "formato incompleto" + +#: py/objstr.c:1490 +msgid "not enough arguments for format string" +msgstr "" + +#: py/objstr.c:1500 +#, c-format +msgid "%%c requires int or char" +msgstr "%%c requer int ou char" + +#: py/objstr.c:1507 +msgid "integer required" +msgstr "inteiro requerido" + +#: py/objstr.c:1570 +#, c-format +msgid "unsupported format character '%c' (0x%x) at index %d" +msgstr "" + +#: py/objstr.c:1577 +msgid "not all arguments converted during string formatting" +msgstr "" + +#: py/objstr.c:2102 +msgid "can't convert to str implicitly" +msgstr "" + +#: py/objstr.c:2106 +msgid "can't convert '%q' object to %q implicitly" +msgstr "" + +#: py/objstrunicode.c:134 +#, c-format +msgid "string indices must be integers, not %s" +msgstr "" + +#: py/objstrunicode.c:145 py/objstrunicode.c:164 +msgid "string index out of range" +msgstr "" + +#: py/objtype.c:358 +msgid "__init__() should return None" +msgstr "" + +#: py/objtype.c:360 +#, c-format +msgid "__init__() should return None, not '%s'" +msgstr "" + +#: py/objtype.c:623 py/objtype.c:1275 py/runtime.c:1065 +msgid "unreadable attribute" +msgstr "atributo ilegível" + +#: py/objtype.c:868 py/runtime.c:653 +msgid "object not callable" +msgstr "" + +#: py/objtype.c:870 py/runtime.c:655 +#, c-format +msgid "'%s' object is not callable" +msgstr "" + +#: py/objtype.c:978 +msgid "type takes 1 or 3 arguments" +msgstr "" + +#: py/objtype.c:989 +msgid "cannot create instance" +msgstr "não é possível criar instância" + +#: py/objtype.c:991 +msgid "cannot create '%q' instances" +msgstr "" + +#: py/objtype.c:1047 +msgid "can't add special method to already-subclassed class" +msgstr "" + +#: py/objtype.c:1091 py/objtype.c:1097 +msgid "type is not an acceptable base type" +msgstr "" + +#: py/objtype.c:1100 +msgid "type '%q' is not an acceptable base type" +msgstr "" + +#: py/objtype.c:1137 +msgid "multiple inheritance not supported" +msgstr "" + +#: py/objtype.c:1164 +msgid "multiple bases have instance lay-out conflict" +msgstr "" + +#: py/objtype.c:1205 +msgid "first argument to super() must be type" +msgstr "" + +#: py/objtype.c:1370 +msgid "issubclass() arg 2 must be a class or a tuple of classes" +msgstr "" + +#: py/objtype.c:1384 +msgid "issubclass() arg 1 must be a class" +msgstr "" + +#: py/parse.c:726 +msgid "constant must be an integer" +msgstr "constante deve ser um inteiro" + +#: py/parse.c:868 +msgid "Unable to init parser" +msgstr "" + +#: py/parse.c:1170 +msgid "unexpected indent" +msgstr "" + +#: py/parse.c:1173 +msgid "unindent does not match any outer indentation level" +msgstr "" + +#: py/parsenum.c:60 +msgid "int() arg 2 must be >= 2 and <= 36" +msgstr "" + +#: py/parsenum.c:151 +msgid "invalid syntax for integer" +msgstr "" + +#: py/parsenum.c:155 +#, c-format +msgid "invalid syntax for integer with base %d" +msgstr "" + +#: py/parsenum.c:339 +msgid "invalid syntax for number" +msgstr "" + +#: py/parsenum.c:342 +msgid "decimal numbers not supported" +msgstr "" + +#: py/persistentcode.c:223 +msgid "" +"Incompatible .mpy file. Please update all .mpy files. See http://adafru.it/" +"mpy-update for more info." +msgstr "" + +#: py/persistentcode.c:326 +msgid "can only save bytecode" +msgstr "" + +#: py/runtime.c:206 +msgid "name not defined" +msgstr "nome não definido" + +#: py/runtime.c:209 +msgid "name '%q' is not defined" +msgstr "" + +#: py/runtime.c:304 py/runtime.c:611 +msgid "unsupported type for operator" +msgstr "" + +#: py/runtime.c:307 +msgid "unsupported type for %q: '%s'" +msgstr "" + +#: py/runtime.c:614 +msgid "unsupported types for %q: '%s', '%s'" +msgstr "" + +#: py/runtime.c:881 py/runtime.c:888 py/runtime.c:945 +msgid "wrong number of values to unpack" +msgstr "" + +#: py/runtime.c:883 py/runtime.c:947 +#, c-format +msgid "need more than %d values to unpack" +msgstr "precisa de mais de %d valores para desempacotar" + +#: py/runtime.c:890 +#, c-format +msgid "too many values to unpack (expected %d)" +msgstr "" + +#: py/runtime.c:984 +msgid "argument has wrong type" +msgstr "argumento tem tipo errado" + +#: py/runtime.c:986 +msgid "argument should be a '%q' not a '%q'" +msgstr "" + +#: py/runtime.c:1123 py/runtime.c:1197 +msgid "no such attribute" +msgstr "" + +#: py/runtime.c:1128 +msgid "type object '%q' has no attribute '%q'" +msgstr "" + +#: py/runtime.c:1132 py/runtime.c:1200 +msgid "'%s' object has no attribute '%q'" +msgstr "" + +#: py/runtime.c:1238 +msgid "object not iterable" +msgstr "objeto não iterável" + +#: py/runtime.c:1241 +#, c-format +msgid "'%s' object is not iterable" +msgstr "" + +#: py/runtime.c:1260 py/runtime.c:1296 +msgid "object not an iterator" +msgstr "" + +#: py/runtime.c:1262 py/runtime.c:1298 +#, c-format +msgid "'%s' object is not an iterator" +msgstr "" + +#: py/runtime.c:1401 +msgid "exceptions must derive from BaseException" +msgstr "" + +#: py/runtime.c:1430 +msgid "cannot import name %q" +msgstr "não pode importar nome %q" + +#: py/runtime.c:1535 +msgid "memory allocation failed, heap is locked" +msgstr "" + +#: py/runtime.c:1539 +#, c-format +msgid "memory allocation failed, allocating %u bytes" +msgstr "" + +#: py/runtime.c:1609 +msgid "maximum recursion depth exceeded" +msgstr "" + +#: py/sequence.c:264 +msgid "object not in sequence" +msgstr "objeto não em seqüência" + +#: py/stream.c:96 +msgid "stream operation not supported" +msgstr "" + +#: py/vm.c:255 +msgid "local variable referenced before assignment" +msgstr "" + +#: py/vm.c:1142 +msgid "no active exception to reraise" +msgstr "" + +#: py/vm.c:1284 +msgid "byte code not implemented" +msgstr "" + +#: shared-bindings/_stage/Layer.c:71 +msgid "graphic must be 2048 bytes long" +msgstr "" + +#: shared-bindings/_stage/Layer.c:77 shared-bindings/_stage/Text.c:75 +msgid "palette must be 32 bytes long" +msgstr "" + +#: shared-bindings/_stage/Layer.c:84 +msgid "map buffer too small" +msgstr "" + +#: shared-bindings/_stage/Text.c:69 +msgid "font must be 2048 bytes long" +msgstr "" + +#: shared-bindings/_stage/Text.c:81 +msgid "chars buffer too small" +msgstr "" + +#: shared-bindings/analogio/AnalogOut.c:118 +msgid "AnalogOut is only 16 bits. Value must be less than 65536." +msgstr "" + +#: shared-bindings/audiobusio/I2SOut.c:225 +#: shared-bindings/audioio/AudioOut.c:226 +msgid "Not playing" +msgstr "" + +#: shared-bindings/audiobusio/PDMIn.c:124 +msgid "Bit depth must be multiple of 8." +msgstr "" + +#: shared-bindings/audiobusio/PDMIn.c:128 +msgid "Oversample must be multiple of 8." +msgstr "" + +#: shared-bindings/audiobusio/PDMIn.c:136 +msgid "Microphone startup delay must be in range 0.0 to 1.0" +msgstr "" + +#: shared-bindings/audiobusio/PDMIn.c:193 +msgid "destination_length must be an int >= 0" +msgstr "destination_length deve ser um int >= 0" + +#: shared-bindings/audiobusio/PDMIn.c:199 +msgid "Cannot record to a file" +msgstr "Não é possível gravar em um arquivo" + +#: shared-bindings/audiobusio/PDMIn.c:202 +msgid "Destination capacity is smaller than destination_length." +msgstr "" + +#: shared-bindings/audiobusio/PDMIn.c:206 +msgid "destination buffer must be an array of type 'H' for bit_depth = 16" +msgstr "" + +#: shared-bindings/audiobusio/PDMIn.c:208 +msgid "" +"destination buffer must be a bytearray or array of type 'B' for bit_depth = 8" +msgstr "" + +#: shared-bindings/audioio/Mixer.c:94 +#, fuzzy +msgid "Invalid voice count" +msgstr "certificado inválido" + +#: shared-bindings/audioio/Mixer.c:99 +#, fuzzy +msgid "Invalid channel count" +msgstr "certificado inválido" + +#: shared-bindings/audioio/Mixer.c:103 +msgid "Sample rate must be positive" +msgstr "" + +#: shared-bindings/audioio/Mixer.c:107 +#, fuzzy +msgid "bits_per_sample must be 8 or 16" +msgstr "bits devem ser 8" + +#: shared-bindings/audioio/RawSample.c:98 +msgid "" +"sample_source buffer must be a bytearray or array of type 'h', 'H', 'b' or " +"'B'" +msgstr "" + +#: shared-bindings/audioio/RawSample.c:104 +msgid "buffer must be a bytes-like object" +msgstr "" + +#: shared-bindings/audioio/WaveFile.c:78 +#: shared-bindings/displayio/OnDiskBitmap.c:85 +msgid "file must be a file opened in byte mode" +msgstr "" + +#: shared-bindings/bitbangio/I2C.c:111 shared-bindings/bitbangio/SPI.c:121 +#: shared-bindings/busio/SPI.c:133 +msgid "Function requires lock" +msgstr "" + +#: shared-bindings/bitbangio/I2C.c:195 shared-bindings/busio/I2C.c:210 +msgid "Buffer must be at least length 1" +msgstr "" + +#: shared-bindings/bitbangio/SPI.c:151 shared-bindings/busio/SPI.c:175 +msgid "Invalid polarity" +msgstr "" + +#: shared-bindings/bitbangio/SPI.c:155 shared-bindings/busio/SPI.c:179 +msgid "Invalid phase" +msgstr "Fase Inválida" + +#: shared-bindings/bitbangio/SPI.c:159 shared-bindings/busio/SPI.c:183 +msgid "Invalid number of bits" +msgstr "Número inválido de bits" + +#: shared-bindings/bitbangio/SPI.c:284 shared-bindings/busio/SPI.c:348 +msgid "buffer slices must be of equal length" +msgstr "" + +#: shared-bindings/bleio/Address.c:101 +msgid "Wrong address length" +msgstr "" + +#: shared-bindings/bleio/Address.c:107 +msgid "Wrong number of bytes provided" +msgstr "" + +#: shared-bindings/bleio/Device.c:210 +msgid "Can't add services in Central mode" +msgstr "" + +#: shared-bindings/bleio/Device.c:226 +msgid "Can't connect in Peripheral mode" +msgstr "" + +#: shared-bindings/bleio/Device.c:256 +msgid "Can't change the name in Central mode" +msgstr "" + +#: shared-bindings/bleio/Device.c:277 shared-bindings/bleio/Device.c:313 +msgid "Can't advertise in Central mode" +msgstr "" + +#: shared-bindings/busio/I2C.c:120 +msgid "Function requires lock." +msgstr "" + +#: shared-bindings/busio/UART.c:102 +msgid "bits must be 7, 8 or 9" +msgstr "" + +#: shared-bindings/busio/UART.c:114 +msgid "stop must be 1 or 2" +msgstr "" + +#: shared-bindings/digitalio/DigitalInOut.c:211 +msgid "Invalid direction." +msgstr "Direção inválida" + +#: shared-bindings/digitalio/DigitalInOut.c:240 +msgid "Cannot set value when direction is input." +msgstr "" + +#: shared-bindings/digitalio/DigitalInOut.c:266 +#: shared-bindings/digitalio/DigitalInOut.c:281 +msgid "Drive mode not used when direction is input." +msgstr "" + +#: shared-bindings/digitalio/DigitalInOut.c:314 +#: shared-bindings/digitalio/DigitalInOut.c:331 +msgid "Pull not used when direction is output." +msgstr "" + +#: shared-bindings/digitalio/DigitalInOut.c:340 +msgid "Unsupported pull value." +msgstr "" + +#: shared-bindings/displayio/Bitmap.c:84 +msgid "y should be an int" +msgstr "y deve ser um int" + +#: shared-bindings/displayio/Bitmap.c:89 +msgid "row buffer must be a bytearray or array of type 'b' or 'B'" +msgstr "" + +#: shared-bindings/displayio/Bitmap.c:94 +msgid "row data must be a buffer" +msgstr "" + +#: shared-bindings/displayio/ColorConverter.c:72 +msgid "color should be an int" +msgstr "cor deve ser um int" + +#: shared-bindings/displayio/FourWire.c:55 +#: shared-bindings/displayio/FourWire.c:64 +msgid "displayio is a work in progress" +msgstr "" + +#: shared-bindings/displayio/Group.c:65 +msgid "Group must have size at least 1" +msgstr "Grupo deve ter tamanho pelo menos 1" + +#: shared-bindings/displayio/Palette.c:96 +msgid "color buffer must be a bytearray or array of type 'b' or 'B'" +msgstr "" + +#: shared-bindings/displayio/Palette.c:102 +msgid "color buffer must be 3 bytes (RGB) or 4 bytes (RGB + pad byte)" +msgstr "" + +#: shared-bindings/displayio/Palette.c:106 +msgid "color must be between 0x000000 and 0xffffff" +msgstr "cor deve estar entre 0x000000 e 0xffffff" + +#: shared-bindings/displayio/Palette.c:110 +msgid "color buffer must be a buffer or int" +msgstr "" + +#: shared-bindings/displayio/Palette.c:123 +#: shared-bindings/displayio/Palette.c:137 +msgid "palette_index should be an int" +msgstr "" + +#: shared-bindings/displayio/Sprite.c:48 +msgid "position must be 2-tuple" +msgstr "" + +#: shared-bindings/displayio/Sprite.c:97 +msgid "unsupported bitmap type" +msgstr "" + +#: shared-bindings/displayio/Sprite.c:162 +msgid "pixel_shader must be displayio.Palette or displayio.ColorConverter" +msgstr "" + +#: shared-bindings/gamepad/GamePad.c:100 +msgid "too many arguments" +msgstr "muitos argumentos" + +#: shared-bindings/gamepad/GamePad.c:104 +msgid "expected a DigitalInOut" +msgstr "" + +#: shared-bindings/i2cslave/I2CSlave.c:98 +msgid "can't convert address to int" +msgstr "" + +#: shared-bindings/i2cslave/I2CSlave.c:101 +msgid "address out of bounds" +msgstr "" + +#: shared-bindings/i2cslave/I2CSlave.c:107 +msgid "addresses is empty" +msgstr "" + +#: shared-bindings/microcontroller/Pin.c:89 +#: shared-bindings/neopixel_write/__init__.c:67 +#: shared-bindings/pulseio/PulseOut.c:76 +msgid "Expected a %q" +msgstr "Esperado um" + +#: shared-bindings/microcontroller/Pin.c:100 +msgid "%q in use" +msgstr "%q em uso" + +#: shared-bindings/microcontroller/__init__.c:126 +msgid "Invalid run mode." +msgstr "" + +#: shared-bindings/multiterminal/__init__.c:68 +msgid "Stream missing readinto() or write() method." +msgstr "" + +#: shared-bindings/nvm/ByteArray.c:99 +msgid "Slice and value different lengths." +msgstr "" + +#: shared-bindings/nvm/ByteArray.c:104 +msgid "Array values should be single bytes." +msgstr "" + +#: shared-bindings/nvm/ByteArray.c:111 shared-bindings/nvm/ByteArray.c:141 +msgid "Unable to write to nvm." +msgstr "Não é possível gravar no nvm." + +#: shared-bindings/nvm/ByteArray.c:137 +msgid "Bytes must be between 0 and 255." +msgstr "Os bytes devem estar entre 0 e 255." + +#: shared-bindings/os/__init__.c:200 +msgid "No hardware random available" +msgstr "" + +#: shared-bindings/pulseio/PWMOut.c:164 +msgid "" +"PWM duty_cycle must be between 0 and 65535 inclusive (16 bit resolution)" +msgstr "" + +#: shared-bindings/pulseio/PWMOut.c:195 +msgid "" +"PWM frequency not writable when variable_frequency is False on construction." +msgstr "" + +#: shared-bindings/pulseio/PulseIn.c:275 +msgid "Cannot delete values" +msgstr "Não é possível excluir valores" + +#: shared-bindings/pulseio/PulseIn.c:281 +msgid "Slices not supported" +msgstr "" + +#: shared-bindings/pulseio/PulseIn.c:287 +msgid "index must be int" +msgstr "index deve ser int" + +#: shared-bindings/pulseio/PulseIn.c:293 +msgid "Read-only" +msgstr "Somente leitura" + +#: shared-bindings/pulseio/PulseOut.c:135 +msgid "Array must contain halfwords (type 'H')" +msgstr "Array deve conter meias palavras (tipo 'H')" + +#: shared-bindings/random/__init__.c:92 shared-bindings/random/__init__.c:100 +msgid "stop not reachable from start" +msgstr "" + +#: shared-bindings/random/__init__.c:111 +msgid "step must be non-zero" +msgstr "o passo deve ser diferente de zero" + +#: shared-bindings/random/__init__.c:114 +msgid "invalid step" +msgstr "passo inválido" + +#: shared-bindings/random/__init__.c:146 +msgid "empty sequence" +msgstr "seqüência vazia" + +#: shared-bindings/rtc/RTC.c:40 shared-bindings/rtc/RTC.c:44 +#: shared-bindings/time/__init__.c:190 +msgid "RTC is not supported on this board" +msgstr "O RTC não é suportado nesta placa" + +#: shared-bindings/rtc/RTC.c:52 +msgid "RTC calibration is not supported on this board" +msgstr "A calibração RTC não é suportada nesta placa" + +#: shared-bindings/socket/__init__.c:516 shared-module/network/__init__.c:81 +msgid "no available NIC" +msgstr "" + +#: shared-bindings/storage/__init__.c:77 +msgid "filesystem must provide mount method" +msgstr "sistema de arquivos deve fornecer método de montagem" + +#: shared-bindings/supervisor/__init__.c:93 +msgid "Brightness must be between 0 and 255" +msgstr "O brilho deve estar entre 0 e 255" + +#: shared-bindings/supervisor/__init__.c:119 +msgid "Stack size must be at least 256" +msgstr "O tamanho da pilha deve ser pelo menos 256" + +#: shared-bindings/time/__init__.c:78 +msgid "sleep length must be non-negative" +msgstr "" + +#: shared-bindings/time/__init__.c:88 +msgid "time.struct_time() takes exactly 1 argument" +msgstr "" + +#: shared-bindings/time/__init__.c:91 +msgid "time.struct_time() takes a 9-sequence" +msgstr "" + +#: shared-bindings/time/__init__.c:169 shared-bindings/time/__init__.c:264 +msgid "Tuple or struct_time argument required" +msgstr "Tuple or struct_time argument required" + +#: shared-bindings/time/__init__.c:174 shared-bindings/time/__init__.c:269 +msgid "function takes exactly 9 arguments" +msgstr "função leva exatamente 9 argumentos" + +#: shared-bindings/time/__init__.c:240 shared-bindings/time/__init__.c:273 +msgid "timestamp out of range for platform time_t" +msgstr "timestamp fora do intervalo para a plataforma time_t" + +#: shared-bindings/touchio/TouchIn.c:173 +msgid "threshold must be in the range 0-65536" +msgstr "Limite deve estar no alcance de 0-65536" + +#: shared-bindings/util.c:38 +msgid "" +"Object has been deinitialized and can no longer be used. Create a new object." +msgstr "" +"Objeto foi desinicializado e não pode ser mais usaado. Crie um novo objeto." + +#: shared-module/audioio/Mixer.c:47 shared-module/audioio/WaveFile.c:117 +msgid "Couldn't allocate first buffer" +msgstr "Não pôde alocar primeiro buffer" + +#: shared-module/audioio/Mixer.c:53 shared-module/audioio/WaveFile.c:123 +msgid "Couldn't allocate second buffer" +msgstr "Não pôde alocar segundo buffer" + +#: shared-module/audioio/Mixer.c:82 +msgid "Voice index too high" +msgstr "" + +#: shared-module/audioio/Mixer.c:85 +msgid "The sample's sample rate does not match the mixer's" +msgstr "" + +#: shared-module/audioio/Mixer.c:88 +msgid "The sample's channel count does not match the mixer's" +msgstr "" + +#: shared-module/audioio/Mixer.c:91 +msgid "The sample's bits_per_sample does not match the mixer's" +msgstr "" + +#: shared-module/audioio/Mixer.c:100 +msgid "The sample's signedness does not match the mixer's" +msgstr "" + +#: shared-module/audioio/WaveFile.c:61 +msgid "Invalid wave file" +msgstr "Aqruivo de ondas inválido" + +#: shared-module/audioio/WaveFile.c:69 +msgid "Invalid format chunk size" +msgstr "Tamanho do pedaço de formato inválido" + +#: shared-module/audioio/WaveFile.c:83 +msgid "Unsupported format" +msgstr "Formato não suportado" + +#: shared-module/audioio/WaveFile.c:99 +msgid "Data chunk must follow fmt chunk" +msgstr "Pedaço de dados deve seguir o pedaço de cortes" + +#: shared-module/audioio/WaveFile.c:107 +msgid "Invalid file" +msgstr "Arquivo inválido" + +#: shared-module/bitbangio/I2C.c:58 +msgid "Clock stretch too long" +msgstr "Clock se estendeu por tempo demais" + +#: shared-module/bitbangio/SPI.c:44 +msgid "Clock pin init failed." +msgstr "Inicialização do pino de Clock falhou." + +#: shared-module/bitbangio/SPI.c:50 +msgid "MOSI pin init failed." +msgstr "Inicialização do pino MOSI falhou." + +#: shared-module/bitbangio/SPI.c:61 +msgid "MISO pin init failed." +msgstr "Inicialização do pino MISO falhou" + +#: shared-module/bitbangio/SPI.c:121 +msgid "Cannot write without MOSI pin." +msgstr "Não é possível ler sem um pino MOSI" + +#: shared-module/bitbangio/SPI.c:176 +msgid "Cannot read without MISO pin." +msgstr "Não é possível ler sem o pino MISO." + +#: shared-module/bitbangio/SPI.c:240 +msgid "Cannot transfer without MOSI and MISO pins." +msgstr "Não é possível transferir sem os pinos MOSI e MISO." + +#: shared-module/displayio/Bitmap.c:49 +msgid "Only bit maps of 8 bit color or less are supported" +msgstr "Apenas bit maps de cores de 8 bit ou menos são suportados" + +#: shared-module/displayio/Bitmap.c:69 +msgid "row must be packed and word aligned" +msgstr "Linha deve ser comprimida e com as palavras alinhadas" + +#: shared-module/displayio/Group.c:39 +msgid "Group full" +msgstr "Grupo cheio" + +#: shared-module/displayio/Group.c:48 +msgid "Group empty" +msgstr "Grupo vazio" + +#: shared-module/displayio/OnDiskBitmap.c:49 +msgid "Invalid BMP file" +msgstr "Arquivo BMP inválido" + +#: shared-module/displayio/OnDiskBitmap.c:59 +#, c-format +msgid "Only Windows format, uncompressed BMP supported %d" +msgstr "Apenas formato Windows, BMP descomprimido suportado" + +#: shared-module/displayio/OnDiskBitmap.c:64 +#, c-format +msgid "Only true color (24 bpp or higher) BMP supported %x" +msgstr "Apenas cores verdadeiras (24 bpp ou maior) BMP suportadas" + +#: shared-module/storage/__init__.c:155 +msgid "Cannot remount '/' when USB is active." +msgstr "Não é possível remontar '/' enquanto o USB estiver ativo." + +#: shared-module/struct/__init__.c:39 +msgid "'S' and 'O' are not supported format types" +msgstr "'S' e 'O' não são tipos de formato suportados" + +#: shared-module/struct/__init__.c:83 +msgid "too many arguments provided with the given format" +msgstr "Muitos argumentos fornecidos com o formato dado" + +#: shared-module/usb_hid/Device.c:45 +#, c-format +msgid "Buffer incorrect size. Should be %d bytes." +msgstr "Buffer de tamanho incorreto. Deve ser %d bytes." + +#: shared-module/usb_hid/Device.c:53 +msgid "USB Busy" +msgstr "USB ocupada" + +#: shared-module/usb_hid/Device.c:59 +msgid "USB Error" +msgstr "Erro na USB" + +#~ msgid "Baud rate too high for this SPI peripheral" +#~ msgstr "Taxa de transmissão muito alta para esse periférico SPI" + +#~ msgid "Can not query for the device address." +#~ msgstr "Não é possível consultar o endereço do dispositivo." + +#~ msgid "Cannot set PPCP parameters." +#~ msgstr "Não é possível definir parâmetros PPCP." + +#~ msgid "Cannot apply GAP parameters." +#~ msgstr "Não é possível aplicar parâmetros GAP." + +#~ msgid "Can encode UUID into the advertisement packet." +#~ msgstr "Pode codificar o UUID no pacote de anúncios." + +#~ msgid "Can not apply advertisement data. status: 0x%02x" +#~ msgstr "Não é possível aplicar dados de anúncio. status: 0x%02x" + +#~ msgid "Can not apply device name in the stack." +#~ msgstr "Não é possível aplicar o nome do dispositivo na pilha." + +#~ msgid "Invalid Service type" +#~ msgstr "Tipo de serviço inválido" + +#~ msgid "Can not add Service." +#~ msgstr "Não é possível adicionar o serviço." + +#~ msgid "Can not add Characteristic." +#~ msgstr "Não é possível adicionar Característica." @@ -51,9 +51,14 @@ #include "supervisor/shared/autoreload.h" #include "supervisor/shared/translate.h" #include "supervisor/shared/rgb_led_status.h" +#include "supervisor/shared/status_leds.h" #include "supervisor/shared/stack.h" #include "supervisor/serial.h" +#ifdef MICROPY_PY_NETWORK +#include "shared-module/network/__init__.h" +#endif + void do_str(const char *src, mp_parse_input_kind_t input_kind) { mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0); if (lex == NULL) { @@ -103,15 +108,22 @@ void start_mp(supervisor_allocation* heap) { mp_obj_list_init(mp_sys_path, 0); mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_)); // current dir (or base dir of the script) mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_)); - mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_lib)); // Frozen modules are in their own pseudo-dir, e.g., ".frozen". + // Prioritize .frozen over /lib. mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_FROZEN_FAKE_DIR_QSTR)); + mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_lib)); mp_obj_list_init(mp_sys_argv, 0); + + #if MICROPY_PY_NETWORK + network_module_init(); + #endif } void stop_mp(void) { - + #if MICROPY_PY_NETWORK + network_module_deinit(); + #endif } #define STRING_LIST(...) {__VA_ARGS__, ""} @@ -378,6 +390,8 @@ int __attribute__((used)) main(void) { // initialise the cpu and peripherals safe_mode_t safe_mode = port_init(); + // Turn on LEDs + init_status_leds(); rgb_led_status_init(); stack_init(); diff --git a/ports/atmel-samd/Makefile b/ports/atmel-samd/Makefile index f8e5051c2..99b8842c6 100644 --- a/ports/atmel-samd/Makefile +++ b/ports/atmel-samd/Makefile @@ -45,16 +45,13 @@ INC += -I. \ -Iasf4/$(CHIP_FAMILY)/hpl/tc \ -Iasf4/$(CHIP_FAMILY)/include \ -Iasf4/$(CHIP_FAMILY)/CMSIS/Include \ - -Iasf4/$(CHIP_FAMILY)/usb \ - -Iasf4/$(CHIP_FAMILY)/usb/class/cdc \ - -Iasf4/$(CHIP_FAMILY)/usb/class/hid \ - -Iasf4/$(CHIP_FAMILY)/usb/class/msc \ - -Iasf4/$(CHIP_FAMILY)/usb/device \ -Iasf4_conf/$(CHIP_FAMILY) \ -Iboards/$(BOARD) \ -Iboards/ \ -Iperipherals/ \ -Ifreetouch \ + -I../../lib/tinyusb/src \ + -I../../supervisor/shared/usb \ -I$(BUILD) BASE_CFLAGS = \ @@ -64,7 +61,6 @@ BASE_CFLAGS = \ -Wno-endif-labels \ -Wstrict-prototypes \ -Werror-implicit-function-declaration \ - -Wpointer-arith \ -Wfloat-equal \ -Wundef \ -Wshadow \ @@ -72,7 +68,6 @@ BASE_CFLAGS = \ -Wsign-compare \ -Wmissing-format-attribute \ -Wno-deprecated-declarations \ - -Wpacked \ -Wnested-externs \ -Wunreachable-code \ -Wcast-align \ @@ -90,11 +85,15 @@ BASE_CFLAGS = \ # NDEBUG disables assert() statements. This reduces code size pretty dramatically, per tannewt. ifeq ($(CHIP_FAMILY), samd21) -CFLAGS = -Os -DNDEBUG +CFLAGS += -Os -DNDEBUG +# TinyUSB defines +CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_SAMD21 -DCFG_TUD_CDC_RX_BUFSIZE=128 -DCFG_TUD_CDC_TX_BUFSIZE=128 -DCFG_TUD_MSC_BUFSIZE=512 endif ifeq ($(CHIP_FAMILY), samd51) -CFLAGS = -Os -DNDEBUG +CFLAGS += -Os -DNDEBUG +# TinyUSB defines +CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_SAMD51 -DCFG_TUD_CDC_RX_BUFSIZE=256 -DCFG_TUD_CDC_TX_BUFSIZE=256 -DCFG_TUD_MSC_BUFSIZE=1024 endif #Debugging/Optimization @@ -104,7 +103,7 @@ ifeq ($(DEBUG), 1) # You may want to disable -flto if it interferes with debugging. CFLAGS += -flto # You may want to enable these flags to make setting breakpoints easier. -## CFLAGS += -fno-inline -fno-ipa-sra + # CFLAGS += -fno-inline -fno-ipa-sra ifeq ($(CHIP_FAMILY), samd21) CFLAGS += -DENABLE_MICRO_TRACE_BUFFER endif @@ -123,7 +122,6 @@ endif CFLAGS += $(INC) -Wall -Werror -std=gnu11 -nostdlib $(BASE_CFLAGS) $(CFLAGS_MOD) $(COPT) - ifeq ($(CHIP_FAMILY), samd21) CFLAGS += \ -mthumb \ @@ -205,7 +203,6 @@ SRC_ASF := \ hal/src/hal_spi_m_sync.c \ hal/src/hal_timer.c \ hal/src/hal_usart_async.c \ - hal/src/hal_usb_device.c \ hpl/adc/hpl_adc.c \ hpl/core/hpl_init.c \ hpl/dac/hpl_dac.c \ @@ -215,12 +212,6 @@ SRC_ASF := \ hpl/rtc/hpl_rtc.c \ hpl/sercom/hpl_sercom.c \ hpl/systick/hpl_systick.c \ - hpl/usb/hpl_usb.c \ - usb/class/cdc/device/cdcdf_acm.c \ - usb/class/hid/device/hiddf_generic.c \ - usb/class/msc/device/mscdf.c \ - usb/device/usbdc.c \ - usb/usb_protocol.c \ hal/utils/src/utils_list.c \ hal/utils/src/utils_ringbuffer.c \ @@ -247,7 +238,6 @@ SRC_C = \ board_busses.c \ background.c \ fatfs_port.c \ - flash_api.c \ mphalport.c \ reset.c \ peripherals/samd/clocks.c \ @@ -266,8 +256,6 @@ SRC_C = \ peripherals/samd/$(CHIP_FAMILY)/sercom.c \ peripherals/samd/$(CHIP_FAMILY)/timers.c \ tick.c \ - usb.c \ - usb_mass_storage.c \ bindings/samd/__init__.c \ bindings/samd/Clock.c \ boards/$(BOARD)/board.c \ @@ -275,6 +263,8 @@ SRC_C = \ lib/oofatfs/ff.c \ lib/oofatfs/option/ccsbcs.c \ lib/timeutils/timeutils.c \ + lib/tinyusb/src/portable/microchip/$(CHIP_FAMILY)/dcd_$(CHIP_FAMILY).c \ + lib/tinyusb/src/portable/microchip/$(CHIP_FAMILY)/hal_$(CHIP_FAMILY).c \ lib/utils/buffer_helper.c \ lib/utils/context_manager_helpers.c \ lib/utils/interrupt_char.c \ @@ -283,22 +273,28 @@ SRC_C = \ lib/utils/sys_stdio_mphal.c \ lib/libc/string0.c \ lib/mp-readline/readline.c \ - $(BUILD)/autogen_usb_descriptor.c \ freetouch/adafruit_ptc.c \ supervisor/shared/memory.c -# Choose which flash filesystem impl to use. -# (Right now INTERNAL_FLASH_FILESYSTEM and SPI_FLASH_FILESYSTEM are mutually exclusive. -# But that might not be true in the future.) -ifeq ($(INTERNAL_FLASH_FILESYSTEM),1) -SRC_C += internal_flash.c -endif -ifeq ($(SPI_FLASH_FILESYSTEM),1) -SRC_C += external_flash/external_flash.c external_flash/spi_flash.c -endif -ifeq ($(QSPI_FLASH_FILESYSTEM),1) -SRC_C += external_flash/external_flash.c external_flash/qspi_flash.c -endif +ifeq ($(MICROPY_PY_NETWORK),1) +CFLAGS += -DMICROPY_PY_NETWORK=1 + +SRC_MOD += lib/netutils/netutils.c + +ifneq ($(MICROPY_PY_WIZNET5K),0) +WIZNET5K_DIR=drivers/wiznet5k +INC += -I$(TOP)/$(WIZNET5K_DIR) +CFLAGS_MOD += -DMICROPY_PY_WIZNET5K=$(MICROPY_PY_WIZNET5K) -D_WIZCHIP_=$(MICROPY_PY_WIZNET5K) +SRC_MOD += $(addprefix $(WIZNET5K_DIR)/,\ + ethernet/w$(MICROPY_PY_WIZNET5K)/w$(MICROPY_PY_WIZNET5K).c \ + ethernet/wizchip_conf.c \ + ethernet/socket.c \ + internet/dns/dns.c \ + internet/dhcp/dhcp.c \ + ) + +endif # MICROPY_PY_WIZNET5K +endif # MICROPY_PY_NETWORK SRC_COMMON_HAL = \ board/__init__.c \ @@ -320,7 +316,6 @@ SRC_COMMON_HAL = \ rotaryio/IncrementalEncoder.c \ rtc/__init__.c \ rtc/RTC.c \ - storage/__init__.c \ supervisor/__init__.c \ supervisor/Runtime.c \ time/__init__.c \ @@ -333,10 +328,8 @@ SRC_COMMON_HAL = \ pulseio/PulseIn.c \ pulseio/PulseOut.c \ pulseio/PWMOut.c \ - usb_hid/__init__.c \ - usb_hid/Device.c \ touchio/__init__.c \ - touchio/TouchIn.c \ + touchio/TouchIn.c ifeq ($(INTERNAL_LIBM),1) SRC_LIBM = $(addprefix lib/,\ @@ -362,7 +355,6 @@ SRC_LIBM = $(addprefix lib/,\ ) endif - # These don't have corresponding files in each port but are still located in # shared-bindings to make it clear what the contents of the modules are. SRC_BINDINGS_ENUMS = \ @@ -394,12 +386,24 @@ SRC_SHARED_MODULE = \ _stage/__init__.c \ _stage/Layer.c \ _stage/Text.c \ + storage/__init__.c \ os/__init__.c \ random/__init__.c \ - storage/__init__.c \ struct/__init__.c \ uheap/__init__.c \ - ustack/__init__.c + ustack/__init__.c \ + usb_hid/__init__.c \ + usb_hid/Device.c + + # usb_midi/__init__.c + # usb_midi/Port.c + +ifeq ($(MICROPY_PY_NETWORK),1) +SRC_SHARED_MODULE += socket/__init__.c network/__init__.c +ifneq ($(MICROPY_PY_WIZNET5K),0) +SRC_SHARED_MODULE += wiznet/__init__.c wiznet/wiznet5k.c +endif +endif # SAMRs don't have a DAC ifneq ($(CHIP_VARIANT),SAMR21G18A) @@ -407,6 +411,8 @@ ifneq ($(CHIP_VARIANT),SAMR21G18A) audioio/__init__.c \ audioio/AudioOut.c SRC_SHARED_MODULE += \ + audioio/__init__.c \ + audioio/Mixer.c \ audioio/RawSample.c \ audioio/WaveFile.c endif @@ -441,6 +447,7 @@ ifeq ($(INTERNAL_LIBM),1) OBJ += $(addprefix $(BUILD)/, $(SRC_LIBM:.c=.o)) endif OBJ += $(addprefix $(BUILD)/, $(SRC_S:.s=.o)) +OBJ += $(addprefix $(BUILD)/, $(SRC_MOD:.c=.o)) SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED) $(STM_SRC_C) # Sources that only hold QSTRs after pre-processing. @@ -461,21 +468,6 @@ $(BUILD)/firmware.uf2: $(BUILD)/firmware.bin $(STEPECHO) "Create $@" $(Q)$(PYTHON3) $(TOP)/tools/uf2/utils/uf2conv.py -b $(BOOTLOADER_SIZE) -c -o $@ $^ -$(BUILD)/autogen_usb_descriptor.c $(BUILD)/genhdr/autogen_usb_descriptor.h: autogen_usb_descriptor.intermediate - -.INTERMEDIATE: autogen_usb_descriptor.intermediate - -autogen_usb_descriptor.intermediate: tools/gen_usb_descriptor.py Makefile | $(HEADER_BUILD) - $(STEPECHO) "GEN $@" - $(Q)install -d $(BUILD)/genhdr - $(Q)$(PYTHON3) tools/gen_usb_descriptor.py \ - --manufacturer $(USB_MANUFACTURER)\ - --product $(USB_PRODUCT)\ - --vid $(USB_VID)\ - --pid $(USB_PID)\ - --output_c_file $(BUILD)/autogen_usb_descriptor.c\ - --output_h_file $(BUILD)/genhdr/autogen_usb_descriptor.h - deploy: $(BUILD)/firmware.bin $(ECHO) "Writing $< to the board" $(BOSSAC) -u $< diff --git a/ports/atmel-samd/audio_dma.c b/ports/atmel-samd/audio_dma.c index 45d698c17..68d6f182d 100644 --- a/ports/atmel-samd/audio_dma.c +++ b/ports/atmel-samd/audio_dma.c @@ -40,82 +40,6 @@ static audio_dma_t* audio_dma_state[AUDIO_DMA_CHANNEL_COUNT]; // This cannot be in audio_dma_state because it's volatile. static volatile bool audio_dma_pending[AUDIO_DMA_CHANNEL_COUNT]; -uint32_t audiosample_sample_rate(mp_obj_t sample_obj) { - if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) { - audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj); - return sample->sample_rate; - } - if (MP_OBJ_IS_TYPE(sample_obj, &audioio_wavefile_type)) { - audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj); - return file->sample_rate; - } - return 16000; -} - -uint8_t audiosample_bits_per_sample(mp_obj_t sample_obj) { - if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) { - audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj); - return sample->bits_per_sample; - } - if (MP_OBJ_IS_TYPE(sample_obj, &audioio_wavefile_type)) { - audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj); - return file->bits_per_sample; - } - return 8; -} - -uint8_t audiosample_channel_count(mp_obj_t sample_obj) { - if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) { - audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj); - return sample->channel_count; - } - if (MP_OBJ_IS_TYPE(sample_obj, &audioio_wavefile_type)) { - audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj); - return file->channel_count; - } - return 1; -} - -static void audiosample_reset_buffer(mp_obj_t sample_obj, bool single_channel, uint8_t audio_channel) { - if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) { - audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj); - audioio_rawsample_reset_buffer(sample, single_channel, audio_channel); - } - if (MP_OBJ_IS_TYPE(sample_obj, &audioio_wavefile_type)) { - audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj); - audioio_wavefile_reset_buffer(file, single_channel, audio_channel); - } -} - -static audioio_get_buffer_result_t audiosample_get_buffer(mp_obj_t sample_obj, - bool single_channel, - uint8_t channel, - uint8_t** buffer, uint32_t* buffer_length) { - if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) { - audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj); - return audioio_rawsample_get_buffer(sample, single_channel, channel, buffer, buffer_length); - } - if (MP_OBJ_IS_TYPE(sample_obj, &audioio_wavefile_type)) { - audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj); - return audioio_wavefile_get_buffer(file, single_channel, channel, buffer, buffer_length); - } - return GET_BUFFER_DONE; -} - -static void audiosample_get_buffer_structure(mp_obj_t sample_obj, bool single_channel, - bool* single_buffer, bool* samples_signed, - uint32_t* max_buffer_length, uint8_t* spacing) { - if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) { - audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj); - audioio_rawsample_get_buffer_structure(sample, single_channel, single_buffer, - samples_signed, max_buffer_length, spacing); - } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_wavefile_type)) { - audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj); - audioio_wavefile_get_buffer_structure(file, single_channel, single_buffer, samples_signed, - max_buffer_length, spacing); - } -} - uint8_t find_free_audio_dma_channel(void) { uint8_t channel; for (channel = 0; channel < AUDIO_DMA_CHANNEL_COUNT; channel++) { diff --git a/ports/atmel-samd/background.c b/ports/atmel-samd/background.c index f25ec7200..099cb8b23 100644 --- a/ports/atmel-samd/background.c +++ b/ports/atmel-samd/background.c @@ -27,10 +27,10 @@ #include "audio_dma.h" #include "tick.h" -#include "usb.h" -#include "usb_mass_storage.h" +#include "supervisor/usb.h" #include "shared-module/displayio/__init__.h" +#include "shared-module/network/__init__.h" volatile uint64_t last_finished_tick = 0; @@ -41,8 +41,11 @@ void run_background_tasks(void) { #ifdef CIRCUITPY_DISPLAYIO displayio_refresh_display(); #endif - usb_msc_background(); - usb_cdc_background(); + #if MICROPY_PY_NETWORK + network_module_background(); + #endif + usb_background(); + last_finished_tick = ticks_ms; } diff --git a/ports/atmel-samd/flash_api.h b/ports/atmel-samd/boards/arduino_mkr1300/board.c index 3e41f59a2..770bc8259 100644 --- a/ports/atmel-samd/flash_api.h +++ b/ports/atmel-samd/boards/arduino_mkr1300/board.c @@ -23,14 +23,18 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_ATMEL_SAMD_FLASH_API_H -#define MICROPY_INCLUDED_ATMEL_SAMD_FLASH_API_H -#include "extmod/vfs_fat.h" +#include "boards/board.h" +#include "mpconfigboard.h" +#include "hal/include/hal_gpio.h" -extern void flash_init_vfs(fs_user_mount_t *vfs); -extern void flash_flush(void); +void board_init(void) +{ +} -void flash_set_usb_writable(bool usb_writable); +bool board_requests_safe_mode(void) { + return false; +} -#endif // MICROPY_INCLUDED_ATMEL_SAMD_FLASH_API_H +void reset_board(void) { +} diff --git a/ports/atmel-samd/boards/arduino_mkr1300/mpconfigboard.h b/ports/atmel-samd/boards/arduino_mkr1300/mpconfigboard.h new file mode 100644 index 000000000..1e8d926fd --- /dev/null +++ b/ports/atmel-samd/boards/arduino_mkr1300/mpconfigboard.h @@ -0,0 +1,24 @@ +#define MICROPY_HW_BOARD_NAME "Arduino MKR1300" +#define MICROPY_HW_MCU_NAME "samd21g18" + +#define MICROPY_PORT_A (0) +#define MICROPY_PORT_B (0) +#define MICROPY_PORT_C (0) + +#define CIRCUITPY_INTERNAL_NVM_SIZE 0 + +#define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - 0x010000) + +#define DEFAULT_I2C_BUS_SCL (&pin_PA09) +#define DEFAULT_I2C_BUS_SDA (&pin_PA08) + +#define DEFAULT_SPI_BUS_SCK (&pin_PA13) +#define DEFAULT_SPI_BUS_MOSI (&pin_PA12) +#define DEFAULT_SPI_BUS_MISO (&pin_PA15) + +#define DEFAULT_UART_BUS_RX (&pin_PB23) +#define DEFAULT_UART_BUS_TX (&pin_PB22) + +// USB is always used internally so skip the pin objects for it. +#define IGNORE_PIN_PA24 1 +#define IGNORE_PIN_PA25 1 diff --git a/ports/atmel-samd/boards/arduino_mkr1300/mpconfigboard.mk b/ports/atmel-samd/boards/arduino_mkr1300/mpconfigboard.mk new file mode 100644 index 000000000..071f7e64c --- /dev/null +++ b/ports/atmel-samd/boards/arduino_mkr1300/mpconfigboard.mk @@ -0,0 +1,11 @@ +LD_FILE = boards/samd21x18-bootloader.ld +USB_VID = 0x2341 +USB_PID = 0x8053 +USB_PRODUCT = "Arduino MKR1300" +USB_MANUFACTURER = "Arduino" + +INTERNAL_FLASH_FILESYSTEM = 1 +LONGINT_IMPL = NONE + +CHIP_VARIANT = SAMD21G18A +CHIP_FAMILY = samd21 diff --git a/ports/atmel-samd/boards/arduino_mkr1300/pins.c b/ports/atmel-samd/boards/arduino_mkr1300/pins.c new file mode 100644 index 000000000..de9f9769c --- /dev/null +++ b/ports/atmel-samd/boards/arduino_mkr1300/pins.c @@ -0,0 +1,44 @@ +#include "shared-bindings/board/__init__.h" + +#include "board_busses.h" + +STATIC const mp_rom_map_elem_t board_global_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA02) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_PB02) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_PB03) }, + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_PA04) }, + { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_PA05) }, + { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_PA06) }, + { MP_ROM_QSTR(MP_QSTR_A6), MP_ROM_PTR(&pin_PA07) }, + { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_PA22) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_PB23) }, + { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_PA23) }, + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_PB22) }, + { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_PA10) }, + { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_PA11) }, + { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_PB10) }, + { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_PB11) }, + { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_PA20) }, + { MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_PA21) }, + { MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_PA16) }, + { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_PA17) }, + { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_PA19) }, + { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_PA08) }, + { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_PA09) }, + { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_PB23) }, + { MP_ROM_QSTR(MP_QSTR_D14), MP_ROM_PTR(&pin_PB22) }, + { MP_ROM_QSTR(MP_QSTR_BOOT), MP_ROM_PTR(&pin_PB09) }, // NOTE: LORA BOOT + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_PA08) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_PA09) }, + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_PA13) }, + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PA12) }, + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_PA15) }, + { MP_ROM_QSTR(MP_QSTR_RFM9X_RST), MP_ROM_PTR(&pin_PA27) }, + { MP_ROM_QSTR(MP_QSTR_RFM9X_CS), MP_ROM_PTR(&pin_PA14) }, + { MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_PB08) }, + { MP_ROM_QSTR(MP_QSTR_BATTERY), MP_ROM_PTR(&pin_PB08) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/ports/atmel-samd/boards/arduino_zero/board.c b/ports/atmel-samd/boards/arduino_zero/board.c index 2dc1683ea..770bc8259 100644 --- a/ports/atmel-samd/boards/arduino_zero/board.c +++ b/ports/atmel-samd/boards/arduino_zero/board.c @@ -30,13 +30,6 @@ void board_init(void) { - gpio_set_pin_function(MICROPY_HW_LED_TX, GPIO_PIN_FUNCTION_OFF); - gpio_set_pin_direction(MICROPY_HW_LED_TX, GPIO_DIRECTION_OUT); - gpio_set_pin_level(MICROPY_HW_LED_TX, true); - - gpio_set_pin_function(MICROPY_HW_LED_RX, GPIO_PIN_FUNCTION_OFF); - gpio_set_pin_direction(MICROPY_HW_LED_RX, GPIO_DIRECTION_OUT); - gpio_set_pin_level(MICROPY_HW_LED_RX, true); } bool board_requests_safe_mode(void) { diff --git a/ports/atmel-samd/boards/arduino_zero/mpconfigboard.h b/ports/atmel-samd/boards/arduino_zero/mpconfigboard.h index 1382d4736..9a6256c68 100644 --- a/ports/atmel-samd/boards/arduino_zero/mpconfigboard.h +++ b/ports/atmel-samd/boards/arduino_zero/mpconfigboard.h @@ -1,16 +1,14 @@ #define MICROPY_HW_BOARD_NAME "Arduino Zero" #define MICROPY_HW_MCU_NAME "samd21g18" -// #define MICROPY_HW_LED_MSC PIN_PA17 // red -#define MICROPY_HW_LED_TX PIN_PA27 -#define MICROPY_HW_LED_RX PIN_PB03 +// #define MICROPY_HW_LED_MSC &pin_PA17 // red +#define MICROPY_HW_LED_TX &pin_PA27 +#define MICROPY_HW_LED_RX &pin_PB03 -#define MICROPY_PORT_A (PORT_PA24 | PORT_PA25 | PORT_PA27) +#define MICROPY_PORT_A (PORT_PA27) #define MICROPY_PORT_B (PORT_PB03) #define MICROPY_PORT_C (0) -#include "internal_flash.h" - #define CIRCUITPY_INTERNAL_NVM_SIZE 0 #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - 0x010000) diff --git a/ports/nrf/usb/usb.h b/ports/atmel-samd/boards/catwan_usbstick/board.c index 203260874..c8e20206a 100644 --- a/ports/nrf/usb/usb.h +++ b/ports/atmel-samd/boards/catwan_usbstick/board.c @@ -1,9 +1,9 @@ /* - * This file is part of the Micro Python project, http://micropython.org/ + * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * - * Copyright (c) 2018 hathach for Adafruit Industries + * Copyright (c) 2017 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 @@ -24,11 +24,15 @@ * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_NRF_USB_H -#define MICROPY_INCLUDED_NRF_USB_H +#include "boards/board.h" -#include "tusb.h" +void board_init(void) +{ +} -void usb_init(void); +bool board_requests_safe_mode(void) { + return false; +} -#endif // MICROPY_INCLUDED_NRF_USB_H +void reset_board(void) { +} diff --git a/ports/atmel-samd/boards/catwan_usbstick/mpconfigboard.h b/ports/atmel-samd/boards/catwan_usbstick/mpconfigboard.h new file mode 100644 index 000000000..341dcc27e --- /dev/null +++ b/ports/atmel-samd/boards/catwan_usbstick/mpconfigboard.h @@ -0,0 +1,58 @@ +#define MICROPY_HW_BOARD_NAME "Electronic Cats CatWAN USBStick" +#define MICROPY_HW_MCU_NAME "samd21e18" + +#define MICROPY_HW_LED_RX &pin_PA14 + +#define MICROPY_PORT_A (PORT_PA14) +#define MICROPY_PORT_B (0) +#define MICROPY_PORT_C (0) + +#define CIRCUITPY_INTERNAL_NVM_SIZE 0 + +#define DEFAULT_SPI_BUS_SCK (&pin_PA19) +#define DEFAULT_SPI_BUS_MOSI (&pin_PA18) +#define DEFAULT_SPI_BUS_MISO (&pin_PA22) + +#define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - 0x010000) + +#define IGNORE_PIN_PA00 1 +#define IGNORE_PIN_PA01 1 +#define IGNORE_PIN_PA02 1 +#define IGNORE_PIN_PA03 1 +#define IGNORE_PIN_PA05 1 +#define IGNORE_PIN_PA06 1 +#define IGNORE_PIN_PA07 1 +#define IGNORE_PIN_PA08 1 +#define IGNORE_PIN_PA09 1 +#define IGNORE_PIN_PA10 1 +#define IGNORE_PIN_PA11 1 +#define IGNORE_PIN_PA12 1 +#define IGNORE_PIN_PA13 1 +#define IGNORE_PIN_PA20 1 +#define IGNORE_PIN_PA21 1 +// USB is always used. +#define IGNORE_PIN_PA24 1 +#define IGNORE_PIN_PA25 1 +#define IGNORE_PIN_PA28 1 +#define IGNORE_PIN_PB01 1 +#define IGNORE_PIN_PB02 1 +#define IGNORE_PIN_PB03 1 +#define IGNORE_PIN_PB04 1 +#define IGNORE_PIN_PB05 1 +#define IGNORE_PIN_PB06 1 +#define IGNORE_PIN_PB07 1 +#define IGNORE_PIN_PB08 1 +#define IGNORE_PIN_PB09 1 +#define IGNORE_PIN_PB10 1 +#define IGNORE_PIN_PB11 1 +#define IGNORE_PIN_PB12 1 +#define IGNORE_PIN_PB13 1 +#define IGNORE_PIN_PB14 1 +#define IGNORE_PIN_PB15 1 +#define IGNORE_PIN_PB16 1 +#define IGNORE_PIN_PB17 1 +#define IGNORE_PIN_PB22 1 +#define IGNORE_PIN_PB23 1 +#define IGNORE_PIN_PB30 1 +#define IGNORE_PIN_PB31 1 +#define IGNORE_PIN_PB00 1 diff --git a/ports/atmel-samd/boards/catwan_usbstick/mpconfigboard.mk b/ports/atmel-samd/boards/catwan_usbstick/mpconfigboard.mk new file mode 100644 index 000000000..fd4590166 --- /dev/null +++ b/ports/atmel-samd/boards/catwan_usbstick/mpconfigboard.mk @@ -0,0 +1,11 @@ +LD_FILE = boards/samd21x18-bootloader.ld +USB_VID = 0xBAB2 +USB_PID = 0x1209 +USB_PRODUCT = "CatWAN USBStick" +USB_MANUFACTURER = "Electronic Cats" + +INTERNAL_FLASH_FILESYSTEM = 1 +LONGINT_IMPL = NONE + +CHIP_VARIANT = SAMD21E18A +CHIP_FAMILY = samd21 diff --git a/ports/atmel-samd/boards/catwan_usbstick/pins.c b/ports/atmel-samd/boards/catwan_usbstick/pins.c new file mode 100644 index 000000000..8997b653f --- /dev/null +++ b/ports/atmel-samd/boards/catwan_usbstick/pins.c @@ -0,0 +1,19 @@ +#include "shared-bindings/board/__init__.h" + +#include "board_busses.h" + +STATIC const mp_rom_map_elem_t board_global_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_PA30) }, + { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_PA31) }, + { MP_ROM_QSTR(MP_QSTR_RFM9X_D0), MP_ROM_PTR(&pin_PA04) }, + { MP_ROM_QSTR(MP_QSTR_RFM9X_D1), MP_ROM_PTR(&pin_PA23) }, + { MP_ROM_QSTR(MP_QSTR_RFM9X_D2), MP_ROM_PTR(&pin_PA27) }, + { MP_ROM_QSTR(MP_QSTR_RFM9X_D5), MP_ROM_PTR(&pin_PA15) }, + { MP_ROM_QSTR(MP_QSTR_RFM9X_RST), MP_ROM_PTR(&pin_PA16) }, + { MP_ROM_QSTR(MP_QSTR_RFM9X_CS), MP_ROM_PTR(&pin_PA17) }, + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_PA19) }, + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PA18) }, + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_PA22) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h b/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h index 5077840cb..2ad13e81c 100644 --- a/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h @@ -8,52 +8,24 @@ #define SPI_FLASH_BAUDRATE (8000000) // On-board flash -#define SPI_FLASH_MOSI_PIN PIN_PA20 -#define SPI_FLASH_MISO_PIN PIN_PA16 -#define SPI_FLASH_SCK_PIN PIN_PA21 -#define SPI_FLASH_CS_PIN PIN_PB22 - -#define SPI_FLASH_MOSI_PIN_FUNCTION PINMUX_PA20D_SERCOM3_PAD2 -#define SPI_FLASH_MISO_PIN_FUNCTION PINMUX_PA16D_SERCOM3_PAD0 -#define SPI_FLASH_SCK_PIN_FUNCTION PINMUX_PA21D_SERCOM3_PAD3 -#define SPI_FLASH_SERCOM SERCOM3 -#define SPI_FLASH_SERCOM_INDEX 3 -#define SPI_FLASH_MOSI_PAD 2 -#define SPI_FLASH_MISO_PAD 0 -#define SPI_FLASH_SCK_PAD 3 - -// <o> Transmit Data Pinout -// <0x0=>PAD[0,1]_DO_SCK -// <0x1=>PAD[2,3]_DO_SCK -// <0x2=>PAD[3,1]_DO_SCK -// <0x3=>PAD[0,3]_DO_SCK -#define SPI_FLASH_DOPO 1 -#define SPI_FLASH_DIPO 0 // same as MISO PAD +#define SPI_FLASH_MOSI_PIN &pin_PA20 +#define SPI_FLASH_MISO_PIN &pin_PA16 +#define SPI_FLASH_SCK_PIN &pin_PA21 +#define SPI_FLASH_CS_PIN &pin_PB22 // These are pins not to reset. -// PA24 and PA25 are USB. -#define MICROPY_PORT_A (PORT_PA16 | PORT_PA20 | PORT_PA21 | PORT_PA24 | PORT_PA25) -#define MICROPY_PORT_B (PORT_PB22) +#define MICROPY_PORT_A (0) +#define MICROPY_PORT_B (0) #define MICROPY_PORT_C (0) #define SPEAKER_ENABLE_PIN (&pin_PA30) -#include "external_flash/devices.h" - // If you change this, then make sure to update the linker scripts as well to // make sure you don't overwrite code. #define CIRCUITPY_INTERNAL_NVM_SIZE 256 #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE) -#include "external_flash/devices.h" - -#define EXTERNAL_FLASH_DEVICE_COUNT 2 -#define EXTERNAL_FLASH_DEVICES S25FL216K, \ - GD25Q16C - -#include "external_flash/external_flash.h" - #define CALIBRATE_CRYSTALLESS 1 // Explanation of how a user got into safe mode. diff --git a/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk b/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk index 831106adc..f701ef173 100644 --- a/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk @@ -5,6 +5,8 @@ USB_PRODUCT = "CircuitPlayground Express" USB_MANUFACTURER = "Adafruit Industries LLC" SPI_FLASH_FILESYSTEM = 1 +EXTERNAL_FLASH_DEVICE_COUNT = 2 +EXTERNAL_FLASH_DEVICES = "S25FL216K, GD25Q16C" LONGINT_IMPL = MPZ CHIP_VARIANT = SAMD21G18A @@ -17,3 +19,6 @@ FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_HID FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_LIS3DH FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Thermistor + +#Adding per @danh to reduce memory usage and get the latest changes in +CFLAGS_INLINE_LIMIT = 55 diff --git a/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.h b/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.h index 638a6646c..250300858 100644 --- a/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.h +++ b/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.h @@ -11,52 +11,24 @@ #define SPI_FLASH_BAUDRATE (8000000) // On-board flash -#define SPI_FLASH_MOSI_PIN PIN_PA20 -#define SPI_FLASH_MISO_PIN PIN_PA16 -#define SPI_FLASH_SCK_PIN PIN_PA21 -#define SPI_FLASH_CS_PIN PIN_PB22 - -#define SPI_FLASH_MOSI_PIN_FUNCTION PINMUX_PA20D_SERCOM3_PAD2 -#define SPI_FLASH_MISO_PIN_FUNCTION PINMUX_PA16D_SERCOM3_PAD0 -#define SPI_FLASH_SCK_PIN_FUNCTION PINMUX_PA21D_SERCOM3_PAD3 -#define SPI_FLASH_SERCOM SERCOM3 -#define SPI_FLASH_SERCOM_INDEX 3 -#define SPI_FLASH_MOSI_PAD 2 -#define SPI_FLASH_MISO_PAD 0 -#define SPI_FLASH_SCK_PAD 3 - -// <o> Transmit Data Pinout -// <0x0=>PAD[0,1]_DO_SCK -// <0x1=>PAD[2,3]_DO_SCK -// <0x2=>PAD[3,1]_DO_SCK -// <0x3=>PAD[0,3]_DO_SCK -#define SPI_FLASH_DOPO 1 -#define SPI_FLASH_DIPO 0 // same as MISO PAD +#define SPI_FLASH_MOSI_PIN &pin_PA20 +#define SPI_FLASH_MISO_PIN &pin_PA16 +#define SPI_FLASH_SCK_PIN &pin_PA21 +#define SPI_FLASH_CS_PIN &pin_PB22 // These are pins not to reset. -// PA24 and PA25 are USB. -#define MICROPY_PORT_A (PORT_PA16 | PORT_PA20 | PORT_PA21 | PORT_PA24 | PORT_PA25) -#define MICROPY_PORT_B (PORT_PB22) +#define MICROPY_PORT_A (0) +#define MICROPY_PORT_B (0) #define MICROPY_PORT_C (0) #define SPEAKER_ENABLE_PIN (&pin_PA30) -#include "external_flash/devices.h" - // If you change this, then make sure to update the linker scripts as well to // make sure you don't overwrite code. #define CIRCUITPY_INTERNAL_NVM_SIZE 256 #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE) -#include "external_flash/devices.h" - -#define EXTERNAL_FLASH_DEVICE_COUNT 2 -#define EXTERNAL_FLASH_DEVICES S25FL216K, \ - GD25Q16C - -#include "external_flash/external_flash.h" - #define CALIBRATE_CRYSTALLESS 1 // Explanation of how a user got into safe mode. diff --git a/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.mk b/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.mk index 972c4b10d..b07d63984 100644 --- a/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.mk +++ b/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.mk @@ -5,6 +5,8 @@ USB_PRODUCT = "CircuitPlayground Express with Crickit libraries" USB_MANUFACTURER = "Adafruit Industries LLC" SPI_FLASH_FILESYSTEM = 1 +EXTERNAL_FLASH_DEVICE_COUNT = 2 +EXTERNAL_FLASH_DEVICES = "S25FL216K, GD25Q16C" # Turn off longints for Crickit build to make room for additional frozen libs. LONGINT_IMPL = NONE diff --git a/ports/nrf/common-hal/storage/__init__.c b/ports/atmel-samd/boards/cp32-m4/board.c index 4ff5f0dac..0f60736a2 100644 --- a/ports/nrf/common-hal/storage/__init__.c +++ b/ports/atmel-samd/boards/cp32-m4/board.c @@ -24,24 +24,16 @@ * THE SOFTWARE. */ -#include <string.h> +#include "boards/board.h" +#include "mpconfigboard.h" +#include "hal/include/hal_gpio.h" -#include "py/mperrno.h" -#include "py/runtime.h" -#include "shared-bindings/microcontroller/__init__.h" -#include "shared-bindings/storage/__init__.h" -#include "supervisor/filesystem.h" - -extern volatile bool mp_msc_enabled; +void board_init(void) { +} -void common_hal_storage_remount(const char *mount_path, bool readonly) { - if (strcmp(mount_path, "/") != 0) { - mp_raise_OSError(MP_EINVAL); - } +bool board_requests_safe_mode(void) { + return false; } -void common_hal_storage_erase_filesystem(void) { - filesystem_init(false, true); // Force a re-format. - common_hal_mcu_reset(); - // We won't actually get here, since we're resetting. +void reset_board(void) { } diff --git a/ports/atmel-samd/boards/cp32-m4/mpconfigboard.h b/ports/atmel-samd/boards/cp32-m4/mpconfigboard.h new file mode 100644 index 000000000..bcad7f18b --- /dev/null +++ b/ports/atmel-samd/boards/cp32-m4/mpconfigboard.h @@ -0,0 +1,39 @@ +#define MICROPY_HW_BOARD_NAME "CP32-M4" +#define MICROPY_HW_MCU_NAME "samd51g19" + +#define MICROPY_HW_APA102_MOSI (&pin_PA17) +#define MICROPY_HW_APA102_SCK (&pin_PA16) + + +#define CIRCUITPY_MCU_FAMILY samd51 + +#define MICROPY_PORT_A (PORT_PA08 | PORT_PA09 | PORT_PA10 | PORT_PA11| PORT_PA16| PORT_PA17) +#define MICROPY_PORT_B ( PORT_PB10 | PORT_PB11) +#define MICROPY_PORT_C (0) +#define MICROPY_PORT_D (0) + +#define AUTORESET_DELAY_MS 500 + +// If you change this, then make sure to update the linker scripts as well to +// make sure you don't overwrite code +#define CIRCUITPY_INTERNAL_NVM_SIZE 8192 + +#define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000 - CIRCUITPY_INTERNAL_NVM_SIZE) + +#include "external_flash/devices.h" + +// these are the labeled pins (SDA, SCL, SCK, MOSI, MISO, etc) +#define EXTERNAL_FLASH_DEVICE_COUNT 1 +#define EXTERNAL_FLASH_DEVICES W25Q128JV_PM + +#include "external_flash/external_flash.h" + +#define DEFAULT_I2C_BUS_SCL (&pin_PB09) +#define DEFAULT_I2C_BUS_SDA (&pin_PB08) + +#define DEFAULT_SPI_BUS_SCK (&pin_PA22) +#define DEFAULT_SPI_BUS_MOSI (&pin_PA23) +#define DEFAULT_SPI_BUS_MISO (&pin_PA21) + +#define DEFAULT_UART_BUS_RX (&pin_PA12) +#define DEFAULT_UART_BUS_TX (&pin_PA13) diff --git a/ports/atmel-samd/boards/cp32-m4/mpconfigboard.mk b/ports/atmel-samd/boards/cp32-m4/mpconfigboard.mk new file mode 100644 index 000000000..56fc9b2fb --- /dev/null +++ b/ports/atmel-samd/boards/cp32-m4/mpconfigboard.mk @@ -0,0 +1,10 @@ +LD_FILE = boards/samd51x19-bootloader-external-flash.ld +USB_VID = 0x239A +USB_PID = 0x8021 +USB_PRODUCT = "CP32-M4" +USB_MANUFACTURER = "Nadda-Reel Company LLC" + +QSPI_FLASH_FILESYSTEM = 1 + +CHIP_VARIANT = SAMD51G19A +CHIP_FAMILY = samd51 diff --git a/ports/atmel-samd/boards/cp32-m4/pins.c b/ports/atmel-samd/boards/cp32-m4/pins.c new file mode 100644 index 000000000..93c169c8b --- /dev/null +++ b/ports/atmel-samd/boards/cp32-m4/pins.c @@ -0,0 +1,41 @@ +#include "shared-bindings/board/__init__.h" + +#include "board_busses.h" + +// This mapping only includes functional names because pins broken +// out on connectors are labeled with their MCU name available from +// microcontroller.pin. +STATIC const mp_rom_map_elem_t board_global_dict_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR_SPEAKER_P), MP_ROM_PTR(&pin_PA02) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_BATTERY), MP_ROM_PTR(&pin_PB08) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SW3_4), MP_ROM_PTR(&pin_PB09) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SW1_2), MP_ROM_PTR(&pin_PA04) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SPEAKER_N), MP_ROM_PTR(&pin_PA05) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_SW9), MP_ROM_PTR(&pin_PA06) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SW7), MP_ROM_PTR(&pin_PA07) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_BACKLIGHT_PWM), MP_ROM_PTR(&pin_PA12) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_EXT_HDR3), MP_ROM_PTR(&pin_PA13) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SW5), MP_ROM_PTR(&pin_PA14) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_EXT_HDR4), MP_ROM_PTR(&pin_PA15) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_APA102_SCK), MP_ROM_PTR(&pin_PA16) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_APA102_MOSI), MP_ROM_PTR(&pin_PA17) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_STATUS_LED), MP_ROM_PTR(&pin_PA18) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SW6), MP_ROM_PTR(&pin_PA19) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_VSPI_CS0), MP_ROM_PTR(&pin_PA20) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_VSPI_MISO), MP_ROM_PTR(&pin_PA21) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_VSPI_SCK), MP_ROM_PTR(&pin_PA22) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_VSPI_MOSI), MP_ROM_PTR(&pin_PA23) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_VSPI_CS1), MP_ROM_PTR(&pin_PB22) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_EXT_HDR5), MP_ROM_PTR(&pin_PB23) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_LCD_DC), MP_ROM_PTR(&pin_PA27) }, + { MP_ROM_QSTR(MP_QSTR_SW8), MP_ROM_PTR(&pin_PB02) }, + { MP_ROM_QSTR(MP_QSTR_SW10), MP_ROM_PTR(&pin_PB03) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/ports/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.h b/ports/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.h index c8b5c56ee..c28c4aafb 100644 --- a/ports/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.h +++ b/ports/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.h @@ -3,12 +3,10 @@ #define MICROPY_HW_BOARD_NAME "Adafruit Feather M0 Adalogger" #define MICROPY_HW_MCU_NAME "samd21g18" -#define MICROPY_PORT_A (PORT_PA24 | PORT_PA25) +#define MICROPY_PORT_A (0) #define MICROPY_PORT_B (0) #define MICROPY_PORT_C (0) -#include "internal_flash.h" - #define CIRCUITPY_INTERNAL_NVM_SIZE 0 #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - 0x010000) diff --git a/ports/atmel-samd/boards/feather_m0_adalogger/pins.c b/ports/atmel-samd/boards/feather_m0_adalogger/pins.c index da97bd253..0029bba1a 100644 --- a/ports/atmel-samd/boards/feather_m0_adalogger/pins.c +++ b/ports/atmel-samd/boards/feather_m0_adalogger/pins.c @@ -28,6 +28,7 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_GREEN_LED), MP_ROM_PTR(&pin_PA06) }, { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_PA07) }, { MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_PA07) }, + { MP_ROM_QSTR(MP_QSTR_BATTERY), MP_ROM_PTR(&pin_PA07) }, { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_PA18) }, { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_PA16) }, { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_PA19) }, diff --git a/ports/atmel-samd/boards/feather_m0_basic/mpconfigboard.h b/ports/atmel-samd/boards/feather_m0_basic/mpconfigboard.h index dcac9749d..d66efb36f 100644 --- a/ports/atmel-samd/boards/feather_m0_basic/mpconfigboard.h +++ b/ports/atmel-samd/boards/feather_m0_basic/mpconfigboard.h @@ -4,12 +4,10 @@ #define MICROPY_HW_BOARD_NAME "Adafruit Feather M0 Basic" #define MICROPY_HW_MCU_NAME "samd21g18" -#define MICROPY_PORT_A (PORT_PA24 | PORT_PA25) +#define MICROPY_PORT_A (0) #define MICROPY_PORT_B (0) #define MICROPY_PORT_C (0) -#include "internal_flash.h" - #define CIRCUITPY_INTERNAL_NVM_SIZE 0 #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - 0x010000) diff --git a/ports/atmel-samd/boards/feather_m0_basic/pins.c b/ports/atmel-samd/boards/feather_m0_basic/pins.c index b5bd45a2f..4400a253d 100644 --- a/ports/atmel-samd/boards/feather_m0_basic/pins.c +++ b/ports/atmel-samd/boards/feather_m0_basic/pins.c @@ -22,6 +22,7 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_PA20) }, { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_PA07) }, { MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_PA07) }, + { MP_ROM_QSTR(MP_QSTR_BATTERY), MP_ROM_PTR(&pin_PA07) }, { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_PA18) }, { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_PA16) }, { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_PA19) }, diff --git a/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.h b/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.h index 03d0ba9bd..1f02ee995 100644 --- a/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.h @@ -3,35 +3,16 @@ #define MICROPY_HW_NEOPIXEL (&pin_PA06) -// Clock rates are off: Salae reads 12MHz which is the limit even though we set it to the safer 8MHz. -#define SPI_FLASH_BAUDRATE (8000000) - -#define SPI_FLASH_MOSI_PIN PIN_PA08 -#define SPI_FLASH_MISO_PIN PIN_PA14 -#define SPI_FLASH_SCK_PIN PIN_PA09 -#define SPI_FLASH_CS_PIN PIN_PA13 -#define SPI_FLASH_MOSI_PIN_FUNCTION PINMUX_PA08D_SERCOM2_PAD0 -#define SPI_FLASH_MISO_PIN_FUNCTION PINMUX_PA14C_SERCOM2_PAD2 -#define SPI_FLASH_SCK_PIN_FUNCTION PINMUX_PA09D_SERCOM2_PAD1 -#define SPI_FLASH_SERCOM SERCOM2 -#define SPI_FLASH_SERCOM_INDEX 2 -#define SPI_FLASH_MOSI_PAD 0 -#define SPI_FLASH_MISO_PAD 2 -#define SPI_FLASH_SCK_PAD 1 -// <o> Transmit Data Pinout -// <0x0=>PAD[0,1]_DO_SCK -// <0x1=>PAD[2,3]_DO_SCK -// <0x2=>PAD[3,1]_DO_SCK -// <0x3=>PAD[0,3]_DO_SCK -#define SPI_FLASH_DOPO 0 -#define SPI_FLASH_DIPO 2 // same as MISO pad +#define SPI_FLASH_MOSI_PIN &pin_PA08 +#define SPI_FLASH_MISO_PIN &pin_PA14 +#define SPI_FLASH_SCK_PIN &pin_PA09 +#define SPI_FLASH_CS_PIN &pin_PA13 // These are pins not to reset. -#define MICROPY_PORT_A (PORT_PA06 | PORT_PA08 | PORT_PA09 | PORT_PA13 | PORT_PA14 | PORT_PA24 | PORT_PA25) +#define MICROPY_PORT_A (PORT_PA06) #define MICROPY_PORT_B ( 0 ) #define MICROPY_PORT_C ( 0 ) -#include "external_flash/external_flash.h" // If you change this, then make sure to update the linker scripts as well to // make sure you don't overwrite code. @@ -39,14 +20,6 @@ #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE) -#include "external_flash/devices.h" - -#define EXTERNAL_FLASH_DEVICE_COUNT 2 -#define EXTERNAL_FLASH_DEVICES S25FL216K, \ - GD25Q16C - -#include "external_flash/external_flash.h" - #define BOARD_HAS_CRYSTAL 1 #define DEFAULT_I2C_BUS_SCL (&pin_PA23) diff --git a/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk index d4725fdf4..57ce96285 100644 --- a/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk @@ -5,7 +5,12 @@ USB_PRODUCT = "Feather M0 Express" USB_MANUFACTURER = "Adafruit Industries LLC" SPI_FLASH_FILESYSTEM = 1 +EXTERNAL_FLASH_DEVICE_COUNT = 2 +EXTERNAL_FLASH_DEVICES = "S25FL216K, GD25Q16C" LONGINT_IMPL = MPZ CHIP_VARIANT = SAMD21G18A CHIP_FAMILY = samd21 + +MICROPY_PY_NETWORK = 1 +MICROPY_PY_WIZNET5K = 5500 diff --git a/ports/atmel-samd/boards/feather_m0_express/pins.c b/ports/atmel-samd/boards/feather_m0_express/pins.c index 1a6aad45b..cd6c351d4 100644 --- a/ports/atmel-samd/boards/feather_m0_express/pins.c +++ b/ports/atmel-samd/boards/feather_m0_express/pins.c @@ -22,6 +22,7 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_PA20) }, { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_PA07) }, { MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_PA07) }, + { MP_ROM_QSTR(MP_QSTR_BATTERY), MP_ROM_PTR(&pin_PA07) }, { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_PA18) }, { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_PA16) }, { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_PA19) }, diff --git a/ports/atmel-samd/boards/feather_m0_express_crickit/mpconfigboard.h b/ports/atmel-samd/boards/feather_m0_express_crickit/mpconfigboard.h index 756462013..b5544e253 100644 --- a/ports/atmel-samd/boards/feather_m0_express_crickit/mpconfigboard.h +++ b/ports/atmel-samd/boards/feather_m0_express_crickit/mpconfigboard.h @@ -3,50 +3,22 @@ #define MICROPY_HW_NEOPIXEL (&pin_PA06) -// Clock rates are off: Salae reads 12MHz which is the limit even though we set it to the safer 8MHz. -#define SPI_FLASH_BAUDRATE (8000000) - -#define SPI_FLASH_MOSI_PIN PIN_PA08 -#define SPI_FLASH_MISO_PIN PIN_PA14 -#define SPI_FLASH_SCK_PIN PIN_PA09 -#define SPI_FLASH_CS_PIN PIN_PA13 -#define SPI_FLASH_MOSI_PIN_FUNCTION PINMUX_PA08D_SERCOM2_PAD0 -#define SPI_FLASH_MISO_PIN_FUNCTION PINMUX_PA14C_SERCOM2_PAD2 -#define SPI_FLASH_SCK_PIN_FUNCTION PINMUX_PA09D_SERCOM2_PAD1 -#define SPI_FLASH_SERCOM SERCOM2 -#define SPI_FLASH_SERCOM_INDEX 2 -#define SPI_FLASH_MOSI_PAD 0 -#define SPI_FLASH_MISO_PAD 2 -#define SPI_FLASH_SCK_PAD 1 -// <o> Transmit Data Pinout -// <0x0=>PAD[0,1]_DO_SCK -// <0x1=>PAD[2,3]_DO_SCK -// <0x2=>PAD[3,1]_DO_SCK -// <0x3=>PAD[0,3]_DO_SCK -#define SPI_FLASH_DOPO 0 -#define SPI_FLASH_DIPO 2 // same as MISO pad +#define SPI_FLASH_MOSI_PIN &pin_PA08 +#define SPI_FLASH_MISO_PIN &pin_PA14 +#define SPI_FLASH_SCK_PIN &pin_PA09 +#define SPI_FLASH_CS_PIN &pin_PA13 // These are pins not to reset. -#define MICROPY_PORT_A (PORT_PA06 | PORT_PA08 | PORT_PA09 | PORT_PA13 | PORT_PA14 | PORT_PA24 | PORT_PA25) +#define MICROPY_PORT_A (PORT_PA06) #define MICROPY_PORT_B ( 0 ) #define MICROPY_PORT_C ( 0 ) -#include "external_flash/external_flash.h" - // If you change this, then make sure to update the linker scripts as well to // make sure you don't overwrite code. #define CIRCUITPY_INTERNAL_NVM_SIZE 256 #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE) -#include "external_flash/devices.h" - -#define EXTERNAL_FLASH_DEVICE_COUNT 2 -#define EXTERNAL_FLASH_DEVICES S25FL216K, \ - GD25Q16C - -#include "external_flash/external_flash.h" - #define BOARD_HAS_CRYSTAL 1 #define DEFAULT_I2C_BUS_SCL (&pin_PA23) 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 7ff5337a3..f773bcb57 100644 --- a/ports/atmel-samd/boards/feather_m0_express_crickit/mpconfigboard.mk +++ b/ports/atmel-samd/boards/feather_m0_express_crickit/mpconfigboard.mk @@ -5,6 +5,8 @@ USB_PRODUCT = "Feather M0 Express" USB_MANUFACTURER = "Adafruit Industries LLC" SPI_FLASH_FILESYSTEM = 1 +EXTERNAL_FLASH_DEVICE_COUNT = 2 +EXTERNAL_FLASH_DEVICES = "S25FL216K, GD25Q16C" LONGINT_IMPL = MPZ CHIP_VARIANT = SAMD21G18A diff --git a/ports/atmel-samd/boards/feather_m0_express_crickit/pins.c b/ports/atmel-samd/boards/feather_m0_express_crickit/pins.c index 1a6aad45b..cd6c351d4 100644 --- a/ports/atmel-samd/boards/feather_m0_express_crickit/pins.c +++ b/ports/atmel-samd/boards/feather_m0_express_crickit/pins.c @@ -22,6 +22,7 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_PA20) }, { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_PA07) }, { MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_PA07) }, + { MP_ROM_QSTR(MP_QSTR_BATTERY), MP_ROM_PTR(&pin_PA07) }, { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_PA18) }, { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_PA16) }, { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_PA19) }, diff --git a/ports/atmel-samd/boards/feather_m0_rfm69/mpconfigboard.h b/ports/atmel-samd/boards/feather_m0_rfm69/mpconfigboard.h index 4a530ed29..c385a97ea 100644 --- a/ports/atmel-samd/boards/feather_m0_rfm69/mpconfigboard.h +++ b/ports/atmel-samd/boards/feather_m0_rfm69/mpconfigboard.h @@ -4,12 +4,10 @@ #define MICROPY_HW_BOARD_NAME "Adafruit Feather M0 RFM69" #define MICROPY_HW_MCU_NAME "samd21g18" -#define MICROPY_PORT_A (PORT_PA24 | PORT_PA25) +#define MICROPY_PORT_A (0) #define MICROPY_PORT_B (0) #define MICROPY_PORT_C (0) -#include "internal_flash.h" - #define CIRCUITPY_INTERNAL_NVM_SIZE 0 #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - 0x010000) diff --git a/ports/atmel-samd/boards/feather_m0_rfm69/pins.c b/ports/atmel-samd/boards/feather_m0_rfm69/pins.c index 072eb4f88..7e14b3f25 100644 --- a/ports/atmel-samd/boards/feather_m0_rfm69/pins.c +++ b/ports/atmel-samd/boards/feather_m0_rfm69/pins.c @@ -22,6 +22,7 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_PA20) }, { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_PA07) }, { MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_PA07) }, + { MP_ROM_QSTR(MP_QSTR_BATTERY), MP_ROM_PTR(&pin_PA07) }, { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_PA18) }, { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_PA16) }, { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_PA19) }, diff --git a/ports/atmel-samd/boards/feather_m0_rfm9x/mpconfigboard.h b/ports/atmel-samd/boards/feather_m0_rfm9x/mpconfigboard.h index 3a6f28c12..1e3a0bda0 100644 --- a/ports/atmel-samd/boards/feather_m0_rfm9x/mpconfigboard.h +++ b/ports/atmel-samd/boards/feather_m0_rfm9x/mpconfigboard.h @@ -4,12 +4,10 @@ #define MICROPY_HW_BOARD_NAME "Adafruit Feather M0 RFM9x" #define MICROPY_HW_MCU_NAME "samd21g18" -#define MICROPY_PORT_A (PORT_PA24 | PORT_PA25) +#define MICROPY_PORT_A (0) #define MICROPY_PORT_B (0) #define MICROPY_PORT_C (0) -#include "internal_flash.h" - #define CIRCUITPY_INTERNAL_NVM_SIZE 0 #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - 0x010000) diff --git a/ports/atmel-samd/boards/feather_m0_rfm9x/pins.c b/ports/atmel-samd/boards/feather_m0_rfm9x/pins.c index 696d2239d..4e77b7fb9 100644 --- a/ports/atmel-samd/boards/feather_m0_rfm9x/pins.c +++ b/ports/atmel-samd/boards/feather_m0_rfm9x/pins.c @@ -22,6 +22,7 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_PA20) }, { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_PA07) }, { MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_PA07) }, + { MP_ROM_QSTR(MP_QSTR_BATTERY), MP_ROM_PTR(&pin_PA07) }, { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_PA18) }, { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_PA16) }, { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_PA19) }, diff --git a/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h index a7a2d7de0..6bf1df156 100644 --- a/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h +++ b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h @@ -5,49 +5,22 @@ #define MICROPY_HW_NEOPIXEL (&pin_PA06) -// Clock rates are off: Salae reads 12MHz which is the limit even though we set it to the safer 8MHz. -#define SPI_FLASH_BAUDRATE (8000000) - -#define SPI_FLASH_MOSI_PIN PIN_PA08 -#define SPI_FLASH_MISO_PIN PIN_PA14 -#define SPI_FLASH_SCK_PIN PIN_PA09 -#define SPI_FLASH_CS_PIN PIN_PA13 -#define SPI_FLASH_MOSI_PIN_FUNCTION PINMUX_PA08D_SERCOM2_PAD0 -#define SPI_FLASH_MISO_PIN_FUNCTION PINMUX_PA14C_SERCOM2_PAD2 -#define SPI_FLASH_SCK_PIN_FUNCTION PINMUX_PA09D_SERCOM2_PAD1 -#define SPI_FLASH_SERCOM SERCOM2 -#define SPI_FLASH_SERCOM_INDEX 2 -#define SPI_FLASH_MOSI_PAD 0 -#define SPI_FLASH_MISO_PAD 2 -#define SPI_FLASH_SCK_PAD 1 -// <o> Transmit Data Pinout -// <0x0=>PAD[0,1]_DO_SCK -// <0x1=>PAD[2,3]_DO_SCK -// <0x2=>PAD[3,1]_DO_SCK -// <0x3=>PAD[0,3]_DO_SCK -#define SPI_FLASH_DOPO 0 -#define SPI_FLASH_DIPO 2 // same as MISO pad +#define SPI_FLASH_MOSI_PIN &pin_PA08 +#define SPI_FLASH_MISO_PIN &pin_PA14 +#define SPI_FLASH_SCK_PIN &pin_PA09 +#define SPI_FLASH_CS_PIN &pin_PA13 // These are pins not to reset. -#define MICROPY_PORT_A (PORT_PA06 | PORT_PA08 | PORT_PA09 | PORT_PA13 | PORT_PA14 | PORT_PA24 | PORT_PA25) +#define MICROPY_PORT_A (PORT_PA06) #define MICROPY_PORT_B ( 0 ) #define MICROPY_PORT_C ( 0 ) -#include "external_flash/external_flash.h" - // If you change this, then make sure to update the linker scripts as well to // make sure you don't overwrite code. #define CIRCUITPY_INTERNAL_NVM_SIZE 256 #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE) -#include "external_flash/devices.h" - -#define EXTERNAL_FLASH_DEVICE_COUNT 1 -#define EXTERNAL_FLASH_DEVICES S25FL064L - -#include "external_flash/external_flash.h" - #define DEFAULT_I2C_BUS_SCL (&pin_PA23) #define DEFAULT_I2C_BUS_SDA (&pin_PA22) diff --git a/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk index 79bf2d34a..4bae6ffa7 100644 --- a/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk +++ b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk @@ -5,6 +5,8 @@ USB_PRODUCT = "Feather M0 Supersized" USB_MANUFACTURER = "Dave Astels" SPI_FLASH_FILESYSTEM = 1 +EXTERNAL_FLASH_DEVICE_COUNT = 1 +EXTERNAL_FLASH_DEVICES = "S25FL064L" LONGINT_IMPL = MPZ CHIP_VARIANT = SAMD21G18A diff --git a/ports/atmel-samd/boards/feather_m0_supersized/pins.c b/ports/atmel-samd/boards/feather_m0_supersized/pins.c index 1a6aad45b..cd6c351d4 100644 --- a/ports/atmel-samd/boards/feather_m0_supersized/pins.c +++ b/ports/atmel-samd/boards/feather_m0_supersized/pins.c @@ -22,6 +22,7 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_PA20) }, { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_PA07) }, { MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_PA07) }, + { MP_ROM_QSTR(MP_QSTR_BATTERY), MP_ROM_PTR(&pin_PA07) }, { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_PA18) }, { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_PA16) }, { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_PA19) }, diff --git a/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.h b/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.h index e9e921b4d..98906a844 100644 --- a/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.h @@ -23,15 +23,8 @@ #define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000 - CIRCUITPY_INTERNAL_NVM_SIZE) -#include "external_flash/devices.h" - -#define EXTERNAL_FLASH_DEVICE_COUNT 1 -#define EXTERNAL_FLASH_DEVICES GD25Q16C - #define EXTERNAL_FLASH_QSPI_DUAL -#include "external_flash/external_flash.h" - #define BOARD_HAS_CRYSTAL 1 #define DEFAULT_I2C_BUS_SCL (&pin_PA13) diff --git a/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk index e19a27b88..3f2cb6ce4 100644 --- a/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk @@ -5,7 +5,13 @@ USB_PRODUCT = "Feather M4 Express" USB_MANUFACTURER = "Adafruit Industries LLC" QSPI_FLASH_FILESYSTEM = 1 + +EXTERNAL_FLASH_DEVICE_COUNT = 1 +EXTERNAL_FLASH_DEVICES = GD25Q16C LONGINT_IMPL = MPZ CHIP_VARIANT = SAMD51J19A CHIP_FAMILY = samd51 + +MICROPY_PY_NETWORK = 1 +MICROPY_PY_WIZNET5K = 5500 diff --git a/ports/atmel-samd/boards/feather_m4_express/pins.c b/ports/atmel-samd/boards/feather_m4_express/pins.c index b9b04e0ac..5004254c5 100644 --- a/ports/atmel-samd/boards/feather_m4_express/pins.c +++ b/ports/atmel-samd/boards/feather_m4_express/pins.c @@ -28,6 +28,7 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_PA23) }, { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_PB03) }, { MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_PB01) }, + { MP_ROM_QSTR(MP_QSTR_BATTERY), MP_ROM_PTR(&pin_PB01) }, { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, diff --git a/ports/atmel-samd/boards/feather_radiofruit_zigbee/mpconfigboard.h b/ports/atmel-samd/boards/feather_radiofruit_zigbee/mpconfigboard.h index 32c549953..c4e025178 100755 --- a/ports/atmel-samd/boards/feather_radiofruit_zigbee/mpconfigboard.h +++ b/ports/atmel-samd/boards/feather_radiofruit_zigbee/mpconfigboard.h @@ -3,50 +3,22 @@ #define MICROPY_HW_NEOPIXEL (&pin_PA22) -// Clock rates are off: Salae reads 12MHz which is the limit even though we set it to the safer 8MHz. -#define SPI_FLASH_BAUDRATE (8000000) - -#define SPI_FLASH_MOSI_PIN PIN_PA31 -#define SPI_FLASH_MISO_PIN PIN_PA30 -#define SPI_FLASH_SCK_PIN PIN_PA17 -#define SPI_FLASH_CS_PIN PIN_PA28 -#define SPI_FLASH_MOSI_PIN_FUNCTION PINMUX_PA31D_SERCOM1_PAD3 -#define SPI_FLASH_MISO_PIN_FUNCTION PINMUX_PA30D_SERCOM1_PAD2 -#define SPI_FLASH_SCK_PIN_FUNCTION PINMUX_PA17C_SERCOM1_PAD1 -#define SPI_FLASH_SERCOM SERCOM1 -#define SPI_FLASH_SERCOM_INDEX 1 -#define SPI_FLASH_MOSI_PAD 3 -#define SPI_FLASH_MISO_PAD 2 -#define SPI_FLASH_SCK_PAD 1 -// <o> Transmit Data Pinout -// <0x0=>PAD[0,1]_DO_SCK -// <0x1=>PAD[2,3]_DO_SCK -// <0x2=>PAD[3,1]_DO_SCK -// <0x3=>PAD[0,3]_DO_SCK -#define SPI_FLASH_DOPO 2 -#define SPI_FLASH_DIPO 2 // same as MISO pad +#define SPI_FLASH_MOSI_PIN &pin_PA31 +#define SPI_FLASH_MISO_PIN &pin_PA30 +#define SPI_FLASH_SCK_PIN &pin_PA17 +#define SPI_FLASH_CS_PIN &pin_PA28 // These are pins not to reset. -#define MICROPY_PORT_A (PORT_PA17 | PORT_PA22 | PORT_PA24 | PORT_PA25 | PORT_PA28 | PORT_PA30 | PORT_PA31) +#define MICROPY_PORT_A (PORT_PA22) #define MICROPY_PORT_B ( 0 ) #define MICROPY_PORT_C ( 0 ) -#include "external_flash/external_flash.h" - // If you change this, then make sure to update the linker scripts as well to // make sure you don't overwrite code. #define CIRCUITPY_INTERNAL_NVM_SIZE 256 #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE) -#include "external_flash/devices.h" - -#define EXTERNAL_FLASH_DEVICE_COUNT 2 -#define EXTERNAL_FLASH_DEVICES S25FL216K, \ - GD25Q16C - -#include "external_flash/external_flash.h" - #define BOARD_HAS_CRYSTAL 1 #define DEFAULT_I2C_BUS_SCL (&pin_PA13) diff --git a/ports/atmel-samd/boards/feather_radiofruit_zigbee/mpconfigboard.mk b/ports/atmel-samd/boards/feather_radiofruit_zigbee/mpconfigboard.mk index 42177d274..634a9ede7 100755 --- a/ports/atmel-samd/boards/feather_radiofruit_zigbee/mpconfigboard.mk +++ b/ports/atmel-samd/boards/feather_radiofruit_zigbee/mpconfigboard.mk @@ -5,6 +5,8 @@ USB_PRODUCT = "Feather RadioFruit Zigbee" USB_MANUFACTURER = "Adafruit Industries LLC" SPI_FLASH_FILESYSTEM = 1 +EXTERNAL_FLASH_DEVICE_COUNT = 2 +EXTERNAL_FLASH_DEVICES = "S25FL216K, GD25Q16C" LONGINT_IMPL = MPZ CHIP_VARIANT = SAMR21G18A diff --git a/ports/atmel-samd/boards/gemma_m0/mpconfigboard.h b/ports/atmel-samd/boards/gemma_m0/mpconfigboard.h index 1ec217096..08d1803f2 100644 --- a/ports/atmel-samd/boards/gemma_m0/mpconfigboard.h +++ b/ports/atmel-samd/boards/gemma_m0/mpconfigboard.h @@ -18,8 +18,6 @@ #define DEFAULT_UART_BUS_RX (&pin_PA05) #define DEFAULT_UART_BUS_TX (&pin_PA04) -#include "internal_flash.h" - #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - 0x010000) #define IGNORE_PIN_PA03 1 diff --git a/ports/atmel-samd/boards/grandcentral_m4_express/board.c b/ports/atmel-samd/boards/grandcentral_m4_express/board.c index 360b5d8f9..7599f02b8 100644 --- a/ports/atmel-samd/boards/grandcentral_m4_express/board.c +++ b/ports/atmel-samd/boards/grandcentral_m4_express/board.c @@ -29,13 +29,6 @@ #include "hal/include/hal_gpio.h" void board_init(void) { - gpio_set_pin_function(MICROPY_HW_LED_TX, GPIO_PIN_FUNCTION_OFF); - gpio_set_pin_direction(MICROPY_HW_LED_TX, GPIO_DIRECTION_OUT); - gpio_set_pin_level(MICROPY_HW_LED_TX, true); - - gpio_set_pin_function(MICROPY_HW_LED_RX, GPIO_PIN_FUNCTION_OFF); - gpio_set_pin_direction(MICROPY_HW_LED_RX, GPIO_DIRECTION_OUT); - gpio_set_pin_level(MICROPY_HW_LED_RX, true); } bool board_requests_safe_mode(void) { diff --git a/ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.h b/ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.h index 231bf20e0..0d2d65ba5 100644 --- a/ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.h @@ -5,8 +5,8 @@ // This is for Rev A which is green -#define MICROPY_HW_LED_TX PIN_PC30 -#define MICROPY_HW_LED_RX PIN_PC31 +#define MICROPY_HW_LED_TX &(pin_PC30) +#define MICROPY_HW_LED_RX &(pin_PC31) #define MICROPY_HW_NEOPIXEL (&pin_PC24) @@ -27,13 +27,6 @@ #define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000 - CIRCUITPY_INTERNAL_NVM_SIZE) -#include "external_flash/devices.h" - -#define EXTERNAL_FLASH_DEVICE_COUNT 1 -#define EXTERNAL_FLASH_DEVICES GD25Q64C - -#include "external_flash/external_flash.h" - #define BOARD_HAS_CRYSTAL 1 #define DEFAULT_I2C_BUS_SCL (&pin_PB21) diff --git a/ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.mk index 3e8717ecf..2605c9f55 100644 --- a/ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.mk @@ -5,6 +5,9 @@ USB_PRODUCT = "Grand Central M4 Express" USB_MANUFACTURER = "Adafruit Industries LLC" QSPI_FLASH_FILESYSTEM = 1 + +EXTERNAL_FLASH_DEVICE_COUNT = 1 +EXTERNAL_FLASH_DEVICES = "GD25Q64C" LONGINT_IMPL = MPZ CHIP_VARIANT = SAMD51P20A diff --git a/ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.h b/ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.h index 8450882b9..5869c01ff 100644 --- a/ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.h @@ -3,51 +3,24 @@ #define MICROPY_HW_NEOPIXEL (&pin_PA12) -// Clock rates are off: Saleae reads 12MHz which is the limit even though we set it to the safer 8MHz. -#define SPI_FLASH_BAUDRATE (8000000) - -#define SPI_FLASH_MOSI_PIN PIN_PB10 -#define SPI_FLASH_MISO_PIN PIN_PA13 -#define SPI_FLASH_SCK_PIN PIN_PB11 -#define SPI_FLASH_CS_PIN PIN_PA07 -#define SPI_FLASH_MOSI_PIN_FUNCTION PINMUX_PB10D_SERCOM4_PAD2 -#define SPI_FLASH_MISO_PIN_FUNCTION PINMUX_PA13D_SERCOM4_PAD1 -#define SPI_FLASH_SCK_PIN_FUNCTION PINMUX_PB11D_SERCOM4_PAD3 -#define SPI_FLASH_SERCOM SERCOM4 -#define SPI_FLASH_SERCOM_INDEX 4 -#define SPI_FLASH_MOSI_PAD 2 -#define SPI_FLASH_MISO_PAD 1 -#define SPI_FLASH_SCK_PAD 3 -// <o> Transmit Data Pinout -// <0x0=>PAD[0,1]_DO_SCK -// <0x1=>PAD[2,3]_DO_SCK -// <0x2=>PAD[3,1]_DO_SCK -// <0x3=>PAD[0,3]_DO_SCK -#define SPI_FLASH_DOPO 0x1 -#define SPI_FLASH_DIPO 1 // same as MISO pad +#define SPI_FLASH_MOSI_PIN &pin_PB10 +#define SPI_FLASH_MISO_PIN &pin_PA13 +#define SPI_FLASH_SCK_PIN &pin_PB11 +#define SPI_FLASH_CS_PIN &pin_PA07 // These are pins not to reset. -#define MICROPY_PORT_A ( PORT_PA01 | PORT_PA07 | PORT_PA12 | PORT_PA13 | PORT_PA24 | PORT_PA25 | PORT_PA27 | PORT_PA28) -#define MICROPY_PORT_B ( PORT_PB10 | PORT_PB11 | PORT_PB22 | PORT_PB23 ) +// NeoPixel and for the display: Reset, Command or data, and Chip select +#define MICROPY_PORT_A ( PORT_PA01 | PORT_PA12 | PORT_PA27 | PORT_PA28) +// Data and Clock for the display +#define MICROPY_PORT_B ( PORT_PB22 | PORT_PB23 ) #define MICROPY_PORT_C ( 0 ) -#include "external_flash/external_flash.h" - // If you change this, then make sure to update the linker scripts as well to // make sure you don't overwrite code. #define CIRCUITPY_INTERNAL_NVM_SIZE 256 #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE) -#include "external_flash/devices.h" - -#define EXTERNAL_FLASH_DEVICE_COUNT 2 - -#define EXTERNAL_FLASH_DEVICES W25Q64JV_IQ, \ - GD25Q64C - -#include "external_flash/external_flash.h" - #define DEFAULT_I2C_BUS_SCL (&pin_PA17) #define DEFAULT_I2C_BUS_SDA (&pin_PA16) diff --git a/ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.mk b/ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.mk index 817d93943..37f1bdef0 100644 --- a/ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.mk @@ -5,6 +5,8 @@ USB_PRODUCT = "HalloWing M0 Express" USB_MANUFACTURER = "Adafruit Industries LLC" SPI_FLASH_FILESYSTEM = 1 +EXTERNAL_FLASH_DEVICE_COUNT = 2 +EXTERNAL_FLASH_DEVICES = "W25Q64JV_IQ, GD25Q64C" LONGINT_IMPL = MPZ CHIP_VARIANT = SAMD21G18A diff --git a/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.h b/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.h index f56f57c46..4de28d388 100644 --- a/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.h @@ -5,32 +5,14 @@ #define MICROPY_HW_APA102_MOSI (&pin_PA01) #define MICROPY_HW_APA102_SCK (&pin_PA00) -// Saleae reads 12mhz which is the limit even though we set it to the safer 8mhz. -#define SPI_FLASH_BAUDRATE (8000000) - -#define SPI_FLASH_MOSI_PIN PIN_PB22 -#define SPI_FLASH_MISO_PIN PIN_PB03 -#define SPI_FLASH_SCK_PIN PIN_PB23 -#define SPI_FLASH_CS_PIN PIN_PA27 -#define SPI_FLASH_MOSI_PIN_FUNCTION PINMUX_PB22D_SERCOM5_PAD2 -#define SPI_FLASH_MISO_PIN_FUNCTION PINMUX_PB03D_SERCOM5_PAD1 -#define SPI_FLASH_SCK_PIN_FUNCTION PINMUX_PB23D_SERCOM5_PAD3 -#define SPI_FLASH_SERCOM SERCOM5 -#define SPI_FLASH_SERCOM_INDEX 5 -#define SPI_FLASH_MOSI_PAD 2 -#define SPI_FLASH_MISO_PAD 1 -#define SPI_FLASH_SCK_PAD 3 -// <o> Transmit Data Pinout -// <0x0=>PAD[0,1]_DO_SCK -// <0x1=>PAD[2,3]_DO_SCK -// <0x2=>PAD[3,1]_DO_SCK -// <0x3=>PAD[0,3]_DO_SCK -#define SPI_FLASH_DOPO 1 -#define SPI_FLASH_DIPO 1 // same as MISO pad +#define SPI_FLASH_MOSI_PIN &pin_PB22 +#define SPI_FLASH_MISO_PIN &pin_PB03 +#define SPI_FLASH_SCK_PIN &pin_PB23 +#define SPI_FLASH_CS_PIN &pin_PA27 // These are pins not to reset. -#define MICROPY_PORT_A (PORT_PA00 | PORT_PA01 | PORT_PA27 | PORT_PA24 | PORT_PA25) -#define MICROPY_PORT_B (PORT_PB22 | PORT_PB23 | PORT_PB03 ) +#define MICROPY_PORT_A (PORT_PA00 | PORT_PA01) +#define MICROPY_PORT_B (0) #define MICROPY_PORT_C (0) // If you change this, then make sure to update the linker scripts as well to @@ -39,14 +21,6 @@ #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE) -#include "external_flash/devices.h" - -#define EXTERNAL_FLASH_DEVICE_COUNT 2 -#define EXTERNAL_FLASH_DEVICES W25Q16FW, \ - GD25Q16C - -#include "external_flash/external_flash.h" - #define DEFAULT_I2C_BUS_SCL (&pin_PA23) #define DEFAULT_I2C_BUS_SDA (&pin_PA22) diff --git a/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.mk b/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.mk index 9f62ae839..8fcf5208f 100644 --- a/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.mk @@ -5,6 +5,8 @@ USB_PRODUCT = "ItsyBitsy M0 Express" USB_MANUFACTURER = "Adafruit Industries LLC" SPI_FLASH_FILESYSTEM = 1 +EXTERNAL_FLASH_DEVICE_COUNT = 2 +EXTERNAL_FLASH_DEVICES = "W25Q16FW, GD25Q16C" LONGINT_IMPL = MPZ CHIP_VARIANT = SAMD21G18A diff --git a/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.h b/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.h index e47d5390d..5bbfec9ce 100644 --- a/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.h @@ -25,13 +25,6 @@ #define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000 - CIRCUITPY_INTERNAL_NVM_SIZE) -#include "external_flash/devices.h" - -#define EXTERNAL_FLASH_DEVICE_COUNT 1 -#define EXTERNAL_FLASH_DEVICES GD25Q16C - -#include "external_flash/external_flash.h" - #define DEFAULT_I2C_BUS_SCL (&pin_PA13) #define DEFAULT_I2C_BUS_SDA (&pin_PA12) diff --git a/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk index 27f5ea2b8..2afff5965 100644 --- a/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk @@ -5,6 +5,8 @@ USB_PRODUCT = "ItsyBitsy M4 Express" USB_MANUFACTURER = "Adafruit Industries LLC" QSPI_FLASH_FILESYSTEM = 1 +EXTERNAL_FLASH_DEVICE_COUNT = 1 +EXTERNAL_FLASH_DEVICES = GD25Q16C LONGINT_IMPL = MPZ CHIP_VARIANT = SAMD51G19A diff --git a/ports/atmel-samd/boards/meowmeow/board.c b/ports/atmel-samd/boards/meowmeow/board.c new file mode 100644 index 000000000..881e15e0c --- /dev/null +++ b/ports/atmel-samd/boards/meowmeow/board.c @@ -0,0 +1,38 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Andrés Sabas for Electronic Cats + * + * 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 "boards/board.h" + +void board_init(void) +{ +} + +bool board_requests_safe_mode(void) { + return false; +} + +void reset_board(void) { +} diff --git a/ports/atmel-samd/boards/meowmeow/mpconfigboard.h b/ports/atmel-samd/boards/meowmeow/mpconfigboard.h new file mode 100644 index 000000000..f07eb9cce --- /dev/null +++ b/ports/atmel-samd/boards/meowmeow/mpconfigboard.h @@ -0,0 +1,32 @@ +#define MICROPY_HW_BOARD_NAME "Meow Meow" +#define MICROPY_HW_MCU_NAME "samd21g18" + +// These are pins not to reset. +#define MICROPY_PORT_A (0) +#define MICROPY_PORT_B (0) +#define MICROPY_PORT_C (0) + +// If you change this, then make sure to update the linker scripts as well to +// make sure you don't overwrite code. +#define CIRCUITPY_INTERNAL_NVM_SIZE 0 + +#define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - 0x010000) + +#define CALIBRATE_CRYSTALLESS 1 + +// Explanation of how a user got into safe mode. +#define BOARD_USER_SAFE_MODE_ACTION "pressing both buttons at start up" + +#define DEFAULT_I2C_BUS_SCL (&pin_PA01) +#define DEFAULT_I2C_BUS_SDA (&pin_PA00) + +#define DEFAULT_SPI_BUS_SCK (&pin_PA15) +#define DEFAULT_SPI_BUS_MOSI (&pin_PA14) +#define DEFAULT_SPI_BUS_MISO (&pin_PA12) + +#define DEFAULT_UART_BUS_RX (&pin_PA11) +#define DEFAULT_UART_BUS_TX (&pin_PA10) + +// USB is always used internally so skip the pin objects for it. +#define IGNORE_PIN_PA24 1 +#define IGNORE_PIN_PA25 1 diff --git a/ports/atmel-samd/boards/meowmeow/mpconfigboard.mk b/ports/atmel-samd/boards/meowmeow/mpconfigboard.mk new file mode 100644 index 000000000..31015ad17 --- /dev/null +++ b/ports/atmel-samd/boards/meowmeow/mpconfigboard.mk @@ -0,0 +1,11 @@ +LD_FILE = boards/samd21x18-bootloader.ld +USB_VID = 0xBAB1 +USB_PID = 0x1209 +USB_PRODUCT = "Meow Meow" +USB_MANUFACTURER = "Electronic Cats" + +INTERNAL_FLASH_FILESYSTEM = 1 +LONGINT_IMPL = NONE + +CHIP_VARIANT = SAMD21G18A +CHIP_FAMILY = samd21
\ No newline at end of file diff --git a/ports/atmel-samd/boards/meowmeow/pins.c b/ports/atmel-samd/boards/meowmeow/pins.c new file mode 100644 index 000000000..59c51f4eb --- /dev/null +++ b/ports/atmel-samd/boards/meowmeow/pins.c @@ -0,0 +1,43 @@ +#include "shared-bindings/board/__init__.h" + +#include "board_busses.h" + +STATIC const mp_rom_map_elem_t board_global_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA02) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_PA03) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_PA04) }, + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_PA05) }, + { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_PA06) }, + { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_PA07) }, + { MP_ROM_QSTR(MP_QSTR_A6), MP_ROM_PTR(&pin_PB02) }, + { MP_ROM_QSTR(MP_QSTR_A7), MP_ROM_PTR(&pin_PB03) }, + { MP_ROM_QSTR(MP_QSTR_A8), MP_ROM_PTR(&pin_PB08) }, + { MP_ROM_QSTR(MP_QSTR_A9), MP_ROM_PTR(&pin_PB09) }, + { MP_ROM_QSTR(MP_QSTR_A10), MP_ROM_PTR(&pin_PA11) }, + { MP_ROM_QSTR(MP_QSTR_A11), MP_ROM_PTR(&pin_PA09) }, + { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_PA11) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_PA11) }, + { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_PA10) }, + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_PA10) }, + { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_PB02) }, + { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_PB03) }, + { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_PA14) }, + { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_PA05) }, + { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_PA15) }, + { MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_PB22) }, + { MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_PA06) }, + { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_PA07) }, + { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_PA30) }, + { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_PA31) }, + { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_PA02) }, + { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_PB23) }, + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_PA00) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_PA01) }, + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_PA15) }, + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PA14) }, + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_PA12) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.h b/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.h index 40ef3ce78..f08d129dc 100644 --- a/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.h @@ -1,37 +1,23 @@ #define MICROPY_HW_BOARD_NAME "Adafruit Metro M0 Express" #define MICROPY_HW_MCU_NAME "samd21g18" -#define MICROPY_HW_LED_TX PIN_PA27 -//#define MICROPY_HW_LED_RX PIN_PA31 +#define MICROPY_HW_LED_TX &pin_PA27 +// Comment this out if you have trouble connecting over SWD. It's one of the SWD pins. +#define MICROPY_HW_LED_RX &pin_PA31 #define MICROPY_HW_NEOPIXEL (&pin_PA30) // Clock rates are off: Salae reads 12MHz which is the limit even though we set it to the safer 8MHz. #define SPI_FLASH_BAUDRATE (8000000) -#define SPI_FLASH_MOSI_PIN PIN_PB22 -#define SPI_FLASH_MISO_PIN PIN_PB03 -#define SPI_FLASH_SCK_PIN PIN_PB23 -#define SPI_FLASH_CS_PIN PIN_PA13 -#define SPI_FLASH_MOSI_PIN_FUNCTION PINMUX_PB22D_SERCOM5_PAD2 -#define SPI_FLASH_MISO_PIN_FUNCTION PINMUX_PB03D_SERCOM5_PAD1 -#define SPI_FLASH_SCK_PIN_FUNCTION PINMUX_PB23D_SERCOM5_PAD3 -#define SPI_FLASH_SERCOM SERCOM5 -#define SPI_FLASH_SERCOM_INDEX 5 -#define SPI_FLASH_MOSI_PAD 2 -#define SPI_FLASH_MISO_PAD 1 -#define SPI_FLASH_SCK_PAD 3 -// <o> Transmit Data Pinout -// <0x0=>PAD[0,1]_DO_SCK -// <0x1=>PAD[2,3]_DO_SCK -// <0x2=>PAD[3,1]_DO_SCK -// <0x3=>PAD[0,3]_DO_SCK -#define SPI_FLASH_DOPO 1 -#define SPI_FLASH_DIPO 1 // same as MISO pad +#define SPI_FLASH_MOSI_PIN &pin_PB22 +#define SPI_FLASH_MISO_PIN &pin_PB03 +#define SPI_FLASH_SCK_PIN &pin_PB23 +#define SPI_FLASH_CS_PIN &pin_PA13 // These are pins not to reset. -#define MICROPY_PORT_A (PORT_PA13 |PORT_PA24 | PORT_PA25 | PORT_PA27 | PORT_PA30 | PORT_PA31) -#define MICROPY_PORT_B (PORT_PB03 | PORT_PB22 | PORT_PB23) +#define MICROPY_PORT_A (0) +#define MICROPY_PORT_B (0) #define MICROPY_PORT_C (0) // If you change this, then make sure to update the linker scripts as well to @@ -40,14 +26,6 @@ #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE) -#include "external_flash/devices.h" - -#define EXTERNAL_FLASH_DEVICE_COUNT 2 -#define EXTERNAL_FLASH_DEVICES S25FL216K, \ - GD25Q16C - -#include "external_flash/external_flash.h" - #define BOARD_HAS_CRYSTAL 1 #define DEFAULT_I2C_BUS_SCL (&pin_PA23) diff --git a/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk b/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk index 0388a408b..49a94144b 100644 --- a/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk @@ -9,3 +9,10 @@ LONGINT_IMPL = MPZ CHIP_VARIANT = SAMD21G18A CHIP_FAMILY = samd21 + +MICROPY_PY_NETWORK = 1 +MICROPY_PY_WIZNET5K = 5500 + +SPI_FLASH_FILESYSTEM = 1 +EXTERNAL_FLASH_DEVICE_COUNT = 2 +EXTERNAL_FLASH_DEVICES = "S25FL216K, GD25Q16C" diff --git a/ports/atmel-samd/boards/metro_m4_express/board.c b/ports/atmel-samd/boards/metro_m4_express/board.c index a98385d29..0f60736a2 100644 --- a/ports/atmel-samd/boards/metro_m4_express/board.c +++ b/ports/atmel-samd/boards/metro_m4_express/board.c @@ -29,13 +29,6 @@ #include "hal/include/hal_gpio.h" void board_init(void) { - gpio_set_pin_function(MICROPY_HW_LED_TX, GPIO_PIN_FUNCTION_OFF); - gpio_set_pin_direction(MICROPY_HW_LED_TX, GPIO_DIRECTION_OUT); - gpio_set_pin_level(MICROPY_HW_LED_TX, true); - - gpio_set_pin_function(MICROPY_HW_LED_RX, GPIO_PIN_FUNCTION_OFF); - gpio_set_pin_direction(MICROPY_HW_LED_RX, GPIO_DIRECTION_OUT); - gpio_set_pin_level(MICROPY_HW_LED_RX, true); } bool board_requests_safe_mode(void) { diff --git a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h index f1201c8a0..06feb1a22 100644 --- a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h @@ -5,16 +5,16 @@ // This is for Rev F which is green -#define MICROPY_HW_LED_TX PIN_PA27 -#define MICROPY_HW_LED_RX PIN_PB06 +#define MICROPY_HW_LED_TX (&pin_PA27) +#define MICROPY_HW_LED_RX (&pin_PB06) #define MICROPY_HW_NEOPIXEL (&pin_PB22) // These are pins not to reset. -// QSPI Data pins and TX LED -#define MICROPY_PORT_A (PORT_PA08 | PORT_PA09 | PORT_PA10 | PORT_PA11 | PORT_PA27) -// RX LED, QSPI CS, QSPI SCK and NeoPixel pin -#define MICROPY_PORT_B ( PORT_PB06 | PORT_PB10 | PORT_PB11 | PORT_PB22) +// QSPI Data pins +#define MICROPY_PORT_A (PORT_PA08 | PORT_PA09 | PORT_PA10 | PORT_PA11) +// QSPI CS, QSPI SCK and NeoPixel pin +#define MICROPY_PORT_B (PORT_PB10 | PORT_PB11 | PORT_PB22) #define MICROPY_PORT_C (0) #define MICROPY_PORT_D (0) @@ -26,13 +26,6 @@ #define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000 - CIRCUITPY_INTERNAL_NVM_SIZE) -#include "external_flash/devices.h" - -#define EXTERNAL_FLASH_DEVICE_COUNT 3 -#define EXTERNAL_FLASH_DEVICES S25FL116K, S25FL216K, GD25Q16C - -#include "external_flash/external_flash.h" - #define BOARD_HAS_CRYSTAL 1 #define DEFAULT_I2C_BUS_SCL (&pin_PB03) diff --git a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk index 38e8a12d7..633856362 100644 --- a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk @@ -5,7 +5,13 @@ USB_PRODUCT = "Metro M4 Express" USB_MANUFACTURER = "Adafruit Industries LLC" QSPI_FLASH_FILESYSTEM = 1 +EXTERNAL_FLASH_DEVICE_COUNT = 3 +EXTERNAL_FLASH_DEVICES = "S25FL116K, S25FL216K, GD25Q16C" + LONGINT_IMPL = MPZ CHIP_VARIANT = SAMD51J19A CHIP_FAMILY = samd51 + +MICROPY_PY_NETWORK = 1 +MICROPY_PY_WIZNET5K = 5500 diff --git a/ports/atmel-samd/boards/pirkey_m0/mpconfigboard.h b/ports/atmel-samd/boards/pirkey_m0/mpconfigboard.h index 15979ae77..cbbd4b569 100644 --- a/ports/atmel-samd/boards/pirkey_m0/mpconfigboard.h +++ b/ports/atmel-samd/boards/pirkey_m0/mpconfigboard.h @@ -15,8 +15,6 @@ // A number of modules are removed for pIRKey to make room for frozen libraries. #define PIRKEY_M0 (1) -#include "internal_flash.h" - #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - 0x010000) #define IGNORE_PIN_PA02 1 diff --git a/ports/atmel-samd/boards/pirkey_m0/mpconfigboard.mk b/ports/atmel-samd/boards/pirkey_m0/mpconfigboard.mk index 0f8d0f9ca..ddc262a57 100644 --- a/ports/atmel-samd/boards/pirkey_m0/mpconfigboard.mk +++ b/ports/atmel-samd/boards/pirkey_m0/mpconfigboard.mk @@ -10,6 +10,8 @@ LONGINT_IMPL = NONE CHIP_VARIANT = SAMD21E18A CHIP_FAMILY = samd21 +CFLAGS_INLINE_LIMIT = 45 + # Include these Python libraries in firmware. FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_DotStar FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_HID diff --git a/ports/atmel-samd/boards/trellis_m4_express/board.c b/ports/atmel-samd/boards/trellis_m4_express/board.c index 0f60736a2..a9b5f8163 100644 --- a/ports/atmel-samd/boards/trellis_m4_express/board.c +++ b/ports/atmel-samd/boards/trellis_m4_express/board.c @@ -24,9 +24,14 @@ * THE SOFTWARE. */ +#include <string.h> + #include "boards/board.h" -#include "mpconfigboard.h" -#include "hal/include/hal_gpio.h" +#include "py/mpconfig.h" + +#include "common-hal/digitalio/DigitalInOut.h" +#include "shared-bindings/digitalio/DigitalInOut.h" +#include "shared-bindings/neopixel_write/__init__.h" void board_init(void) { } @@ -36,4 +41,11 @@ bool board_requests_safe_mode(void) { } void reset_board(void) { + uint8_t zeroes[96]; + memset(zeroes, 0, 96); + digitalio_digitalinout_obj_t neopixel; + common_hal_digitalio_digitalinout_construct(&neopixel, &pin_PA27); + common_hal_digitalio_digitalinout_switch_to_output(&neopixel, false, DRIVE_MODE_PUSH_PULL); + common_hal_neopixel_write(&neopixel, zeroes, 96); + common_hal_digitalio_digitalinout_deinit(&neopixel); } diff --git a/ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.h b/ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.h index 117a8ae8e..6870b86ba 100644 --- a/ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.h @@ -1,19 +1,20 @@ + #define MICROPY_HW_BOARD_NAME "Adafruit Trellis M4 Express" #define MICROPY_HW_MCU_NAME "samd51g19" #define CIRCUITPY_MCU_FAMILY samd51 -// This is for Rev A -#define MICROPY_HW_APA102_MOSI (&pin_PA01) -#define MICROPY_HW_APA102_SCK (&pin_PA00) +// This is for Rev D +#define MICROPY_HW_APA102_MOSI (&pin_PB03) +#define MICROPY_HW_APA102_SCK (&pin_PB02) #define CIRCUITPY_BITBANG_APA102 // These are pins not to reset. -// QSPI Data pins & DotStar pins -#define MICROPY_PORT_A (PORT_PA00 | PORT_PA01 | PORT_PA08 | PORT_PA09 | PORT_PA10 | PORT_PA11) -// QSPI CS, and QSPI SCK -#define MICROPY_PORT_B (PORT_PB10 | PORT_PB11) +// QSPI Data pins +#define MICROPY_PORT_A (PORT_PA08 | PORT_PA09 | PORT_PA10 | PORT_PA11) +// DotStar Pins, QSPI CS, and QSPI SCK +#define MICROPY_PORT_B (PORT_PB02 | PORT_PB03 | PORT_PB10 | PORT_PB11) #define MICROPY_PORT_C (0) #define MICROPY_PORT_D (0) @@ -25,13 +26,6 @@ #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE) -#include "external_flash/devices.h" - -#define EXTERNAL_FLASH_DEVICE_COUNT 1 -#define EXTERNAL_FLASH_DEVICES GD25Q64C - -#include "external_flash/external_flash.h" - #define DEFAULT_I2C_BUS_SCL (&pin_PB08) #define DEFAULT_I2C_BUS_SDA (&pin_PB09) diff --git a/ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.mk index 3841a87c7..7094b79be 100644 --- a/ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.mk @@ -5,6 +5,8 @@ USB_PRODUCT = "Trellis M4 Express" USB_MANUFACTURER = "Adafruit Industries LLC" QSPI_FLASH_FILESYSTEM = 1 +EXTERNAL_FLASH_DEVICE_COUNT = 1 +EXTERNAL_FLASH_DEVICES = GD25Q64C LONGINT_IMPL = MPZ CHIP_VARIANT = SAMD51G19A diff --git a/ports/atmel-samd/boards/trellis_m4_express/pins.c b/ports/atmel-samd/boards/trellis_m4_express/pins.c index 57abfeba4..9626f525f 100644 --- a/ports/atmel-samd/boards/trellis_m4_express/pins.c +++ b/ports/atmel-samd/boards/trellis_m4_express/pins.c @@ -15,6 +15,9 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_PB08) }, { MP_OBJ_NEW_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_PB09) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_ACCELEROMETER_SDA), MP_ROM_PTR(&pin_PA12) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_ACCELEROMETER_SCL), MP_ROM_PTR(&pin_PA13) }, + // Key Grid columns { MP_OBJ_NEW_QSTR(MP_QSTR_COL0), MP_ROM_PTR(&pin_PA14) }, { MP_OBJ_NEW_QSTR(MP_QSTR_COL1), MP_ROM_PTR(&pin_PA15) }, @@ -36,8 +39,8 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = { // NeoPixels { MP_OBJ_NEW_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_PA27) }, - { MP_ROM_QSTR(MP_QSTR_APA102_MOSI), MP_ROM_PTR(&pin_PA01) }, - { MP_ROM_QSTR(MP_QSTR_APA102_SCK), MP_ROM_PTR(&pin_PA00) }, + { MP_ROM_QSTR(MP_QSTR_APA102_MOSI), MP_ROM_PTR(&pin_PB03) }, + { MP_ROM_QSTR(MP_QSTR_APA102_SCK), MP_ROM_PTR(&pin_PB02) }, { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, }; diff --git a/ports/atmel-samd/boards/trinket_m0/mpconfigboard.h b/ports/atmel-samd/boards/trinket_m0/mpconfigboard.h index 9036f8e7b..c311f540c 100644 --- a/ports/atmel-samd/boards/trinket_m0/mpconfigboard.h +++ b/ports/atmel-samd/boards/trinket_m0/mpconfigboard.h @@ -5,12 +5,10 @@ #define MICROPY_HW_APA102_MOSI (&pin_PA00) #define MICROPY_HW_APA102_SCK (&pin_PA01) -#define MICROPY_PORT_A (PORT_PA00 | PORT_PA01 | PORT_PA24 | PORT_PA25) +#define MICROPY_PORT_A (PORT_PA00 | PORT_PA01) #define MICROPY_PORT_B (0) #define MICROPY_PORT_C (0) -#include "internal_flash.h" - #define CIRCUITPY_INTERNAL_NVM_SIZE 0 #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - 0x010000) diff --git a/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.h b/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.h index 8e3fdd7a8..dfbd873b6 100644 --- a/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.h +++ b/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.h @@ -5,56 +5,24 @@ // #define MICROPY_HW_APA102_MOSI (&pin_PA00) // #define MICROPY_HW_APA102_SCK (&pin_PA01) -// Salae reads 12mhz which is the limit even though we set it to the -// safer 8mhz. -#define SPI_FLASH_BAUDRATE (8000000) - -#define SPI_FLASH_MOSI_PIN PIN_PA16 -#define SPI_FLASH_MISO_PIN PIN_PA19 -#define SPI_FLASH_SCK_PIN PIN_PA17 -#define SPI_FLASH_CS_PIN PIN_PA11 -#define SPI_FLASH_MOSI_PIN_FUNCTION PINMUX_PA16D_SERCOM3_PAD0 -#define SPI_FLASH_MISO_PIN_FUNCTION PINMUX_PA19D_SERCOM3_PAD3 -#define SPI_FLASH_SCK_PIN_FUNCTION PINMUX_PA17D_SERCOM3_PAD1 -#define SPI_FLASH_SERCOM SERCOM3 -#define SPI_FLASH_SERCOM_INDEX 3 -#define SPI_FLASH_MOSI_PAD 0 -#define SPI_FLASH_MISO_PAD 3 -#define SPI_FLASH_SCK_PAD 1 -// <o> Transmit Data Pinout -// <0x0=>PAD[0,1]_DO_SCK -// <0x1=>PAD[2,3]_DO_SCK -// <0x2=>PAD[3,1]_DO_SCK -// <0x3=>PAD[0,3]_DO_SCK -#define SPI_FLASH_DOPO 0 -#define SPI_FLASH_DIPO 3 // same as MISO pad - -#define SPI_FLASH_CS PIN_PA11 +#define SPI_FLASH_MOSI_PIN &pin_PA16 +#define SPI_FLASH_MISO_PIN &pin_PA19 +#define SPI_FLASH_SCK_PIN &pin_PA17 +#define SPI_FLASH_CS_PIN &pin_PA11 // These are pins not to reset. -#define MICROPY_PORT_A (PORT_PA00 | PORT_PA01 | PORT_PA11 | PORT_PA16 |\ - PORT_PA17 | PORT_PA18 | PORT_PA19 | PORT_PA24 |\ - PORT_PA25) +#define MICROPY_PORT_A (PORT_PA00 | PORT_PA01 | PORT_PA18) #define MICROPY_PORT_B (0) #define MICROPY_PORT_C (0) #define CALIBRATE_CRYSTALLESS 1 -#include "external_flash/external_flash.h" - // If you change this, then make sure to update the linker scripts as well to // make sure you don't overwrite code. #define CIRCUITPY_INTERNAL_NVM_SIZE 256 #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE) -#include "external_flash/devices.h" - -#define EXTERNAL_FLASH_DEVICE_COUNT 1 -#define EXTERNAL_FLASH_DEVICES W25Q32BV - -#include "external_flash/external_flash.h" - #define DEFAULT_I2C_BUS_SCL (&pin_PA09) #define DEFAULT_I2C_BUS_SDA (&pin_PA08) diff --git a/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk b/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk index d97aa08ab..c9c196da7 100644 --- a/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk +++ b/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk @@ -5,6 +5,8 @@ USB_PRODUCT="Trinket M0 Haxpress" USB_MANUFACTURER="Radomir Dopieralski" SPI_FLASH_FILESYSTEM = 1 +EXTERNAL_FLASH_DEVICE_COUNT = 1 +EXTERNAL_FLASH_DEVICES = W25Q32BV LONGINT_IMPL = MPZ CHIP_VARIANT = SAMD21E18A diff --git a/ports/atmel-samd/boards/ugame10/mpconfigboard.h b/ports/atmel-samd/boards/ugame10/mpconfigboard.h index ed822952d..c22a3f735 100644 --- a/ports/atmel-samd/boards/ugame10/mpconfigboard.h +++ b/ports/atmel-samd/boards/ugame10/mpconfigboard.h @@ -1,53 +1,24 @@ #define MICROPY_HW_BOARD_NAME "uGame10" #define MICROPY_HW_MCU_NAME "samd21e18" -// Salae reads 12mhz which is the limit even though we set it to the -// safer 8mhz. -#define SPI_FLASH_BAUDRATE (8000000) - -#define SPI_FLASH_MOSI_PIN PIN_PA16 -#define SPI_FLASH_MISO_PIN PIN_PA19 -#define SPI_FLASH_SCK_PIN PIN_PA17 -#define SPI_FLASH_CS_PIN PIN_PA18 -#define SPI_FLASH_MOSI_PIN_FUNCTION PINMUX_PA16D_SERCOM3_PAD0 -#define SPI_FLASH_MISO_PIN_FUNCTION PINMUX_PA19D_SERCOM3_PAD3 -#define SPI_FLASH_SCK_PIN_FUNCTION PINMUX_PA17D_SERCOM3_PAD1 -#define SPI_FLASH_SERCOM SERCOM3 -#define SPI_FLASH_SERCOM_INDEX 3 -#define SPI_FLASH_MOSI_PAD 0 -#define SPI_FLASH_MISO_PAD 3 -#define SPI_FLASH_SCK_PAD 1 -// <o> Transmit Data Pinout -// <0x0=>PAD[0,1]_DO_SCK -// <0x1=>PAD[2,3]_DO_SCK -// <0x2=>PAD[3,1]_DO_SCK -// <0x3=>PAD[0,3]_DO_SCK -#define SPI_FLASH_DOPO 0 -#define SPI_FLASH_DIPO 3 // same as MISO pad +#define SPI_FLASH_MOSI_PIN &pin_PA16 +#define SPI_FLASH_MISO_PIN &pin_PA19 +#define SPI_FLASH_SCK_PIN &pin_PA17 +#define SPI_FLASH_CS_PIN &pin_PA18 // These are pins not to reset. -#define MICROPY_PORT_A (PORT_PA16 | PORT_PA17 | PORT_PA18 | PORT_PA19 |\ - PORT_PA24 | PORT_PA25) +#define MICROPY_PORT_A (0) #define MICROPY_PORT_B (0) #define MICROPY_PORT_C (0) #define CALIBRATE_CRYSTALLESS 1 -#include "external_flash/external_flash.h" - // If you change this, then make sure to update the linker scripts as well to // make sure you don't overwrite code. #define CIRCUITPY_INTERNAL_NVM_SIZE 256 #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE) -#include "external_flash/devices.h" - -#define EXTERNAL_FLASH_DEVICE_COUNT 1 -#define EXTERNAL_FLASH_DEVICES S25FL216K - -#include "external_flash/external_flash.h" - #define EXTRA_BUILTIN_MODULES \ { MP_OBJ_NEW_QSTR(MP_QSTR_audioio), (mp_obj_t)&audioio_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_gamepad),(mp_obj_t)&gamepad_module }, \ diff --git a/ports/atmel-samd/boards/ugame10/mpconfigboard.mk b/ports/atmel-samd/boards/ugame10/mpconfigboard.mk index 2386531f9..6dc0af9cf 100644 --- a/ports/atmel-samd/boards/ugame10/mpconfigboard.mk +++ b/ports/atmel-samd/boards/ugame10/mpconfigboard.mk @@ -6,6 +6,8 @@ USB_PRODUCT = "uGame10" USB_MANUFACTURER = "Radomir Dopieralski" SPI_FLASH_FILESYSTEM = 1 +EXTERNAL_FLASH_DEVICE_COUNT = 1 +EXTERNAL_FLASH_DEVICES = S25FL216K LONGINT_IMPL = MPZ CHIP_VARIANT = SAMD21E18A diff --git a/ports/atmel-samd/common-hal/analogio/AnalogOut.c b/ports/atmel-samd/common-hal/analogio/AnalogOut.c index 2e42abdd4..19475e00b 100644 --- a/ports/atmel-samd/common-hal/analogio/AnalogOut.c +++ b/ports/atmel-samd/common-hal/analogio/AnalogOut.c @@ -138,16 +138,5 @@ void common_hal_analogio_analogout_set_value(analogio_analogout_obj_t *self, } void analogout_reset(void) { - #if defined(SAMD21) && !defined(PIN_PA02) - return; - #endif - #ifdef SAMD21 - while (DAC->STATUS.reg & DAC_STATUS_SYNCBUSY) {} - #endif - #ifdef SAMD51 - while (DAC->SYNCBUSY.reg & DAC_SYNCBUSY_SWRST) {} - #endif - DAC->CTRLA.reg |= DAC_CTRLA_SWRST; - - // TODO(tannewt): Turn off the DAC clocks to save power. + // AudioOut resets the DAC in case its been used for audio which requires special handling. } diff --git a/ports/atmel-samd/common-hal/audioio/AudioOut.c b/ports/atmel-samd/common-hal/audioio/AudioOut.c index 0592775a5..596f3214a 100644 --- a/ports/atmel-samd/common-hal/audioio/AudioOut.c +++ b/ports/atmel-samd/common-hal/audioio/AudioOut.c @@ -33,6 +33,7 @@ #include "py/runtime.h" #include "common-hal/audioio/AudioOut.h" #include "shared-bindings/audioio/AudioOut.h" +#include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/microcontroller/Pin.h" #include "supervisor/shared/translate.h" @@ -52,11 +53,73 @@ #include "samd/pins.h" #include "samd/timers.h" +#ifdef SAMD21 +static void ramp_value(uint16_t start, uint16_t end) { + start = DAC->DATA.reg; + int32_t diff = (int32_t) end - start; + int32_t step = 49; + int32_t steps = diff / step; + if (diff < 0) { + steps = -steps; + step = -step; + } + for (int32_t i = 0; i < steps; i++) { + uint32_t value = start + step * i; + DAC->DATA.reg = value; + DAC->DATABUF.reg = value; + common_hal_mcu_delay_us(50); + #ifdef MICROPY_VM_HOOK_LOOP + MICROPY_VM_HOOK_LOOP + #endif + } +} +#endif + +#ifdef SAMD51 +static void ramp_value(uint16_t start, uint16_t end) { + int32_t diff = (int32_t) end - start; + int32_t step = 49; + int32_t steps = diff / step; + if (diff < 0) { + steps = -steps; + step = -step; + } + + for (int32_t i = 0; i < steps; i++) { + uint16_t value = start + step * i; + DAC->DATA[0].reg = value; + DAC->DATABUF[0].reg = value; + DAC->DATA[1].reg = value; + DAC->DATABUF[1].reg = value; + + common_hal_mcu_delay_us(50); + #ifdef MICROPY_VM_HOOK_LOOP + MICROPY_VM_HOOK_LOOP + #endif + } +} +#endif + void audioout_reset(void) { + #if defined(SAMD21) && !defined(PIN_PA02) + return; + #endif + #ifdef SAMD21 + while (DAC->STATUS.reg & DAC_STATUS_SYNCBUSY) {} + #endif + #ifdef SAMD51 + while (DAC->SYNCBUSY.reg & DAC_SYNCBUSY_SWRST) {} + #endif + if (DAC->CTRLA.bit.ENABLE) { + ramp_value(0x8000, 0); + } + DAC->CTRLA.reg |= DAC_CTRLA_SWRST; + + // TODO(tannewt): Turn off the DAC clocks to save power. } void common_hal_audioio_audioout_construct(audioio_audioout_obj_t* self, - const mcu_pin_obj_t* left_channel, const mcu_pin_obj_t* right_channel) { + const mcu_pin_obj_t* left_channel, const mcu_pin_obj_t* right_channel, uint16_t quiescent_value) { #ifdef SAMD51 bool dac_clock_enabled = hri_mclk_get_APBDMASK_DAC_bit(MCLK); #endif @@ -94,12 +157,10 @@ void common_hal_audioio_audioout_construct(audioio_audioout_obj_t* self, if (right_channel != NULL) { claim_pin(right_channel); self->right_channel = right_channel; - gpio_set_pin_function(self->right_channel->number, GPIO_PIN_FUNCTION_B); audio_dma_init(&self->right_dma); } #endif self->left_channel = left_channel; - gpio_set_pin_function(self->left_channel->number, GPIO_PIN_FUNCTION_B); audio_dma_init(&self->left_dma); #ifdef SAMD51 @@ -118,6 +179,10 @@ void common_hal_audioio_audioout_construct(audioio_audioout_obj_t* self, DAC->CTRLA.bit.SWRST = 1; while (DAC->CTRLA.bit.SWRST == 1) {} + // Make sure there are no outstanding access errors. (Reading DATA can cause this.) + #ifdef SAMD51 + PAC->INTFLAGD.reg = PAC_INTFLAGD_DAC; + #endif bool channel0_enabled = true; #ifdef SAMD51 @@ -159,6 +224,8 @@ void common_hal_audioio_audioout_construct(audioio_audioout_obj_t* self, #endif #ifdef SAMD51 while (DAC->SYNCBUSY.bit.ENABLE == 1) {} + while (channel0_enabled && DAC->STATUS.bit.READY0 == 0) {} + while (channel1_enabled && DAC->STATUS.bit.READY1 == 0) {} #endif // Use a timer to coordinate when DAC conversions occur. @@ -220,13 +287,21 @@ void common_hal_audioio_audioout_construct(audioio_audioout_obj_t* self, #ifdef SAMD51 connect_event_user_to_channel(EVSYS_ID_USER_DAC_START_1, channel); + if (right_channel != NULL) { + gpio_set_pin_function(self->right_channel->number, GPIO_PIN_FUNCTION_B); + } #define EVSYS_ID_USER_DAC_START EVSYS_ID_USER_DAC_START_0 #endif connect_event_user_to_channel(EVSYS_ID_USER_DAC_START, channel); + gpio_set_pin_function(self->left_channel->number, GPIO_PIN_FUNCTION_B); init_async_event_channel(channel, tc_gen_id); self->tc_to_dac_event_channel = channel; + // Ramp the DAC up. + self->quiescent_value = quiescent_value; + ramp_value(0, quiescent_value); + // Leave the DMA setup to playback. } @@ -239,6 +314,9 @@ void common_hal_audioio_audioout_deinit(audioio_audioout_obj_t* self) { return; } + // Ramp the DAC down. + ramp_value(self->quiescent_value, 0); + DAC->CTRLA.bit.ENABLE = 0; #ifdef SAMD21 while (DAC->STATUS.bit.SYNCBUSY == 1) {} @@ -381,6 +459,9 @@ void common_hal_audioio_audioout_stop(audioio_audioout_obj_t* self) { #ifdef SAMD51 audio_dma_stop(&self->right_dma); #endif + // Ramp the DAC to default. The start is ignored when the current value can be readback. + // Otherwise, we just set it immediately. + ramp_value(self->quiescent_value, self->quiescent_value); } bool common_hal_audioio_audioout_get_playing(audioio_audioout_obj_t* self) { diff --git a/ports/atmel-samd/common-hal/audioio/AudioOut.h b/ports/atmel-samd/common-hal/audioio/AudioOut.h index efbfe2a1d..56b6b75c8 100644 --- a/ports/atmel-samd/common-hal/audioio/AudioOut.h +++ b/ports/atmel-samd/common-hal/audioio/AudioOut.h @@ -44,6 +44,7 @@ typedef struct { uint8_t tc_to_dac_event_channel; bool playing; + uint16_t quiescent_value; } audioio_audioout_obj_t; void audioout_reset(void); diff --git a/ports/atmel-samd/common-hal/busio/SPI.c b/ports/atmel-samd/common-hal/busio/SPI.c index a292f9e3d..4de34c975 100644 --- a/ports/atmel-samd/common-hal/busio/SPI.c +++ b/ports/atmel-samd/common-hal/busio/SPI.c @@ -31,6 +31,8 @@ #include "hpl_sercom_config.h" #include "peripheral_clk_config.h" +#include "boards/board.h" +#include "common-hal/microcontroller/Pin.h" #include "hal/include/hal_gpio.h" #include "hal/include/hal_spi_m_sync.h" #include "hal/include/hpl_spi_m_sync.h" @@ -39,6 +41,43 @@ #include "samd/dma.h" #include "samd/sercom.h" +bool never_reset_sercoms[SERCOM_INST_NUM]; + +void never_reset_sercom(Sercom* sercom) { + // Reset all SERCOMs except the ones being used by on-board devices. + Sercom *sercom_instances[SERCOM_INST_NUM] = SERCOM_INSTS; + for (int i = 0; i < SERCOM_INST_NUM; i++) { + if (sercom_instances[i] == sercom) { + never_reset_sercoms[i] = true; + break; + } + } +} + +void reset_sercoms(void) { + // Reset all SERCOMs except the ones being used by on-board devices. + Sercom *sercom_instances[SERCOM_INST_NUM] = SERCOM_INSTS; + for (int i = 0; i < SERCOM_INST_NUM; i++) { + if (never_reset_sercoms[i]) { + continue; + } + #ifdef MICROPY_HW_APA102_SERCOM + if (sercom_instances[i] == MICROPY_HW_APA102_SERCOM) { + continue; + } + #endif + #ifdef CIRCUITPY_DISPLAYIO + // TODO(tannewt): Make this dynamic. + if (sercom_instances[i] == board_display_obj.bus.spi_desc.dev.prvt) { + continue; + } + #endif + // SWRST is same for all modes of SERCOMs. + sercom_instances[i]->SPI.CTRLA.bit.SWRST = 1; + } +} + + void common_hal_busio_spi_construct(busio_spi_obj_t *self, const mcu_pin_obj_t * clock, const mcu_pin_obj_t * mosi, const mcu_pin_obj_t * miso) { @@ -186,6 +225,14 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, spi_m_sync_enable(&self->spi_desc); } +void common_hal_busio_spi_never_reset(busio_spi_obj_t *self) { + never_reset_sercom(self->spi_desc.dev.prvt); + + never_reset_pin_number(self->clock_pin); + never_reset_pin_number(self->MOSI_pin); + never_reset_pin_number(self->MISO_pin); +} + bool common_hal_busio_spi_deinited(busio_spi_obj_t *self) { return self->clock_pin == NO_PIN; } diff --git a/ports/atmel-samd/common-hal/busio/SPI.h b/ports/atmel-samd/common-hal/busio/SPI.h index 2fced6d64..56d163a9d 100644 --- a/ports/atmel-samd/common-hal/busio/SPI.h +++ b/ports/atmel-samd/common-hal/busio/SPI.h @@ -42,4 +42,7 @@ typedef struct { uint8_t MISO_pin; } busio_spi_obj_t; +void reset_sercoms(void); + + #endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_BUSIO_SPI_H diff --git a/ports/atmel-samd/common-hal/microcontroller/Pin.c b/ports/atmel-samd/common-hal/microcontroller/Pin.c index 0f179a6c1..7dd9c6b09 100644 --- a/ports/atmel-samd/common-hal/microcontroller/Pin.c +++ b/ports/atmel-samd/common-hal/microcontroller/Pin.c @@ -43,15 +43,19 @@ bool apa102_mosi_in_use; bool speaker_enable_in_use; #endif +#define PORT_COUNT (PORT_BITS / 32 + 1) + +STATIC uint32_t never_reset_pins[PORT_COUNT]; + void reset_all_pins(void) { - uint32_t pin_mask[PORT_BITS / 32 + 1] = PORT_OUT_IMPLEMENTED; + uint32_t pin_mask[PORT_COUNT] = PORT_OUT_IMPLEMENTED; // Do not full reset USB or SWD lines. pin_mask[0] &= ~(PORT_PA24 | PORT_PA25 | PORT_PA30 | PORT_PA31); - #ifdef SAMD21 - pin_mask[0] &= ~(PORT_PA31); - #endif + for (uint32_t i = 0; i < PORT_COUNT; i++) { + pin_mask[i] &= ~never_reset_pins[i]; + } gpio_set_port_direction(GPIO_PORTA, pin_mask[0] & ~MICROPY_PORT_A, GPIO_DIRECTION_OFF); gpio_set_port_direction(GPIO_PORTB, pin_mask[1] & ~MICROPY_PORT_B, GPIO_DIRECTION_OFF); @@ -91,6 +95,10 @@ void reset_all_pins(void) { #endif } +void never_reset_pin_number(uint8_t pin_number) { + never_reset_pins[GPIO_PORT(pin_number)] |= 1 << GPIO_PIN(pin_number); +} + void reset_pin_number(uint8_t pin_number) { if (pin_number >= PORT_BITS) { return; diff --git a/ports/atmel-samd/common-hal/microcontroller/Pin.h b/ports/atmel-samd/common-hal/microcontroller/Pin.h index dcd80997e..f798ea300 100644 --- a/ports/atmel-samd/common-hal/microcontroller/Pin.h +++ b/ports/atmel-samd/common-hal/microcontroller/Pin.h @@ -43,6 +43,7 @@ void reset_all_pins(void); // reset_pin_number takes the pin number instead of the pointer so that objects don't // need to store a full pointer. void reset_pin_number(uint8_t pin_number); +void never_reset_pin_number(uint8_t pin_number); void claim_pin(const mcu_pin_obj_t* pin); #endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_MICROCONTROLLER_PIN_H diff --git a/ports/atmel-samd/common-hal/microcontroller/__init__.c b/ports/atmel-samd/common-hal/microcontroller/__init__.c index 746207787..0ca3a0835 100644 --- a/ports/atmel-samd/common-hal/microcontroller/__init__.c +++ b/ports/atmel-samd/common-hal/microcontroller/__init__.c @@ -107,7 +107,6 @@ const nvm_bytearray_obj_t common_hal_mcu_nvm_obj = { // This maps MCU pin names to pin objects. STATIC const mp_rom_map_elem_t mcu_pin_global_dict_table[] = { -// Pins in datasheet order. #if defined(PIN_PA00) && !defined(IGNORE_PIN_PA00) { MP_ROM_QSTR(MP_QSTR_PA00), MP_ROM_PTR(&pin_PA00) }, #endif @@ -120,24 +119,6 @@ STATIC const mp_rom_map_elem_t mcu_pin_global_dict_table[] = { #if defined(PIN_PA03) && !defined(IGNORE_PIN_PA03) { MP_ROM_QSTR(MP_QSTR_PA03), MP_ROM_PTR(&pin_PA03) }, #endif -#if defined(PIN_PB04) && !defined(IGNORE_PIN_PB04) - { MP_ROM_QSTR(MP_QSTR_PB04), MP_ROM_PTR(&pin_PB04) }, -#endif -#if defined(PIN_PB05) && !defined(IGNORE_PIN_PB05) - { MP_ROM_QSTR(MP_QSTR_PB05), MP_ROM_PTR(&pin_PB05) }, -#endif -#if defined(PIN_PB06) && !defined(IGNORE_PIN_PB06) - { MP_ROM_QSTR(MP_QSTR_PB06), MP_ROM_PTR(&pin_PB06) }, -#endif -#if defined(PIN_PB07) && !defined(IGNORE_PIN_PB07) - { MP_ROM_QSTR(MP_QSTR_PB07), MP_ROM_PTR(&pin_PB07) }, -#endif -#if defined(PIN_PB08) && !defined(IGNORE_PIN_PB08) - { MP_ROM_QSTR(MP_QSTR_PB08), MP_ROM_PTR(&pin_PB08) }, -#endif -#if defined(PIN_PB09) && !defined(IGNORE_PIN_PB09) - { MP_ROM_QSTR(MP_QSTR_PB09), MP_ROM_PTR(&pin_PB09) }, -#endif #if defined(PIN_PA04) && !defined(IGNORE_PIN_PA04) { MP_ROM_QSTR(MP_QSTR_PA04), MP_ROM_PTR(&pin_PA04) }, #endif @@ -162,26 +143,6 @@ STATIC const mp_rom_map_elem_t mcu_pin_global_dict_table[] = { #if defined(PIN_PA11) && !defined(IGNORE_PIN_PA11) { MP_ROM_QSTR(MP_QSTR_PA11), MP_ROM_PTR(&pin_PA11) }, #endif -#if defined(PIN_PB10) && !defined(IGNORE_PIN_PB10) - { MP_ROM_QSTR(MP_QSTR_PB10), MP_ROM_PTR(&pin_PB10) }, -#endif -#if defined(PIN_PB11) && !defined(IGNORE_PIN_PB11) - { MP_ROM_QSTR(MP_QSTR_PB11), MP_ROM_PTR(&pin_PB11) }, -#endif -#if defined(PIN_PB12) && !defined(IGNORE_PIN_PB12) - { MP_ROM_QSTR(MP_QSTR_PB12), MP_ROM_PTR(&pin_PB12) }, -#endif -#if defined(PIN_PB13) && !defined(IGNORE_PIN_PB13) - { MP_ROM_QSTR(MP_QSTR_PB13), MP_ROM_PTR(&pin_PB13) }, -#endif -#if defined(PIN_PB14) && !defined(IGNORE_PIN_PB14) - { MP_ROM_QSTR(MP_QSTR_PB14), MP_ROM_PTR(&pin_PB14) }, -#endif - -// Second page. -#if defined(PIN_PB15) && !defined(IGNORE_PIN_PB15) - { MP_ROM_QSTR(MP_QSTR_PB15), MP_ROM_PTR(&pin_PB15) }, -#endif #if defined(PIN_PA12) && !defined(IGNORE_PIN_PA12) { MP_ROM_QSTR(MP_QSTR_PA12), MP_ROM_PTR(&pin_PA12) }, #endif @@ -206,12 +167,6 @@ STATIC const mp_rom_map_elem_t mcu_pin_global_dict_table[] = { #if defined(PIN_PA19) && !defined(IGNORE_PIN_PA19) { MP_ROM_QSTR(MP_QSTR_PA19), MP_ROM_PTR(&pin_PA19) }, #endif -#if defined(PIN_PB16) && !defined(IGNORE_PIN_PB16) - { MP_ROM_QSTR(MP_QSTR_PB16), MP_ROM_PTR(&pin_PB16) }, -#endif -#if defined(PIN_PB17) && !defined(IGNORE_PIN_PB17) - { MP_ROM_QSTR(MP_QSTR_PB17), MP_ROM_PTR(&pin_PB17) }, -#endif #if defined(PIN_PA20) && !defined(IGNORE_PIN_PA20) { MP_ROM_QSTR(MP_QSTR_PA20), MP_ROM_PTR(&pin_PA20) }, #endif @@ -230,12 +185,6 @@ STATIC const mp_rom_map_elem_t mcu_pin_global_dict_table[] = { #if defined(PIN_PA25) && !defined(IGNORE_PIN_PA25) { MP_ROM_QSTR(MP_QSTR_PA25), MP_ROM_PTR(&pin_PA25) }, #endif -#if defined(PIN_PB22) && !defined(IGNORE_PIN_PB22) - { MP_ROM_QSTR(MP_QSTR_PB22), MP_ROM_PTR(&pin_PB22) }, -#endif -#if defined(PIN_PB23) && !defined(IGNORE_PIN_PB23) - { MP_ROM_QSTR(MP_QSTR_PB23), MP_ROM_PTR(&pin_PB23) }, -#endif #if defined(PIN_PA27) && !defined(IGNORE_PIN_PA27) { MP_ROM_QSTR(MP_QSTR_PA27), MP_ROM_PTR(&pin_PA27) }, #endif @@ -248,12 +197,7 @@ STATIC const mp_rom_map_elem_t mcu_pin_global_dict_table[] = { #if defined(PIN_PA31) && !defined(IGNORE_PIN_PA31) { MP_ROM_QSTR(MP_QSTR_PA31), MP_ROM_PTR(&pin_PA31) }, #endif -#if defined(PIN_PB30) && !defined(IGNORE_PIN_PB30) - { MP_ROM_QSTR(MP_QSTR_PB30), MP_ROM_PTR(&pin_PB30) }, -#endif -#if defined(PIN_PB31) && !defined(IGNORE_PIN_PB31) - { MP_ROM_QSTR(MP_QSTR_PB31), MP_ROM_PTR(&pin_PB31) }, -#endif + #if defined(PIN_PB00) && !defined(IGNORE_PIN_PB00) { MP_ROM_QSTR(MP_QSTR_PB00), MP_ROM_PTR(&pin_PB00) }, #endif @@ -266,14 +210,176 @@ STATIC const mp_rom_map_elem_t mcu_pin_global_dict_table[] = { #if defined(PIN_PB03) && !defined(IGNORE_PIN_PB03) { MP_ROM_QSTR(MP_QSTR_PB03), MP_ROM_PTR(&pin_PB03) }, #endif +#if defined(PIN_PB04) && !defined(IGNORE_PIN_PB04) + { MP_ROM_QSTR(MP_QSTR_PB04), MP_ROM_PTR(&pin_PB04) }, +#endif +#if defined(PIN_PB05) && !defined(IGNORE_PIN_PB05) + { MP_ROM_QSTR(MP_QSTR_PB05), MP_ROM_PTR(&pin_PB05) }, +#endif +#if defined(PIN_PB06) && !defined(IGNORE_PIN_PB06) + { MP_ROM_QSTR(MP_QSTR_PB06), MP_ROM_PTR(&pin_PB06) }, +#endif +#if defined(PIN_PB07) && !defined(IGNORE_PIN_PB07) + { MP_ROM_QSTR(MP_QSTR_PB07), MP_ROM_PTR(&pin_PB07) }, +#endif +#if defined(PIN_PB08) && !defined(IGNORE_PIN_PB08) + { MP_ROM_QSTR(MP_QSTR_PB08), MP_ROM_PTR(&pin_PB08) }, +#endif +#if defined(PIN_PB09) && !defined(IGNORE_PIN_PB09) + { MP_ROM_QSTR(MP_QSTR_PB09), MP_ROM_PTR(&pin_PB09) }, +#endif +#if defined(PIN_PB10) && !defined(IGNORE_PIN_PB10) + { MP_ROM_QSTR(MP_QSTR_PB10), MP_ROM_PTR(&pin_PB10) }, +#endif +#if defined(PIN_PB11) && !defined(IGNORE_PIN_PB11) + { MP_ROM_QSTR(MP_QSTR_PB11), MP_ROM_PTR(&pin_PB11) }, +#endif +#if defined(PIN_PB12) && !defined(IGNORE_PIN_PB12) + { MP_ROM_QSTR(MP_QSTR_PB12), MP_ROM_PTR(&pin_PB12) }, +#endif +#if defined(PIN_PB13) && !defined(IGNORE_PIN_PB13) + { MP_ROM_QSTR(MP_QSTR_PB13), MP_ROM_PTR(&pin_PB13) }, +#endif +#if defined(PIN_PB14) && !defined(IGNORE_PIN_PB14) + { MP_ROM_QSTR(MP_QSTR_PB14), MP_ROM_PTR(&pin_PB14) }, +#endif +#if defined(PIN_PB15) && !defined(IGNORE_PIN_PB15) + { MP_ROM_QSTR(MP_QSTR_PB15), MP_ROM_PTR(&pin_PB15) }, +#endif +#if defined(PIN_PB16) && !defined(IGNORE_PIN_PB16) + { MP_ROM_QSTR(MP_QSTR_PB16), MP_ROM_PTR(&pin_PB16) }, +#endif +#if defined(PIN_PB17) && !defined(IGNORE_PIN_PB17) + { MP_ROM_QSTR(MP_QSTR_PB17), MP_ROM_PTR(&pin_PB17) }, +#endif +#if defined(PIN_PB22) && !defined(IGNORE_PIN_PB22) + { MP_ROM_QSTR(MP_QSTR_PB22), MP_ROM_PTR(&pin_PB22) }, +#endif +#if defined(PIN_PB23) && !defined(IGNORE_PIN_PB23) + { MP_ROM_QSTR(MP_QSTR_PB23), MP_ROM_PTR(&pin_PB23) }, +#endif +#if defined(PIN_PB30) && !defined(IGNORE_PIN_PB30) + { MP_ROM_QSTR(MP_QSTR_PB30), MP_ROM_PTR(&pin_PB30) }, +#endif +#if defined(PIN_PB31) && !defined(IGNORE_PIN_PB31) + { MP_ROM_QSTR(MP_QSTR_PB31), MP_ROM_PTR(&pin_PB31) }, +#endif + +// These are SAMD51 specific so we assume we want them in RAM +#if defined(PIN_PC00) + { MP_ROM_QSTR(MP_QSTR_PC00), MP_ROM_PTR(&pin_PC00) }, +#endif +#if defined(PIN_PC01) + { MP_ROM_QSTR(MP_QSTR_PC01), MP_ROM_PTR(&pin_PC01) }, +#endif +#if defined(PIN_PC02) + { MP_ROM_QSTR(MP_QSTR_PC02), MP_ROM_PTR(&pin_PC02) }, +#endif +#if defined(PIN_PC03) + { MP_ROM_QSTR(MP_QSTR_PC03), MP_ROM_PTR(&pin_PC03) }, +#endif +#if defined(PIN_PC04) + { MP_ROM_QSTR(MP_QSTR_PC04), MP_ROM_PTR(&pin_PC04) }, +#endif +#if defined(PIN_PC05) + { MP_ROM_QSTR(MP_QSTR_PC05), MP_ROM_PTR(&pin_PC05) }, +#endif +#if defined(PIN_PC06) + { MP_ROM_QSTR(MP_QSTR_PC06), MP_ROM_PTR(&pin_PC06) }, +#endif +#if defined(PIN_PC07) + { MP_ROM_QSTR(MP_QSTR_PC07), MP_ROM_PTR(&pin_PC07) }, +#endif +#if defined(PIN_PC10) + { MP_ROM_QSTR(MP_QSTR_PC10), MP_ROM_PTR(&pin_PC10) }, +#endif +#if defined(PIN_PC11) + { MP_ROM_QSTR(MP_QSTR_PC11), MP_ROM_PTR(&pin_PC11) }, +#endif +#if defined(PIN_PC12) + { MP_ROM_QSTR(MP_QSTR_PC12), MP_ROM_PTR(&pin_PC12) }, +#endif +#if defined(PIN_PC13) + { MP_ROM_QSTR(MP_QSTR_PC13), MP_ROM_PTR(&pin_PC13) }, +#endif +#if defined(PIN_PC14) + { MP_ROM_QSTR(MP_QSTR_PC14), MP_ROM_PTR(&pin_PC14) }, +#endif +#if defined(PIN_PC15) + { MP_ROM_QSTR(MP_QSTR_PC15), MP_ROM_PTR(&pin_PC15) }, +#endif #if defined(PIN_PC16) { MP_ROM_QSTR(MP_QSTR_PC16), MP_ROM_PTR(&pin_PC16) }, #endif +#if defined(PIN_PC17) + { MP_ROM_QSTR(MP_QSTR_PC17), MP_ROM_PTR(&pin_PC17) }, +#endif #if defined(PIN_PC18) { MP_ROM_QSTR(MP_QSTR_PC18), MP_ROM_PTR(&pin_PC18) }, #endif #if defined(PIN_PC19) { MP_ROM_QSTR(MP_QSTR_PC19), MP_ROM_PTR(&pin_PC19) }, #endif +#if defined(PIN_PC20) + { MP_ROM_QSTR(MP_QSTR_PC20), MP_ROM_PTR(&pin_PC20) }, +#endif +#if defined(PIN_PC21) + { MP_ROM_QSTR(MP_QSTR_PC21), MP_ROM_PTR(&pin_PC21) }, +#endif +#if defined(PIN_PC22) + { MP_ROM_QSTR(MP_QSTR_PC22), MP_ROM_PTR(&pin_PC22) }, +#endif +#if defined(PIN_PC23) + { MP_ROM_QSTR(MP_QSTR_PC23), MP_ROM_PTR(&pin_PC23) }, +#endif +#if defined(PIN_PC24) + { MP_ROM_QSTR(MP_QSTR_PC24), MP_ROM_PTR(&pin_PC24) }, +#endif +#if defined(PIN_PC25) + { MP_ROM_QSTR(MP_QSTR_PC25), MP_ROM_PTR(&pin_PC25) }, +#endif +#if defined(PIN_PC26) + { MP_ROM_QSTR(MP_QSTR_PC26), MP_ROM_PTR(&pin_PC26) }, +#endif +#if defined(PIN_PC27) + { MP_ROM_QSTR(MP_QSTR_PC27), MP_ROM_PTR(&pin_PC27) }, +#endif +#if defined(PIN_PC28) + { MP_ROM_QSTR(MP_QSTR_PC28), MP_ROM_PTR(&pin_PC28) }, +#endif +#if defined(PIN_PC30) + { MP_ROM_QSTR(MP_QSTR_PC30), MP_ROM_PTR(&pin_PC30) }, +#endif +#if defined(PIN_PC31) + { MP_ROM_QSTR(MP_QSTR_PC31), MP_ROM_PTR(&pin_PC31) }, +#endif + +#if defined(PIN_PD00) + { MP_ROM_QSTR(MP_QSTR_PD00), MP_ROM_PTR(&pin_PD00) }, +#endif +#if defined(PIN_PD01) + { MP_ROM_QSTR(MP_QSTR_PD01), MP_ROM_PTR(&pin_PD01) }, +#endif +#if defined(PIN_PD08) + { MP_ROM_QSTR(MP_QSTR_PD08), MP_ROM_PTR(&pin_PD08) }, +#endif +#if defined(PIN_PD09) + { MP_ROM_QSTR(MP_QSTR_PD09), MP_ROM_PTR(&pin_PD09) }, +#endif +#if defined(PIN_PD10) + { MP_ROM_QSTR(MP_QSTR_PD10), MP_ROM_PTR(&pin_PD10) }, +#endif +#if defined(PIN_PD11) + { MP_ROM_QSTR(MP_QSTR_PD11), MP_ROM_PTR(&pin_PD11) }, +#endif +#if defined(PIN_PD12) + { MP_ROM_QSTR(MP_QSTR_PD12), MP_ROM_PTR(&pin_PD12) }, +#endif +#if defined(PIN_PD20) + { MP_ROM_QSTR(MP_QSTR_PD20), MP_ROM_PTR(&pin_PD20) }, +#endif +#if defined(PIN_PD21) + { MP_ROM_QSTR(MP_QSTR_PD21), MP_ROM_PTR(&pin_PD21) }, +#endif }; MP_DEFINE_CONST_DICT(mcu_pin_globals, mcu_pin_global_dict_table); diff --git a/ports/atmel-samd/common-hal/neopixel_write/__init__.c b/ports/atmel-samd/common-hal/neopixel_write/__init__.c index b30ad47d4..57e963c91 100644 --- a/ports/atmel-samd/common-hal/neopixel_write/__init__.c +++ b/ports/atmel-samd/common-hal/neopixel_write/__init__.c @@ -48,6 +48,11 @@ } #endif +// Ensure this code is compiled with -Os. Any other optimization level may change the timing of it +// and break neopixels. +#pragma GCC push_options +#pragma GCC optimize ("Os") + uint64_t next_start_tick_ms = 0; uint32_t next_start_tick_us = 1000; @@ -183,3 +188,5 @@ void common_hal_neopixel_write(const digitalio_digitalinout_obj_t* digitalinout, mp_hal_enable_all_interrupts(); } + +#pragma GCC pop_options diff --git a/ports/atmel-samd/common-hal/supervisor/Runtime.c b/ports/atmel-samd/common-hal/supervisor/Runtime.c index 8efe7cb78..6be38f216 100755 --- a/ports/atmel-samd/common-hal/supervisor/Runtime.c +++ b/ports/atmel-samd/common-hal/supervisor/Runtime.c @@ -26,9 +26,12 @@ #include <stdbool.h> #include "shared-bindings/supervisor/Runtime.h" -#include "usb.h" +#include "supervisor/serial.h" bool common_hal_get_serial_connected(void) { - return (bool) usb_connected(); + return (bool) serial_connected(); } +bool common_hal_get_serial_bytes_available(void) { + return (bool) serial_bytes_available(); +} diff --git a/ports/atmel-samd/common-hal/usb_hid/Device.c b/ports/atmel-samd/common-hal/usb_hid/Device.c deleted file mode 100644 index 31bace018..000000000 --- a/ports/atmel-samd/common-hal/usb_hid/Device.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2017 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. - */ - -#include <string.h> - -#include "common-hal/usb_hid/Device.h" - -#include "py/runtime.h" -#include "shared-bindings/microcontroller/__init__.h" -#include "shared-bindings/usb_hid/Device.h" -#include "supervisor/shared/translate.h" -#include "genhdr/autogen_usb_descriptor.h" - -#include "tick.h" - -#include "usb/class/hid/device/hiddf_generic.h" - -static uint32_t usb_hid_send_report(usb_hid_device_obj_t *self, uint8_t* report, uint8_t len) { - - int32_t status; - - // Don't get stuck if USB fails in some way; timeout after a while. - uint64_t end_ticks = ticks_ms + 2000; - - while (ticks_ms < end_ticks) { - status = usb_d_ep_get_status(self->endpoint, NULL); - if (status == USB_BUSY) { - continue; - } - if (status == USB_OK) { - break; - } - // Some error. Give up. - return status; - } - - // Copy the data only when endpoint is ready to send. The previous - // buffer load gets zero'd out when transaction completes, so if - // you copy before it's ready, only zeros will get sent. - - // Prefix with a report id if one is supplied. - if (self->report_id > 0) { - self->report_buffer[0] = self->report_id; - memcpy(&(self->report_buffer[1]), report, len); - return hiddf_generic_write(self->report_buffer, len + 1); - } else { - memcpy(self->report_buffer, report, len); - return hiddf_generic_write(self->report_buffer, len); - } - -} - -void common_hal_usb_hid_device_send_report(usb_hid_device_obj_t *self, uint8_t* report, uint8_t len) { - if (len != self->report_length) { - mp_raise_ValueError_varg(translate("Buffer incorrect size. Should be %d bytes."), self->report_length); - } - int32_t status = usb_hid_send_report(self, report, len); - if (status != ERR_NONE) { - mp_raise_msg(&mp_type_OSError, status == USB_BUSY ? translate("USB Busy") : translate("USB Error")); - } -} - -uint8_t common_hal_usb_hid_device_get_usage_page(usb_hid_device_obj_t *self) { - return self->usage_page; -} - -uint8_t common_hal_usb_hid_device_get_usage(usb_hid_device_obj_t *self) { - return self->usage; -} - - -void usb_hid_init() { -} - -void usb_hid_reset() { - // We don't actually reset. We just set a report that is empty to prevent - // long keypresses and such. - uint8_t report[USB_HID_MAX_REPORT_LENGTH] = {0}; - - for (size_t i = 0; i < USB_HID_NUM_DEVICES; i++) { - usb_hid_send_report(&usb_hid_devices[i], report, usb_hid_devices[i].report_length); - } -} diff --git a/ports/atmel-samd/common-hal/usb_hid/__init__.c b/ports/atmel-samd/common-hal/usb_hid/__init__.c deleted file mode 100644 index 770d221c7..000000000 --- a/ports/atmel-samd/common-hal/usb_hid/__init__.c +++ /dev/null @@ -1,152 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2017 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. - */ - -#include "py/obj.h" -#include "py/mphal.h" -#include "py/runtime.h" - -#include "common-hal/usb_hid/Device.h" - -#include "shared-bindings/usb_hid/Device.h" - -#include "genhdr/autogen_usb_descriptor.h" - -// Buffers are report size + 1 to include the Report ID prefix byte if needed. -#ifdef USB_HID_REPORT_ID_KEYBOARD -static uint8_t keyboard_report_buffer[USB_HID_REPORT_LENGTH_KEYBOARD + 1]; -#endif -#ifdef USB_HID_REPORT_ID_MOUSE -static uint8_t mouse_report_buffer[USB_HID_REPORT_LENGTH_MOUSE + 1]; -#endif -#ifdef USB_HID_REPORT_ID_CONSUMER -static uint8_t consumer_report_buffer[USB_HID_REPORT_LENGTH_CONSUMER + 1]; -#endif -#ifdef USB_HID_REPORT_ID_SYS_CONTROL -static uint8_t sys_control_report_buffer[USB_HID_REPORT_LENGTH_SYS_CONTROL + 1]; -#endif -#ifdef USB_HID_REPORT_ID_GAMEPAD -static uint8_t gamepad_report_buffer[USB_HID_REPORT_LENGTH_GAMEPAD + 1]; -#endif -#ifdef USB_HID_REPORT_ID_DIGITIZER -static uint8_t digitizer_report_buffer[USB_HID_REPORT_LENGTH_DIGITIZER + 1]; -#endif - -usb_hid_device_obj_t usb_hid_devices[USB_HID_NUM_DEVICES] = { -#ifdef USB_HID_REPORT_ID_KEYBOARD - { - .base = { .type = &usb_hid_device_type }, - .report_buffer = keyboard_report_buffer, - .endpoint = USB_HID_ENDPOINT_IN, - .report_id = USB_HID_REPORT_ID_KEYBOARD, - .report_length = USB_HID_REPORT_LENGTH_KEYBOARD, - .usage_page = 0x01, - .usage = 0x06, - }, -#endif -#ifdef USB_HID_REPORT_ID_MOUSE - { - .base = { .type = &usb_hid_device_type }, - .report_buffer = mouse_report_buffer, - .endpoint = USB_HID_ENDPOINT_IN, - .report_id = USB_HID_REPORT_ID_MOUSE, - .report_length = USB_HID_REPORT_LENGTH_MOUSE, - .usage_page = 0x01, - .usage = 0x02, - }, -#endif -#ifdef USB_HID_REPORT_ID_CONSUMER - { - .base = { .type = &usb_hid_device_type }, - .report_buffer = consumer_report_buffer, - .endpoint = USB_HID_ENDPOINT_IN, - .report_id = USB_HID_REPORT_ID_CONSUMER, - .report_length = USB_HID_REPORT_LENGTH_CONSUMER, - .usage_page = 0x0C, - .usage = 0x01, - }, -#endif -#ifdef USB_HID_REPORT_ID_SYS_CONTROL - { - .base = { .type = &usb_hid_device_type }, - .report_buffer = sys_control_report_buffer, - .endpoint = USB_HID_ENDPOINT_IN, - .report_id = USB_HID_REPORT_ID_SYS_CONTROL, - .report_length = USB_HID_REPORT_LENGTH_SYS_CONTROL, - .usage_page = 0x01, - .usage = 0x80, - }, -#endif -#ifdef USB_HID_REPORT_ID_GAMEPAD - { - .base = { .type = &usb_hid_device_type }, - .report_buffer = gamepad_report_buffer, - .endpoint = USB_HID_ENDPOINT_IN, - .report_id = USB_HID_REPORT_ID_GAMEPAD, - .report_length = USB_HID_REPORT_LENGTH_GAMEPAD, - .usage_page = 0x01, - .usage = 0x05, - }, -#endif -#ifdef USB_HID_REPORT_ID_DIGITIZER - { - .base = { .type = &usb_hid_device_type }, - .report_buffer = digitizer_report_buffer, - .endpoint = USB_HID_ENDPOINT_IN, - .report_id = USB_HID_REPORT_ID_DIGITIZER, - .report_length = USB_HID_REPORT_LENGTH_DIGITIZER, - .usage_page = 0x0D, - .usage = 0x02, - }, -#endif -}; - - -mp_obj_tuple_t common_hal_usb_hid_devices = { - .base = { - .type = &mp_type_tuple, - }, - .len = USB_HID_NUM_DEVICES, - .items = { -#if USB_HID_NUM_DEVICES >= 1 - (mp_obj_t) &usb_hid_devices[0], -#endif -#if USB_HID_NUM_DEVICES >= 2 - (mp_obj_t) &usb_hid_devices[1], -#endif -#if USB_HID_NUM_DEVICES >= 3 - (mp_obj_t) &usb_hid_devices[2], -#endif -#if USB_HID_NUM_DEVICES >= 4 - (mp_obj_t) &usb_hid_devices[3], -#endif -#if USB_HID_NUM_DEVICES >= 5 - (mp_obj_t) &usb_hid_devices[4], -#endif -#if USB_HID_NUM_DEVICES >= 6 - (mp_obj_t) &usb_hid_devices[5], -#endif - } -}; diff --git a/ports/atmel-samd/external_flash/external_flash.h b/ports/atmel-samd/external_flash/external_flash.h deleted file mode 100644 index f8ec5673c..000000000 --- a/ports/atmel-samd/external_flash/external_flash.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2013, 2014 Damien P. George - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#ifndef MICROPY_INCLUDED_ATMEL_SAMD_EXTERNAL_FLASH_H -#define MICROPY_INCLUDED_ATMEL_SAMD_EXTERNAL_FLASH_H - -#include <stdbool.h> - -#include "mpconfigport.h" - -// We use this when we can allocate the whole cache in RAM. -#define FLASH_ROOT_POINTERS \ - uint8_t** flash_ram_cache; \ - -// Erase sector size. -#define SPI_FLASH_SECTOR_SIZE (0x1000 - 100) - -// These are common across all NOR Flash. -#define SPI_FLASH_ERASE_SIZE (1 << 12) -#define SPI_FLASH_PAGE_SIZE (256) - -#define SPI_FLASH_SYSTICK_MASK (0x1ff) // 512ms -#define SPI_FLASH_IDLE_TICK(tick) (((tick) & SPI_FLASH_SYSTICK_MASK) == 2) - -void external_flash_init(void); -uint32_t external_flash_get_block_size(void); -uint32_t external_flash_get_block_count(void); -void external_flash_irq_handler(void); -void external_flash_flush(void); -bool external_flash_read_block(uint8_t *dest, uint32_t block); -bool external_flash_write_block(const uint8_t *src, uint32_t block); - -// these return 0 on success, non-zero on error -mp_uint_t external_flash_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks); -mp_uint_t external_flash_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks); - -extern const struct _mp_obj_type_t external_flash_type; - -struct _fs_user_mount_t; -void flash_init_vfs(struct _fs_user_mount_t *vfs); - -#endif // MICROPY_INCLUDED_ATMEL_SAMD_EXTERNAL_FLASH_H diff --git a/ports/atmel-samd/internal_flash.c b/ports/atmel-samd/internal_flash.c deleted file mode 100644 index 35eb52da2..000000000 --- a/ports/atmel-samd/internal_flash.c +++ /dev/null @@ -1,285 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2013, 2014 Damien P. George - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include "internal_flash.h" - -#include <stdint.h> -#include <string.h> - -#include "extmod/vfs.h" -#include "extmod/vfs_fat.h" -#include "py/mphal.h" -#include "py/obj.h" -#include "py/runtime.h" -#include "lib/oofatfs/ff.h" - -#ifdef SAMD21 -#include "hpl/pm/hpl_pm_base.h" -#endif -#include "hal/include/hal_flash.h" - -#include "supervisor/shared/rgb_led_status.h" - -static struct flash_descriptor internal_flash_desc; - -void internal_flash_init(void) { - // Activity LED for flash writes. - #ifdef MICROPY_HW_LED_MSC - struct port_config pin_conf; - port_get_config_defaults(&pin_conf); - - pin_conf.direction = PORT_PIN_DIR_OUTPUT; - port_pin_set_config(MICROPY_HW_LED_MSC, &pin_conf); - port_pin_set_output_level(MICROPY_HW_LED_MSC, false); - #endif - - #ifdef SAMD51 - hri_mclk_set_AHBMASK_NVMCTRL_bit(MCLK); - #endif - #ifdef SAMD21 - _pm_enable_bus_clock(PM_BUS_APBB, NVMCTRL); - #endif - flash_init(&internal_flash_desc, NVMCTRL); -} - -uint32_t internal_flash_get_block_size(void) { - return FILESYSTEM_BLOCK_SIZE; -} - -uint32_t internal_flash_get_block_count(void) { - return INTERNAL_FLASH_PART1_START_BLOCK + INTERNAL_FLASH_PART1_NUM_BLOCKS; -} - -void internal_flash_flush(void) { -} - -void flash_flush(void) { - internal_flash_flush(); -} - -static void build_partition(uint8_t *buf, int boot, int type, uint32_t start_block, uint32_t num_blocks) { - buf[0] = boot; - - if (num_blocks == 0) { - buf[1] = 0; - buf[2] = 0; - buf[3] = 0; - } else { - buf[1] = 0xff; - buf[2] = 0xff; - buf[3] = 0xff; - } - - buf[4] = type; - - if (num_blocks == 0) { - buf[5] = 0; - buf[6] = 0; - buf[7] = 0; - } else { - buf[5] = 0xff; - buf[6] = 0xff; - buf[7] = 0xff; - } - - buf[8] = start_block; - buf[9] = start_block >> 8; - buf[10] = start_block >> 16; - buf[11] = start_block >> 24; - - buf[12] = num_blocks; - buf[13] = num_blocks >> 8; - buf[14] = num_blocks >> 16; - buf[15] = num_blocks >> 24; -} - -static int32_t convert_block_to_flash_addr(uint32_t block) { - if (INTERNAL_FLASH_PART1_START_BLOCK <= block && block < INTERNAL_FLASH_PART1_START_BLOCK + INTERNAL_FLASH_PART1_NUM_BLOCKS) { - // a block in partition 1 - block -= INTERNAL_FLASH_PART1_START_BLOCK; - return INTERNAL_FLASH_MEM_SEG1_START_ADDR + block * FILESYSTEM_BLOCK_SIZE; - } - // bad block - return -1; -} - -bool internal_flash_read_block(uint8_t *dest, uint32_t block) { - if (block == 0) { - // fake the MBR so we can decide on our own partition table - - for (int i = 0; i < 446; i++) { - dest[i] = 0; - } - - build_partition(dest + 446, 0, 0x01 /* FAT12 */, INTERNAL_FLASH_PART1_START_BLOCK, INTERNAL_FLASH_PART1_NUM_BLOCKS); - build_partition(dest + 462, 0, 0, 0, 0); - build_partition(dest + 478, 0, 0, 0, 0); - build_partition(dest + 494, 0, 0, 0, 0); - - dest[510] = 0x55; - dest[511] = 0xaa; - - return true; - - } else { - // non-MBR block, get data from flash memory - int32_t src = convert_block_to_flash_addr(block); - if (src == -1) { - // bad block number - return false; - } - int32_t error_code = flash_read(&internal_flash_desc, src, dest, FILESYSTEM_BLOCK_SIZE); - return error_code == ERR_NONE; - } -} - -bool internal_flash_write_block(const uint8_t *src, uint32_t block) { - if (block == 0) { - // can't write MBR, but pretend we did - return true; - - } else { - #ifdef MICROPY_HW_LED_MSC - port_pin_set_output_level(MICROPY_HW_LED_MSC, true); - #endif - temp_status_color(ACTIVE_WRITE); - // non-MBR block, copy to cache - int32_t dest = convert_block_to_flash_addr(block); - if (dest == -1) { - // bad block number - return false; - } - int32_t error_code; - error_code = flash_erase(&internal_flash_desc, - dest, - FILESYSTEM_BLOCK_SIZE / flash_get_page_size(&internal_flash_desc)); - if (error_code != ERR_NONE) { - return false; - } - - error_code = flash_append(&internal_flash_desc, dest, src, FILESYSTEM_BLOCK_SIZE); - if (error_code != ERR_NONE) { - return false; - } - clear_temp_status(); - #ifdef MICROPY_HW_LED_MSC - port_pin_set_output_level(MICROPY_HW_LED_MSC, false); - #endif - return true; - } -} - -mp_uint_t internal_flash_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks) { - for (size_t i = 0; i < num_blocks; i++) { - if (!internal_flash_read_block(dest + i * FILESYSTEM_BLOCK_SIZE, block_num + i)) { - return 1; // error - } - } - return 0; // success -} - -mp_uint_t internal_flash_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks) { - for (size_t i = 0; i < num_blocks; i++) { - if (!internal_flash_write_block(src + i * FILESYSTEM_BLOCK_SIZE, block_num + i)) { - return 1; // error - } - } - return 0; // success -} - -/******************************************************************************/ -// MicroPython bindings -// -// Expose the flash as an object with the block protocol. - -// there is a singleton Flash object -STATIC const mp_obj_base_t internal_flash_obj = {&internal_flash_type}; - -STATIC mp_obj_t internal_flash_obj_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - // check arguments - mp_arg_check_num(n_args, n_kw, 0, 0, false); - - // return singleton object - return (mp_obj_t)&internal_flash_obj; -} - -STATIC mp_obj_t internal_flash_obj_readblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) { - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_WRITE); - mp_uint_t ret = internal_flash_read_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / FILESYSTEM_BLOCK_SIZE); - return MP_OBJ_NEW_SMALL_INT(ret); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_3(internal_flash_obj_readblocks_obj, internal_flash_obj_readblocks); - -STATIC mp_obj_t internal_flash_obj_writeblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) { - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ); - mp_uint_t ret = internal_flash_write_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / FILESYSTEM_BLOCK_SIZE); - return MP_OBJ_NEW_SMALL_INT(ret); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_3(internal_flash_obj_writeblocks_obj, internal_flash_obj_writeblocks); - -STATIC mp_obj_t internal_flash_obj_ioctl(mp_obj_t self, mp_obj_t cmd_in, mp_obj_t arg_in) { - mp_int_t cmd = mp_obj_get_int(cmd_in); - switch (cmd) { - case BP_IOCTL_INIT: internal_flash_init(); return MP_OBJ_NEW_SMALL_INT(0); - case BP_IOCTL_DEINIT: internal_flash_flush(); return MP_OBJ_NEW_SMALL_INT(0); // TODO properly - case BP_IOCTL_SYNC: internal_flash_flush(); return MP_OBJ_NEW_SMALL_INT(0); - case BP_IOCTL_SEC_COUNT: return MP_OBJ_NEW_SMALL_INT(internal_flash_get_block_count()); - case BP_IOCTL_SEC_SIZE: return MP_OBJ_NEW_SMALL_INT(internal_flash_get_block_size()); - default: return mp_const_none; - } -} -STATIC MP_DEFINE_CONST_FUN_OBJ_3(internal_flash_obj_ioctl_obj, internal_flash_obj_ioctl); - -STATIC const mp_rom_map_elem_t internal_flash_obj_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&internal_flash_obj_readblocks_obj) }, - { MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&internal_flash_obj_writeblocks_obj) }, - { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&internal_flash_obj_ioctl_obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(internal_flash_obj_locals_dict, internal_flash_obj_locals_dict_table); - -const mp_obj_type_t internal_flash_type = { - { &mp_type_type }, - .name = MP_QSTR_InternalFlash, - .make_new = internal_flash_obj_make_new, - .locals_dict = (mp_obj_t)&internal_flash_obj_locals_dict, -}; - -void flash_init_vfs(fs_user_mount_t *vfs) { - vfs->base.type = &mp_fat_vfs_type; - vfs->flags |= FSUSER_NATIVE | FSUSER_HAVE_IOCTL; - vfs->fatfs.drv = vfs; - vfs->fatfs.part = 1; // flash filesystem lives on first partition - vfs->readblocks[0] = (mp_obj_t)&internal_flash_obj_readblocks_obj; - vfs->readblocks[1] = (mp_obj_t)&internal_flash_obj; - vfs->readblocks[2] = (mp_obj_t)internal_flash_read_blocks; // native version - vfs->writeblocks[0] = (mp_obj_t)&internal_flash_obj_writeblocks_obj; - vfs->writeblocks[1] = (mp_obj_t)&internal_flash_obj; - vfs->writeblocks[2] = (mp_obj_t)internal_flash_write_blocks; // native version - vfs->u.ioctl[0] = (mp_obj_t)&internal_flash_obj_ioctl_obj; - vfs->u.ioctl[1] = (mp_obj_t)&internal_flash_obj; -} diff --git a/ports/atmel-samd/mpconfigport.h b/ports/atmel-samd/mpconfigport.h index 14f72ccfb..8df56ec4e 100644 --- a/ports/atmel-samd/mpconfigport.h +++ b/ports/atmel-samd/mpconfigport.h @@ -20,8 +20,6 @@ #define MICROPY_COMP_CONST (1) #define MICROPY_COMP_DOUBLE_TUPLE_ASSIGN (1) #define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (1) -// Turn off for consistency -#define MICROPY_CPYTHON_COMPAT (0) #define MICROPY_MEM_STATS (0) #define MICROPY_DEBUG_PRINTERS (0) #define MICROPY_ENABLE_GC (1) @@ -39,7 +37,6 @@ #define MICROPY_PY_BUILTINS_ENUMERATE (1) #define MICROPY_PY_BUILTINS_HELP (1) #define MICROPY_PY_BUILTINS_HELP_MODULES (1) -#define MICROPY_PY_BUILTINS_HELP_TEXT circuitpython_help_text #define MICROPY_PY_BUILTINS_INPUT (1) #define MICROPY_PY_BUILTINS_FILTER (1) #define MICROPY_PY_BUILTINS_SET (1) @@ -57,7 +54,6 @@ #define MICROPY_PY_DESCRIPTORS (1) #define MICROPY_PY_MATH (0) #define MICROPY_PY_CMATH (0) -#define MICROPY_PY_IO (0) #define MICROPY_PY_URANDOM (0) #define MICROPY_PY_URANDOM_EXTRA_FUNCS (0) #define MICROPY_PY_STRUCT (0) @@ -67,6 +63,18 @@ #define MICROPY_FLOAT_HIGH_QUALITY_HASH (1) #define MICROPY_STREAMS_NON_BLOCK (1) +#ifndef MICROPY_PY_NETWORK +#define MICROPY_PY_NETWORK (0) +#endif + +#ifndef MICROPY_PY_WIZNET5K +#define MICROPY_PY_WIZNET5K (0) +#endif + +#ifndef MICROPY_PY_CC3K +#define MICROPY_PY_CC3K (0) +#endif + // fatfs configuration used in ffconf.h #define MICROPY_FATFS_ENABLE_LFN (1) #define MICROPY_FATFS_LFN_CODE_PAGE (437) /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */ @@ -84,7 +92,6 @@ #define MICROPY_VFS (1) #define MICROPY_VFS_FAT (1) #define MICROPY_PY_MACHINE (1) -#define MICROPY_MODULE_WEAK_LINKS (0) #define MICROPY_REPL_AUTO_INDENT (1) #define MICROPY_HW_ENABLE_DAC (1) #define MICROPY_ENABLE_FINALISER (1) @@ -121,6 +128,9 @@ typedef unsigned mp_uint_t; // must be pointer size typedef long mp_off_t; +// XXX check we don't need this +#define MICROPY_THREAD_YIELD() + #define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len) #define mp_type_fileio mp_type_vfs_fat_fileio @@ -140,15 +150,48 @@ typedef long mp_off_t; #include "include/sam.h" #ifdef SAMD21 -#define CIRCUITPY_MCU_FAMILY samd21 +#define CIRCUITPY_MCU_FAMILY samd21 #define MICROPY_PY_SYS_PLATFORM "Atmel SAMD21" -#define PORT_HEAP_SIZE (16384 + 4096) +#define PORT_HEAP_SIZE (16384 + 4096) +#define SPI_FLASH_MAX_BAUDRATE 8000000 +#define CIRCUITPY_DEFAULT_STACK_SIZE 4096 +#define MICROPY_CPYTHON_COMPAT (0) +#define MICROPY_MODULE_WEAK_LINKS (0) +#define MICROPY_PY_BUILTINS_NOTIMPLEMENTED (0) +#define MICROPY_PY_COLLECTIONS_ORDEREDDICT (0) +#define MICROPY_PY_FUNCTION_ATTRS (0) +#define MICROPY_PY_IO (0) +#define MICROPY_PY_REVERSE_SPECIAL_METHODS (0) +#define MICROPY_PY_SYS_EXC_INFO (0) +#define MICROPY_PY_UERRNO_LIST \ + X(EPERM) \ + X(ENOENT) \ + X(EIO) \ + X(EAGAIN) \ + X(ENOMEM) \ + X(EACCES) \ + X(EEXIST) \ + X(ENODEV) \ + X(EISDIR) \ + X(EINVAL) \ + #endif #ifdef SAMD51 -#define CIRCUITPY_MCU_FAMILY samd51 +#define CIRCUITPY_MCU_FAMILY samd51 #define MICROPY_PY_SYS_PLATFORM "MicroChip SAMD51" -#define PORT_HEAP_SIZE (0x20000) // 128KiB +#define PORT_HEAP_SIZE (0x20000) // 128KiB +#define SPI_FLASH_MAX_BAUDRATE 24000000 +#define CIRCUITPY_DEFAULT_STACK_SIZE 8192 +#define MICROPY_CPYTHON_COMPAT (1) +#define MICROPY_MODULE_WEAK_LINKS (1) +#define MICROPY_PY_BUILTINS_NOTIMPLEMENTED (1) +#define MICROPY_PY_COLLECTIONS_ORDEREDDICT (1) +#define MICROPY_PY_FUNCTION_ATTRS (1) +#define MICROPY_PY_IO (1) +#define MICROPY_PY_REVERSE_SPECIAL_METHODS (1) +#define MICROPY_PY_SYS_EXC_INFO (1) +// MICROPY_PY_UERRNO_LIST - Use the default #endif #ifdef LONGINT_IMPL_NONE @@ -194,6 +237,9 @@ extern const struct _mp_obj_module_t gamepad_module; extern const struct _mp_obj_module_t stage_module; extern const struct _mp_obj_module_t touchio_module; extern const struct _mp_obj_module_t usb_hid_module; +extern const struct _mp_obj_module_t network_module; +extern const struct _mp_obj_module_t socket_module; +extern const struct _mp_obj_module_t wiznet_module; // Internal flash size dependent settings. #if BOARD_FLASH_SIZE > 192000 @@ -207,7 +253,7 @@ extern const struct _mp_obj_module_t usb_hid_module; #define MICROPY_PY_URE (1) #define MICROPY_PY_MICROPYTHON_MEM_INFO (1) #ifndef MICROPY_PY_FRAMEBUF - #define MICROPY_PY_FRAMEBUF (1) + #define MICROPY_PY_FRAMEBUF (0) #endif #define MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG (1) @@ -234,11 +280,34 @@ extern const struct _mp_obj_module_t usb_hid_module; #endif #ifdef CIRCUITPY_DISPLAYIO - #define DISPLAYIO_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_displayio), (mp_obj_t)&displayio_module }, + #define DISPLAYIO_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_displayio), (mp_obj_t)&displayio_module }, #else - #define DISPLAYIO_MODULE + #define DISPLAYIO_MODULE #endif + #if MICROPY_PY_NETWORK + #define NETWORK_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_network), (mp_obj_t)&network_module }, + #define SOCKET_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_socket), (mp_obj_t)&socket_module }, + #if MICROPY_PY_WIZNET5K + #define WIZNET_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_wiznet), (mp_obj_t)&wiznet_module }, + #else + #define WIZNET_MODULE + #endif + #else + #define NETWORK_MODULE + #define SOCKET_MODULE + #define WIZNET_MODULE + #endif + + // (u)json depends, perhaps erroneously, on MICROPY_PY_IO + #if MICROPY_PY_IO + #define JSON_MODULE { MP_ROM_QSTR(MP_QSTR_json), MP_ROM_PTR(&mp_module_ujson) }, + #define MICROPY_PY_UJSON (1) + #else + #define JSON_MODULE + #endif + + #ifndef EXTRA_BUILTIN_MODULES #define EXTRA_BUILTIN_MODULES \ AUDIOIO_MODULE \ @@ -246,6 +315,10 @@ extern const struct _mp_obj_module_t usb_hid_module; { MP_OBJ_NEW_QSTR(MP_QSTR_bitbangio), (mp_obj_t)&bitbangio_module }, \ DISPLAYIO_MODULE \ I2CSLAVE_MODULE \ + NETWORK_MODULE \ + SOCKET_MODULE \ + WIZNET_MODULE \ + JSON_MODULE \ { MP_OBJ_NEW_QSTR(MP_QSTR_rotaryio), (mp_obj_t)&rotaryio_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_gamepad),(mp_obj_t)&gamepad_module } #endif @@ -290,6 +363,34 @@ extern const struct _mp_obj_module_t usb_hid_module; { MP_OBJ_NEW_QSTR(MP_QSTR_supervisor), (mp_obj_t)&supervisor_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&time_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_usb_hid),(mp_obj_t)&usb_hid_module }, +#elif MICROPY_MODULE_WEAK_LINKS +#define MICROPY_PORT_BUILTIN_MODULES \ + { MP_OBJ_NEW_QSTR(MP_QSTR_analogio), (mp_obj_t)&analogio_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_board), (mp_obj_t)&board_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_busio), (mp_obj_t)&busio_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_digitalio), (mp_obj_t)&digitalio_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_microcontroller), (mp_obj_t)µcontroller_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_neopixel_write),(mp_obj_t)&neopixel_write_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR__os), (mp_obj_t)&os_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_pulseio), (mp_obj_t)&pulseio_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_random), (mp_obj_t)&random_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_rtc), (mp_obj_t)&rtc_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_samd),(mp_obj_t)&samd_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_storage), (mp_obj_t)&storage_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_struct), (mp_obj_t)&struct_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_supervisor), (mp_obj_t)&supervisor_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_math), (mp_obj_t)&math_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR__time), (mp_obj_t)&time_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_usb_hid),(mp_obj_t)&usb_hid_module }, \ + TOUCHIO_MODULE \ + EXTRA_BUILTIN_MODULES + +#define MICROPY_PORT_BUILTIN_MODULE_WEAK_LINKS \ + { MP_ROM_QSTR(MP_QSTR_errno), MP_ROM_PTR(&mp_module_uerrno) }, \ + { MP_ROM_QSTR(MP_QSTR_io), MP_ROM_PTR(&mp_module_io) }, \ + { MP_ROM_QSTR(MP_QSTR_os), MP_ROM_PTR(&os_module) }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&time_module }, \ + #else #define MICROPY_PORT_BUILTIN_MODULES \ { MP_OBJ_NEW_QSTR(MP_QSTR_analogio), (mp_obj_t)&analogio_module }, \ @@ -317,18 +418,6 @@ extern const struct _mp_obj_module_t usb_hid_module; { MP_OBJ_NEW_QSTR(MP_QSTR_uheap),(mp_obj_t)&uheap_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_ustack),(mp_obj_t)&ustack_module } -#define MICROPY_PY_UERRNO_LIST \ - X(EPERM) \ - X(ENOENT) \ - X(EIO) \ - X(EAGAIN) \ - X(ENOMEM) \ - X(EACCES) \ - X(EEXIST) \ - X(ENODEV) \ - X(EISDIR) \ - X(EINVAL) \ - // We need to provide a declaration/definition of alloca() #include <alloca.h> @@ -343,8 +432,19 @@ extern const struct _mp_obj_module_t usb_hid_module; #define MP_STATE_PORT MP_STATE_VM +void run_background_tasks(void); +#define MICROPY_VM_HOOK_LOOP run_background_tasks(); +#define MICROPY_VM_HOOK_RETURN run_background_tasks(); + #include "peripherals/samd/dma.h" +#include "supervisor/flash_root_pointers.h" +#if MICROPY_PY_NETWORK + #define NETWORK_ROOT_POINTERS mp_obj_list_t mod_network_nic_list; +#else + #define NETWORK_ROOT_POINTERS +#endif + #define MICROPY_PORT_ROOT_POINTERS \ const char *readline_hist[8]; \ vstr_t *repl_line; \ @@ -352,16 +452,10 @@ extern const struct _mp_obj_module_t usb_hid_module; mp_obj_t rtc_time_source; \ FLASH_ROOT_POINTERS \ mp_obj_t gamepad_singleton; \ + NETWORK_ROOT_POINTERS \ -void run_background_tasks(void); -#define MICROPY_VM_HOOK_LOOP run_background_tasks(); -#define MICROPY_VM_HOOK_RETURN run_background_tasks(); #define CIRCUITPY_AUTORELOAD_DELAY_MS 500 #define CIRCUITPY_BOOT_OUTPUT_FILE "/boot_out.txt" -// TODO(tannewt): Make this 6k+ for any non-express M4 boards because they cache sectors on the -// stack. -#define CIRCUITPY_DEFAULT_STACK_SIZE 4096 - #endif // __INCLUDED_MPCONFIGPORT_H diff --git a/ports/atmel-samd/mpconfigport.mk b/ports/atmel-samd/mpconfigport.mk index c2eedfdc3..7db581dd6 100644 --- a/ports/atmel-samd/mpconfigport.mk +++ b/ports/atmel-samd/mpconfigport.mk @@ -14,5 +14,6 @@ ifeq ($(LONGINT_IMPL),LONGLONG) MPY_TOOL_LONGINT_IMPL = -mlongint-impl=longlong endif - INTERNAL_LIBM = 1 + +USB_SERIAL_NUMBER_LENGTH = 32 diff --git a/ports/atmel-samd/mphalport.c b/ports/atmel-samd/mphalport.c index a4eca1c74..ac5b0fbca 100644 --- a/ports/atmel-samd/mphalport.c +++ b/ports/atmel-samd/mphalport.c @@ -46,43 +46,9 @@ #include "mphalport.h" #include "reset.h" #include "tick.h" -#include "usb.h" -extern struct usart_module usart_instance; extern uint32_t common_hal_mcu_processor_get_frequency(void); -int mp_hal_stdin_rx_chr(void) { - for (;;) { - #ifdef MICROPY_VM_HOOK_LOOP - MICROPY_VM_HOOK_LOOP - #endif - // if (reload_requested) { - // return CHAR_CTRL_D; - // } - if (usb_bytes_available()) { - #ifdef MICROPY_HW_LED_RX - gpio_toggle_pin_level(MICROPY_HW_LED_RX); - #endif - return usb_read(); - } - } -} - -void mp_hal_stdout_tx_strn(const char *str, size_t len) { - #ifdef MICROPY_HW_LED_TX - gpio_toggle_pin_level(MICROPY_HW_LED_TX); - #endif - - #ifdef CIRCUITPY_BOOT_OUTPUT_FILE - if (boot_output_file != NULL) { - UINT bytes_written = 0; - f_write(boot_output_file, str, len, &bytes_written); - } - #endif - - usb_write(str, len); -} - void mp_hal_delay_ms(mp_uint_t delay) { uint64_t start_tick = ticks_ms; uint64_t duration = 0; diff --git a/ports/atmel-samd/mphalport.h b/ports/atmel-samd/mphalport.h index 3bc824d4e..64269b201 100644 --- a/ports/atmel-samd/mphalport.h +++ b/ports/atmel-samd/mphalport.h @@ -41,8 +41,6 @@ static inline mp_uint_t mp_hal_ticks_ms(void) { volatile uint8_t usb_rx_count; volatile bool mp_cdc_enabled; -FIL* boot_output_file; - int receive_usb(void); void mp_hal_set_interrupt_char(int c); diff --git a/ports/atmel-samd/peripherals b/ports/atmel-samd/peripherals -Subproject d0dcba251c27f629c0a89b5ced4433dd0a609ca +Subproject f20fcf642b5654ee68d7d551ea7db39716ef83b diff --git a/ports/atmel-samd/reset.c b/ports/atmel-samd/reset.c index ba5bf9ba1..735639cc4 100644 --- a/ports/atmel-samd/reset.c +++ b/ports/atmel-samd/reset.c @@ -34,10 +34,6 @@ void reset(void) { NVIC_SystemReset(); } -void reset_to_bootloader(void) { - _bootloader_dbl_tap = DBL_TAP_MAGIC; - reset(); -} extern uint32_t _srelocate; bool bootloader_available(void) { diff --git a/ports/atmel-samd/supervisor/internal_flash.c b/ports/atmel-samd/supervisor/internal_flash.c new file mode 100644 index 000000000..f1ceb5c92 --- /dev/null +++ b/ports/atmel-samd/supervisor/internal_flash.c @@ -0,0 +1,149 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "supervisor/internal_flash.h" + +#include <stdint.h> +#include <string.h> + +#include "extmod/vfs.h" +#include "extmod/vfs_fat.h" +#include "py/mphal.h" +#include "py/obj.h" +#include "py/runtime.h" +#include "lib/oofatfs/ff.h" + +#ifdef SAMD21 +#include "hpl/pm/hpl_pm_base.h" +#endif +#include "hal/include/hal_flash.h" + +#include "supervisor/shared/rgb_led_status.h" + +static struct flash_descriptor supervisor_flash_desc; + +void supervisor_flash_init(void) { + // Activity LED for flash writes. + #ifdef MICROPY_HW_LED_MSC + struct port_config pin_conf; + port_get_config_defaults(&pin_conf); + + pin_conf.direction = PORT_PIN_DIR_OUTPUT; + port_pin_set_config(MICROPY_HW_LED_MSC, &pin_conf); + port_pin_set_output_level(MICROPY_HW_LED_MSC, false); + #endif + + #ifdef SAMD51 + hri_mclk_set_AHBMASK_NVMCTRL_bit(MCLK); + #endif + #ifdef SAMD21 + _pm_enable_bus_clock(PM_BUS_APBB, NVMCTRL); + #endif + flash_init(&supervisor_flash_desc, NVMCTRL); +} + +uint32_t supervisor_flash_get_block_size(void) { + return FILESYSTEM_BLOCK_SIZE; +} + +uint32_t supervisor_flash_get_block_count(void) { + return INTERNAL_FLASH_PART1_NUM_BLOCKS; +} + +void supervisor_flash_flush(void) { +} + +void flash_flush(void) { + supervisor_flash_flush(); +} + +static int32_t convert_block_to_flash_addr(uint32_t block) { + if (0 <= block && block < INTERNAL_FLASH_PART1_NUM_BLOCKS) { + // a block in partition 1 + return INTERNAL_FLASH_MEM_SEG1_START_ADDR + block * FILESYSTEM_BLOCK_SIZE; + } + // bad block + return -1; +} + +bool supervisor_flash_read_block(uint8_t *dest, uint32_t block) { + // non-MBR block, get data from flash memory + int32_t src = convert_block_to_flash_addr(block); + if (src == -1) { + // bad block number + return false; + } + int32_t error_code = flash_read(&supervisor_flash_desc, src, dest, FILESYSTEM_BLOCK_SIZE); + return error_code == ERR_NONE; +} + +bool supervisor_flash_write_block(const uint8_t *src, uint32_t block) { + #ifdef MICROPY_HW_LED_MSC + port_pin_set_output_level(MICROPY_HW_LED_MSC, true); + #endif + temp_status_color(ACTIVE_WRITE); + // non-MBR block, copy to cache + int32_t dest = convert_block_to_flash_addr(block); + if (dest == -1) { + // bad block number + return false; + } + int32_t error_code; + error_code = flash_erase(&supervisor_flash_desc, + dest, + FILESYSTEM_BLOCK_SIZE / flash_get_page_size(&supervisor_flash_desc)); + if (error_code != ERR_NONE) { + return false; + } + + error_code = flash_append(&supervisor_flash_desc, dest, src, FILESYSTEM_BLOCK_SIZE); + if (error_code != ERR_NONE) { + return false; + } + clear_temp_status(); + #ifdef MICROPY_HW_LED_MSC + port_pin_set_output_level(MICROPY_HW_LED_MSC, false); + #endif + return true; +} + +mp_uint_t supervisor_flash_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks) { + for (size_t i = 0; i < num_blocks; i++) { + if (!supervisor_flash_read_block(dest + i * FILESYSTEM_BLOCK_SIZE, block_num + i)) { + return 1; // error + } + } + return 0; // success +} + +mp_uint_t supervisor_flash_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks) { + for (size_t i = 0; i < num_blocks; i++) { + if (!supervisor_flash_write_block(src + i * FILESYSTEM_BLOCK_SIZE, block_num + i)) { + return 1; // error + } + } + return 0; // success +} diff --git a/ports/atmel-samd/internal_flash.h b/ports/atmel-samd/supervisor/internal_flash.h index 88c105386..0939a3454 100644 --- a/ports/atmel-samd/internal_flash.h +++ b/ports/atmel-samd/supervisor/internal_flash.h @@ -32,8 +32,6 @@ #include "sam.h" -#define FLASH_ROOT_POINTERS - #ifdef SAMD51 #define TOTAL_INTERNAL_FLASH_SIZE (FLASH_SIZE / 2) #endif @@ -43,27 +41,9 @@ #endif #define INTERNAL_FLASH_MEM_SEG1_START_ADDR (FLASH_SIZE - TOTAL_INTERNAL_FLASH_SIZE - CIRCUITPY_INTERNAL_NVM_SIZE) -#define INTERNAL_FLASH_PART1_START_BLOCK (0x1) #define INTERNAL_FLASH_PART1_NUM_BLOCKS (TOTAL_INTERNAL_FLASH_SIZE / FILESYSTEM_BLOCK_SIZE) #define INTERNAL_FLASH_SYSTICK_MASK (0x1ff) // 512ms #define INTERNAL_FLASH_IDLE_TICK(tick) (((tick) & INTERNAL_FLASH_SYSTICK_MASK) == 2) -void internal_flash_init(void); -uint32_t internal_flash_get_block_size(void); -uint32_t internal_flash_get_block_count(void); -void internal_flash_irq_handler(void); -void internal_flash_flush(void); -bool internal_flash_read_block(uint8_t *dest, uint32_t block); -bool internal_flash_write_block(const uint8_t *src, uint32_t block); - -// these return 0 on success, non-zero on error -mp_uint_t internal_flash_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks); -mp_uint_t internal_flash_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks); - -extern const struct _mp_obj_type_t internal_flash_type; - -struct _fs_user_mount_t; -void flash_init_vfs(struct _fs_user_mount_t *vfs); - #endif // MICROPY_INCLUDED_ATMEL_SAMD_INTERNAL_FLASH_H diff --git a/ports/atmel-samd/supervisor/internal_flash_root_pointers.h b/ports/atmel-samd/supervisor/internal_flash_root_pointers.h new file mode 100644 index 000000000..3e9148ce0 --- /dev/null +++ b/ports/atmel-samd/supervisor/internal_flash_root_pointers.h @@ -0,0 +1,31 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries LLC + * + * 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_ATMEL_SAMD_INTERNAL_FLASH_ROOT_POINTERS_H +#define MICROPY_INCLUDED_ATMEL_SAMD_INTERNAL_FLASH_ROOT_POINTERS_H + +#define FLASH_ROOT_POINTERS + +#endif // MICROPY_INCLUDED_ATMEL_SAMD_INTERNAL_FLASH_ROOT_POINTERS_H diff --git a/ports/atmel-samd/supervisor/port.c b/ports/atmel-samd/supervisor/port.c index 2349a7418..9f951b035 100644 --- a/ports/atmel-samd/supervisor/port.c +++ b/ports/atmel-samd/supervisor/port.c @@ -32,7 +32,6 @@ #include "hal/include/hal_delay.h" #include "hal/include/hal_gpio.h" #include "hal/include/hal_init.h" -#include "hal/include/hal_usb_device.h" #include "hpl/gclk/hpl_gclk_base.h" #include "hpl/pm/hpl_pm_base.h" @@ -48,13 +47,13 @@ #include "common-hal/audiobusio/PDMIn.h" #include "common-hal/audiobusio/I2SOut.h" #include "common-hal/audioio/AudioOut.h" +#include "common-hal/busio/SPI.h" #include "common-hal/microcontroller/Pin.h" #include "common-hal/pulseio/PulseIn.h" #include "common-hal/pulseio/PulseOut.h" #include "common-hal/pulseio/PWMOut.h" #include "common-hal/rtc/RTC.h" #include "common-hal/touchio/TouchIn.h" -#include "common-hal/usb_hid/Device.h" #include "samd/cache.h" #include "samd/clocks.h" #include "samd/events.h" @@ -62,8 +61,10 @@ #include "samd/dma.h" #include "shared-bindings/rtc/__init__.h" #include "board_busses.h" +#include "reset.h" #include "tick.h" -#include "usb.h" + +#include "tusb.h" #ifdef CIRCUITPY_GAMEPAD_TICKS #include "shared-module/gamepad/__init__.h" @@ -225,35 +226,14 @@ safe_mode_t port_init(void) { } void reset_port(void) { - // Reset all SERCOMs except the ones being used by on-board devices. - Sercom *sercom_instances[SERCOM_INST_NUM] = SERCOM_INSTS; - for (int i = 0; i < SERCOM_INST_NUM; i++) { -#ifdef SPI_FLASH_SERCOM - if (sercom_instances[i] == SPI_FLASH_SERCOM) { - continue; - } -#endif -#ifdef MICROPY_HW_APA102_SERCOM - if (sercom_instances[i] == MICROPY_HW_APA102_SERCOM) { - continue; - } -#endif -#ifdef CIRCUITPY_DISPLAYIO - // TODO(tannewt): Make this dynamic. - if (sercom_instances[i] == board_display_obj.bus.spi_desc.dev.prvt) { - continue; - } -#endif - // SWRST is same for all modes of SERCOMs. - sercom_instances[i]->SPI.CTRLA.bit.SWRST = 1; - } + reset_sercoms(); #if defined(EXPRESS_BOARD) && !defined(__SAMR21G18A__) + audio_dma_reset(); audioout_reset(); #if !defined(__SAMD51G19A__) && !defined(__SAMD51G18A__) i2sout_reset(); #endif - audio_dma_reset(); //pdmin_reset(); #endif #ifdef SAMD21 @@ -290,13 +270,16 @@ void reset_port(void) { // gpio_set_pin_function(PIN_PB15, GPIO_PIN_FUNCTION_M); // GCLK1, D6 // #endif - usb_hid_reset(); - - if (usb_connected()) { + if (tud_cdc_connected()) { save_usb_clock_calibration(); } } +void reset_to_bootloader(void) { + _bootloader_dbl_tap = DBL_TAP_MAGIC; + reset(); +} + /** * \brief Default interrupt handler for unused IRQs. */ diff --git a/ports/atmel-samd/external_flash/qspi_flash.c b/ports/atmel-samd/supervisor/qspi_flash.c index f6dc00d50..eca47b164 100644 --- a/ports/atmel-samd/external_flash/qspi_flash.c +++ b/ports/atmel-samd/supervisor/qspi_flash.c @@ -24,14 +24,15 @@ * THE SOFTWARE. */ -#include "spi_flash_api.h" +#include "supervisor/spi_flash_api.h" #include <stdint.h> #include <string.h> #include "mpconfigboard.h" // for EXTERNAL_FLASH_QSPI_DUAL -#include "external_flash/common_commands.h" +#include "supervisor/shared/external_flash/common_commands.h" +#include "supervisor/shared/external_flash/qspi_flash.h" #include "samd/cache.h" #include "samd/dma.h" @@ -225,18 +226,7 @@ void spi_flash_init(void) { } void spi_flash_init_device(const external_flash_device* device) { - // Verify that QSPI mode is enabled. - uint8_t status; - spi_flash_read_command(CMD_READ_STATUS2, &status, 1); - - // Bit 1 is Quad Enable - if ((status & 0x2) == 0) { - uint8_t full_status[2] = {0x0, 0x2}; - spi_flash_command(CMD_ENABLE_WRITE); - if (device->write_status_register_split) { - spi_flash_write_command(CMD_WRITE_STATUS_BYTE2, full_status + 1, 1); - } else { - spi_flash_write_command(CMD_WRITE_STATUS_BYTE1, full_status, 2); - } - } + check_quad_enable(device); + + // TODO(tannewt): Adjust the speed for the found device. } diff --git a/ports/atmel-samd/supervisor/serial.c b/ports/atmel-samd/supervisor/serial.c deleted file mode 100644 index 4917dfb5b..000000000 --- a/ports/atmel-samd/supervisor/serial.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2017 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. - */ - -#include <string.h> - -#include "supervisor/serial.h" - -#include "common-hal/usb_hid/Device.h" - -#include "usb.h" -#include "genhdr/autogen_usb_descriptor.h" - -// Serial number as hex characters. This writes directly to the USB -// descriptor. -void load_serial_number(void) { - char nibble_to_hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - 'A', 'B', 'C', 'D', 'E', 'F'}; - #ifdef SAMD21 - uint32_t* addresses[4] = {(uint32_t *) 0x0080A00C, (uint32_t *) 0x0080A040, - (uint32_t *) 0x0080A044, (uint32_t *) 0x0080A048}; - #endif - #ifdef SAMD51 - uint32_t* addresses[4] = {(uint32_t *) 0x008061FC, (uint32_t *) 0x00806010, - (uint32_t *) 0x00806014, (uint32_t *) 0x00806018}; - #endif - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 8; j++) { - uint8_t nibble = (*(addresses[i]) >> j * 4) & 0xf; - // Strings are UTF-16-LE encoded. - serial_number[i * 16 + j * 2] = nibble_to_hex[nibble]; - serial_number[i * 16 + j * 2 + 1] = 0; - } - } -} - -void serial_init(void) { - load_serial_number(); - init_usb(); - usb_hid_init(); -} - -bool serial_connected(void) { - return usb_connected(); -} - -char serial_read(void) { - return usb_read(); -} - -bool serial_bytes_available(void) { - return usb_bytes_available(); -} - -void serial_write(const char* text) { - usb_write(text, strlen(text)); -} diff --git a/ports/atmel-samd/supervisor/usb.c b/ports/atmel-samd/supervisor/usb.c new file mode 100644 index 000000000..d13ca0ef1 --- /dev/null +++ b/ports/atmel-samd/supervisor/usb.c @@ -0,0 +1,59 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017, 2018 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. + */ + +#include "atmel_start_pins.h" +#include "hpl/pm/hpl_pm_base.h" +#include "hpl/gclk/hpl_gclk_base.h" +#include "hal_gpio.h" + +void init_usb_hardware(void) { + #ifdef SAMD21 + _pm_enable_bus_clock(PM_BUS_APBB, USB); + _pm_enable_bus_clock(PM_BUS_AHB, USB); + _gclk_enable_channel(USB_GCLK_ID, GCLK_CLKCTRL_GEN_GCLK0_Val); + #endif + + #ifdef SAMD51 + hri_gclk_write_PCHCTRL_reg(GCLK, USB_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK1_Val | GCLK_PCHCTRL_CHEN); + hri_mclk_set_AHBMASK_USB_bit(MCLK); + hri_mclk_set_APBBMASK_USB_bit(MCLK); + #endif + + gpio_set_pin_direction(PIN_PA24, GPIO_DIRECTION_OUT); + gpio_set_pin_level(PIN_PA24, false); + gpio_set_pin_pull_mode(PIN_PA24, GPIO_PULL_OFF); + gpio_set_pin_direction(PIN_PA25, GPIO_DIRECTION_OUT); + gpio_set_pin_level(PIN_PA25, false); + gpio_set_pin_pull_mode(PIN_PA25, GPIO_PULL_OFF); + #ifdef SAMD21 + gpio_set_pin_function(PIN_PA24, PINMUX_PA24G_USB_DM); + gpio_set_pin_function(PIN_PA25, PINMUX_PA25G_USB_DP); + #endif + #ifdef SAMD51 + gpio_set_pin_function(PIN_PA24, PINMUX_PA24H_USB_DM); + gpio_set_pin_function(PIN_PA25, PINMUX_PA25H_USB_DP); + #endif +} diff --git a/ports/atmel-samd/tick.h b/ports/atmel-samd/tick.h index 80e7bc9af..c8c8d739a 100644 --- a/ports/atmel-samd/tick.h +++ b/ports/atmel-samd/tick.h @@ -26,7 +26,7 @@ #ifndef MICROPY_INCLUDED_ATMEL_SAMD_TICK_H #define MICROPY_INCLUDED_ATMEL_SAMD_TICK_H -#include "mpconfigport.h" +#include "py/mpconfig.h" extern volatile uint64_t ticks_ms; diff --git a/ports/atmel-samd/usb.c b/ports/atmel-samd/usb.c deleted file mode 100644 index 1f1ba550f..000000000 --- a/ports/atmel-samd/usb.c +++ /dev/null @@ -1,326 +0,0 @@ -/* - * This file is part of the Micro Python project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2017 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. - */ - -#include "usb.h" - -#include <stdint.h> - -// We must include this early because it sets values used in the ASF4 includes -// below. -#include "py/mpconfig.h" - -#include "hal/include/hal_gpio.h" -#include "usb/class/cdc/device/cdcdf_acm.h" -#include "usb/class/hid/device/hiddf_generic.h" -#include "usb/class/composite/device/composite_desc.h" -#include "usb/class/msc/device/mscdf.h" -#include "peripheral_clk_config.h" -#include "hpl/pm/hpl_pm_base.h" -#include "hpl/gclk/hpl_gclk_base.h" - -#include "lib/utils/interrupt_char.h" -#include "genhdr/autogen_usb_descriptor.h" -#include "reset.h" -#include "usb_mass_storage.h" - -#include "supervisor/shared/autoreload.h" - -extern struct usbd_descriptors descriptor_bounds; - -// Store received characters on our own so that we can filter control characters -// and act immediately on CTRL-C for example. - -// Receive buffer -static uint8_t usb_rx_buf[USB_RX_BUF_SIZE]; - -// Receive buffer head -static volatile uint8_t usb_rx_buf_head = 0; - -// Receive buffer tail -static volatile uint8_t usb_rx_buf_tail = 0; - -// Number of bytes in receive buffer -volatile uint8_t usb_rx_count = 0; - -volatile bool mp_cdc_enabled = false; -volatile bool usb_transmitting = false; - -/** Ctrl endpoint buffer */ -COMPILER_ALIGNED(4) static uint8_t ctrl_buffer[64]; - -static void init_hardware(void) { - #ifdef SAMD21 - _pm_enable_bus_clock(PM_BUS_APBB, USB); - _pm_enable_bus_clock(PM_BUS_AHB, USB); - _gclk_enable_channel(USB_GCLK_ID, GCLK_CLKCTRL_GEN_GCLK0_Val); - #endif - - #ifdef SAMD51 - hri_gclk_write_PCHCTRL_reg(GCLK, USB_GCLK_ID, CONF_GCLK_USB_SRC | GCLK_PCHCTRL_CHEN); - hri_mclk_set_AHBMASK_USB_bit(MCLK); - hri_mclk_set_APBBMASK_USB_bit(MCLK); - #endif - - usb_d_init(); - - gpio_set_pin_direction(PIN_PA24, GPIO_DIRECTION_OUT); - gpio_set_pin_level(PIN_PA24, false); - gpio_set_pin_pull_mode(PIN_PA24, GPIO_PULL_OFF); - gpio_set_pin_direction(PIN_PA25, GPIO_DIRECTION_OUT); - gpio_set_pin_level(PIN_PA25, false); - gpio_set_pin_pull_mode(PIN_PA25, GPIO_PULL_OFF); - #ifdef SAMD21 - gpio_set_pin_function(PIN_PA24, PINMUX_PA24G_USB_DM); - gpio_set_pin_function(PIN_PA25, PINMUX_PA25G_USB_DP); - #endif - #ifdef SAMD51 - gpio_set_pin_function(PIN_PA24, PINMUX_PA24H_USB_DM); - gpio_set_pin_function(PIN_PA25, PINMUX_PA25H_USB_DP); - #endif -} - -#define CDC_BULKOUT_SIZE CONF_USB_COMPOSITE_CDC_ACM_DATA_BULKOUT_MAXPKSZ -COMPILER_ALIGNED(4) uint8_t cdc_packet_buffer[CDC_BULKOUT_SIZE]; -static volatile bool pending_read; - -static int32_t start_read(void) { - pending_read = true; - int32_t result = cdcdf_acm_read(cdc_packet_buffer, CDC_BULKOUT_SIZE); - if (result != ERR_NONE) { - pending_read = false; - } - return result; -} - -static bool read_complete(const uint8_t ep, const enum usb_xfer_code rc, const uint32_t count) { - if (rc != USB_XFER_DONE) { - return false; // No errors. - } - pending_read = false; - volatile hal_atomic_t flags; - atomic_enter_critical(&flags); - // If our buffer can't fit the data received, then error out. - if (count > (uint8_t) (USB_RX_BUF_SIZE - usb_rx_count)) { - atomic_leave_critical(&flags); - return true; - } - - for (uint16_t i = 0; i < count; i++) { - uint8_t c = cdc_packet_buffer[i]; - if (c == mp_interrupt_char) { - mp_keyboard_interrupt(); - // If interrupted, flush all the input. - usb_rx_count = 0; - usb_rx_buf_head = 0; - usb_rx_buf_tail = 0; - break; - } else { - // The count of characters present in receive buffer is - // incremented. - usb_rx_count++; - usb_rx_buf[usb_rx_buf_tail] = c; - usb_rx_buf_tail++; - if (usb_rx_buf_tail == USB_RX_BUF_SIZE) { - // Reached the end of buffer, revert back to beginning of - // buffer. - usb_rx_buf_tail = 0; - } - } - } - atomic_leave_critical(&flags); - - /* No error. */ - return false; -} - -static bool write_complete(const uint8_t ep, - const enum usb_xfer_code rc, - const uint32_t count) { - if (rc != USB_XFER_DONE) { - return false; // No errors. - } - // This is called after writes are finished. - - usb_transmitting = false; - - /* No error. */ - return false; -} - -volatile bool reset_on_disconnect = false; -volatile bool cdc_connected = false; - -static bool usb_device_cb_state_c(usb_cdc_control_signal_t state) -{ - cdc_connected = state.rs232.DTR; - if (state.rs232.DTR) { - } else if (!state.rs232.DTR && reset_on_disconnect) { - reset_to_bootloader(); - } - - /* No error. */ - return false; -} - -static bool usb_device_cb_line_coding_c(const usb_cdc_line_coding_t* coding) -{ - reset_on_disconnect = coding->dwDTERate == 1200; - /* Ok to change. */ - return true; -} - -void init_usb(void) { - init_hardware(); - - mp_cdc_enabled = false; - - usbdc_init(ctrl_buffer); - - /* usbdc_register_function inside */ - cdcdf_acm_init(); - pending_read = false; - - mscdf_init(1); - mscdf_register_callback(MSCDF_CB_INQUIRY_DISK, (FUNC_PTR)usb_msc_inquiry_info); - mscdf_register_callback(MSCDF_CB_GET_DISK_CAPACITY, (FUNC_PTR)usb_msc_get_capacity); - mscdf_register_callback(MSCDF_CB_START_READ_DISK, (FUNC_PTR)usb_msc_new_read); - mscdf_register_callback(MSCDF_CB_START_WRITE_DISK, (FUNC_PTR)usb_msc_new_write); - mscdf_register_callback(MSCDF_CB_EJECT_DISK, (FUNC_PTR)usb_msc_disk_eject); - mscdf_register_callback(MSCDF_CB_TEST_DISK_READY, (FUNC_PTR)usb_msc_disk_is_ready); - mscdf_register_callback(MSCDF_CB_XFER_BLOCKS_DONE, (FUNC_PTR)usb_msc_xfer_done); - mscdf_register_callback(MSCDF_CB_IS_WRITABLE, (FUNC_PTR)usb_msc_disk_is_writable); - - hiddf_generic_init(hid_report_descriptor, sizeof(hid_report_descriptor)); - - usbdc_start(&descriptor_bounds); - - usbdc_attach(); - - -} - -static bool cdc_enabled(void) { - if (!cdcdf_acm_is_enabled()) { - mp_cdc_enabled = false; - return false; - } - if (!mp_cdc_enabled) { - cdcdf_acm_register_callback(CDCDF_ACM_CB_READ, (FUNC_PTR)read_complete); - cdcdf_acm_register_callback(CDCDF_ACM_CB_WRITE, (FUNC_PTR)write_complete); - cdcdf_acm_register_callback(CDCDF_ACM_CB_STATE_C, (FUNC_PTR)usb_device_cb_state_c); - cdcdf_acm_register_callback(CDCDF_ACM_CB_LINE_CODING_C, (FUNC_PTR)usb_device_cb_line_coding_c); - mp_cdc_enabled = true; - } - - return true; -} - -bool usb_bytes_available(void) { - // Check if the buffer has data, but not enough - // space to hold another read. - if (usb_rx_count > USB_RX_BUF_SIZE - CDC_BULKOUT_SIZE) { - return true; - } - // Buffer has enough room - if (cdc_enabled() && !pending_read) { - start_read(); - } - // Buffer is empty and/or no new data is available - if (usb_rx_count == 0) { - return false; - } - return usb_rx_count > 0; -} - -int usb_read(void) { - if (!cdc_enabled() || usb_rx_count == 0) { - return 0; - } - - // Copy from head. - int data; - CRITICAL_SECTION_ENTER(); - data = usb_rx_buf[usb_rx_buf_head]; - usb_rx_buf_head++; - usb_rx_count--; - if (usb_rx_buf_head == USB_RX_BUF_SIZE) { - usb_rx_buf_head = 0; - } - CRITICAL_SECTION_LEAVE(); - - return data; -} - -// TODO(tannewt): See if we can disable the internal CDC IN cache since we -// we manage this one ourselves. -#define CDC_BULKIN_SIZE CONF_USB_COMPOSITE_CDC_ACM_DATA_BULKIN_MAXPKSZ -COMPILER_ALIGNED(4) uint8_t cdc_output_buffer[CDC_BULKIN_SIZE]; - -void usb_write(const char* buffer, uint32_t len) { - if (!cdc_enabled()) { - return; - } - if (!cdc_connected) { - // TODO(tannewt): Should we write to a file instead? - return; - } - uint8_t * output_buffer; - uint32_t output_len; - while (len > 0) { - while (usb_transmitting) {} - output_buffer = (uint8_t *) buffer; - output_len = len; - // Use our own cache in two different cases: - // * When we're at the end of a transmission and we'll return before - // the given buffer is actually transferred to the USB device. - // * When our given buffer isn't aligned on word boundaries. - if (output_len <= CDC_BULKIN_SIZE || ((uint32_t) buffer) % 4 != 0) { - output_buffer = cdc_output_buffer; - output_len = output_len > CDC_BULKIN_SIZE ? CDC_BULKIN_SIZE : output_len; - memcpy(cdc_output_buffer, buffer, output_len); - } else { - output_len = CDC_BULKIN_SIZE; - } - usb_transmitting = true; - cdcdf_acm_write(output_buffer, output_len); - buffer += output_len * sizeof(char); - len -= output_len; - } -} - -bool usb_connected(void) { - return cdc_enabled(); -} - -// Poll for input if keyboard interrupts are enabled, -// so that we can check for the interrupt char. read_complete() does the checking. -// also make sure we have enough room in the local buffer -void usb_cdc_background() { - // - if (mp_interrupt_char != -1 && cdc_enabled() && !pending_read && (usb_rx_count < USB_RX_BUF_SIZE - CDC_BULKOUT_SIZE)) { - start_read(); - } -} diff --git a/ports/atmel-samd/usb_mass_storage.c b/ports/atmel-samd/usb_mass_storage.c deleted file mode 100644 index 9b6715158..000000000 --- a/ports/atmel-samd/usb_mass_storage.c +++ /dev/null @@ -1,338 +0,0 @@ -/* - * 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. - */ - -#include <string.h> - -#include "usb_mass_storage.h" -#include "supervisor/shared/autoreload.h" - -#include "hal/utils/include/err_codes.h" -#include "hal/utils/include/utils.h" -#include "usb/class/msc/device/mscdf.h" - -#include "extmod/vfs.h" -#include "extmod/vfs_fat.h" -#include "lib/oofatfs/ff.h" -#include "lib/oofatfs/diskio.h" -#include "lib/oofatfs/ffconf.h" -#include "py/mpconfig.h" -#include "py/mphal.h" -#include "py/mpstate.h" -#include "py/misc.h" - -// The root FS is always at the end of the list. -static fs_user_mount_t* get_vfs(int lun) { - // TODO(tannewt): Return the mount which matches the lun where 0 is the end - // and is counted in reverse. - if (lun > 0) { - return NULL; - } - mp_vfs_mount_t* current_mount = MP_STATE_VM(vfs_mount_table); - if (current_mount == NULL) { - return NULL; - } - while (current_mount->next != NULL) { - current_mount = current_mount->next; - } - return current_mount->obj; -} - -/* Inquiry Information */ -// This is designed to handle the common case where we have an internal file -// system and an optional SD card. -COMPILER_ALIGNED(4) static uint8_t inquiry_info[2][36]; - -/* Capacities of Disk */ -COMPILER_ALIGNED(4) static uint8_t format_capa[2][8]; - -/** - * \brief Eject Disk - * \param[in] lun logic unit number - * \return Operation status. - */ -int32_t usb_msc_disk_eject(uint8_t lun) { - if (lun > 1) { - return ERR_NOT_FOUND; - } - fs_user_mount_t* current_mount = get_vfs(lun); - // Return ERR_NOT_READY if not ready, otherwise ERR_NONE. - if (current_mount == NULL) { - return ERR_NOT_FOUND; - } - // TODO(tannewt): Should we flush here? - return ERR_NONE; -} - -/** - * \brief Inquiry whether Disk is writable. ERR_DENIED if it is not writable. - * ERR_NONE if it is. ERR_NOT_FOUND if its missing. - * \param[in] lun logic unit number - * \return Operation status. - */ -int32_t usb_msc_disk_is_writable(uint8_t lun) { - if (lun > 1) { - return ERR_NOT_FOUND; - } - - fs_user_mount_t* vfs = get_vfs(lun); - if (vfs == NULL) { - return ERR_NOT_FOUND; - } - if (vfs->writeblocks[0] == MP_OBJ_NULL || - (vfs->flags & FSUSER_USB_WRITABLE) == 0) { - return ERR_DENIED; - } - return ERR_NONE; -} - -/** - * \brief Inquiry whether Disk is ready - * \param[in] lun logic unit number - * \return Operation status. - */ -int32_t usb_msc_disk_is_ready(uint8_t lun) { - if (lun > 1) { - return ERR_NOT_FOUND; - } - - fs_user_mount_t* current_mount = get_vfs(lun); - if (current_mount == NULL) { - return ERR_NOT_FOUND; - } - return ERR_NONE; -} - -/** - * \brief Callback invoked when inquiry data command received - * \param[in] lun logic unit number - * \return Operation status. - */ -uint8_t *usb_msc_inquiry_info(uint8_t lun) { - if (lun > 1) { - return NULL; - } else { - for (uint8_t i = 0; i < 36; i++) { - inquiry_info[lun][i] = 0; - } - inquiry_info[lun][0] = SCSI_INQ_PQ_CONNECTED | SCSI_INQ_DT_DIR_ACCESS; - // connected, direct access - inquiry_info[lun][1] = SCSI_INQ_RMB; // removable medium - inquiry_info[lun][2] = SCSI_INQ_VER_SPC; // SBC version of SCSI primary commands - inquiry_info[lun][3] = SCSI_INQ_RSP_SPC2;// SPC-2 response format - inquiry_info[lun][4] = 31; // 31 bytes following - return &inquiry_info[lun][0]; - } -} - -/** - * \brief Callback invoked when read format capacities command received - * \param[in] lun logic unit number - */ -uint8_t *usb_msc_get_capacity(uint8_t lun) { - if (lun > 1) { - return NULL; - } else { - fs_user_mount_t * vfs = get_vfs(lun); - uint32_t last_valid_sector = 0; - uint32_t sector_size = 0; - if (vfs == NULL || - disk_ioctl(vfs, GET_SECTOR_COUNT, &last_valid_sector) != RES_OK || - disk_ioctl(vfs, GET_SECTOR_SIZE, §or_size) != RES_OK) { - return NULL; - } - // Subtract one from the sector count to get the last valid sector. - last_valid_sector--; - - format_capa[lun][0] = (uint8_t)(last_valid_sector >> 24); - format_capa[lun][1] = (uint8_t)(last_valid_sector >> 16); - format_capa[lun][2] = (uint8_t)(last_valid_sector >> 8); - format_capa[lun][3] = (uint8_t)(last_valid_sector >> 0); - format_capa[lun][4] = (uint8_t)(sector_size >> 24); - format_capa[lun][5] = (uint8_t)(sector_size >> 16); - format_capa[lun][6] = (uint8_t)(sector_size >> 8); - format_capa[lun][7] = (uint8_t)(sector_size >> 0); - - // 8 byte response. First 4 bytes are last block address. Second 4 - // bytes are sector size. - return &format_capa[lun][0]; - } -} - -// USB transfer state. -volatile bool usb_busy; -volatile bool active_read; -volatile bool active_write; -volatile uint8_t active_lun; -volatile uint32_t active_addr; -volatile uint32_t active_nblocks; -volatile bool sector_loaded; -COMPILER_ALIGNED(4) uint8_t sector_buffer[512]; - -/** - * \brief Callback invoked when a new read blocks command received - * \param[in] lun logic unit number - * \param[in] addr start address of disk to be read - * \param[in] nblocks block amount to be read - * \return Operation status. - */ -int32_t usb_msc_new_read(uint8_t lun, uint32_t addr, uint32_t nblocks) { - if (lun > 1) { - return ERR_NOT_FOUND; - } - - // Store transfer info so we can service it in the "background". - active_lun = lun; - active_addr = addr; - active_nblocks = nblocks; - active_read = true; - - return ERR_NONE; -} - -/** - * \brief Callback invoked when a new write blocks command received - * \param[in] lun logic unit number - * \param[in] addr start address of disk to be written - * \param[in] nblocks block amount to be written - * \return Operation status. - */ -int32_t usb_msc_new_write(uint8_t lun, uint32_t addr, uint32_t nblocks) { - if (lun > 1) { - return ERR_NOT_FOUND; - } - - fs_user_mount_t * vfs = get_vfs(lun); - // This is used to determine the writeability of the disk from USB. - if (vfs == NULL) { - return ERR_NOT_FOUND; - } - if (vfs->writeblocks[0] == MP_OBJ_NULL || - (vfs->flags & FSUSER_USB_WRITABLE) == 0) { - return ERR_DENIED; - } - - // Store transfer info so we can service it in the "background". - active_lun = lun; - active_addr = addr; - active_nblocks = nblocks; - active_write = true; - sector_loaded = false; - - // Return ERR_DENIED when the file system is read-only to the USB host. - - return ERR_NONE; -} - -/** - * \brief Callback invoked when a blocks transfer is done - * \param[in] lun logic unit number - * \return Operation status. - */ -int32_t usb_msc_xfer_done(uint8_t lun) { - if (lun > 1) { - return ERR_DENIED; - } - - CRITICAL_SECTION_ENTER(); - if (active_read) { - active_addr += 1; - active_nblocks--; - if (active_nblocks == 0) { - active_read = false; - } - } - - if (active_write) { - sector_loaded = true; - } - usb_busy = false; - CRITICAL_SECTION_LEAVE(); - - return ERR_NONE; -} - -// The start_read callback begins a read transaction which we accept -// but delay our response until the "main thread" calls -// usb_msc_background. Once it does, we read immediately from the -// drive into our cache and trigger the USB DMA to output the -// sector. Once the sector is transmitted, xfer_done will be called. -void usb_msc_background(void) { - // Check USB busy first because we never want to queue another transfer if it is. Checking - // active_read or active_write first leaves the possibility that they are true, an xfer done - // interrupt occurs (setting them false), turning off usb_busy and causing us to queue a - // spurious transfer. - if (usb_busy) { - return; - } - if (active_read) { - fs_user_mount_t * vfs = get_vfs(active_lun); - disk_read(vfs, sector_buffer, active_addr, 1); - CRITICAL_SECTION_ENTER(); - int32_t result = mscdf_xfer_blocks(true, sector_buffer, 1); - usb_busy = result == ERR_NONE; - CRITICAL_SECTION_LEAVE(); - } - if (active_write) { - if (sector_loaded) { - fs_user_mount_t * vfs = get_vfs(active_lun); - disk_write(vfs, sector_buffer, active_addr, 1); - // Since by getting here we assume the mount is read-only to - // MicroPython let's update the cached FatFs sector if it's the one - // we just wrote. - #if _MAX_SS != _MIN_SS - if (vfs->ssize == FILESYSTEM_BLOCK_SIZE) { - #else - // The compiler can optimize this away. - if (_MAX_SS == FILESYSTEM_BLOCK_SIZE) { - #endif - if (active_addr == vfs->fatfs.winsect && active_addr > 0) { - memcpy(vfs->fatfs.win, - sector_buffer, - FILESYSTEM_BLOCK_SIZE); - } - } - sector_loaded = false; - active_addr += 1; - active_nblocks--; - } - // Load more blocks from USB if they are needed. - if (active_nblocks > 0) { - // Turn off interrupts because with them on, - // usb_msc_xfer_done could be called before we update - // usb_busy. If that happened, we'd overwrite the fact that - // the transfer actually already finished. - CRITICAL_SECTION_ENTER(); - int32_t result = mscdf_xfer_blocks(false, sector_buffer, 1); - usb_busy = result == ERR_NONE; - CRITICAL_SECTION_LEAVE(); - } else { - mscdf_xfer_blocks(false, NULL, 0); - active_write = false; - // This write is complete, start the autoreload clock. - autoreload_start(); - } - } -} diff --git a/ports/esp8266/Makefile b/ports/esp8266/Makefile index 3b6cc1fb4..03d5a65cb 100644 --- a/ports/esp8266/Makefile +++ b/ports/esp8266/Makefile @@ -119,7 +119,6 @@ SRC_COMMON_HAL = \ multiterminal/__init__.c \ neopixel_write/__init__.c \ os/__init__.c \ - storage/__init__.c \ time/__init__.c \ board/__init__.c @@ -147,7 +146,6 @@ SRC_SHARED_MODULE = \ multiterminal/__init__.c \ os/__init__.c \ random/__init__.c \ - storage/__init__.c \ struct/__init__.c SRC_SHARED_MODULE_EXPANDED = $(addprefix shared-bindings/, $(SRC_SHARED_MODULE)) \ diff --git a/ports/esp8266/README.md b/ports/esp8266/README.md index f4dddd1ca..5f0ad8073 100644 --- a/ports/esp8266/README.md +++ b/ports/esp8266/README.md @@ -34,6 +34,14 @@ run `make` in its directory to build and install the SDK locally. Make sure to add toolchain bin directory to your PATH. Read esp-open-sdk's README for additional important information on toolchain setup. +Travis builds, including releases are actually built using a specific +esp-open-sdk binary. The location of the binary can be seen in the +`.travis.yml` in the top-level directory of CircuitPython. This may be ahead +of or behind the pfalcon repository, depending on the specific needs of +CircuitPython. If your local system is binary-compatible with Travis +(most Ubuntu and Debian based systems are), you can download the binary and +skip building it locally. + Add the external dependencies to the MicroPython repository checkout: ```bash $ git submodule update --init diff --git a/ports/esp8266/main.c b/ports/esp8266/main.c index 4882bf599..969d35bbf 100644 --- a/ports/esp8266/main.c +++ b/ports/esp8266/main.c @@ -95,10 +95,11 @@ STATIC void mp_reset(void) { mp_init(); mp_obj_list_init(mp_sys_path, 0); mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_)); // current dir (or base dir of the script) - mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_lib)); mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_)); // Frozen modules are in their own pseudo-dir, e.g., ".frozen". + // Prioritize .frozen over /lib. mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_FROZEN_FAKE_DIR_QSTR)); + mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_lib)); mp_obj_list_init(mp_sys_argv, 0); diff --git a/ports/esp8266/mpconfigport.h b/ports/esp8266/mpconfigport.h index eca3f525d..435f2c5cd 100644 --- a/ports/esp8266/mpconfigport.h +++ b/ports/esp8266/mpconfigport.h @@ -162,7 +162,6 @@ extern const struct _mp_obj_module_t esp_module; extern const struct _mp_obj_module_t network_module; extern const struct _mp_obj_module_t os_module; extern const struct _mp_obj_module_t random_module; -extern const struct _mp_obj_module_t storage_module; extern const struct _mp_obj_module_t struct_module; extern const struct _mp_obj_module_t mp_module_lwip; extern const struct _mp_obj_module_t mp_module_machine; @@ -194,7 +193,6 @@ extern const struct _mp_obj_module_t neopixel_write_module; { MP_OBJ_NEW_QSTR(MP_QSTR_pulseio), (mp_obj_t)&pulseio_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_busio), (mp_obj_t)&busio_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_bitbangio), (mp_obj_t)&bitbangio_module }, \ - { MP_OBJ_NEW_QSTR(MP_QSTR_storage), (mp_obj_t)&storage_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_random), (mp_obj_t)&random_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_struct), (mp_obj_t)&struct_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_math), (mp_obj_t)&math_module }, \ diff --git a/ports/nrf/.gitignore b/ports/nrf/.gitignore index ace93515a..227a82e50 100644 --- a/ports/nrf/.gitignore +++ b/ports/nrf/.gitignore @@ -1,6 +1,6 @@ # Nordic files ##################### -drivers/bluetooth/s1*/ +bluetooth/s1*/ # Build files ##################### diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile index 0e9d224be..558731a44 100755 --- a/ports/nrf/Makefile +++ b/ports/nrf/Makefile @@ -21,7 +21,7 @@ include ../../py/mkenv.mk -include mpconfigport.mk ifneq ($(SD), ) - include drivers/bluetooth/bluetooth_common.mk + include bluetooth/bluetooth_common.mk endif FROZEN_MPY_DIR = freeze @@ -29,6 +29,10 @@ FROZEN_MPY_DIR = freeze # include py core make definitions include ../../py/py.mk +ifneq ($(MCU_SUB_VARIANT),nrf52840) +USB = FALSE +endif + include $(TOP)/supervisor/supervisor.mk FATFS_DIR = lib/oofatfs @@ -47,12 +51,11 @@ INC += -I./nrfx INC += -I./nrfx/hal INC += -I./nrfx/mdk INC += -I./nrfx/drivers/include -INC += -I../../lib/mp-readline -INC += -I./drivers/bluetooth -INC += -I./drivers +INC += -I./bluetooth INC += -I./peripherals +INC += -I../../lib/mp-readline INC += -I../../lib/tinyusb/src -INC += -I./usb +INC += -I../../supervisor/shared/usb NRF_DEFINES += -DCONFIG_GPIO_AS_PINRESET @@ -69,6 +72,9 @@ LDFLAGS += -Xlinker -Map=$(@:.elf=.map) LDFLAGS += -mthumb -mabi=aapcs -T $(LD_FILE) -L boards/ LDFLAGS += -Wl,--gc-sections +# TinyUSB defines +CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_NRF5X -DCFG_TUD_CDC_RX_BUFSIZE=1024 -DCFG_TUD_CDC_TX_BUFSIZE=1024 -DCFG_TUD_MSC_BUFSIZE=4096 + #Debugging/Optimization ifeq ($(DEBUG), 1) #ASMFLAGS += -g -gtabs+ @@ -90,21 +96,29 @@ LIBS += -L $(dir $(LIBGCC_FILE_NAME)) -lgcc SRC_NRFX = $(addprefix nrfx/,\ drivers/src/nrfx_power.c \ drivers/src/nrfx_spim.c \ + drivers/src/nrfx_timer.c \ drivers/src/nrfx_twim.c \ - drivers/src/nrfx_uart.c \ + drivers/src/nrfx_uarte.c \ ) +ifdef EXTERNAL_FLASH_DEVICES + ifeq ($(QSPI_FLASH_FILESYSTEM),1) + SRC_NRFX += nrfx/drivers/src/nrfx_qspi.c + endif +endif + + SRC_C += \ background.c \ fatfs_port.c \ - internal_flash.c \ mphalport.c \ tick.c \ + board_busses.c \ boards/$(BOARD)/board.c \ boards/$(BOARD)/pins.c \ device/$(MCU_VARIANT)/startup_$(MCU_SUB_VARIANT).c \ - drivers/bluetooth/ble_drv.c \ - drivers/bluetooth/ble_uart.c \ + bluetooth/ble_drv.c \ + bluetooth/ble_uart.c \ lib/libc/string0.c \ lib/mp-readline/readline.c \ lib/oofatfs/ff.c \ @@ -122,20 +136,9 @@ SRC_C += \ peripherals/nrf/clocks.c \ peripherals/nrf/$(MCU_CHIP)/pins.c \ peripherals/nrf/$(MCU_CHIP)/power.c \ + peripherals/nrf/timers.c \ supervisor/shared/memory.c -DRIVERS_SRC_C += $(addprefix modules/,\ - ubluepy/modubluepy.c \ - ubluepy/ubluepy_peripheral.c \ - ubluepy/ubluepy_service.c \ - ubluepy/ubluepy_characteristic.c \ - ubluepy/ubluepy_uuid.c \ - ubluepy/ubluepy_delegate.c \ - ubluepy/ubluepy_constants.c \ - ubluepy/ubluepy_descriptor.c \ - ubluepy/ubluepy_scanner.c \ - ubluepy/ubluepy_scan_entry.c \ - ) SRC_COMMON_HAL += \ analogio/AnalogIn.c \ @@ -157,7 +160,6 @@ SRC_COMMON_HAL += \ pulseio/PulseIn.c \ pulseio/PulseOut.c \ pulseio/__init__.c \ - storage/__init__.c \ supervisor/Runtime.c \ supervisor/__init__.c \ time/__init__.c \ @@ -165,7 +167,13 @@ SRC_COMMON_HAL += \ ifneq ($(SD), ) SRC_COMMON_HAL += \ bleio/__init__.c \ - bleio/Adapter.c + bleio/Adapter.c \ + bleio/Characteristic.c \ + bleio/Descriptor.c \ + bleio/Device.c \ + bleio/Scanner.c \ + bleio/Service.c \ + bleio/UUID.c endif # These don't have corresponding files in each port but are still located in @@ -180,14 +188,18 @@ SRC_BINDINGS_ENUMS = \ math/__init__.c \ util.c -SRC_COMMON_HAL_EXPANDED = $(addprefix shared-bindings/, $(SRC_COMMON_HAL)) \ - $(addprefix shared-bindings/, $(SRC_BINDINGS_ENUMS)) \ - $(addprefix common-hal/, $(SRC_COMMON_HAL)) +ifneq ($(SD), ) +SRC_BINDINGS_ENUMS += \ + bleio/Address.c \ + bleio/AddressType.c \ + bleio/AdvertisementData.c \ + bleio/ScanEntry.c \ + bleio/UUIDType.c +endif SRC_SHARED_MODULE = \ os/__init__.c \ random/__init__.c \ - storage/__init__.c \ struct/__init__.c \ gamepad/__init__.c \ gamepad/GamePad.c \ @@ -196,44 +208,29 @@ SRC_SHARED_MODULE = \ bitbangio/OneWire.c \ bitbangio/SPI.c \ busio/OneWire.c \ + storage/__init__.c # uheap/__init__.c \ ustack/__init__.c -SRC_SHARED_BINDINGS = \ - struct/__init__.c \ - gamepad/__init__.c \ - gamepad/GamePad.c \ - bitbangio/__init__.c \ - bitbangio/I2C.c \ - bitbangio/SPI.c \ - bitbangio/OneWire.c \ - random/__init__.c \ - # USB source files for nrf52840 ifeq ($(MCU_SUB_VARIANT),nrf52840) SRC_C += \ - usb/usb.c \ - usb/usb_msc_flash.c \ - usb/usb_desc.c \ lib/tinyusb/src/portable/nordic/nrf5x/dcd_nrf5x.c \ - lib/tinyusb/src/portable/nordic/nrf5x/hal_nrf5x.c \ - lib/tinyusb/src/common/tusb_fifo.c \ - lib/tinyusb/src/device/usbd.c \ - lib/tinyusb/src/class/msc/msc_device.c \ - lib/tinyusb/src/class/cdc/cdc_device.c \ - lib/tinyusb/src/class/hid/hid_device.c \ - lib/tinyusb/src/tusb.c \ + lib/tinyusb/src/portable/nordic/nrf5x/hal_nrf5x.c -SRC_COMMON_HAL += \ +SRC_SHARED_MODULE += \ usb_hid/__init__.c \ usb_hid/Device.c \ endif +SRC_COMMON_HAL_EXPANDED = $(addprefix shared-bindings/, $(SRC_COMMON_HAL)) \ + $(addprefix shared-bindings/, $(SRC_BINDINGS_ENUMS)) \ + $(addprefix common-hal/, $(SRC_COMMON_HAL)) -SRC_SHARED_MODULE_EXPANDED = $(addprefix shared-bindings/, $(SRC_SHARED_BINDINGS)) \ +SRC_SHARED_MODULE_EXPANDED = $(addprefix shared-bindings/, $(SRC_SHARED_MODULE)) \ $(addprefix shared-module/, $(SRC_SHARED_MODULE)) SRC_S = supervisor/cpu.s @@ -297,16 +294,16 @@ sd: $(BUILD)/$(OUTPUT_FILENAME).hex else ifeq ($(FLASHER), pyocd) flash: $(BUILD)/$(OUTPUT_FILENAME).hex - pyocd-flashtool -t $(MCU_SUB_VARIANT) $< --sector_erase - pyocd-tool -t $(MCU_SUB_VARIANT) erase $(BOOT_SETTING_ADDR) - pyocd-tool -t $(MCU_SUB_VARIANT) write32 $(BOOT_SETTING_ADDR) 0x00000001 - pyocd-tool -t $(MCU_SUB_VARIANT) reset + pyocd-flashtool -t $(MCU_VARIANT) $< --sector_erase + #pyocd-tool -t $(MCU_VARIANT) erase $(BOOT_SETTING_ADDR) + pyocd-tool -t $(MCU_VARIANT) write32 $(BOOT_SETTING_ADDR) 0x00000001 + pyocd-tool -t $(MCU_VARIANT) reset sd: $(BUILD)/$(OUTPUT_FILENAME).hex - pyocd-flashtool -t $(MCU_SUB_VARIANT) --chip_erase - pyocd-flashtool -t $(MCU_SUB_VARIANT) $(SOFTDEV_HEX) - pyocd-flashtool -t $(MCU_SUB_VARIANT) $< --sector_erase - pyocd-tool -t $(MCU_SUB_VARIANT) reset $(BOOT_SETTING_ADDR) + pyocd-flashtool -t $(MCU_VARIANT) --chip_erase + pyocd-flashtool -t $(MCU_VARIANT) $(SOFTDEV_HEX) + pyocd-flashtool -t $(MCU_VARIANT) $< --sector_erase + pyocd-tool -t $(MCU_VARIANT) reset $(BOOT_SETTING_ADDR) endif @@ -341,9 +338,10 @@ dfu-gen: $(BUILD)/dfu-package.zip $(BUILD)/dfu-package.zip: $(BUILD)/$(OUTPUT_FILENAME).hex $(NRFUTIL) dfu genpkg --sd-req 0xFFFE --dev-type 0x0052 --application $^ $(BUILD)/dfu-package.zip +# You must have $^ here because it deduplicates entries in $(OBJ) $(BUILD)/$(OUTPUT_FILENAME).elf: $(OBJ) $(ECHO) "LINK $@" - $(Q)$(CC) $(LDFLAGS) -o $@ $(OBJ) -Wl,--start-group $(LIBS) -Wl,--end-group + $(Q)$(CC) $(LDFLAGS) -o $@ $^ -Wl,--start-group $(LIBS) -Wl,--end-group $(Q)$(SIZE) $@ # List of sources for qstr extraction diff --git a/ports/nrf/README.md b/ports/nrf/README.md index c21bd5d63..34e58cb78 100644 --- a/ports/nrf/README.md +++ b/ports/nrf/README.md @@ -39,6 +39,7 @@ the following links: * Adafruit [Feather nRF52](boards/feather_nrf52832/README.md): 512KB Flash, 64KB SRAM * Adafruit [Feather nRF52840](boards/feather_nrf52840_express/README.md): 1MB Flash, 256KB SRAM * Nordic PCA10056 see [Feather nRF52840](boards/pca10056/README.md) +* MakerDiary NRF52840 MDK see [its README](boards/makerdiary_nrf52840_mdk/README.md) For all other board targets, see the generic notes below. @@ -60,7 +61,7 @@ To build and flash issue the following command inside the ports/nrf/ folder: First prepare the bluetooth folder by downloading Bluetooth LE stacks and headers: - ./drivers/bluetooth/download_ble_stack.sh + ./bluetooth/download_ble_stack.sh If the Bluetooth stacks has been downloaded, compile the target with the following command: @@ -80,6 +81,7 @@ pca10040 | s132 | Peripheral and Scanner | [S pca10056 | s140 | Peripheral and Scanner | [Segger](#segger-targets) feather_nrf52832 | s132 | Peripheral and Scanner | [UART DFU](#dfu-targets) feather_nrf52840_express | s140 | Peripheral and Scanner | UF2 bootloader +makerdiary_nrf52840_mdk | s140 | Peripheral and Scanner | pyocd or ARM mbed DAPLink ## Segger Targets diff --git a/ports/nrf/background.c b/ports/nrf/background.c index d19604f68..f614b6bd0 100644 --- a/ports/nrf/background.c +++ b/ports/nrf/background.c @@ -24,11 +24,12 @@ * THE SOFTWARE. */ -#include "tusb.h" +#ifdef NRF52840 +#include "supervisor/usb.h" +#endif void run_background_tasks(void) { -#ifdef NRF52840_XXAA - tusb_task(); - tud_cdc_write_flush(); -#endif + #ifdef NRF52840 + usb_background(); + #endif } diff --git a/ports/nrf/bluetooth/ble_drv.c b/ports/nrf/bluetooth/ble_drv.c new file mode 100644 index 000000000..0b6daf711 --- /dev/null +++ b/ports/nrf/bluetooth/ble_drv.c @@ -0,0 +1,97 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Glenn Ruben Bakke + * Copyright (c) 2018 Artur Pacholec + * + * 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 <stdbool.h> +#include <stdio.h> + +#include "ble.h" +#include "ble_drv.h" +#include "nrf_nvic.h" +#include "nrf_sdm.h" +#include "py/misc.h" + +nrf_nvic_state_t nrf_nvic_state = { 0 }; + +__attribute__((aligned(4))) +static uint8_t m_ble_evt_buf[sizeof(ble_evt_t) + (BLE_GATT_ATT_MTU_DEFAULT)]; + +typedef struct event_handler { + struct event_handler *next; + void *param; + ble_drv_evt_handler_t func; +} event_handler_t; + +static event_handler_t *m_event_handlers; + +void ble_drv_add_event_handler(ble_drv_evt_handler_t func, void *param) { + event_handler_t *handler = m_new_ll(event_handler_t, 1); + handler->next = NULL; + handler->param = param; + handler->func = func; + + if (m_event_handlers == NULL) { + m_event_handlers = handler; + return; + } + + event_handler_t *it = m_event_handlers; + while (it->next != NULL) { + if ((it->func == func) && (it->param == param)) { + m_free(handler); + return; + } + + it = it->next; + } + + it->next = handler; +} + +void SD_EVT_IRQHandler(void) { + uint32_t evt_id; + while (sd_evt_get(&evt_id) != NRF_ERROR_NOT_FOUND) { +// sd_evt_handler(evt_id); + } + + while (1) { + uint16_t evt_len = sizeof(m_ble_evt_buf); + const uint32_t err_code = sd_ble_evt_get(m_ble_evt_buf, &evt_len); + if (err_code != NRF_SUCCESS) { + if (err_code == NRF_ERROR_DATA_SIZE) { + printf("NRF_ERROR_DATA_SIZE\n"); + } + + break; + } + + event_handler_t *it = m_event_handlers; + while (it != NULL) { + it->func((ble_evt_t *)m_ble_evt_buf, it->param); + it = it->next; + } + } +} diff --git a/ports/nrf/bluetooth/ble_drv.h b/ports/nrf/bluetooth/ble_drv.h new file mode 100644 index 000000000..0443b41b8 --- /dev/null +++ b/ports/nrf/bluetooth/ble_drv.h @@ -0,0 +1,53 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Glenn Ruben Bakke + * Copyright (c) 2018 Artur Pacholec + * + * 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_NRF_BLUETOOTH_BLE_DRV_H +#define MICROPY_INCLUDED_NRF_BLUETOOTH_BLE_DRV_H + +#include "ble.h" + +#if (BLUETOOTH_SD == 132) && (BLE_API_VERSION == 2) +#define NRF52 +#endif + +#define MAX_TX_IN_PROGRESS 10 + +#ifndef BLE_GATT_ATT_MTU_DEFAULT + #define BLE_GATT_ATT_MTU_DEFAULT GATT_MTU_SIZE_DEFAULT +#endif + +#define BLE_CONN_CFG_TAG_CUSTOM 1 + +#define MSEC_TO_UNITS(TIME, RESOLUTION) (((TIME) * 1000) / (RESOLUTION)) +#define UNIT_0_625_MS (625) +#define UNIT_10_MS (10000) + +typedef void (*ble_drv_evt_handler_t)(ble_evt_t*, void*); + +void ble_drv_add_event_handler(ble_drv_evt_handler_t func, void *param); + +#endif // MICROPY_INCLUDED_NRF_BLUETOOTH_BLE_DRV_H diff --git a/ports/nrf/bluetooth/ble_uart.c b/ports/nrf/bluetooth/ble_uart.c new file mode 100644 index 000000000..7faaafb0e --- /dev/null +++ b/ports/nrf/bluetooth/ble_uart.c @@ -0,0 +1,196 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Glenn Ruben Bakke + * Copyright (c) 2018 Artur Pacholec + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include <string.h> + +#include "ble.h" +#include "ble_uart.h" +#include "ringbuffer.h" +#include "py/mphal.h" +#include "py/runtime.h" +#include "lib/utils/interrupt_char.h" +#include "shared-bindings/bleio/Adapter.h" +#include "shared-bindings/bleio/Characteristic.h" +#include "shared-bindings/bleio/Device.h" +#include "shared-bindings/bleio/Service.h" +#include "shared-bindings/bleio/UUID.h" + +#if (MICROPY_PY_BLE_NUS == 1) + +static const char default_name[] = "CP-REPL"; // max 8 chars or uuid won't fit in adv data +static const char NUS_UUID[] = "6e400001-b5a3-f393-e0a9-e50e24dcca9e"; + +#define NUS_RX_UUID 0x0002 +#define NUS_TX_UUID 0x0003 +#define BUFFER_SIZE 128 + +ringBuffer_typedef(uint8_t, ringbuffer_t); + +static bleio_device_obj_t m_device; +static bleio_service_obj_t *m_nus; +static bleio_characteristic_obj_t *m_tx_chara; +static bleio_characteristic_obj_t *m_rx_chara; + +static volatile bool m_cccd_enabled; + +static uint8_t m_rx_ring_buffer_data[BUFFER_SIZE]; +static ringbuffer_t m_rx_ring_buffer = { + .size = sizeof(m_rx_ring_buffer_data) + 1, + .elems = m_rx_ring_buffer_data, +}; + +STATIC void on_ble_evt(ble_evt_t *ble_evt, void *param) { + switch (ble_evt->header.evt_id) { + case BLE_GAP_EVT_DISCONNECTED: + { + mp_obj_t device_obj = MP_OBJ_FROM_PTR(&m_device); + mp_call_function_0(mp_load_attr(device_obj, qstr_from_str("start_advertising"))); + break; + } + + case BLE_GATTS_EVT_WRITE: + { + ble_gatts_evt_write_t *write = &ble_evt->evt.gatts_evt.params.write; + + if (write->handle == m_tx_chara->cccd_handle) { + m_cccd_enabled = true; + } else if (write->handle == m_rx_chara->handle) { + for (size_t i = 0; i < write->len; ++i) { +#if MICROPY_KBD_EXCEPTION + if (write->data[i] == mp_interrupt_char) { + mp_keyboard_interrupt(); + } else +#endif + { + bufferWrite(&m_rx_ring_buffer, write->data[i]); + } + } + } + } + } +} + +void ble_uart_init(void) { + mp_obj_t device_obj = MP_OBJ_FROM_PTR(&m_device); + m_device.base.type = &bleio_device_type; + m_device.service_list = mp_obj_new_list(0, NULL); + m_device.notif_handler = mp_const_none; + m_device.conn_handler = mp_const_none; + m_device.conn_handle = 0xFFFF; + m_device.is_peripheral = true; + m_device.name = mp_obj_new_str(default_name, strlen(default_name), false); + common_hal_bleio_adapter_get_address(&m_device.address); + + mp_obj_t nus_uuid_str = mp_obj_new_str(NUS_UUID, strlen(NUS_UUID), false); + mp_obj_t nus_uuid_obj = bleio_uuid_type.make_new(&bleio_uuid_type, 1, 0, &nus_uuid_str); + mp_obj_t nus_obj = bleio_service_type.make_new(&bleio_service_type, 1, 0, &nus_uuid_obj); + m_nus = MP_OBJ_TO_PTR(nus_obj); + mp_call_function_1(mp_load_attr(device_obj, qstr_from_str("add_service")), nus_obj); + + mp_obj_t tx_uuid_int = mp_obj_new_int(NUS_TX_UUID); + mp_obj_t tx_uuid_obj = bleio_uuid_type.make_new(&bleio_uuid_type, 1, 0, &tx_uuid_int); + mp_obj_t tx_obj = bleio_characteristic_type.make_new(&bleio_characteristic_type, 1, 0, &tx_uuid_obj); + m_tx_chara = MP_OBJ_TO_PTR(tx_obj); + m_tx_chara->uuid->type = UUID_TYPE_128BIT; + m_tx_chara->uuid->uuid_vs_idx = m_nus->uuid->uuid_vs_idx; + m_tx_chara->props.notify = true; + mp_call_function_1(mp_load_attr(nus_obj, qstr_from_str("add_characteristic")), tx_obj); + + mp_obj_t rx_uuid_int = mp_obj_new_int(NUS_RX_UUID); + mp_obj_t rx_uuid_obj = bleio_uuid_type.make_new(&bleio_uuid_type, 1, 0, &rx_uuid_int); + mp_obj_t rx_obj = bleio_characteristic_type.make_new(&bleio_characteristic_type, 1, 0, &rx_uuid_obj); + m_rx_chara = MP_OBJ_TO_PTR(rx_obj); + m_rx_chara->uuid->type = UUID_TYPE_128BIT; + m_rx_chara->uuid->uuid_vs_idx = m_nus->uuid->uuid_vs_idx; + m_rx_chara->props.write = true; + m_rx_chara->props.write_wo_resp = true; + mp_call_function_1(mp_load_attr(nus_obj, qstr_from_str("add_characteristic")), rx_obj); + + mp_call_function_0(mp_load_attr(device_obj, qstr_from_str("start_advertising"))); + + ble_drv_add_event_handler(on_ble_evt, &m_device); + + m_cccd_enabled = false; + + while (!m_cccd_enabled) { +#ifdef MICROPY_VM_HOOK_LOOP + MICROPY_VM_HOOK_LOOP +#endif + } +} + +bool ble_uart_connected(void) { + return (m_device.conn_handle != BLE_CONN_HANDLE_INVALID); +} + +char ble_uart_rx_chr(void) { + while (isBufferEmpty(&m_rx_ring_buffer)) { +#ifdef MICROPY_VM_HOOK_LOOP + MICROPY_VM_HOOK_LOOP +#endif + } + + uint8_t byte; + bufferRead(&m_rx_ring_buffer, byte); + return (int)byte; +} + +bool ble_uart_stdin_any(void) { + return !isBufferEmpty(&m_rx_ring_buffer); +} + +void ble_uart_stdout_tx_str(const char *text) { + mp_hal_stdout_tx_strn(text, strlen(text)); +} + +int mp_hal_stdin_rx_chr(void) { + return ble_uart_rx_chr(); +} + +void mp_hal_stdout_tx_strn(const char *str, size_t len) { + size_t send_len; + + while (len > 0) { + if (len >= BLE_GATT_ATT_MTU_DEFAULT - 3) { + send_len = (BLE_GATT_ATT_MTU_DEFAULT - 3); + } else { + send_len = len; + } + + mp_buffer_info_t bufinfo = { + .buf = (uint8_t*)str, + .len = send_len, + }; + + common_hal_bleio_characteristic_write_value(m_tx_chara, &bufinfo); + + len -= send_len; + str += send_len; + } +} + +#endif // MICROPY_PY_BLE_NUS diff --git a/ports/nrf/drivers/bluetooth/ble_uart.h b/ports/nrf/bluetooth/ble_uart.h index e67176a26..d86e6293a 100644 --- a/ports/nrf/drivers/bluetooth/ble_uart.h +++ b/ports/nrf/bluetooth/ble_uart.h @@ -24,19 +24,17 @@ * THE SOFTWARE. */ -#ifndef BLUETOOTH_LE_UART_H__ -#define BLUETOOTH_LE_UART_H__ +#ifndef MICROPY_INCLUDED_NRF_BLUETOOTH_BLE_UART_H +#define MICROPY_INCLUDED_NRF_BLUETOOTH_BLE_UART_H -#if BLUETOOTH_SD +#include <stdbool.h> -#include "modubluepy.h" #include "ble_drv.h" -void ble_uart_init0(void); -void ble_uart_advertise(void); +void ble_uart_init(void); bool ble_uart_connected(void); -bool ble_uart_enabled(void); +char ble_uart_rx_chr(void); +bool ble_uart_stdin_any(void); +void ble_uart_stdout_tx_str(const char *text); -#endif // BLUETOOTH_SD - -#endif // BLUETOOTH_LE_UART_H__ +#endif // MICROPY_INCLUDED_NRF_BLUETOOTH_BLE_UART_H diff --git a/ports/nrf/drivers/bluetooth/bluetooth_common.mk b/ports/nrf/bluetooth/bluetooth_common.mk index 81e50e333..7dad38e9e 100644 --- a/ports/nrf/drivers/bluetooth/bluetooth_common.mk +++ b/ports/nrf/bluetooth/bluetooth_common.mk @@ -15,11 +15,11 @@ endif CFLAGS += -DBLUETOOTH_SD_DEBUG=1 -INC += -Idrivers/bluetooth/$(SD)_$(MCU_VARIANT)_$(SOFTDEV_VERSION)/$(SD)_$(MCU_VARIANT)_$(SOFTDEV_VERSION)_API/include -INC += -Idrivers/bluetooth/$(SD)_$(MCU_VARIANT)_$(SOFTDEV_VERSION)/$(SD)_$(MCU_VARIANT)_$(SOFTDEV_VERSION)_API/include/$(MCU_VARIANT) +INC += -Ibluetooth/$(SD)_$(MCU_VARIANT)_$(SOFTDEV_VERSION)/$(SD)_$(MCU_VARIANT)_$(SOFTDEV_VERSION)_API/include +INC += -Ibluetooth/$(SD)_$(MCU_VARIANT)_$(SOFTDEV_VERSION)/$(SD)_$(MCU_VARIANT)_$(SOFTDEV_VERSION)_API/include/$(MCU_VARIANT) SOFTDEV_HEX_NAME = $(SD)_$(MCU_VARIANT)_$(SOFTDEV_VERSION)_softdevice.hex -SOFTDEV_HEX_PATH = drivers/bluetooth/$(SD)_$(MCU_VARIANT)_$(SOFTDEV_VERSION) +SOFTDEV_HEX_PATH = bluetooth/$(SD)_$(MCU_VARIANT)_$(SOFTDEV_VERSION) SOFTDEV_HEX = $(SOFTDEV_HEX_PATH)/$(SOFTDEV_HEX_NAME) define STACK_MISSING_ERROR @@ -32,7 +32,7 @@ define STACK_MISSING_ERROR # # # Please run the download script: # # # -# drivers/bluetooth/download_ble_stack.sh # +# bluetooth/download_ble_stack.sh # # # ####################################################### diff --git a/ports/nrf/drivers/bluetooth/download_ble_stack.sh b/ports/nrf/bluetooth/download_ble_stack.sh index 385dbb451..385dbb451 100755 --- a/ports/nrf/drivers/bluetooth/download_ble_stack.sh +++ b/ports/nrf/bluetooth/download_ble_stack.sh diff --git a/ports/nrf/drivers/bluetooth/ringbuffer.h b/ports/nrf/bluetooth/ringbuffer.h index 3438b5c9b..9a06e7ccc 100644 --- a/ports/nrf/drivers/bluetooth/ringbuffer.h +++ b/ports/nrf/bluetooth/ringbuffer.h @@ -79,21 +79,21 @@ BUF.elems = (T*)calloc(BUF.size, sizeof(T)) -#define bufferDestroy(BUF) free(BUF->elems) -#define nextStartIndex(BUF) ((BUF->start + 1) % BUF->size) -#define nextEndIndex(BUF) ((BUF->end + 1) % BUF->size) -#define isBufferEmpty(BUF) (BUF->end == BUF->start) -#define isBufferFull(BUF) (nextEndIndex(BUF) == BUF->start) +#define bufferDestroy(BUF) free((BUF)->elems) +#define nextStartIndex(BUF) (((BUF)->start + 1) % (BUF)->size) +#define nextEndIndex(BUF) (((BUF)->end + 1) % (BUF)->size) +#define isBufferEmpty(BUF) ((BUF)->end == (BUF)->start) +#define isBufferFull(BUF) (nextEndIndex(BUF) == (BUF)->start) #define bufferWrite(BUF, ELEM) \ - BUF->elems[BUF->end] = ELEM; \ - BUF->end = (BUF->end + 1) % BUF->size; \ + (BUF)->elems[(BUF)->end] = ELEM; \ + (BUF)->end = ((BUF)->end + 1) % (BUF)->size; \ if (isBufferEmpty(BUF)) { \ - BUF->start = nextStartIndex(BUF); \ + (BUF)->start = nextStartIndex(BUF); \ } #define bufferRead(BUF, ELEM) \ - ELEM = BUF->elems[BUF->start]; \ - BUF->start = nextStartIndex(BUF); + ELEM = (BUF)->elems[(BUF)->start]; \ + (BUF)->start = nextStartIndex(BUF); #endif diff --git a/ports/nrf/board_busses.c b/ports/nrf/board_busses.c index 91f0def6d..6d5cbd041 100644 --- a/ports/nrf/board_busses.c +++ b/ports/nrf/board_busses.c @@ -30,8 +30,8 @@ #include "shared-bindings/microcontroller/Pin.h" #include "supervisor/shared/translate.h" -#include "mpconfigboard.h" #include "nrf/pins.h" +#include "py/mpconfig.h" #include "py/runtime.h" #if !defined(DEFAULT_I2C_BUS_SDA) || !defined(DEFAULT_I2C_BUS_SCL) diff --git a/ports/nrf/boards/feather_nrf52832/README.md b/ports/nrf/boards/feather_nrf52832/README.md index b5acd6360..ef910509a 100644 --- a/ports/nrf/boards/feather_nrf52832/README.md +++ b/ports/nrf/boards/feather_nrf52832/README.md @@ -18,7 +18,7 @@ You then need to download the SD and Nordic SDK files via: ``` $ cd ports/nrf -$ ./drivers/bluetooth/download_ble_stack.sh +$ ./bluetooth/download_ble_stack.sh ``` ## Installing `adafruit-nrfutil` diff --git a/ports/nrf/boards/feather_nrf52832/mpconfigboard.h b/ports/nrf/boards/feather_nrf52832/mpconfigboard.h index 0da1abfc4..e751ec182 100644 --- a/ports/nrf/boards/feather_nrf52832/mpconfigboard.h +++ b/ports/nrf/boards/feather_nrf52832/mpconfigboard.h @@ -30,7 +30,6 @@ #define MICROPY_HW_UART_RX NRF_GPIO_PIN_MAP(0, 8) #define MICROPY_HW_UART_TX NRF_GPIO_PIN_MAP(0, 6) -#define MICROPY_HW_UART_HWFC (0) #define PORT_HEAP_SIZE (32 * 1024) #define CIRCUITPY_AUTORELOAD_DELAY_MS 500 diff --git a/ports/nrf/boards/feather_nrf52840_express/README.md b/ports/nrf/boards/feather_nrf52840_express/README.md index 5d2177ff3..8d515010f 100644 --- a/ports/nrf/boards/feather_nrf52840_express/README.md +++ b/ports/nrf/boards/feather_nrf52840_express/README.md @@ -33,7 +33,7 @@ You then need to download the SD and Nordic SDK files via: ``` $ cd ports/nrf -$ ./drivers/bluetooth/download_ble_stack.sh +$ ./bluetooth/download_ble_stack.sh ``` ## Installing the Serial Bootloader @@ -198,4 +198,4 @@ Converting to uf2, output size: 392192, start address: 0x26000 Wrote 392192 bytes to build-feather52840-s140/firmware.uf2. ``` -Simply drag and drop firmware.uf2 to the MSC, the nrf52840 will blink fast and reset after done.
\ No newline at end of file +Simply drag and drop firmware.uf2 to the MSC, the nrf52840 will blink fast and reset after done. diff --git a/ports/nrf/boards/feather_nrf52840_express/board.c b/ports/nrf/boards/feather_nrf52840_express/board.c index a6d050fce..4421970ee 100644 --- a/ports/nrf/boards/feather_nrf52840_express/board.c +++ b/ports/nrf/boards/feather_nrf52840_express/board.c @@ -25,10 +25,8 @@ */ #include "boards/board.h" -#include "usb.h" void board_init(void) { - usb_init(); } bool board_requests_safe_mode(void) { diff --git a/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.h b/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.h index 81818741d..bd1cad504 100644 --- a/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.h +++ b/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.h @@ -25,20 +25,31 @@ * THE SOFTWARE. */ +#include "nrfx/hal/nrf_gpio.h" + #define FEATHER52840 #define MICROPY_HW_BOARD_NAME "Adafruit Feather nRF52840 Express" #define MICROPY_HW_MCU_NAME "nRF52840" #define MICROPY_PY_SYS_PLATFORM "Feather52840Express" -#define MICROPY_HW_NEOPIXEL (&pin_P0_13) +#define MICROPY_HW_NEOPIXEL (&pin_P0_16) + +#ifdef QSPI_FLASH_FILESYSTEM +#define MICROPY_QSPI_DATA0 NRF_GPIO_PIN_MAP(0, 17) +#define MICROPY_QSPI_DATA1 NRF_GPIO_PIN_MAP(0, 22) +#define MICROPY_QSPI_DATA2 NRF_GPIO_PIN_MAP(0, 23) +#define MICROPY_QSPI_DATA3 NRF_GPIO_PIN_MAP(0, 21) +#define MICROPY_QSPI_SCK NRF_GPIO_PIN_MAP(0, 19) +#define MICROPY_QSPI_CS NRF_GPIO_PIN_MAP(0, 20) +#endif -#define MICROPY_QSPI_DATA0 (&pin_P1_09) -#define MICROPY_QSPI_DATA1 (&pin_P0_11) -#define MICROPY_QSPI_DATA2 (&pin_P0_12) -#define MICROPY_QSPI_DATA3 (&pin_P0_14) -#define MICROPY_QSPI_SCK (&pin_P0_08) -#define MICROPY_QSPI_CS (&pin_P1_08) +#ifdef SPI_FLASH_FILESYSTEM +#define SPI_FLASH_MOSI_PIN &pin_P0_17 +#define SPI_FLASH_MISO_PIN &pin_P0_22 +#define SPI_FLASH_SCK_PIN &pin_P0_19 +#define SPI_FLASH_CS_PIN &pin_P0_20 +#endif #define CIRCUITPY_AUTORELOAD_DELAY_MS 500 @@ -49,23 +60,14 @@ #define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000 - CIRCUITPY_INTERNAL_NVM_SIZE) -// TODO #include "external_flash/devices.h" - -#define EXTERNAL_FLASH_DEVICE_COUNT 1 -#define EXTERNAL_FLASH_DEVICES GD25Q16C - -#define EXTERNAL_FLASH_QSPI_DUAL - -// TODO include "external_flash/external_flash.h" - #define BOARD_HAS_CRYSTAL 1 -#define DEFAULT_I2C_BUS_SCL (&pin_P1_11) -#define DEFAULT_I2C_BUS_SDA (&pin_P1_12) +#define DEFAULT_I2C_BUS_SCL (&pin_P0_11) +#define DEFAULT_I2C_BUS_SDA (&pin_P0_12) -#define DEFAULT_SPI_BUS_SCK (&pin_P0_20) -#define DEFAULT_SPI_BUS_MOSI (&pin_P0_23) -#define DEFAULT_SPI_BUS_MISO (&pin_P0_22) +#define DEFAULT_SPI_BUS_SCK (&pin_P0_14) +#define DEFAULT_SPI_BUS_MOSI (&pin_P0_13) +#define DEFAULT_SPI_BUS_MISO (&pin_P0_15) -#define DEFAULT_UART_BUS_RX (&pin_P1_0) -#define DEFAULT_UART_BUS_TX (&pin_P0_24) +#define DEFAULT_UART_BUS_RX (&pin_P0_24) +#define DEFAULT_UART_BUS_TX (&pin_P0_25) diff --git a/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.mk b/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.mk index caf580ec4..905921a5d 100644 --- a/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.mk +++ b/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.mk @@ -1,3 +1,8 @@ +USB_VID = 0x239A +USB_PID = 0x802A +USB_PRODUCT = "Feather nRF52840 Express" +USB_MANUFACTURER = "Adafruit Industries LLC" + MCU_SERIES = m4 MCU_VARIANT = nrf52 MCU_SUB_VARIANT = nrf52840 @@ -14,3 +19,7 @@ else endif NRF_DEFINES += -DNRF52840_XXAA -DNRF52840 + +QSPI_FLASH_FILESYSTEM = 1 +EXTERNAL_FLASH_DEVICE_COUNT = 1 +EXTERNAL_FLASH_DEVICES = "GD25Q16C" diff --git a/ports/nrf/boards/feather_nrf52840_express/pins.c b/ports/nrf/boards/feather_nrf52840_express/pins.c index 0f5eab31d..b85b72af0 100644 --- a/ports/nrf/boards/feather_nrf52840_express/pins.c +++ b/ports/nrf/boards/feather_nrf52840_express/pins.c @@ -3,39 +3,47 @@ #include "board_busses.h" STATIC const mp_rom_map_elem_t board_module_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_P0_30) }, - { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_P0_28) }, - { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_P0_31) }, - { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_P0_02) }, - { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_P0_29) }, + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_P0_04) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_P0_05) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_P0_30) }, + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_P0_28) }, + { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_P0_02) }, { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_P0_03) }, - { MP_ROM_QSTR(MP_QSTR_AREF), MP_ROM_PTR(&pin_P0_04) }, - { MP_ROM_QSTR(MP_QSTR_VDIV), MP_ROM_PTR(&pin_P0_05) }, + { MP_ROM_QSTR(MP_QSTR_AREF), MP_ROM_PTR(&pin_P0_31) }, - { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_P1_13) }, - { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_P1_14) }, - { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_P1_15) }, + { MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_P0_29) }, + { MP_ROM_QSTR(MP_QSTR_BATTERY), MP_ROM_PTR(&pin_P0_29) }, + + { MP_ROM_QSTR(MP_QSTR_SWITCH), MP_ROM_PTR(&pin_P1_02) }, + + { MP_ROM_QSTR(MP_QSTR_NFC1), MP_ROM_PTR(&pin_P0_09) }, + { MP_ROM_QSTR(MP_QSTR_NFC2), MP_ROM_PTR(&pin_P0_10) }, + + { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_P0_10) }, + { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_P1_08) }, + { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_P0_07) }, + { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_P0_26) }, { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_P0_27) }, - { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_P0_26) }, - { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_P0_06) }, - { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_P0_07) }, - { MP_ROM_QSTR(MP_QSTR_L), MP_ROM_PTR(&pin_P0_07) }, + { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_P0_06) }, + { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_P0_08) }, + { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_P1_09) }, - { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_P0_13) }, + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_P0_16) }, - { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_P0_20) }, - { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_P0_23) }, - { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_P0_22) }, + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_P0_14) }, + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_P0_13) }, + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_P0_15) }, - { MP_ROM_QSTR(MP_QSTR_TXD), MP_ROM_PTR(&pin_P0_24) }, - { MP_ROM_QSTR(MP_QSTR_RXD), MP_ROM_PTR(&pin_P1_00) }, + { MP_ROM_QSTR(MP_QSTR_TXD), MP_ROM_PTR(&pin_P0_25) }, + { MP_ROM_QSTR(MP_QSTR_RXD), MP_ROM_PTR(&pin_P0_24) }, - { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_P1_11) }, - { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_P1_12) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_P0_11) }, + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_P0_12) }, - { MP_ROM_QSTR(MP_QSTR_LED_RED), MP_ROM_PTR(&pin_P1_02) }, - { MP_ROM_QSTR(MP_QSTR_LED_BLUE), MP_ROM_PTR(&pin_P1_10) }, + { MP_ROM_QSTR(MP_QSTR_L), MP_ROM_PTR(&pin_P1_15) }, + { MP_ROM_QSTR(MP_QSTR_RED_LED), MP_ROM_PTR(&pin_P1_15) }, + { MP_ROM_QSTR(MP_QSTR_BLUE_LED), MP_ROM_PTR(&pin_P1_10) }, }; MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/nrf/boards/makerdiary_nrf52840_mdk/README.md b/ports/nrf/boards/makerdiary_nrf52840_mdk/README.md new file mode 100644 index 000000000..f1ba8151a --- /dev/null +++ b/ports/nrf/boards/makerdiary_nrf52840_mdk/README.md @@ -0,0 +1,102 @@ +# MakerDiary NRF52840 MDK + +Refer to https://github.com/makerdiary/nrf52840-mdk or +https://wiki.makerdiary.com/nrf52840-mdk/ for more details about the device. + +Notably, CircuitPython does not currently support QSPI external flash on NRF +devices, so neither does this port - the 64Mb flash device is not used for +anything. Also, don't confuse this with the 64MiB drive that shows up on your +computer - it's actually part of the MSC driver provided by the DAPLink +debugger, and is inaccessible at all from Python land (this drive is where you +can copy `firmware.hex` if you'd prefer to flash that way as opposed to with +`pyocd`. You'll still have access to 256KB of the onboard flash, however, for +storing your Python files, cat pictures, or whatever. + +It's also interesting to note that all three LEDs and the "user button" on this +device are wired through sinks, not sources, so flip your boolean expectations +when dealing with `digitalio.DigitalInOut` on this device - `my_led.value = +True` turns the LED off! Likewise, the user button will read `False` when +pressed. + +## Installing CircuitPython submodules + +Before you can build, you will need to run the following commands once, which +will install the submodules that are part of the CircuitPython ecosystem, and +build the `mpy-cross` tool: + +``` +$ cd circuitpython +$ git submodule update --init +$ make -C mpy-cross +``` + +You then need to download the SD and Nordic SDK files via: + +> This script relies on `wget`, which must be available from the command line. + +``` +$ cd ports/nrf +$ ./drivers/bluetooth/download_ble_stack.sh +``` + +## Note about bootloaders + +While most Adafruit devices come with (or can easily be flashed with) an +Adafruit-provided bootloader (supporting niceties like UF2 flashing), this +board comes with DAPLink which (apparently?) handles everything from debugging +to programming the device, as well as the boot sequence. What's particularly +awesome about this board is that there is no physical interaction with the board +required to flash new code (read: CircuitPython builds) - the device is _always_ +listening for new firmware uploads (via `pyocd-flashtool`), even if userspace +code is running. + +## Building and Flashing CircuitPython + +You'll need to have [pyocd](https://github.com/mbedmicro/pyOCD) installed as +appropriate for your system. + +```sh +make BOARD=makerdiary_nrf52840_mdk FLASHER=pyocd SD=s140 flash +``` + +This should give you the following (or very similar) output, and you will see +a DFU blinky pattern on one of the board LEDs: + +``` +$ make BOARD=makerdiary_nrf52840_mdk FLASHER=pyocd SD=s140 flash +Use make V=1, make V=2 or set BUILD_VERBOSE similarly in your environment to increase build verbosity. +pyocd-flashtool -t nrf52 build-makerdiary_nrf52840_mdk-s140/firmware.hex --sector_erase +INFO:root:DAP SWD MODE initialised +INFO:root:ROM table #0 @ 0xe00ff000 cidr=b105100d pidr=2002c4008 +INFO:root:[0]<e000e000:SCS-M4 cidr=b105e00d, pidr=4000bb00c, class=14> +WARNING:root:Invalid coresight component, cidr=0x0 +INFO:root:[1]<e0001000: cidr=0, pidr=0, component invalid> +INFO:root:[2]<e0002000:FPB cidr=b105e00d, pidr=4002bb003, class=14> +WARNING:root:Invalid coresight component, cidr=0x1010101 +INFO:root:[3]<e0000000: cidr=1010101, pidr=101010101010101, component invalid> +WARNING:root:Invalid coresight component, cidr=0x0 +INFO:root:[4]<e0040000: cidr=0, pidr=0, component invalid> +INFO:root:[5]<e0041000:ETM-M4 cidr=b105900d, pidr=4000bb925, class=9, devtype=13, devid=0> +INFO:root:CPU core is Cortex-M4 +INFO:root:FPU present +INFO:root:6 hardware breakpoints, 4 literal comparators +INFO:root:4 hardware watchpoints +[====================] 100% +INFO:root:Programmed 237568 bytes (58 pages) at 14.28 kB/s +#pyocd-tool -t nrf52 erase 0xFF000 +pyocd-tool -t nrf52 write32 0xFF000 0x00000001 +WARNING:root:Invalid coresight component, cidr=0x0 +WARNING:root:Invalid coresight component, cidr=0x1010101 +WARNING:root:Invalid coresight component, cidr=0x0 +pyocd-tool -t nrf52 reset +WARNING:root:Invalid coresight component, cidr=0x0 +WARNING:root:Invalid coresight component, cidr=0x1010101 +WARNING:root:Invalid coresight component, cidr=0x0 +Resetting target +``` + +Alternatively (and untested by me), it's apparently possible to copy +`firmware.hex` to the MSC device provided by DAPLink and flash that way. Refer +to [the upstream +documentation](https://wiki.makerdiary.com/nrf52840-mdk/getting-started/#drag-n-drop-programming) +for details. diff --git a/ports/atmel-samd/usb.h b/ports/nrf/boards/makerdiary_nrf52840_mdk/board.c index f01c5ebfb..4421970ee 100644 --- a/ports/atmel-samd/usb.h +++ b/ports/nrf/boards/makerdiary_nrf52840_mdk/board.c @@ -1,5 +1,5 @@ /* - * This file is part of the Micro Python project, http://micropython.org/ + * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * @@ -24,19 +24,15 @@ * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_ATMEL_SAMD_USB_H -#define MICROPY_INCLUDED_ATMEL_SAMD_USB_H +#include "boards/board.h" -#include <stdbool.h> -#include <stdint.h> +void board_init(void) { +} -#define USB_RX_BUF_SIZE 128 +bool board_requests_safe_mode(void) { + return false; +} -void init_usb(void); -int usb_read(void); -void usb_write(const char* buffer, uint32_t len); -bool usb_bytes_available(void); -bool usb_connected(void); -void usb_cdc_background(void); +void reset_board(void) { -#endif // MICROPY_INCLUDED_ATMEL_SAMD_USB_H +} diff --git a/ports/nrf/boards/makerdiary_nrf52840_mdk/mpconfigboard.h b/ports/nrf/boards/makerdiary_nrf52840_mdk/mpconfigboard.h new file mode 100644 index 000000000..40b6487ec --- /dev/null +++ b/ports/nrf/boards/makerdiary_nrf52840_mdk/mpconfigboard.h @@ -0,0 +1,55 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Glenn Ruben Bakke + * Copyright (c) 2018 Dan Halbert 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. + */ + +#include "nrfx/hal/nrf_gpio.h" + +#define MAKERDIARYNRF52840MDK + +#define MICROPY_HW_BOARD_NAME "MakerDiary nRF52840 MDK" +#define MICROPY_HW_MCU_NAME "nRF52840" +#define MICROPY_PY_SYS_PLATFORM "MakerDiary52840MDK" + +#define MICROPY_QSPI_DATA0 NRF_GPIO_PIN_MAP(1, 5) +#define MICROPY_QSPI_DATA1 NRF_GPIO_PIN_MAP(1, 4) +#define MICROPY_QSPI_DATA2 NRF_GPIO_PIN_MAP(1, 2) +#define MICROPY_QSPI_DATA3 NRF_GPIO_PIN_MAP(1, 1) +#define MICROPY_QSPI_SCK NRF_GPIO_PIN_MAP(1, 3) +#define MICROPY_QSPI_CS NRF_GPIO_PIN_MAP(1, 8) + +#define CIRCUITPY_AUTORELOAD_DELAY_MS 500 + +// If you change this, then make sure to update the linker scripts as well to +// make sure you don't overwrite code +#define PORT_HEAP_SIZE (128 * 1024) +// TODO #define CIRCUITPY_INTERNAL_NVM_SIZE 8192 + +#define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000 - CIRCUITPY_INTERNAL_NVM_SIZE) + +#define BOARD_HAS_CRYSTAL 0 + +#define DEFAULT_UART_BUS_RX (&pin_P0_19) +#define DEFAULT_UART_BUS_TX (&pin_P0_20) diff --git a/ports/nrf/boards/makerdiary_nrf52840_mdk/mpconfigboard.mk b/ports/nrf/boards/makerdiary_nrf52840_mdk/mpconfigboard.mk new file mode 100644 index 000000000..84dff0bc4 --- /dev/null +++ b/ports/nrf/boards/makerdiary_nrf52840_mdk/mpconfigboard.mk @@ -0,0 +1,25 @@ +USB_VID = 0x239A +USB_PID = 0x802A +USB_PRODUCT = "nRF52840-MDK" +USB_MANUFACTURER = "makerdiary" + +MCU_SERIES = m4 +MCU_VARIANT = nrf52 +MCU_SUB_VARIANT = nrf52840 +MCU_CHIP = nrf52840 +SD ?= s140 +SOFTDEV_VERSION ?= 6.1.0 + +BOOT_SETTING_ADDR = 0xFF000 + +ifeq ($(SD),) + LD_FILE = boards/nrf52840_1M_256k.ld +else + LD_FILE = boards/adafruit_$(MCU_SUB_VARIANT)_$(SD_LOWER)_v$(firstword $(subst ., ,$(SOFTDEV_VERSION))).ld +endif + +NRF_DEFINES += -DNRF52840_XXAA -DNRF52840 + +QSPI_FLASH_FILESYSTEM = 1 +EXTERNAL_FLASH_DEVICE_COUNT = 1 +EXTERNAL_FLASH_DEVICES = "MX25R6435F" diff --git a/ports/nrf/boards/makerdiary_nrf52840_mdk/pins.c b/ports/nrf/boards/makerdiary_nrf52840_mdk/pins.c new file mode 100644 index 000000000..27f0c6797 --- /dev/null +++ b/ports/nrf/boards/makerdiary_nrf52840_mdk/pins.c @@ -0,0 +1,63 @@ +#include "shared-bindings/board/__init__.h" + +#include "board_busses.h" + +STATIC const mp_rom_map_elem_t board_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR_AIN0), MP_ROM_PTR(&pin_P0_02) }, + { MP_ROM_QSTR(MP_QSTR_AIN1), MP_ROM_PTR(&pin_P0_03) }, + { MP_ROM_QSTR(MP_QSTR_AIN2), MP_ROM_PTR(&pin_P0_04) }, + { MP_ROM_QSTR(MP_QSTR_AIN3), MP_ROM_PTR(&pin_P0_05) }, + { MP_ROM_QSTR(MP_QSTR_AIN4), MP_ROM_PTR(&pin_P0_28) }, + { MP_ROM_QSTR(MP_QSTR_AIN5), MP_ROM_PTR(&pin_P0_29) }, + { MP_ROM_QSTR(MP_QSTR_AIN6), MP_ROM_PTR(&pin_P0_30) }, + { MP_ROM_QSTR(MP_QSTR_AIN7), MP_ROM_PTR(&pin_P0_31) }, + + { MP_ROM_QSTR(MP_QSTR_AREF), MP_ROM_PTR(&pin_P0_04) }, + { MP_ROM_QSTR(MP_QSTR_VDIV), MP_ROM_PTR(&pin_P0_05) }, + + { MP_ROM_QSTR(MP_QSTR_NFC1), MP_ROM_PTR(&pin_P0_09) }, + { MP_ROM_QSTR(MP_QSTR_NFC2), MP_ROM_PTR(&pin_P0_10) }, + + { MP_ROM_QSTR(MP_QSTR_P2), MP_ROM_PTR(&pin_P0_02) }, + { MP_ROM_QSTR(MP_QSTR_P3), MP_ROM_PTR(&pin_P0_03) }, + { MP_ROM_QSTR(MP_QSTR_P4), MP_ROM_PTR(&pin_P0_04) }, + { MP_ROM_QSTR(MP_QSTR_P5), MP_ROM_PTR(&pin_P0_05) }, + { MP_ROM_QSTR(MP_QSTR_P6), MP_ROM_PTR(&pin_P0_06) }, + { MP_ROM_QSTR(MP_QSTR_P7), MP_ROM_PTR(&pin_P0_07) }, + { MP_ROM_QSTR(MP_QSTR_P8), MP_ROM_PTR(&pin_P0_08) }, + { MP_ROM_QSTR(MP_QSTR_P9), MP_ROM_PTR(&pin_P0_09) }, + { MP_ROM_QSTR(MP_QSTR_P10), MP_ROM_PTR(&pin_P0_10) }, + { MP_ROM_QSTR(MP_QSTR_P11), MP_ROM_PTR(&pin_P0_11) }, + { MP_ROM_QSTR(MP_QSTR_P12), MP_ROM_PTR(&pin_P0_12) }, + { MP_ROM_QSTR(MP_QSTR_P13), MP_ROM_PTR(&pin_P0_13) }, + { MP_ROM_QSTR(MP_QSTR_P14), MP_ROM_PTR(&pin_P0_14) }, + { MP_ROM_QSTR(MP_QSTR_P15), MP_ROM_PTR(&pin_P0_15) }, + { MP_ROM_QSTR(MP_QSTR_P16), MP_ROM_PTR(&pin_P0_16) }, + { MP_ROM_QSTR(MP_QSTR_P17), MP_ROM_PTR(&pin_P0_17) }, + { MP_ROM_QSTR(MP_QSTR_P21), MP_ROM_PTR(&pin_P0_21) }, + { MP_ROM_QSTR(MP_QSTR_P25), MP_ROM_PTR(&pin_P0_25) }, + { MP_ROM_QSTR(MP_QSTR_P26), MP_ROM_PTR(&pin_P0_26) }, + { MP_ROM_QSTR(MP_QSTR_P27), MP_ROM_PTR(&pin_P0_27) }, + { MP_ROM_QSTR(MP_QSTR_P28), MP_ROM_PTR(&pin_P0_28) }, + { MP_ROM_QSTR(MP_QSTR_P29), MP_ROM_PTR(&pin_P0_29) }, + { MP_ROM_QSTR(MP_QSTR_P30), MP_ROM_PTR(&pin_P0_30) }, + { MP_ROM_QSTR(MP_QSTR_P31), MP_ROM_PTR(&pin_P0_31) }, + + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_P1_03) }, + { MP_ROM_QSTR(MP_QSTR_CSN), MP_ROM_PTR(&pin_P1_06) }, + { MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_P1_05) }, + { MP_ROM_QSTR(MP_QSTR_IO1), MP_ROM_PTR(&pin_P1_04) }, + { MP_ROM_QSTR(MP_QSTR_IO2), MP_ROM_PTR(&pin_P1_02) }, + { MP_ROM_QSTR(MP_QSTR_IO3), MP_ROM_PTR(&pin_P1_01) }, + + { MP_ROM_QSTR(MP_QSTR_TXD), MP_ROM_PTR(&pin_P0_20) }, + { MP_ROM_QSTR(MP_QSTR_RXD), MP_ROM_PTR(&pin_P0_19) }, + + { MP_ROM_QSTR(MP_QSTR_LED_RED), MP_ROM_PTR(&pin_P0_23) }, + { MP_ROM_QSTR(MP_QSTR_LED_GREEN), MP_ROM_PTR(&pin_P0_22) }, + { MP_ROM_QSTR(MP_QSTR_LED_BLUE), MP_ROM_PTR(&pin_P0_24) }, + + { MP_ROM_QSTR(MP_QSTR_USR_BTN), MP_ROM_PTR(&pin_P1_00) }, +}; + +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/nrf/boards/pca10056/board.c b/ports/nrf/boards/pca10056/board.c index a6d050fce..4421970ee 100644 --- a/ports/nrf/boards/pca10056/board.c +++ b/ports/nrf/boards/pca10056/board.c @@ -25,10 +25,8 @@ */ #include "boards/board.h" -#include "usb.h" void board_init(void) { - usb_init(); } bool board_requests_safe_mode(void) { diff --git a/ports/nrf/boards/pca10056/mpconfigboard.h b/ports/nrf/boards/pca10056/mpconfigboard.h index de4545d62..83c3f66c1 100644 --- a/ports/nrf/boards/pca10056/mpconfigboard.h +++ b/ports/nrf/boards/pca10056/mpconfigboard.h @@ -24,21 +24,15 @@ * THE SOFTWARE. */ +#include "nrfx/hal/nrf_gpio.h" + #define MICROPY_HW_BOARD_NAME "PCA10056 nRF52840-DK" #define MICROPY_HW_MCU_NAME "nRF52840" #define MICROPY_PY_SYS_PLATFORM "nRF52840-DK" -// See legend on bottom of board -#define MICROPY_HW_UART_RX NRF_GPIO_PIN_MAP(0, 8) -#define MICROPY_HW_UART_TX NRF_GPIO_PIN_MAP(0, 6) -#define MICROPY_HW_UART_HWFC (0) - #define PORT_HEAP_SIZE (128 * 1024) #define CIRCUITPY_AUTORELOAD_DELAY_MS 500 -// Temp (could be removed) 0: usb cdc (default), 1 : hwuart (jlink) -#define CFG_HWUART_FOR_SERIAL 0 - #define DEFAULT_I2C_BUS_SCL (&pin_P0_27) #define DEFAULT_I2C_BUS_SDA (&pin_P0_26) @@ -48,3 +42,24 @@ #define DEFAULT_UART_BUS_RX (&pin_P1_01) #define DEFAULT_UART_BUS_TX (&pin_P1_02) + +// Flash operation mode is determined by MICROPY_QSPI_DATAn pin configuration. +// A pin config is valid if it is defined and its value is not 0xFF. +// Quad mode: If all DATA0 --> DATA3 are valid +// Dual mode: If DATA0 and DATA1 are valid while either DATA2 and/or DATA3 are invalid +// Single mode: If only DATA0 is valid +#ifdef QSPI_FLASH_FILESYSTEM +#define MICROPY_QSPI_DATA0 NRF_GPIO_PIN_MAP(0, 20) +#define MICROPY_QSPI_DATA1 NRF_GPIO_PIN_MAP(0, 21) +#define MICROPY_QSPI_DATA2 NRF_GPIO_PIN_MAP(0, 22) +#define MICROPY_QSPI_DATA3 NRF_GPIO_PIN_MAP(0, 23) +#define MICROPY_QSPI_SCK NRF_GPIO_PIN_MAP(0, 19) +#define MICROPY_QSPI_CS NRF_GPIO_PIN_MAP(0, 17) +#endif + +#ifdef SPI_FLASH_FILESYSTEM +#define SPI_FLASH_MOSI_PIN &pin_P0_20 +#define SPI_FLASH_MISO_PIN &pin_P0_21 +#define SPI_FLASH_SCK_PIN &pin_P0_19 +#define SPI_FLASH_CS_PIN &pin_P0_17 +#endif diff --git a/ports/nrf/boards/pca10056/mpconfigboard.mk b/ports/nrf/boards/pca10056/mpconfigboard.mk index caf580ec4..49c708cff 100644 --- a/ports/nrf/boards/pca10056/mpconfigboard.mk +++ b/ports/nrf/boards/pca10056/mpconfigboard.mk @@ -1,3 +1,8 @@ +USB_VID = 0x239A +USB_PID = 0x802A +USB_PRODUCT = "PCA10056" +USB_MANUFACTURER = "Nordic Semiconductor" + MCU_SERIES = m4 MCU_VARIANT = nrf52 MCU_SUB_VARIANT = nrf52840 @@ -14,3 +19,7 @@ else endif NRF_DEFINES += -DNRF52840_XXAA -DNRF52840 + +QSPI_FLASH_FILESYSTEM = 1 +EXTERNAL_FLASH_DEVICE_COUNT = 1 +EXTERNAL_FLASH_DEVICES = "MX25R6435F" diff --git a/ports/nrf/boards/pca10056/pins.c b/ports/nrf/boards/pca10056/pins.c index 1c208f89b..a57c9d1c9 100644 --- a/ports/nrf/boards/pca10056/pins.c +++ b/ports/nrf/boards/pca10056/pins.c @@ -124,6 +124,8 @@ STATIC const mp_rom_map_elem_t board_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_P1_15), MP_ROM_PTR(&pin_P1_15) }, { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_P1_15) }, { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_P1_15) }, + + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, }; MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/nrf/boards/pca10059/board.c b/ports/nrf/boards/pca10059/board.c index cbb4ef3b6..4421970ee 100644 --- a/ports/nrf/boards/pca10059/board.c +++ b/ports/nrf/boards/pca10059/board.c @@ -24,14 +24,9 @@ * THE SOFTWARE. */ -#include <string.h> -#include <stdbool.h> #include "boards/board.h" -#include "nrfx.h" -#include "usb.h" void board_init(void) { - usb_init(); } bool board_requests_safe_mode(void) { diff --git a/ports/nrf/boards/pca10059/mpconfigboard.mk b/ports/nrf/boards/pca10059/mpconfigboard.mk index f399927fd..030c9a823 100644 --- a/ports/nrf/boards/pca10059/mpconfigboard.mk +++ b/ports/nrf/boards/pca10059/mpconfigboard.mk @@ -1,3 +1,8 @@ +USB_VID = 0x239A +USB_PID = 0x802A +USB_PRODUCT = "PCA10059" +USB_MANUFACTURER = "Nordic Semiconductor" + MCU_SERIES = m4 MCU_VARIANT = nrf52 MCU_SUB_VARIANT = nrf52840 diff --git a/ports/nrf/common-hal/analogio/AnalogOut.c b/ports/nrf/common-hal/analogio/AnalogOut.c index dc0f53740..adafa15d5 100644 --- a/ports/nrf/common-hal/analogio/AnalogOut.c +++ b/ports/nrf/common-hal/analogio/AnalogOut.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2018 Dan Halbert 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 diff --git a/ports/nrf/common-hal/bleio/Adapter.c b/ports/nrf/common-hal/bleio/Adapter.c index 52069e305..985e262e4 100644 --- a/ports/nrf/common-hal/bleio/Adapter.c +++ b/ports/nrf/common-hal/bleio/Adapter.c @@ -26,35 +26,135 @@ */ #include <stdio.h> +#include <string.h> +#include "ble.h" #include "ble_drv.h" -#include "nrfx.h" -#include "nrf_error.h" -#include "py/misc.h" +#include "nrfx_power.h" +#include "nrf_nvic.h" +#include "nrf_sdm.h" +#include "py/nlr.h" +#include "shared-bindings/bleio/Adapter.h" + +STATIC void softdevice_assert_handler(uint32_t id, uint32_t pc, uint32_t info) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_AssertionError, + translate("Soft device assert, id: 0x%08lX, pc: 0x%08lX"), id, pc)); +} + +STATIC uint32_t ble_stack_enable(void) { + nrf_clock_lf_cfg_t clock_config = { + .source = NRF_CLOCK_LF_SRC_XTAL, +#if (BLE_API_VERSION == 4) + .accuracy = NRF_CLOCK_LF_ACCURACY_20_PPM +#else + .xtal_accuracy = NRF_CLOCK_LF_XTAL_ACCURACY_20_PPM +#endif + }; + +#if (BLUETOOTH_SD == 140) + // The SD takes over the POWER IRQ and will fail if the IRQ is already in use + nrfx_power_uninit(); +#endif + + uint32_t err_code = sd_softdevice_enable(&clock_config, softdevice_assert_handler); + if (err_code != NRF_SUCCESS) + return err_code; + + err_code = sd_nvic_EnableIRQ(SD_EVT_IRQn); + if (err_code != NRF_SUCCESS) + return err_code; + + uint32_t app_ram_start; +#if (BLE_API_VERSION == 2) + ble_enable_params_t ble_enable_params = { + .gatts_enable_params.attr_tab_size = BLE_GATTS_ATTR_TAB_SIZE_DEFAULT, + .gap_enable_params.central_conn_count = 1, + .gap_enable_params.periph_conn_count = 1, + }; + + app_ram_start = 0x200039c0; + err_code = sd_ble_enable(&ble_enable_params, &app_ram_start); +#else + app_ram_start = 0x20004000; + + ble_cfg_t ble_conf; + ble_conf.conn_cfg.conn_cfg_tag = BLE_CONN_CFG_TAG_CUSTOM; + ble_conf.conn_cfg.params.gap_conn_cfg.conn_count = BLE_GAP_CONN_COUNT_DEFAULT; + ble_conf.conn_cfg.params.gap_conn_cfg.event_length = BLE_GAP_EVENT_LENGTH_DEFAULT; + err_code = sd_ble_cfg_set(BLE_CONN_CFG_GAP, &ble_conf, app_ram_start); + if (err_code != NRF_SUCCESS) + return err_code; + + memset(&ble_conf, 0, sizeof(ble_conf)); + ble_conf.gap_cfg.role_count_cfg.periph_role_count = 1; + ble_conf.gap_cfg.role_count_cfg.central_role_count = 1; + err_code = sd_ble_cfg_set(BLE_GAP_CFG_ROLE_COUNT, &ble_conf, app_ram_start); + if (err_code != NRF_SUCCESS) + return err_code; + + memset(&ble_conf, 0, sizeof(ble_conf)); + ble_conf.conn_cfg.conn_cfg_tag = BLE_CONN_CFG_TAG_CUSTOM; + ble_conf.conn_cfg.params.gatts_conn_cfg.hvn_tx_queue_size = MAX_TX_IN_PROGRESS; + err_code = sd_ble_cfg_set(BLE_CONN_CFG_GATTS, &ble_conf, app_ram_start); + if (err_code != NRF_SUCCESS) + return err_code; + + err_code = sd_ble_enable(&app_ram_start); +#endif + + return err_code; +} void common_hal_bleio_adapter_set_enabled(bool enabled) { - if (enabled) { - const uint32_t err = ble_drv_stack_enable(); - if (err != NRF_SUCCESS) { - NRFX_ASSERT(err); - } + const bool is_enabled = common_hal_bleio_adapter_get_enabled(); + + // Don't enable or disable twice + if ((is_enabled && enabled) || (!is_enabled && !enabled)) { + return; + } - printf("SoftDevice enabled\n"); + uint32_t err_code; + if (enabled) { + err_code = ble_stack_enable(); } else { - ble_drv_stack_disable(); + err_code = sd_softdevice_disable(); + } + + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + translate("Failed to change softdevice state, error: 0x%08lX"), err_code)); } } bool common_hal_bleio_adapter_get_enabled(void) { - return ble_drv_stack_enabled(); + uint8_t is_enabled; + + const uint32_t err_code = sd_softdevice_is_enabled(&is_enabled); + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + translate("Failed to get softdevice state, error: 0x%08lX"), err_code)); + } + + return is_enabled; } -void common_hal_bleio_adapter_get_address(vstr_t *vstr) { - ble_drv_addr_t address; - ble_drv_address_get(&address); +void common_hal_bleio_adapter_get_address(bleio_address_obj_t *address) { + ble_gap_addr_t local_address; + uint32_t err_code; + + common_hal_bleio_adapter_set_enabled(true); + +#if (BLE_API_VERSION == 2) + err_code = sd_ble_gap_address_get(&local_address); +#else + err_code = sd_ble_gap_addr_get(&local_address); +#endif + + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + translate("Failed to get local address, error: 0x%08lX"), err_code)); + } - vstr_printf(vstr, ""HEX2_FMT":"HEX2_FMT":"HEX2_FMT":" \ - HEX2_FMT":"HEX2_FMT":"HEX2_FMT"", - address.addr[5], address.addr[4], address.addr[3], - address.addr[2], address.addr[1], address.addr[0]); + address->type = local_address.addr_type; + memcpy(address->value, local_address.addr, BLEIO_ADDRESS_BYTES); } diff --git a/ports/nrf/common-hal/bleio/Characteristic.c b/ports/nrf/common-hal/bleio/Characteristic.c new file mode 100644 index 000000000..246c35005 --- /dev/null +++ b/ports/nrf/common-hal/bleio/Characteristic.c @@ -0,0 +1,191 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Artur Pacholec + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include <string.h> +#include <stdio.h> + +#include "ble_drv.h" +#include "ble_gatts.h" +#include "nrf_soc.h" +#include "py/nlr.h" +#include "shared-module/bleio/Characteristic.h" + +static volatile bleio_characteristic_obj_t *m_read_characteristic; +static volatile uint8_t m_tx_in_progress; +static nrf_mutex_t *m_write_mutex; + +STATIC void gatts_write(bleio_characteristic_obj_t *characteristic, mp_buffer_info_t *bufinfo) { + bleio_device_obj_t *device = characteristic->service->device; + const uint16_t conn_handle = device->conn_handle; + + ble_gatts_value_t gatts_value = { + .p_value = bufinfo->buf, + .len = bufinfo->len, + }; + + const uint32_t err_code = sd_ble_gatts_value_set(conn_handle, characteristic->handle, &gatts_value); + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + translate("Failed to write gatts value, status: 0x%08lX"), err_code)); + } +} + +STATIC void gatts_notify(bleio_characteristic_obj_t *characteristic, mp_buffer_info_t *bufinfo) { + bleio_device_obj_t *device = characteristic->service->device; + uint16_t hvx_len = bufinfo->len; + + ble_gatts_hvx_params_t hvx_params = { + .handle = characteristic->handle, + .type = BLE_GATT_HVX_NOTIFICATION, + .p_len = &hvx_len, + .p_data = bufinfo->buf, + }; + + while (m_tx_in_progress > MAX_TX_IN_PROGRESS) { +#ifdef MICROPY_VM_HOOK_LOOP + MICROPY_VM_HOOK_LOOP +#endif + } + + const uint32_t err_code = sd_ble_gatts_hvx(device->conn_handle, &hvx_params); + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + translate("Failed to notify attribute value, status: 0x%08lX"), err_code)); + } + + m_tx_in_progress += 1; +} + +STATIC void gattc_read(bleio_characteristic_obj_t *characteristic) { + bleio_service_obj_t *service = characteristic->service; + bleio_device_obj_t *device = service->device; + + m_read_characteristic = characteristic; + + const uint32_t err_code = sd_ble_gattc_read(device->conn_handle, characteristic->handle, 0); + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + translate("Failed to read attribute value, status: 0x%08lX"), err_code)); + } + + while (m_read_characteristic != NULL) { +#ifdef MICROPY_VM_HOOK_LOOP + MICROPY_VM_HOOK_LOOP +#endif + } +} + +STATIC void gattc_write(bleio_characteristic_obj_t *characteristic, mp_buffer_info_t *bufinfo) { + bleio_device_obj_t *device = characteristic->service->device; + uint32_t err_code; + + ble_gattc_write_params_t write_params = { + .flags = BLE_GATT_EXEC_WRITE_FLAG_PREPARED_CANCEL, + .write_op = BLE_GATT_OP_WRITE_REQ, + .handle = characteristic->handle, + .p_value = bufinfo->buf, + .len = bufinfo->len, + }; + + if (characteristic->props.write_wo_resp) { + write_params.write_op = BLE_GATT_OP_WRITE_CMD; + + err_code = sd_mutex_acquire(m_write_mutex); + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + translate("Failed to acquire mutex, status: 0x%08lX"), err_code)); + } + } + + err_code = sd_ble_gattc_write(device->conn_handle, &write_params); + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + translate("Failed to write attribute value, status: 0x%08lX"), err_code)); + } + + while (sd_mutex_acquire(m_write_mutex) == NRF_ERROR_SOC_MUTEX_ALREADY_TAKEN) { +#ifdef MICROPY_VM_HOOK_LOOP + MICROPY_VM_HOOK_LOOP +#endif + } + + err_code = sd_mutex_release(m_write_mutex); + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + translate("Failed to release mutex, status: 0x%08lX"), err_code)); + } +} + +STATIC void on_ble_evt(ble_evt_t *ble_evt, void *param) { + switch (ble_evt->header.evt_id) { +#if (BLE_API_VERSION == 4) + case BLE_GATTS_EVT_HVN_TX_COMPLETE: + m_tx_in_progress -= ble_evt->evt.gatts_evt.params.hvn_tx_complete.count; + break; +#else + case BLE_EVT_TX_COMPLETE: + m_tx_in_progress -= ble_evt->evt.common_evt.params.tx_complete.count; + break; +#endif + + case BLE_GATTC_EVT_READ_RSP: + { + ble_gattc_evt_read_rsp_t *response = &ble_evt->evt.gattc_evt.params.read_rsp; + m_read_characteristic->value_data = mp_obj_new_bytearray(response->len, response->data); + m_read_characteristic = NULL; + break; + } + + case BLE_GATTC_EVT_WRITE_RSP: + sd_mutex_release(m_write_mutex); +// m_write_done = true; + break; + } +} + +void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self) { + ble_drv_add_event_handler(on_ble_evt, NULL); +} + +void common_hal_bleio_characteristic_read_value(bleio_characteristic_obj_t *self) { + gattc_read(self); +} + +void common_hal_bleio_characteristic_write_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo) { + const bleio_device_obj_t *device = self->service->device; + + if (device->is_peripheral) { + // TODO: Add indications + if (self->props.notify) { + gatts_notify(self, bufinfo); + } else { + gatts_write(self, bufinfo); + } + } else { + gattc_write(self, bufinfo); + } + +} diff --git a/ports/nrf/common-hal/bleio/Descriptor.c b/ports/nrf/common-hal/bleio/Descriptor.c new file mode 100644 index 000000000..9b61345fa --- /dev/null +++ b/ports/nrf/common-hal/bleio/Descriptor.c @@ -0,0 +1,45 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Glenn Ruben Bakke + * Copyright (c) 2018 Artur Pacholec + * + * 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 "common-hal/bleio/Descriptor.h" + +void common_hal_bleio_descriptor_construct(bleio_descriptor_obj_t *self, bleio_uuid_obj_t *uuid) { + self->uuid = uuid; +} + +void common_hal_bleio_descriptor_print(bleio_descriptor_obj_t *self, const mp_print_t *print) { + mp_printf(print, "Descriptor(uuid: 0x" HEX2_FMT HEX2_FMT ")", + self->uuid->value[1], self->uuid->value[0]); +} + +mp_int_t common_hal_bleio_descriptor_get_handle(bleio_descriptor_obj_t *self) { + return self->handle; +} + +mp_int_t common_hal_bleio_descriptor_get_uuid(bleio_descriptor_obj_t *self) { + return self->uuid->value[0] | (self->uuid->value[1] << 8); +} diff --git a/ports/nrf/common-hal/bleio/Descriptor.h b/ports/nrf/common-hal/bleio/Descriptor.h new file mode 100644 index 000000000..ee0886c22 --- /dev/null +++ b/ports/nrf/common-hal/bleio/Descriptor.h @@ -0,0 +1,40 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Glenn Ruben Bakke + * Copyright (c) 2018 Artur Pacholec + * + * 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_NRF_COMMON_HAL_BLEIO_DESCRIPTOR_H +#define MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_DESCRIPTOR_H + +#include "py/obj.h" +#include "common-hal/bleio/UUID.h" + +typedef struct { + mp_obj_base_t base; + uint16_t handle; + bleio_uuid_obj_t *uuid; +} bleio_descriptor_obj_t; + +#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_DESCRIPTOR_H diff --git a/ports/nrf/common-hal/bleio/Device.c b/ports/nrf/common-hal/bleio/Device.c new file mode 100644 index 000000000..2c000ae2e --- /dev/null +++ b/ports/nrf/common-hal/bleio/Device.c @@ -0,0 +1,627 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Artur Pacholec + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include <string.h> +#include <stdio.h> + +#include "ble.h" +#include "ble_drv.h" +#include "ble_hci.h" +#include "nrf_soc.h" +#include "py/objstr.h" +#include "py/runtime.h" +#include "shared-bindings/bleio/Adapter.h" +#include "shared-bindings/bleio/Characteristic.h" +#include "shared-bindings/bleio/Device.h" +#include "shared-bindings/bleio/Service.h" +#include "shared-bindings/bleio/UUID.h" + +#define BLE_MIN_CONN_INTERVAL MSEC_TO_UNITS(15, UNIT_0_625_MS) +#define BLE_MAX_CONN_INTERVAL MSEC_TO_UNITS(300, UNIT_0_625_MS) +#define BLE_SLAVE_LATENCY 0 +#define BLE_CONN_SUP_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS) + +#define BLE_ADV_LENGTH_FIELD_SIZE 1 +#define BLE_ADV_AD_TYPE_FIELD_SIZE 1 +#define BLE_AD_TYPE_FLAGS_DATA_SIZE 1 + +#ifndef BLE_GAP_ADV_MAX_SIZE +#define BLE_GAP_ADV_MAX_SIZE 31 +#endif + +static bleio_service_obj_t *m_char_discovery_service; +static volatile bool m_discovery_successful; +static nrf_mutex_t *m_discovery_mutex; + +#if (BLUETOOTH_SD == 140) +static uint8_t m_adv_handle = BLE_GAP_ADV_SET_HANDLE_NOT_SET; + +static uint8_t m_scan_buffer_data[BLE_GAP_SCAN_BUFFER_MIN]; + +static ble_data_t m_scan_buffer = { + .p_data = m_scan_buffer_data, + .len = BLE_GAP_SCAN_BUFFER_MIN +}; +#endif + +STATIC uint32_t set_advertisement_data(bleio_device_obj_t *device, bool connectable, mp_buffer_info_t *raw_data) { + common_hal_bleio_adapter_set_enabled(true); + + uint8_t adv_data[BLE_GAP_ADV_MAX_SIZE]; + uint8_t byte_pos = 0; + uint32_t err_code; + +#define ADD_FIELD(field, len) \ + do { \ + if (byte_pos + (len) > BLE_GAP_ADV_MAX_SIZE) { \ + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, \ + translate("Can not fit data into the advertisment packet"))); \ + } \ + adv_data[byte_pos] = (field); \ + byte_pos += (len); \ + } while (0) + + GET_STR_DATA_LEN(device->name, name_data, name_len); + if (name_len > 0) { + ble_gap_conn_sec_mode_t sec_mode; + BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); + + err_code = sd_ble_gap_device_name_set(&sec_mode, name_data, name_len); + if (err_code != NRF_SUCCESS) { + return err_code; + } + + // TODO: Shorten if too long + + ADD_FIELD(BLE_ADV_AD_TYPE_FIELD_SIZE + name_len, BLE_ADV_LENGTH_FIELD_SIZE); + ADD_FIELD(BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME, BLE_ADV_AD_TYPE_FIELD_SIZE); + + memcpy(&adv_data[byte_pos], name_data, name_len); + byte_pos += name_len; + } + + // set flags, default to disc mode + if (raw_data->len == 0) { + ADD_FIELD(BLE_ADV_AD_TYPE_FIELD_SIZE + BLE_AD_TYPE_FLAGS_DATA_SIZE, BLE_ADV_LENGTH_FIELD_SIZE); + ADD_FIELD(BLE_GAP_AD_TYPE_FLAGS, BLE_AD_TYPE_FLAGS_DATA_SIZE); + ADD_FIELD(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE, BLE_AD_TYPE_FLAGS_DATA_SIZE); + } else { + if (byte_pos + raw_data->len > BLE_GAP_ADV_MAX_SIZE) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + translate("Can not fit data into the advertisment packet"))); + } + + memcpy(&adv_data[byte_pos], raw_data->buf, raw_data->len); + byte_pos += raw_data->len; + } + + const mp_obj_list_t *service_list = MP_OBJ_TO_PTR(device->service_list); + if (service_list->len > 0) { + bool has_128bit_services = false; + bool has_16bit_services = false; + + for (size_t i = 0; i < service_list->len; ++i) { + const bleio_service_obj_t *service = MP_OBJ_TO_PTR(service_list->items[i]); + + if (service->is_secondary) { + continue; + } + + if (service->uuid->type == UUID_TYPE_16BIT) { + has_16bit_services = true; + } + + if (service->uuid->type == UUID_TYPE_128BIT) { + has_128bit_services = true; + } + } + + if (has_16bit_services) { + const uint8_t size_byte_pos = byte_pos; + uint8_t uuid_total_size = 0; + + // skip length byte for now, apply total length post calculation + byte_pos += BLE_ADV_LENGTH_FIELD_SIZE; + + ADD_FIELD(BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE, BLE_ADV_AD_TYPE_FIELD_SIZE); + + for (size_t i = 0; i < service_list->len; ++i) { + const bleio_service_obj_t *service = MP_OBJ_TO_PTR(service_list->items[i]); + uint8_t encoded_size = 0; + + if ((service->uuid->type != UUID_TYPE_16BIT) || service->is_secondary) { + continue; + } + + ble_uuid_t uuid; + uuid.type = BLE_UUID_TYPE_BLE; + uuid.uuid = service->uuid->value[0] | (service->uuid->value[1] << 8); + + err_code = sd_ble_uuid_encode(&uuid, &encoded_size, &adv_data[byte_pos]); + if (err_code != NRF_SUCCESS) { + return err_code; + } + + uuid_total_size += encoded_size; + byte_pos += encoded_size; + } + + adv_data[size_byte_pos] = (BLE_ADV_AD_TYPE_FIELD_SIZE + uuid_total_size); + } + + if (has_128bit_services) { + const uint8_t size_byte_pos = byte_pos; + uint8_t uuid_total_size = 0; + + // skip length byte for now, apply total length post calculation + byte_pos += BLE_ADV_LENGTH_FIELD_SIZE; + + ADD_FIELD(BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE, BLE_ADV_AD_TYPE_FIELD_SIZE); + + for (size_t i = 0; i < service_list->len; ++i) { + const bleio_service_obj_t *service = MP_OBJ_TO_PTR(service_list->items[i]); + uint8_t encoded_size = 0; + + if ((service->uuid->type != UUID_TYPE_128BIT) || service->is_secondary) { + continue; + } + + ble_uuid_t uuid; + uuid.type = service->uuid->uuid_vs_idx; + uuid.uuid = service->uuid->value[0] | (service->uuid->value[1] << 8); + + err_code = sd_ble_uuid_encode(&uuid, &encoded_size, &adv_data[byte_pos]); + if (err_code != NRF_SUCCESS) { + return err_code; + } + + uuid_total_size += encoded_size; + byte_pos += encoded_size; + } + + adv_data[size_byte_pos] = (BLE_ADV_AD_TYPE_FIELD_SIZE + uuid_total_size); + } + } + +#if (BLUETOOTH_SD == 132) + err_code = sd_ble_gap_adv_data_set(adv_data, byte_pos, NULL, 0); + if (err_code != NRF_SUCCESS) { + return err_code; + } +#endif + + static ble_gap_adv_params_t m_adv_params = { + .interval = MSEC_TO_UNITS(100, UNIT_0_625_MS), +#if (BLUETOOTH_SD == 140) + .properties.type = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED, + .duration = BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED, + .filter_policy = BLE_GAP_ADV_FP_ANY, + .primary_phy = BLE_GAP_PHY_1MBPS, +#else + .type = BLE_GAP_ADV_TYPE_ADV_IND, + .fp = BLE_GAP_ADV_FP_ANY, +#endif + }; + + if (!connectable) { +#if (BLUETOOTH_SD == 140) + m_adv_params.properties.type = BLE_GAP_ADV_TYPE_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED; +#else + m_adv_params.type = BLE_GAP_ADV_TYPE_ADV_NONCONN_IND; +#endif + } + + common_hal_bleio_device_stop_advertising(device); + +#if (BLUETOOTH_SD == 140) + const ble_gap_adv_data_t ble_gap_adv_data = { + .adv_data.p_data = adv_data, + .adv_data.len = byte_pos, + }; + + err_code = sd_ble_gap_adv_set_configure(&m_adv_handle, &ble_gap_adv_data, &m_adv_params); + if (err_code != NRF_SUCCESS) { + return err_code; + } + + err_code = sd_ble_gap_adv_start(m_adv_handle, BLE_CONN_CFG_TAG_CUSTOM); +#elif (BLUETOOTH_SD == 132 && BLE_API_VERSION == 4) + err_code = sd_ble_gap_adv_start(&m_adv_params, BLE_CONN_CFG_TAG_CUSTOM); +#else + err_code = sd_ble_gap_adv_start(&m_adv_params); +#endif + + return err_code; +} + +STATIC bool discover_services(bleio_device_obj_t *device, uint16_t start_handle) { + m_discovery_successful = false; + + uint32_t err_code = sd_ble_gattc_primary_services_discover(device->conn_handle, start_handle, NULL); + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + translate("Failed to discover serivices, status: 0x%08lX"), err_code)); + } + + err_code = sd_mutex_acquire(m_discovery_mutex); + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + translate("Failed to acquire mutex, status: 0x%08lX"), err_code)); + } + + while (sd_mutex_acquire(m_discovery_mutex) == NRF_ERROR_SOC_MUTEX_ALREADY_TAKEN) { +#ifdef MICROPY_VM_HOOK_LOOP + MICROPY_VM_HOOK_LOOP +#endif + } + + err_code = sd_mutex_release(m_discovery_mutex); + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + translate("Failed to release mutex, status: 0x%08lX"), err_code)); + } + + return m_discovery_successful; +} + +STATIC bool discover_characteristics(bleio_device_obj_t *device, bleio_service_obj_t *service, uint16_t start_handle) { + m_char_discovery_service = service; + + ble_gattc_handle_range_t handle_range; + handle_range.start_handle = start_handle; + handle_range.end_handle = service->end_handle; + + m_discovery_successful = false; + + uint32_t err_code = sd_ble_gattc_characteristics_discover(device->conn_handle, &handle_range); + if (err_code != NRF_SUCCESS) { + return false; + } + + err_code = sd_mutex_acquire(m_discovery_mutex); + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + translate("Failed to acquire mutex, status: 0x%08lX"), err_code)); + } + + while (sd_mutex_acquire(m_discovery_mutex) == NRF_ERROR_SOC_MUTEX_ALREADY_TAKEN) { +#ifdef MICROPY_VM_HOOK_LOOP + MICROPY_VM_HOOK_LOOP +#endif + } + + err_code = sd_mutex_release(m_discovery_mutex); + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + translate("Failed to release mutex, status: 0x%08lX"), err_code)); + } + + return m_discovery_successful; +} + +STATIC void on_primary_srv_discovery_rsp(ble_gattc_evt_prim_srvc_disc_rsp_t *response, bleio_device_obj_t *device) { + for (size_t i = 0; i < response->count; ++i) { + const ble_gattc_service_t *gattc_service = &response->services[i]; + + bleio_service_obj_t *service = m_new_obj(bleio_service_obj_t); + service->base.type = &bleio_service_type; + service->device = device; + service->char_list = mp_obj_new_list(0, NULL); + service->start_handle = gattc_service->handle_range.start_handle; + service->end_handle = gattc_service->handle_range.end_handle; + service->handle = gattc_service->handle_range.start_handle; + + bleio_uuid_obj_t *uuid = m_new_obj(bleio_uuid_obj_t); + uuid->base.type = &bleio_uuid_type; + uuid->type = (gattc_service->uuid.type == BLE_UUID_TYPE_BLE) ? UUID_TYPE_16BIT : UUID_TYPE_128BIT; + uuid->value[0] = gattc_service->uuid.uuid & 0xFF; + uuid->value[1] = gattc_service->uuid.uuid >> 8; + service->uuid = uuid; + + mp_obj_list_append(device->service_list, service); + } + + if (response->count > 0) { + m_discovery_successful = true; + } + + const uint32_t err_code = sd_mutex_release(m_discovery_mutex); + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + translate("Failed to release mutex, status: 0x%08lX"), err_code)); + } +} + +STATIC void on_char_discovery_rsp(ble_gattc_evt_char_disc_rsp_t *response, bleio_device_obj_t *device) { + for (size_t i = 0; i < response->count; ++i) { + const ble_gattc_char_t *gattc_char = &response->chars[i]; + + bleio_characteristic_obj_t *characteristic = m_new_obj(bleio_characteristic_obj_t); + characteristic->base.type = &bleio_characteristic_type; + + bleio_uuid_obj_t *uuid = m_new_obj(bleio_uuid_obj_t); + uuid->base.type = &bleio_uuid_type; + uuid->type = (gattc_char->uuid.type == BLE_UUID_TYPE_BLE) ? UUID_TYPE_16BIT : UUID_TYPE_128BIT; + uuid->value[0] = gattc_char->uuid.uuid & 0xFF; + uuid->value[1] = gattc_char->uuid.uuid >> 8; + characteristic->uuid = uuid; + + characteristic->props.broadcast = gattc_char->char_props.broadcast; + characteristic->props.indicate = gattc_char->char_props.indicate; + characteristic->props.notify = gattc_char->char_props.notify; + characteristic->props.read = gattc_char->char_props.read; + characteristic->props.write = gattc_char->char_props.write; + characteristic->props.write_wo_resp = gattc_char->char_props.write_wo_resp; + characteristic->handle = gattc_char->handle_value; + characteristic->service = m_char_discovery_service; + + mp_obj_list_append(m_char_discovery_service->char_list, MP_OBJ_FROM_PTR(characteristic)); + } + + if (response->count > 0) { + m_discovery_successful = true; + } + + const uint32_t err_code = sd_mutex_release(m_discovery_mutex); + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + translate("Failed to release mutex, status: 0x%08lX"), err_code)); + } +} + +STATIC void on_adv_report(ble_gap_evt_adv_report_t *report, bleio_device_obj_t *device) { + uint32_t err_code; + + if (memcmp(report->peer_addr.addr, device->address.value, BLEIO_ADDRESS_BYTES) != 0) { +#if (BLUETOOTH_SD == 140) + err_code = sd_ble_gap_scan_start(NULL, &m_scan_buffer); + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + translate("Failed to continue scanning, status: 0x%0xlX"), err_code)); + } +#endif + return; + } + + ble_gap_scan_params_t scan_params = { + .active = 1, + .interval = MSEC_TO_UNITS(100, UNIT_0_625_MS), + .window = MSEC_TO_UNITS(100, UNIT_0_625_MS), + }; + + ble_gap_addr_t addr; + memset(&addr, 0, sizeof(addr)); + + addr.addr_type = report->peer_addr.addr_type; + memcpy(addr.addr, report->peer_addr.addr, BLEIO_ADDRESS_BYTES); + + ble_gap_conn_params_t conn_params = { + .min_conn_interval = BLE_MIN_CONN_INTERVAL, + .max_conn_interval = BLE_MAX_CONN_INTERVAL, + .conn_sup_timeout = BLE_CONN_SUP_TIMEOUT, + .slave_latency = BLE_SLAVE_LATENCY, + }; + +#if (BLE_API_VERSION == 2) + err_code = sd_ble_gap_connect(&addr, &scan_params, &conn_params); +#else + err_code = sd_ble_gap_connect(&addr, &scan_params, &conn_params, BLE_CONN_CFG_TAG_CUSTOM); +#endif + + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + translate("Failed to connect, status: 0x%08lX"), err_code)); + } +} + +STATIC void on_ble_evt(ble_evt_t *ble_evt, void *device_in) { + bleio_device_obj_t *device = (bleio_device_obj_t*)device_in; + + switch (ble_evt->header.evt_id) { + case BLE_GAP_EVT_CONNECTED: + { + ble_gap_conn_params_t conn_params; + device->conn_handle = ble_evt->evt.gap_evt.conn_handle; + + sd_ble_gap_ppcp_get(&conn_params); + sd_ble_gap_conn_param_update(ble_evt->evt.gap_evt.conn_handle, &conn_params); + break; + } + + case BLE_GAP_EVT_DISCONNECTED: + device->conn_handle = BLE_CONN_HANDLE_INVALID; + break; + + case BLE_GAP_EVT_ADV_REPORT: + on_adv_report(&ble_evt->evt.gap_evt.params.adv_report, device); + break; + + case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP: + on_primary_srv_discovery_rsp(&ble_evt->evt.gattc_evt.params.prim_srvc_disc_rsp, device); + break; + + case BLE_GATTC_EVT_CHAR_DISC_RSP: + on_char_discovery_rsp(&ble_evt->evt.gattc_evt.params.char_disc_rsp, device); + break; + + case BLE_GATTS_EVT_SYS_ATTR_MISSING: + sd_ble_gatts_sys_attr_set(ble_evt->evt.gatts_evt.conn_handle, NULL, 0, 0); + break; + +#if (BLE_API_VERSION == 4) + case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST: + sd_ble_gatts_exchange_mtu_reply(device->conn_handle, BLE_GATT_ATT_MTU_DEFAULT); + break; +#endif + + case BLE_GAP_EVT_SEC_PARAMS_REQUEST: + sd_ble_gap_sec_params_reply(device->conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL); + break; + + case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST: + { + ble_gap_evt_conn_param_update_request_t *request = &ble_evt->evt.gap_evt.params.conn_param_update_request; + sd_ble_gap_conn_param_update(device->conn_handle, &request->conn_params); + break; + } + } +} + +void common_hal_bleio_device_add_service(bleio_device_obj_t *device, bleio_service_obj_t *service) { + ble_uuid_t uuid = { + .type = BLE_UUID_TYPE_BLE, + .uuid = service->uuid->value[0] | (service->uuid->value[1] << 8) + }; + + if (service->uuid->type == UUID_TYPE_128BIT) { + uuid.type = service->uuid->uuid_vs_idx; + } + + uint8_t service_type = BLE_GATTS_SRVC_TYPE_PRIMARY; + if (service->is_secondary) { + service_type = BLE_GATTS_SRVC_TYPE_SECONDARY; + } + + common_hal_bleio_adapter_set_enabled(true); + + const uint32_t err_code = sd_ble_gatts_service_add(service_type, &uuid, &service->handle); + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + translate("Failed to add service, status: 0x%08lX"), err_code)); + } + + const mp_obj_list_t *char_list = MP_OBJ_TO_PTR(service->char_list); + for (size_t i = 0; i < char_list->len; ++i) { + bleio_characteristic_obj_t *characteristic = char_list->items[i]; + common_hal_bleio_service_add_characteristic(service, characteristic); + } +} + +void common_hal_bleio_device_start_advertising(bleio_device_obj_t *device, bool connectable, mp_buffer_info_t *raw_data) { + if (connectable) { + ble_drv_add_event_handler(on_ble_evt, device); + } + + const uint32_t err_code = set_advertisement_data(device, connectable, raw_data); + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + translate("Failed to start advertisment, status: 0x%08lX"), err_code)); + } +} + +void common_hal_bleio_device_stop_advertising(bleio_device_obj_t *device) { + uint32_t err_code; + +#if (BLUETOOTH_SD == 140) + if (m_adv_handle == BLE_GAP_ADV_SET_HANDLE_NOT_SET) + return; + + err_code = sd_ble_gap_adv_stop(m_adv_handle); +#else + err_code = sd_ble_gap_adv_stop(); +#endif + + if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_INVALID_STATE)) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + translate("Failed to stop advertisment, status: 0x%08lX"), err_code)); + } +} + +void common_hal_bleio_device_connect(bleio_device_obj_t *device) { + ble_drv_add_event_handler(on_ble_evt, device); + + ble_gap_scan_params_t scan_params = { + .interval = MSEC_TO_UNITS(100, UNIT_0_625_MS), + .window = MSEC_TO_UNITS(100, UNIT_0_625_MS), +#if (BLUETOOTH_SD == 140) + .scan_phys = BLE_GAP_PHY_1MBPS, +#endif + }; + + common_hal_bleio_adapter_set_enabled(true); + + uint32_t err_code; +#if (BLUETOOTH_SD == 140) + err_code = sd_ble_gap_scan_start(&scan_params, &m_scan_buffer); +#else + err_code = sd_ble_gap_scan_start(&scan_params); +#endif + + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + translate("Failed to start scanning, status: 0x%0xlX"), err_code)); + } + + while (device->conn_handle == BLE_CONN_HANDLE_INVALID) { +#ifdef MICROPY_VM_HOOK_LOOP + MICROPY_VM_HOOK_LOOP +#endif + } + + // TODO: read name + + if (m_discovery_mutex == NULL) { + m_discovery_mutex = m_new_ll(nrf_mutex_t, 1); + + err_code = sd_mutex_new(m_discovery_mutex); + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + translate("Failed to create mutex, status: 0x%0xlX"), err_code)); + } + } + + // find services + bool found_service = discover_services(device, BLE_GATT_HANDLE_START); + while (found_service) { + const mp_obj_list_t *service_list = MP_OBJ_TO_PTR(device->service_list); + const bleio_service_obj_t *service = service_list->items[service_list->len - 1]; + + found_service = discover_services(device, service->end_handle + 1); + } + + // find characteristics in each service + const mp_obj_list_t *service_list = MP_OBJ_TO_PTR(device->service_list); + for (size_t i = 0; i < service_list->len; ++i) { + bleio_service_obj_t *service = service_list->items[i]; + + bool found_char = discover_characteristics(device, service, service->start_handle); + while (found_char) { + const mp_obj_list_t *char_list = MP_OBJ_TO_PTR(service->char_list); + const bleio_characteristic_obj_t *characteristic = char_list->items[char_list->len - 1]; + + const uint16_t next_handle = characteristic->handle + 1; + if (next_handle >= service->end_handle) { + break; + } + + found_char = discover_characteristics(device, service, next_handle); + } + } +} + +void common_hal_bleio_device_disconnect(bleio_device_obj_t *device) { + sd_ble_gap_disconnect(device->conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); +} diff --git a/ports/nrf/common-hal/bleio/Scanner.c b/ports/nrf/common-hal/bleio/Scanner.c new file mode 100644 index 000000000..e56c1860c --- /dev/null +++ b/ports/nrf/common-hal/bleio/Scanner.c @@ -0,0 +1,110 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Glenn Ruben Bakke + * Copyright (c) 2018 Artur Pacholec + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include <string.h> + +#include "ble_drv.h" +#include "ble_gap.h" +#include "py/mphal.h" +#include "py/nlr.h" +#include "shared-bindings/bleio/Adapter.h" +#include "shared-bindings/bleio/ScanEntry.h" +#include "shared-bindings/bleio/Scanner.h" +#include "shared-module/bleio/ScanEntry.h" + +#if (BLUETOOTH_SD == 140) +static uint8_t m_scan_buffer_data[BLE_GAP_SCAN_BUFFER_MIN]; + +static ble_data_t m_scan_buffer = { + m_scan_buffer_data, + BLE_GAP_SCAN_BUFFER_MIN +}; +#endif + +STATIC void on_ble_evt(ble_evt_t *ble_evt, void *scanner_in) { + bleio_scanner_obj_t *scanner = (bleio_scanner_obj_t*)scanner_in; + ble_gap_evt_adv_report_t *report = &ble_evt->evt.gap_evt.params.adv_report; + + if (ble_evt->header.evt_id != BLE_GAP_EVT_ADV_REPORT) { + return; + } + + // TODO: Don't add new entry for each item, group by address and update + bleio_scanentry_obj_t *entry = m_new_obj(bleio_scanentry_obj_t); + entry->base.type = &bleio_scanentry_type; + entry->rssi = report->rssi; + + entry->address.type = report->peer_addr.addr_type; + memcpy(entry->address.value, report->peer_addr.addr, BLEIO_ADDRESS_BYTES); + +#if (BLUETOOTH_SD == 140) + entry->data = mp_obj_new_bytearray(report->data.len, report->data.p_data); +#else + entry->data = mp_obj_new_bytearray(report->dlen, report->data); +#endif + + mp_obj_list_append(scanner->adv_reports, entry); + +#if (BLUETOOTH_SD == 140) + const uint32_t err_code = sd_ble_gap_scan_start(NULL, &m_scan_buffer); + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + translate("Failed to continue scanning, status: 0x%0xlX"), err_code)); + } +#endif +} + +void common_hal_bleio_scanner_scan(bleio_scanner_obj_t *self, mp_int_t timeout) { + ble_drv_add_event_handler(on_ble_evt, self); + + ble_gap_scan_params_t scan_params = { + .interval = MSEC_TO_UNITS(self->interval, UNIT_0_625_MS), + .window = MSEC_TO_UNITS(self->window, UNIT_0_625_MS), +#if (BLUETOOTH_SD == 140) + .scan_phys = BLE_GAP_PHY_1MBPS, +#endif + }; + + common_hal_bleio_adapter_set_enabled(true); + + uint32_t err_code; +#if (BLUETOOTH_SD == 140) + err_code = sd_ble_gap_scan_start(&scan_params, &m_scan_buffer); +#else + err_code = sd_ble_gap_scan_start(&scan_params); +#endif + + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + translate("Failed to start scanning, status: 0x%0xlX"), err_code)); + } + + if (timeout > 0) { + mp_hal_delay_ms(timeout); + sd_ble_gap_scan_stop(); + } +} diff --git a/ports/nrf/common-hal/bleio/Service.c b/ports/nrf/common-hal/bleio/Service.c new file mode 100644 index 000000000..c17c16904 --- /dev/null +++ b/ports/nrf/common-hal/bleio/Service.c @@ -0,0 +1,90 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Artur Pacholec + * + * 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 "ble_drv.h" +#include "ble.h" +#include "py/nlr.h" +#include "shared-bindings/bleio/Service.h" +#include "shared-bindings/bleio/Adapter.h" + +void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self, bleio_characteristic_obj_t *characteristic) { + ble_gatts_char_md_t char_md = { + .char_props.broadcast = characteristic->props.broadcast, + .char_props.read = characteristic->props.read, + .char_props.write_wo_resp = characteristic->props.write_wo_resp, + .char_props.write = characteristic->props.write, + .char_props.notify = characteristic->props.notify, + .char_props.indicate = characteristic->props.indicate, + }; + + ble_gatts_attr_md_t cccd_md = { + .vloc = BLE_GATTS_VLOC_STACK, + }; + + if (char_md.char_props.notify || char_md.char_props.indicate) { + BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm); + BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm); + + char_md.p_cccd_md = &cccd_md; + } + + ble_uuid_t uuid = { + .type = BLE_UUID_TYPE_BLE, + .uuid = characteristic->uuid->value[0] | (characteristic->uuid->value[1] << 8), + }; + + if (characteristic->uuid->type == UUID_TYPE_128BIT) + uuid.type = characteristic->uuid->uuid_vs_idx; + + ble_gatts_attr_md_t attr_md = { + .vloc = BLE_GATTS_VLOC_STACK, + .vlen = 1, + }; + + BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm); + BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm); + + ble_gatts_attr_t attr_char_value = { + .p_uuid = &uuid, + .p_attr_md = &attr_md, + .init_len = sizeof(uint8_t), + .max_len = (BLE_GATT_ATT_MTU_DEFAULT - 3), + }; + + ble_gatts_char_handles_t handles; + + uint32_t err_code; + err_code = sd_ble_gatts_characteristic_add(self->handle, &char_md, &attr_char_value, &handles); + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + translate("Failed to add characteristic, status: 0x%08lX"), err_code)); + } + + characteristic->user_desc_handle = handles.user_desc_handle; + characteristic->cccd_handle = handles.cccd_handle; + characteristic->sccd_handle = handles.sccd_handle; + characteristic->handle = handles.value_handle; +} diff --git a/ports/nrf/common-hal/bleio/UUID.c b/ports/nrf/common-hal/bleio/UUID.c new file mode 100644 index 000000000..9a2e101ea --- /dev/null +++ b/ports/nrf/common-hal/bleio/UUID.c @@ -0,0 +1,124 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Glenn Ruben Bakke + * Copyright (c) 2018 Artur Pacholec + * + * 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 "ble.h" +#include "ble_drv.h" +#include "common-hal/bleio/UUID.h" +#include "nrf_error.h" +#include "py/objstr.h" +#include "py/runtime.h" +#include "shared-bindings/bleio/Adapter.h" +#include "shared-bindings/bleio/UUID.h" + +#define UUID_STR_16BIT_LEN 6 +#define UUID_STR_128BIT_LEN 36 + +static uint8_t xdigit_8b_value(byte nibble1, byte nibble2) { + return unichar_xdigit_value(nibble1) | + (unichar_xdigit_value(nibble2) << 4); +} + +void common_hal_bleio_uuid_construct(bleio_uuid_obj_t *self, const mp_obj_t *uuid) { + if (MP_OBJ_IS_INT(*uuid)) { + self->type = UUID_TYPE_16BIT; + + self->value[1] = (mp_obj_get_int(*uuid) >> 8) & 0xFF; + self->value[0] = (mp_obj_get_int(*uuid) >> 0) & 0xFF; + return; + } + + if (MP_OBJ_IS_STR(*uuid)) { + GET_STR_DATA_LEN(*uuid, str_data, str_len); + + if (str_len == UUID_STR_16BIT_LEN) { + self->type = UUID_TYPE_16BIT; + + self->value[0] = xdigit_8b_value(str_data[5], str_data[4]); + self->value[1] = xdigit_8b_value(str_data[3], str_data[2]); + } else if (str_len == UUID_STR_128BIT_LEN) { + self->type = UUID_TYPE_128BIT; + + ble_uuid128_t vs_uuid; + vs_uuid.uuid128[0] = xdigit_8b_value(str_data[35], str_data[34]); + vs_uuid.uuid128[1] = xdigit_8b_value(str_data[33], str_data[32]); + vs_uuid.uuid128[2] = xdigit_8b_value(str_data[31], str_data[30]); + vs_uuid.uuid128[3] = xdigit_8b_value(str_data[29], str_data[28]); + vs_uuid.uuid128[4] = xdigit_8b_value(str_data[27], str_data[26]); + vs_uuid.uuid128[5] = xdigit_8b_value(str_data[25], str_data[24]); + + // 23 '-' + vs_uuid.uuid128[6] = xdigit_8b_value(str_data[22], str_data[21]); + vs_uuid.uuid128[7] = xdigit_8b_value(str_data[20], str_data[19]); + + // 18 '-' + vs_uuid.uuid128[8] = xdigit_8b_value(str_data[17], str_data[16]); + vs_uuid.uuid128[9] = xdigit_8b_value(str_data[15], str_data[14]); + + // 13 '-' + vs_uuid.uuid128[10] = xdigit_8b_value(str_data[12], str_data[11]); + vs_uuid.uuid128[11] = xdigit_8b_value(str_data[10], str_data[9]); + + // 8 '-' + self->value[0] = xdigit_8b_value(str_data[7], str_data[6]); + self->value[1] = xdigit_8b_value(str_data[5], str_data[4]); + + vs_uuid.uuid128[14] = xdigit_8b_value(str_data[3], str_data[2]); + vs_uuid.uuid128[15] = xdigit_8b_value(str_data[1], str_data[0]); + + common_hal_bleio_adapter_set_enabled(true); + + const uint32_t err_code = sd_ble_uuid_vs_add(&vs_uuid, &self->uuid_vs_idx); + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + translate("Failed to add Vendor Specific UUID, status: 0x%08lX"), err_code)); + } + + } else { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, + translate("Invalid UUID string length"))); + } + + return; + } + + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, + translate("Invalid UUID parameter"))); +} + +void common_hal_bleio_uuid_print(bleio_uuid_obj_t *self, const mp_print_t *print) { + if (self->type == UUID_TYPE_16BIT) { + mp_printf(print, "UUID(uuid: 0x" HEX2_FMT HEX2_FMT ")", + self->value[1], self->value[0]); + } else { + mp_printf(print, "UUID(uuid: 0x" HEX2_FMT HEX2_FMT ", VS idx: " HEX2_FMT ")", + self->value[1], self->value[0], self->uuid_vs_idx); + } +} + +bleio_uuid_type_t common_hal_bleio_uuid_get_type(bleio_uuid_obj_t *self) { + return self->type; +} diff --git a/ports/nrf/common-hal/bleio/UUID.h b/ports/nrf/common-hal/bleio/UUID.h new file mode 100644 index 000000000..cb0fddcfd --- /dev/null +++ b/ports/nrf/common-hal/bleio/UUID.h @@ -0,0 +1,40 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Glenn Ruben Bakke + * Copyright (c) 2018 Artur Pacholec + * + * 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_NRF_COMMON_HAL_BLEIO_UUID_H +#define MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_UUID_H + +#include "shared-bindings/bleio/UUIDType.h" + +typedef struct { + mp_obj_base_t base; + bleio_uuid_type_t type; + uint8_t uuid_vs_idx; + uint8_t value[2]; +} bleio_uuid_obj_t; + +#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_UUID_H diff --git a/ports/nrf/common-hal/board/__init__.c b/ports/nrf/common-hal/board/__init__.c index 287f546d5..350f2eea5 100644 --- a/ports/nrf/common-hal/board/__init__.c +++ b/ports/nrf/common-hal/board/__init__.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2018 Dan Halbert 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 diff --git a/ports/nrf/common-hal/busio/I2C.c b/ports/nrf/common-hal/busio/I2C.c index c2a6cab70..4c42e58cd 100644 --- a/ports/nrf/common-hal/busio/I2C.c +++ b/ports/nrf/common-hal/busio/I2C.c @@ -56,6 +56,7 @@ STATIC twim_peripheral_t twim_peripherals[] = { void i2c_reset(void) { for (size_t i = 0 ; i < MP_ARRAY_SIZE(twim_peripherals); i++) { + nrf_twim_disable(twim_peripherals[i].twim.p_twim); twim_peripherals[i].in_use = false; } } diff --git a/ports/nrf/common-hal/busio/SPI.c b/ports/nrf/common-hal/busio/SPI.c index 54ae6e47c..19bd4d1ba 100644 --- a/ports/nrf/common-hal/busio/SPI.c +++ b/ports/nrf/common-hal/busio/SPI.c @@ -59,46 +59,64 @@ STATIC spim_peripheral_t spim_peripherals[] = { #endif }; +STATIC bool never_reset[4]; + void spi_reset(void) { for (size_t i = 0 ; i < MP_ARRAY_SIZE(spim_peripherals); i++) { - nrfx_spim_uninit(&spim_peripherals[i].spim); + if (never_reset[i]) { + continue; + } + nrf_spim_disable(spim_peripherals[i].spim.p_reg); } } -// Convert frequency to clock-speed-dependent value -static nrf_spim_frequency_t baudrate_to_spim_frequency(const uint32_t baudrate) { - if (baudrate <= 125000) { - return NRF_SPIM_FREQ_125K; - } - if (baudrate <= 250000) { - return NRF_SPIM_FREQ_250K; - } - if (baudrate <= 500000) { - return NRF_SPIM_FREQ_500K; - } - if (baudrate <= 1000000) { - return NRF_SPIM_FREQ_1M; - } - if (baudrate <= 2000000) { - return NRF_SPIM_FREQ_2M; - } - if (baudrate <= 4000000) { - return NRF_SPIM_FREQ_4M; - } - if (baudrate <= 8000000) { - return NRF_SPIM_FREQ_8M; - } -#ifdef SPIM_FREQUENCY_FREQUENCY_M16 - if (baudrate <= 16000000) { - return NRF_SPIM_FREQ_16M; +void common_hal_busio_spi_never_reset(busio_spi_obj_t *self) { + for (size_t i = 0 ; i < MP_ARRAY_SIZE(spim_peripherals); i++) { + if (self->spim_peripheral == &spim_peripherals[i]) { + never_reset[i] = true; + + never_reset_pin_number(self->clock_pin_number); + never_reset_pin_number(self->MOSI_pin_number); + never_reset_pin_number(self->MISO_pin_number); + break; + } } -#endif +} +// Convert frequency to clock-speed-dependent value. Choose the next lower baudrate if in between +// available baudrates. +static nrf_spim_frequency_t baudrate_to_spim_frequency(const uint32_t baudrate) { + + static const struct { + const uint32_t boundary; + nrf_spim_frequency_t spim_frequency; + } baudrate_map[] = { #ifdef SPIM_FREQUENCY_FREQUENCY_M32 - return NRF_SPIM_FREQ_32M; -#else - return NRF_SPIM_FREQ_8M; + { 32000000, NRF_SPIM_FREQ_32M }, +#endif +#ifdef SPIM_FREQUENCY_FREQUENCY_M16 + { 16000000, NRF_SPIM_FREQ_16M }, #endif + { 8000000, NRF_SPIM_FREQ_8M }, + { 4000000, NRF_SPIM_FREQ_4M }, + { 2000000, NRF_SPIM_FREQ_2M }, + { 1000000, NRF_SPIM_FREQ_1M }, + { 500000, NRF_SPIM_FREQ_500K }, + { 250000, NRF_SPIM_FREQ_250K }, + { 0, NRF_SPIM_FREQ_125K }, + }; + + size_t i = 0; + uint32_t boundary; + do { + boundary = baudrate_map[i].boundary; + if (baudrate >= boundary) { + return baudrate_map[i].spim_frequency; + } + i++; + } while (boundary != 0); + // Should not get here. + return 0; } void common_hal_busio_spi_construct(busio_spi_obj_t *self, const mcu_pin_obj_t * clock, const mcu_pin_obj_t * mosi, const mcu_pin_obj_t * miso) { @@ -168,26 +186,26 @@ void common_hal_busio_spi_deinit(busio_spi_obj_t *self) { } bool common_hal_busio_spi_configure(busio_spi_obj_t *self, uint32_t baudrate, uint8_t polarity, uint8_t phase, uint8_t bits) { - // nrf52 does not support 16 bit - if (bits != 8) + // nrf52 does not support 16 bit + if (bits != 8) { return false; + } - if (baudrate > self->spim_peripheral->max_frequency_MHz * 1000000) { - mp_raise_ValueError(translate("Baud rate too high for this SPI peripheral")); - return false; - } - nrf_spim_frequency_set(self->spim_peripheral->spim.p_reg, baudrate_to_spim_frequency(baudrate)); + // Set desired frequency, rounding down, and don't go above available frequency for this SPIM. + nrf_spim_frequency_set(self->spim_peripheral->spim.p_reg, + baudrate_to_spim_frequency(MIN(baudrate, + self->spim_peripheral->max_frequency_MHz * 1000000))); - nrf_spim_mode_t mode = NRF_SPIM_MODE_0; - if (polarity) { - mode = (phase) ? NRF_SPIM_MODE_3 : NRF_SPIM_MODE_2; - } else { - mode = (phase) ? NRF_SPIM_MODE_1 : NRF_SPIM_MODE_0; - } + nrf_spim_mode_t mode = NRF_SPIM_MODE_0; + if (polarity) { + mode = (phase) ? NRF_SPIM_MODE_3 : NRF_SPIM_MODE_2; + } else { + mode = (phase) ? NRF_SPIM_MODE_1 : NRF_SPIM_MODE_0; + } - nrf_spim_configure(self->spim_peripheral->spim.p_reg, mode, NRF_SPIM_BIT_ORDER_MSB_FIRST); + nrf_spim_configure(self->spim_peripheral->spim.p_reg, mode, NRF_SPIM_BIT_ORDER_MSB_FIRST); - return true; + return true; } bool common_hal_busio_spi_try_lock(busio_spi_obj_t *self) { diff --git a/ports/nrf/common-hal/busio/UART.c b/ports/nrf/common-hal/busio/UART.c index 06a348b76..516a7747d 100644 --- a/ports/nrf/common-hal/busio/UART.c +++ b/ports/nrf/common-hal/busio/UART.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2016 Damien P. George + * Copyright (c) 2018 Ha Thach 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 @@ -27,7 +27,7 @@ #include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/busio/UART.h" -#include "mpconfigport.h" +#include "py/mpconfig.h" #include "py/gc.h" #include "py/mperrno.h" #include "py/runtime.h" @@ -35,58 +35,333 @@ #include "supervisor/shared/translate.h" #include "tick.h" +#include "nrfx_uarte.h" +#include <string.h> -void common_hal_busio_uart_construct(busio_uart_obj_t *self, - const mcu_pin_obj_t * tx, const mcu_pin_obj_t * rx, uint32_t baudrate, - uint8_t bits, uart_parity_t parity, uint8_t stop, uint32_t timeout, - uint8_t receiver_buffer_size) { - mp_raise_NotImplementedError(translate("busio.UART not yet implemented")); +#ifdef NRF52840_XXAA + +// expression to examine, and return value in case of failing +#define _VERIFY_ERR(_exp) \ + do {\ + uint32_t _err = (_exp);\ + if (NRFX_SUCCESS != _err ) {\ + mp_raise_msg_varg(&mp_type_RuntimeError, translate("error = 0x%08lX"), _err);\ + }\ + }while(0) + +static uint32_t get_nrf_baud (uint32_t baudrate); + +static void uart_callback_irq (const nrfx_uarte_event_t * event, void * context) { + busio_uart_obj_t* self = (busio_uart_obj_t*) context; + + switch ( event->type ) { + case NRFX_UARTE_EVT_RX_DONE: + self->rx_count = event->data.rxtx.bytes; + break; + + case NRFX_UARTE_EVT_TX_DONE: + break; + + case NRFX_UARTE_EVT_ERROR: + if ( self->rx_count == -1 ) { + self->rx_count = 0; + } + break; + + default: + break; + } +} + + +void common_hal_busio_uart_construct (busio_uart_obj_t *self, + const mcu_pin_obj_t * tx, const mcu_pin_obj_t * rx, uint32_t baudrate, + uint8_t bits, uart_parity_t parity, uint8_t stop, uint32_t timeout, + uint8_t receiver_buffer_size) { + if ( (tx == mp_const_none) && (rx == mp_const_none) ) { + mp_raise_ValueError(translate("tx and rx cannot both be None")); + } + + if ( receiver_buffer_size == 0 ) { + mp_raise_ValueError(translate("Invalid buffer size")); + } + + if ( parity == PARITY_ODD ) { + mp_raise_ValueError(translate("Odd parity is not supported")); + } + + nrfx_uarte_config_t config = { + .pseltxd = (tx == mp_const_none) ? NRF_UARTE_PSEL_DISCONNECTED : tx->number, + .pselrxd = (rx == mp_const_none) ? NRF_UARTE_PSEL_DISCONNECTED : rx->number, + .pselcts = NRF_UARTE_PSEL_DISCONNECTED, + .pselrts = NRF_UARTE_PSEL_DISCONNECTED, + .p_context = self, + .hwfc = NRF_UARTE_HWFC_DISABLED, + .parity = (parity == PARITY_NONE) ? NRF_UARTE_PARITY_EXCLUDED : NRF_UARTE_PARITY_INCLUDED, + .baudrate = get_nrf_baud(baudrate), + .interrupt_priority = 7 + }; + + // support only 1 instance for now + self->uarte = (nrfx_uarte_t ) NRFX_UARTE_INSTANCE(0); + nrfx_uarte_uninit(&self->uarte); + _VERIFY_ERR(nrfx_uarte_init(&self->uarte, &config, uart_callback_irq)); + + // Init buffer for rx + if ( rx != mp_const_none ) { + self->buffer = (uint8_t *) gc_alloc(receiver_buffer_size, false, false); + if ( !self->buffer ) { + nrfx_uarte_uninit(&self->uarte); + mp_raise_msg(&mp_type_MemoryError, translate("Failed to allocate RX buffer")); + } + self->bufsize = receiver_buffer_size; + + claim_pin(rx); + } + + if ( tx != mp_const_none ) { + claim_pin(tx); + } + + self->baudrate = baudrate; + self->timeout_ms = timeout; + + // queue 1-byte transfer for rx_characters_available() + self->rx_count = -1; + _VERIFY_ERR(nrfx_uarte_rx(&self->uarte, self->buffer, 1)); } bool common_hal_busio_uart_deinited(busio_uart_obj_t *self) { - mp_raise_NotImplementedError(translate("busio.UART not yet implemented")); + return (nrf_uarte_rx_pin_get(self->uarte.p_reg) == NRF_UARTE_PSEL_DISCONNECTED) && + (nrf_uarte_tx_pin_get(self->uarte.p_reg) == NRF_UARTE_PSEL_DISCONNECTED); } void common_hal_busio_uart_deinit(busio_uart_obj_t *self) { - mp_raise_NotImplementedError(translate("busio.UART not yet implemented")); - if (common_hal_busio_uart_deinited(self)) { - return; + if ( !common_hal_busio_uart_deinited(self) ) { + nrfx_uarte_uninit(&self->uarte); + gc_free(self->buffer); } - // Do deinit; } // Read characters. size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t len, int *errcode) { - mp_raise_NotImplementedError(translate("busio.UART not yet implemented")); - return 0; + if ( nrf_uarte_rx_pin_get(self->uarte.p_reg) == NRF_UARTE_PSEL_DISCONNECTED ) { + mp_raise_ValueError(translate("No RX pin")); + } + + size_t remain = len; + uint64_t start_ticks = ticks_ms; + + while ( 1 ) { + // Wait for on-going transfer to complete + while ( (self->rx_count == -1) && (ticks_ms - start_ticks < self->timeout_ms) ) { +#ifdef MICROPY_VM_HOOK_LOOP + MICROPY_VM_HOOK_LOOP +#endif + } + + // copy received data + if ( self->rx_count > 0 ) { + memcpy(data, self->buffer, self->rx_count); + data += self->rx_count; + remain -= self->rx_count; + + self->rx_count = 0; + } + + // exit if complete or time up + if ( !remain || !(ticks_ms - start_ticks < self->timeout_ms) ) { + break; + } + + // prepare next receiving + const size_t cnt = MIN(self->bufsize, remain); + self->rx_count = -1; + _VERIFY_ERR(nrfx_uarte_rx(&self->uarte, self->buffer, cnt)); + } + + // queue 1-byte transfer for rx_characters_available() + if ( self->rx_count == 0 ) { + self->rx_count = -1; + _VERIFY_ERR(nrfx_uarte_rx(&self->uarte, self->buffer, 1)); + } + + return len - remain; } // Write characters. -size_t common_hal_busio_uart_write(busio_uart_obj_t *self, const uint8_t *data, size_t len, int *errcode) { - mp_raise_NotImplementedError(translate("busio.UART not yet implemented")); - return 0; +size_t common_hal_busio_uart_write (busio_uart_obj_t *self, const uint8_t *data, size_t len, int *errcode) { + if ( nrf_uarte_tx_pin_get(self->uarte.p_reg) == NRF_UARTE_PSEL_DISCONNECTED ) { + mp_raise_ValueError(translate("No TX pin")); + } + + if ( len == 0 ) return 0; + + uint64_t start_ticks = ticks_ms; + + // Wait for on-going transfer to complete + while ( nrfx_uarte_tx_in_progress(&self->uarte) && (ticks_ms - start_ticks < self->timeout_ms) ) { +#ifdef MICROPY_VM_HOOK_LOOP + MICROPY_VM_HOOK_LOOP +#endif + } + + // Time up + if ( !(ticks_ms - start_ticks < self->timeout_ms) ) { + *errcode = MP_EAGAIN; + return MP_STREAM_ERROR; + } + + // EasyDMA can only access SRAM + uint8_t * tx_buf = (uint8_t*) data; + if ( !nrfx_is_in_ram(data) ) { + tx_buf = (uint8_t *) gc_alloc(len, false, false); + memcpy(tx_buf, data, len); + } + + (*errcode) = nrfx_uarte_tx(&self->uarte, tx_buf, len); + _VERIFY_ERR(*errcode); + (*errcode) = 0; + + while ( nrfx_uarte_tx_in_progress(&self->uarte) && (ticks_ms - start_ticks < self->timeout_ms) ) { +#ifdef MICROPY_VM_HOOK_LOOP + MICROPY_VM_HOOK_LOOP +#endif + } + + if ( !nrfx_is_in_ram(data) ) { + gc_free(tx_buf); + } + + return len; } uint32_t common_hal_busio_uart_get_baudrate(busio_uart_obj_t *self) { - mp_raise_NotImplementedError(translate("busio.UART not yet implemented")); return self->baudrate; } void common_hal_busio_uart_set_baudrate(busio_uart_obj_t *self, uint32_t baudrate) { - mp_raise_NotImplementedError(translate("busio.UART not yet implemented")); self->baudrate = baudrate; + nrf_uarte_baudrate_set(self->uarte.p_reg, get_nrf_baud(baudrate)); } uint32_t common_hal_busio_uart_rx_characters_available(busio_uart_obj_t *self) { - mp_raise_NotImplementedError(translate("busio.UART not yet implemented")); - return 0; + return (self->rx_count > 0) ? self->rx_count : 0; } void common_hal_busio_uart_clear_rx_buffer(busio_uart_obj_t *self) { - mp_raise_NotImplementedError(translate("busio.UART not yet implemented")); + // Discard received byte, and queue 1-byte transfer for rx_characters_available() + if ( self->rx_count > 0 ) { + self->rx_count = -1; + _VERIFY_ERR(nrfx_uarte_rx(&self->uarte, self->buffer, 1)); + } } bool common_hal_busio_uart_ready_to_tx(busio_uart_obj_t *self) { - mp_raise_NotImplementedError(translate("busio.UART not yet implemented")); + return !nrfx_uarte_tx_in_progress(&self->uarte); +} + +static uint32_t get_nrf_baud (uint32_t baudrate) +{ + if ( baudrate <= 1200 ) { + return NRF_UARTE_BAUDRATE_1200; + } + else if ( baudrate <= 2400 ) { + return NRF_UARTE_BAUDRATE_2400; + } + else if ( baudrate <= 4800 ) { + return NRF_UARTE_BAUDRATE_4800; + } + else if ( baudrate <= 9600 ) { + return NRF_UARTE_BAUDRATE_9600; + } + else if ( baudrate <= 14400 ) { + return NRF_UARTE_BAUDRATE_14400; + } + else if ( baudrate <= 19200 ) { + return NRF_UARTE_BAUDRATE_19200; + } + else if ( baudrate <= 28800 ) { + return NRF_UARTE_BAUDRATE_28800; + } + else if ( baudrate <= 38400 ) { + return NRF_UARTE_BAUDRATE_38400; + } + else if ( baudrate <= 57600 ) { + return NRF_UARTE_BAUDRATE_57600; + } + else if ( baudrate <= 76800 ) { + return NRF_UARTE_BAUDRATE_76800; + } + else if ( baudrate <= 115200 ) { + return NRF_UARTE_BAUDRATE_115200; + } + else if ( baudrate <= 230400 ) { + return NRF_UARTE_BAUDRATE_230400; + } + else if ( baudrate <= 250000 ) { + return NRF_UARTE_BAUDRATE_250000; + } + else if ( baudrate <= 460800 ) { + return NRF_UARTE_BAUDRATE_460800; + } + else if ( baudrate <= 921600 ) { + return NRF_UARTE_BAUDRATE_921600; + } + else { + return NRF_UARTE_BAUDRATE_1000000; + } +} + +#else + +void common_hal_busio_uart_construct (busio_uart_obj_t *self, + const mcu_pin_obj_t * tx, const mcu_pin_obj_t * rx, uint32_t baudrate, + uint8_t bits, uart_parity_t parity, uint8_t stop, uint32_t timeout, + uint8_t receiver_buffer_size) { + mp_raise_NotImplementedError(translate("busio.UART not available")); +} + +bool common_hal_busio_uart_deinited (busio_uart_obj_t *self) { + mp_raise_NotImplementedError(translate("busio.UART not available")); + return true; +} + +void common_hal_busio_uart_deinit (busio_uart_obj_t *self) { + mp_raise_NotImplementedError(translate("busio.UART not available")); +} + +// Read characters. +size_t common_hal_busio_uart_read (busio_uart_obj_t *self, uint8_t *data, size_t len, int *errcode) { + mp_raise_NotImplementedError(translate("busio.UART not available")); + return 0; +} + +// Write characters. +size_t common_hal_busio_uart_write (busio_uart_obj_t *self, const uint8_t *data, size_t len, int *errcode) { + mp_raise_NotImplementedError(translate("busio.UART not available")); + return 0; +} + +uint32_t common_hal_busio_uart_get_baudrate (busio_uart_obj_t *self) { + mp_raise_NotImplementedError(translate("busio.UART not available")); + return self->baudrate; +} + +void common_hal_busio_uart_set_baudrate (busio_uart_obj_t *self, uint32_t baudrate) { + mp_raise_NotImplementedError(translate("busio.UART not available")); +} + +uint32_t common_hal_busio_uart_rx_characters_available (busio_uart_obj_t *self) { + mp_raise_NotImplementedError(translate("busio.UART not available")); +} + +void common_hal_busio_uart_clear_rx_buffer (busio_uart_obj_t *self) { + +} + +bool common_hal_busio_uart_ready_to_tx (busio_uart_obj_t *self) { + mp_raise_NotImplementedError(translate("busio.UART not available")); return false; } +#endif diff --git a/ports/nrf/common-hal/busio/UART.h b/ports/nrf/common-hal/busio/UART.h index 7c0493e37..aef377f14 100644 --- a/ports/nrf/common-hal/busio/UART.h +++ b/ports/nrf/common-hal/busio/UART.h @@ -28,23 +28,22 @@ #define MICROPY_INCLUDED_NRF_COMMON_HAL_BUSIO_UART_H #include "common-hal/microcontroller/Pin.h" +#include "nrfx_uarte.h" #include "py/obj.h" +#include "py/ringbuf.h" typedef struct { mp_obj_base_t base; - uint8_t rx_pin; - uint8_t tx_pin; - uint8_t character_bits; - bool rx_error; + + nrfx_uarte_t uarte; + uint32_t baudrate; uint32_t timeout_ms; - // Index of the oldest received character. - uint32_t buffer_start; - // Index of the next available spot to store a character. - uint32_t buffer_size; - uint32_t buffer_length; + uint8_t* buffer; + uint32_t bufsize; + volatile int32_t rx_count; } busio_uart_obj_t; #endif // MICROPY_INCLUDED_NRF_COMMON_HAL_BUSIO_UART_H diff --git a/ports/nrf/common-hal/digitalio/DigitalInOut.c b/ports/nrf/common-hal/digitalio/DigitalInOut.c index f05cf568f..0836962c6 100644 --- a/ports/nrf/common-hal/digitalio/DigitalInOut.c +++ b/ports/nrf/common-hal/digitalio/DigitalInOut.c @@ -30,6 +30,11 @@ #include "nrf_gpio.h" +void common_hal_digitalio_digitalinout_never_reset( + digitalio_digitalinout_obj_t *self) { + never_reset_pin_number(self->pin->number); +} + digitalinout_result_t common_hal_digitalio_digitalinout_construct( digitalio_digitalinout_obj_t *self, const mcu_pin_obj_t *pin) { claim_pin(pin); diff --git a/ports/nrf/common-hal/microcontroller/Pin.c b/ports/nrf/common-hal/microcontroller/Pin.c index 7a069eeda..02847e150 100644 --- a/ports/nrf/common-hal/microcontroller/Pin.c +++ b/ports/nrf/common-hal/microcontroller/Pin.c @@ -45,13 +45,17 @@ bool speaker_enable_in_use; // Bit mask of claimed pins on each of up to two ports. nrf52832 has one port; nrf52840 has two. STATIC uint32_t claimed_pins[GPIO_COUNT]; +STATIC uint32_t never_reset_pins[GPIO_COUNT]; void reset_all_pins(void) { for (size_t i = 0; i < GPIO_COUNT; i++) { - claimed_pins[i] = 0; + claimed_pins[i] = never_reset_pins[i]; } for (uint32_t pin = 0; pin < NUMBER_OF_PINS; ++pin) { + if (!(never_reset_pins[nrf_pin_port(pin)] & (1 << nrf_relative_pin_number(pin)))) { + continue; + } nrf_gpio_cfg_default(pin); } @@ -108,6 +112,11 @@ void reset_pin_number(uint8_t pin_number) { #endif } + +void never_reset_pin_number(uint8_t pin_number) { + never_reset_pins[nrf_pin_port(pin_number)] |= 1 << nrf_relative_pin_number(pin_number); +} + void claim_pin(const mcu_pin_obj_t* pin) { // Set bit in claimed_pins bitmask. claimed_pins[nrf_pin_port(pin->number)] |= 1 << nrf_relative_pin_number(pin->number); diff --git a/ports/nrf/common-hal/microcontroller/Pin.h b/ports/nrf/common-hal/microcontroller/Pin.h index 2cdf440b5..61be8bc35 100644 --- a/ports/nrf/common-hal/microcontroller/Pin.h +++ b/ports/nrf/common-hal/microcontroller/Pin.h @@ -44,6 +44,7 @@ void reset_all_pins(void); // need to store a full pointer. void reset_pin_number(uint8_t pin); void claim_pin(const mcu_pin_obj_t* pin); +void never_reset_pin_number(uint8_t pin_number); // Lower 5 bits of a pin number are the pin number in a port. // upper bits (just one bit for current chips) is port number. diff --git a/ports/nrf/common-hal/microcontroller/Processor.c b/ports/nrf/common-hal/microcontroller/Processor.c index 2ce3e8bf5..e4d9439c9 100644 --- a/ports/nrf/common-hal/microcontroller/Processor.c +++ b/ports/nrf/common-hal/microcontroller/Processor.c @@ -72,12 +72,7 @@ uint32_t common_hal_mcu_processor_get_frequency(void) { } void common_hal_mcu_processor_get_uid(uint8_t raw_id[]) { - - uint32_t* id_addresses[2] = {(uint32_t *) 0x060, (uint32_t *) 0x064}; - for (int i=0; i<2; i++) { - for (int k=0; k<4; k++) { - raw_id[4 * i + k] = (*(id_addresses[i]) >> k * 8) & 0xff; - } + ((uint32_t*) raw_id)[i] = NRF_FICR->DEVICEID[i]; } } diff --git a/ports/nrf/common-hal/neopixel_write/__init__.c b/ports/nrf/common-hal/neopixel_write/__init__.c index ef5e8beb1..c4cb194f3 100644 --- a/ports/nrf/common-hal/neopixel_write/__init__.c +++ b/ports/nrf/common-hal/neopixel_write/__init__.c @@ -108,12 +108,21 @@ void common_hal_neopixel_write (const digitalio_digitalinout_obj_t* digitalinout // using DWT uint32_t pattern_size = numBytes * 8 * sizeof(uint16_t) + 2 * sizeof(uint16_t); uint16_t* pixels_pattern = NULL; + bool pattern_on_heap = false; + + // Use the stack to store 1 pixels worth of PWM data for the status led. uint32_t to ensure alignment. + uint32_t one_pixel[8 * sizeof(uint16_t) + 1]; NRF_PWM_Type* pwm = find_free_pwm(); // only malloc if there is PWM device available if ( pwm != NULL ) { - pixels_pattern = (uint16_t *) m_malloc(pattern_size, false); + if (numBytes == 4) { + pixels_pattern = (uint16_t *) one_pixel; + } else { + pixels_pattern = (uint16_t *) m_malloc_maybe(pattern_size, false); + pattern_on_heap = true; + } } // Use the identified device to choose the implementation @@ -193,7 +202,10 @@ void common_hal_neopixel_write (const digitalio_digitalinout_obj_t* digitalinout nrf_pwm_disable(pwm); nrf_pwm_pins_set(pwm, (uint32_t[]) {0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL, 0xFFFFFFFFUL} ); - m_free(pixels_pattern); + if (pattern_on_heap) { + m_free(pixels_pattern); + } + } // End of DMA implementation // --------------------------------------------------------------------- else { diff --git a/ports/nrf/common-hal/pulseio/PWMOut.c b/ports/nrf/common-hal/pulseio/PWMOut.c index c3c51d566..f321f848d 100644 --- a/ports/nrf/common-hal/pulseio/PWMOut.c +++ b/ports/nrf/common-hal/pulseio/PWMOut.c @@ -3,8 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries - * Copyright (c) 2016 Damien P. George + * Copyright (c) 2018 Dan Halbert 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 @@ -30,154 +29,160 @@ #include "py/runtime.h" #include "common-hal/pulseio/PWMOut.h" -#include "nrf_gpio.h" #include "shared-bindings/pulseio/PWMOut.h" #include "supervisor/shared/translate.h" -#define PWM_MAX_MODULE 3 -#define PWM_MAX_CHANNEL 4 +#include "nrf_gpio.h" #define PWM_MAX_FREQ (16000000) -NRF_PWM_Type* const pwm_arr[PWM_MAX_MODULE] = { NRF_PWM0, NRF_PWM1, NRF_PWM2 }; - -uint16_t _seq0[PWM_MAX_MODULE][PWM_MAX_CHANNEL]; - - -static int pin2channel(NRF_PWM_Type* pwm, uint8_t pin) -{ - for(int i=0; i < PWM_MAX_CHANNEL; i++) - { - if ( pwm->PSEL.OUT[i] == ((uint32_t)pin) ) return i; - } - - return -1; -} - -static int find_free_channel(NRF_PWM_Type* pwm) -{ - for(int i=0; i < PWM_MAX_CHANNEL; i++) - { - if (pwm->PSEL.OUT[i] == 0xFFFFFFFFUL) - { - return i; +STATIC NRF_PWM_Type* pwms[] = { +#if NRFX_CHECK(NRFX_PWM0_ENABLED) + NRF_PWM0, +#endif +#if NRFX_CHECK(NRFX_PWM1_ENABLED) + NRF_PWM1, +#endif +#if NRFX_CHECK(NRFX_PWM2_ENABLED) + NRF_PWM2, +#endif +#if NRFX_CHECK(NRFX_PWM3_ENABLED) + NRF_PWM3, +#endif +}; + +#define CHANNELS_PER_PWM 4 + +STATIC uint16_t pwm_seq[MP_ARRAY_SIZE(pwms)][CHANNELS_PER_PWM]; + +void pwmout_reset(void) { + for(int i=0; i < MP_ARRAY_SIZE(pwms); i++) { + NRF_PWM_Type* pwm = pwms[i]; + + pwm->ENABLE = 0; + pwm->MODE = PWM_MODE_UPDOWN_Up; + pwm->DECODER = PWM_DECODER_LOAD_Individual; + pwm->LOOP = 0; + pwm->PRESCALER = PWM_PRESCALER_PRESCALER_DIV_1; // default is 500 hz + pwm->COUNTERTOP = (PWM_MAX_FREQ/500); // default is 500 hz + + pwm->SEQ[0].PTR = (uint32_t) pwm_seq[i]; + pwm->SEQ[0].CNT = CHANNELS_PER_PWM; // default mode is Individual --> count must be 4 + pwm->SEQ[0].REFRESH = 0; + pwm->SEQ[0].ENDDELAY = 0; + + pwm->SEQ[1].PTR = 0; + pwm->SEQ[1].CNT = 0; + pwm->SEQ[1].REFRESH = 0; + pwm->SEQ[1].ENDDELAY = 0; + + for(int ch =0; ch < CHANNELS_PER_PWM; ch++) { + pwm_seq[i][ch] = (1 << 15); // polarity = 0 + } } - } - - return -1; } -static bool pwm_is_unused(NRF_PWM_Type* pwm) -{ - for(int i=0; i < PWM_MAX_CHANNEL; i++) - { - if (pwm->PSEL.OUT[i] != 0xFFFFFFFFUL) - { - return false; +// Find the smallest prescaler value that will allow the divisor to be in range. +// This allows the most accuracy. +bool convert_frequency(uint32_t frequency, uint16_t *countertop, nrf_pwm_clk_t *base_clock) { + uint32_t divisor = 1; + // Use a 32-bit number so we don't overflow the uint16_t; + uint32_t tentative_countertop; + for (*base_clock = PWM_PRESCALER_PRESCALER_DIV_1; + *base_clock <= PWM_PRESCALER_PRESCALER_DIV_128; + (*base_clock)++) { + tentative_countertop = PWM_MAX_FREQ / divisor / frequency; + // COUNTERTOP must be 3..32767, according to datasheet, but 3 doesn't work. 4 does. + if (tentative_countertop <= 32767 && tentative_countertop >= 4) { + // In range, OK to return. + *countertop = tentative_countertop; + return true; + } + divisor *= 2; } - } - return true; + return false; } -static void find_new_pwm(pulseio_pwmout_obj_t* self) -{ - // First find unused PWM module - for(int i=0; i<PWM_MAX_MODULE; i++) - { - if ( pwm_is_unused(pwm_arr[i]) ) - { - self->pwm = pwm_arr[i]; - self->channel = 0; - return; - } - } - - // Find available channel in a using PWM - for(int i=0; i<PWM_MAX_MODULE; i++) - { - int ch = find_free_channel(pwm_arr[i]); - if ( ch >= 0 ) - { - self->pwm = pwm_arr[i]; - self->channel = (uint8_t) ch; - return; +void common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, + const mcu_pin_obj_t* pin, + uint16_t duty, + uint32_t frequency, + bool variable_frequency) { + + // We don't use the nrfx driver here because we want to dynamically allocate channels + // as needed in an already-enabled PWM. + + uint16_t countertop; + nrf_pwm_clk_t base_clock; + if (frequency == 0 || !convert_frequency(frequency, &countertop, &base_clock)) { + mp_raise_ValueError(translate("Invalid PWM frequency")); } - } -} -void pwmout_reset(void) -{ - for(int i=0; i<PWM_MAX_MODULE; i++) - { - NRF_PWM_Type* pwm = pwm_arr[i]; - - pwm->MODE = PWM_MODE_UPDOWN_Up; - pwm->DECODER = PWM_DECODER_LOAD_Individual; - pwm->LOOP = 0; - pwm->PRESCALER = PWM_PRESCALER_PRESCALER_DIV_1; // default is 500 hz - pwm->COUNTERTOP = (PWM_MAX_FREQ/500); // default is 500 hz - - pwm->SEQ[0].PTR = (uint32_t) _seq0[i]; - pwm->SEQ[0].CNT = PWM_MAX_CHANNEL; // default mode is Individual --> count must be 4 - pwm->SEQ[0].REFRESH = 0; - pwm->SEQ[0].ENDDELAY = 0; - - pwm->SEQ[1].PTR = 0; - pwm->SEQ[1].CNT = 0; - pwm->SEQ[1].REFRESH = 0; - pwm->SEQ[1].ENDDELAY = 0; - - for(int ch =0; ch < PWM_MAX_CHANNEL; ch++) - { - _seq0[i][ch] = (1UL << 15); // polarity = 0 + self->pwm = NULL; + self->channel = CHANNELS_PER_PWM; // out-of-range value. + bool pwm_already_in_use; + NRF_PWM_Type* pwm; + + for (size_t i = 0 ; i < MP_ARRAY_SIZE(pwms); i++) { + pwm = pwms[i]; + pwm_already_in_use = pwm->ENABLE & SPIM_ENABLE_ENABLE_Msk; + if (pwm_already_in_use) { + if (variable_frequency) { + // Variable frequency requires exclusive use of a PWM, so try the next one. + continue; + } + + // PWM is in use, but see if it's set to the same frequency we need. If so, + // look for a free channel. + if (pwm->COUNTERTOP == countertop && pwm->PRESCALER == base_clock) { + for (size_t chan = 0; chan < CHANNELS_PER_PWM; chan++) { + if (pwm->PSEL.OUT[chan] == 0xFFFFFFFF) { + // Channel is free. + self->pwm = pwm; + self->channel = chan; + break; + } + } + // Did we find a channel? If not, loop and check the next pwm. + if (self->pwm != NULL) { + break; + } + } + } else { + // PWM not yet in use, so we can start to use it. Use channel 0. + self->pwm = pwm; + self->channel = 0; + break; + } } - } -} -void common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self, - const mcu_pin_obj_t* pin, - uint16_t duty, - uint32_t frequency, - bool variable_frequency) { - self->pwm = NULL; - self->pin = pin; - - // check if mapped to PWM channel already - for(int i=0; i<PWM_MAX_MODULE; i++) - { - int ch = pin2channel(pwm_arr[i], pin->number); - if ( ch >= 0 ) - { - self->pwm = pwm_arr[i]; - self->channel = (uint8_t) ch; - break; + if (self->pwm == NULL) { + mp_raise_ValueError(translate("All PWM peripherals are in use")); } - } - // Haven't mapped before - if ( !self->pwm ) - { - find_new_pwm(self); - } + self->pin_number = pin->number; + claim_pin(pin); + + self->frequency = frequency; + self->variable_frequency = variable_frequency; - if (self->pwm) - { - nrf_gpio_cfg_output(pin->number); + // Note this is standard, not strong drive. + nrf_gpio_cfg_output(self->pin_number); // disable before mapping pin channel - self->pwm->ENABLE = 0; + nrf_pwm_disable(pwm); - self->pwm->PSEL.OUT[self->channel] = pin->number; + if (!pwm_already_in_use) { + nrf_pwm_configure(pwm, base_clock, NRF_PWM_MODE_UP, countertop); + } - self->pwm->COUNTERTOP = (PWM_MAX_FREQ/frequency); - self->freq = frequency; - self->variable_freq = variable_frequency; + // Connect channel to pin, without disturbing other channels. + pwm->PSEL.OUT[self->channel] = pin->number; - self->pwm->ENABLE = 1; + nrf_pwm_enable(pwm); common_hal_pulseio_pwmout_set_duty_cycle(self, duty); - } } bool common_hal_pulseio_pwmout_deinited(pulseio_pwmout_obj_t* self) { @@ -185,57 +190,60 @@ bool common_hal_pulseio_pwmout_deinited(pulseio_pwmout_obj_t* self) { } void common_hal_pulseio_pwmout_deinit(pulseio_pwmout_obj_t* self) { - if (common_hal_pulseio_pwmout_deinited(self)) { - return; - } + if (common_hal_pulseio_pwmout_deinited(self)) { + return; + } - self->pwm->ENABLE = 0; + nrf_gpio_cfg_default(self->pin_number); - self->pwm->PSEL.OUT[self->channel] = 0xFFFFFFFFUL; + NRF_PWM_Type* pwm = self->pwm; + self->pwm = NULL; - // re-enable PWM module if there is other active channel - for(int i=0; i < PWM_MAX_CHANNEL; i++) - { - if (self->pwm->PSEL.OUT[i] != 0xFFFFFFFFUL) - { - self->pwm->ENABLE = 1; - break; - } - } + // Disconnect pin from channel. + pwm->PSEL.OUT[self->channel] = 0xFFFFFFFF; - nrf_gpio_cfg_default(self->pin->number); + for(int i=0; i < CHANNELS_PER_PWM; i++) { + if (self->pwm->PSEL.OUT[i] != 0xFFFFFFFF) { + // Some channel is still being used, so don't disable. + return; + } + } - self->pwm = NULL; - self->pin = mp_const_none; + nrf_pwm_disable(pwm); } -void common_hal_pulseio_pwmout_set_duty_cycle(pulseio_pwmout_obj_t* self, uint16_t duty) { - self->duty = duty; +void common_hal_pulseio_pwmout_set_duty_cycle(pulseio_pwmout_obj_t* self, uint16_t duty_cycle) { + self->duty_cycle = duty_cycle; - uint16_t* p_value = ((uint16_t*)self->pwm->SEQ[0].PTR) + self->channel; - *p_value = ((duty * self->pwm->COUNTERTOP) / 0xFFFF) | (1 << 15); + uint16_t* p_value = ((uint16_t*)self->pwm->SEQ[0].PTR) + self->channel; + *p_value = ((duty_cycle * self->pwm->COUNTERTOP) / 0xFFFF) | (1 << 15); - self->pwm->TASKS_SEQSTART[0] = 1; + self->pwm->TASKS_SEQSTART[0] = 1; } uint16_t common_hal_pulseio_pwmout_get_duty_cycle(pulseio_pwmout_obj_t* self) { - return self->duty; + return self->duty_cycle; } void common_hal_pulseio_pwmout_set_frequency(pulseio_pwmout_obj_t* self, uint32_t frequency) { - if (frequency == 0 || frequency > 16000000) { - mp_raise_ValueError(translate("Invalid PWM frequency")); - } + // COUNTERTOP is 3..32767, so highest available frequency is PWM_MAX_FREQ / 3. + uint16_t countertop; + nrf_pwm_clk_t base_clock; + if (frequency == 0 || !convert_frequency(frequency, &countertop, &base_clock)) { + mp_raise_ValueError(translate("Invalid PWM frequency")); + } + self->frequency = frequency; - self->freq = frequency; - self->pwm->COUNTERTOP = (PWM_MAX_FREQ/frequency); - self->pwm->TASKS_SEQSTART[0] = 1; + nrf_pwm_configure(self->pwm, base_clock, NRF_PWM_MODE_UP, countertop); + // Set the duty cycle again, because it depends on COUNTERTOP, which probably changed. + // Setting the duty cycle will also do a SEQSTART. + common_hal_pulseio_pwmout_set_duty_cycle(self, self->duty_cycle); } uint32_t common_hal_pulseio_pwmout_get_frequency(pulseio_pwmout_obj_t* self) { - return self->freq; + return self->frequency; } bool common_hal_pulseio_pwmout_get_variable_frequency(pulseio_pwmout_obj_t* self) { - return self->variable_freq; + return self->variable_frequency; } diff --git a/ports/nrf/common-hal/pulseio/PWMOut.h b/ports/nrf/common-hal/pulseio/PWMOut.h index 9de127ac7..a4e58dc1a 100644 --- a/ports/nrf/common-hal/pulseio/PWMOut.h +++ b/ports/nrf/common-hal/pulseio/PWMOut.h @@ -27,19 +27,17 @@ #ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_PULSEIO_PWMOUT_H #define MICROPY_INCLUDED_NRF_COMMON_HAL_PULSEIO_PWMOUT_H -#include "common-hal/microcontroller/Pin.h" - +#include "nrfx_pwm.h" #include "py/obj.h" typedef struct { mp_obj_base_t base; - const mcu_pin_obj_t *pin; NRF_PWM_Type* pwm; - - uint8_t channel; - bool variable_freq; - uint16_t duty; - uint32_t freq; + uint8_t pin_number; + uint8_t channel: 7; + bool variable_frequency: 1; + uint16_t duty_cycle; + uint32_t frequency; } pulseio_pwmout_obj_t; void pwmout_reset(void); diff --git a/ports/nrf/common-hal/pulseio/PulseIn.c b/ports/nrf/common-hal/pulseio/PulseIn.c index 950cc877d..3d6d266af 100644 --- a/ports/nrf/common-hal/pulseio/PulseIn.c +++ b/ports/nrf/common-hal/pulseio/PulseIn.c @@ -28,7 +28,7 @@ #include <stdint.h> -#include "mpconfigport.h" +#include "py/mpconfig.h" #include "py/gc.h" #include "py/runtime.h" diff --git a/ports/nrf/common-hal/pulseio/PulseOut.c b/ports/nrf/common-hal/pulseio/PulseOut.c index 3495f38f7..be5deca9f 100644 --- a/ports/nrf/common-hal/pulseio/PulseOut.c +++ b/ports/nrf/common-hal/pulseio/PulseOut.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2016 Damien P. George + * Copyright (c) 2018 Dan Halbert 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 @@ -28,32 +28,137 @@ #include <stdint.h> -#include "mpconfigport.h" +#include "py/mpconfig.h" +#include "nrf/pins.h" +#include "nrf/timers.h" #include "py/gc.h" #include "py/runtime.h" - #include "shared-bindings/pulseio/PulseOut.h" +#include "shared-bindings/pulseio/PWMOut.h" +#include "supervisor/shared/translate.h" -//void pulse_finish(struct tc_module *const module) { -// -//} +// A single timer is shared amongst all PulseOut objects under the assumption that +// the code is single threaded. +static uint8_t refcount = 0; -void pulseout_reset() { +static nrfx_timer_t *timer = NULL; + +static uint16_t *pulse_array = NULL; +static volatile uint16_t pulse_array_index = 0; +static uint16_t pulse_array_length; + +static void turn_on(pulseio_pulseout_obj_t *pulseout) { + pulseout->pwmout->pwm->PSEL.OUT[0] = pulseout->pwmout->pin_number; +} + +static void turn_off(pulseio_pulseout_obj_t *pulseout) { + // Disconnect pin from PWM. + pulseout->pwmout->pwm->PSEL.OUT[0] = 0xffffffff; + // Make sure pin is low. + nrf_gpio_pin_clear(pulseout->pwmout->pin_number); +} + +static void start_timer(void) { + nrfx_timer_clear(timer); + // true enables interrupt. + nrfx_timer_compare(timer, NRF_TIMER_CC_CHANNEL0, pulse_array[pulse_array_index], true); + nrfx_timer_resume(timer); +} + +static void pulseout_event_handler(nrf_timer_event_t event_type, void *p_context) { + pulseio_pulseout_obj_t *pulseout = (pulseio_pulseout_obj_t*) p_context; + if (event_type != NRF_TIMER_EVENT_COMPARE0) { + // Spurious event. + return; + } + nrfx_timer_pause(timer); + + pulse_array_index++; + // No more pulses. Turn off output and don't restart. + if (pulse_array_index >= pulse_array_length) { + turn_off(pulseout); + return; + } + + // Alternate on and off, starting with on. + if (pulse_array_index % 2 == 0) { + turn_on(pulseout); + } else { + turn_off(pulseout); + } + + // Count up to the next given value. + start_timer(); } -void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t* self, const pulseio_pwmout_obj_t* carrier) { - mp_raise_NotImplementedError(NULL); +void pulseout_reset() { + if (timer != NULL) { + nrf_peripherals_free_timer(timer); + } + refcount = 0; +} + +void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t* self, + const pulseio_pwmout_obj_t* carrier) { + if (refcount == 0) { + timer = nrf_peripherals_allocate_timer(); + if (timer == NULL) { + mp_raise_RuntimeError(translate("All timers in use")); + } + } + refcount++; + + nrfx_timer_config_t timer_config = { + // PulseOut durations are in microseconds, so this is convenient. + .frequency = NRF_TIMER_FREQ_1MHz, + .mode = NRF_TIMER_MODE_TIMER, + .bit_width = NRF_TIMER_BIT_WIDTH_32, + .interrupt_priority = NRFX_TIMER_DEFAULT_CONFIG_IRQ_PRIORITY, + .p_context = self, + }; + + self->pwmout = carrier; + + nrfx_timer_init(timer, &timer_config, &pulseout_event_handler); + turn_off(self); } bool common_hal_pulseio_pulseout_deinited(pulseio_pulseout_obj_t* self) { - return 1; + return self->pwmout == NULL; } void common_hal_pulseio_pulseout_deinit(pulseio_pulseout_obj_t* self) { + if (common_hal_pulseio_pulseout_deinited(self)) { + return; + } + turn_on(self); + self->pwmout = NULL; + refcount--; + if (refcount == 0) { + nrf_peripherals_free_timer(timer); + } } void common_hal_pulseio_pulseout_send(pulseio_pulseout_obj_t* self, uint16_t* pulses, uint16_t length) { + pulse_array = pulses; + pulse_array_index = 0; + pulse_array_length = length; + + nrfx_timer_enable(timer); + + turn_on(self); + // Count up to the next given value. + start_timer(); + + while(pulse_array_index < length) { + // Do other things while we wait. The interrupts will handle sending the + // signal. + #ifdef MICROPY_VM_HOOK_LOOP + MICROPY_VM_HOOK_LOOP + #endif + } + nrfx_timer_disable(timer); } diff --git a/ports/nrf/common-hal/pulseio/PulseOut.h b/ports/nrf/common-hal/pulseio/PulseOut.h index 9a764e302..42ec52e30 100644 --- a/ports/nrf/common-hal/pulseio/PulseOut.h +++ b/ports/nrf/common-hal/pulseio/PulseOut.h @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * Copyright (c) 2018 Dan Halbert 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 @@ -28,13 +28,13 @@ #define MICROPY_INCLUDED_NRF_COMMON_HAL_PULSEIO_PULSEOUT_H #include "common-hal/microcontroller/Pin.h" +#include "common-hal/pulseio/PWMOut.h" #include "py/obj.h" typedef struct { mp_obj_base_t base; -// __IO PORT_PINCFG_Type *pincfg; - uint8_t pin; + const pulseio_pwmout_obj_t *pwmout; } pulseio_pulseout_obj_t; void pulseout_reset(void); diff --git a/ports/nrf/common-hal/supervisor/Runtime.c b/ports/nrf/common-hal/supervisor/Runtime.c index b73a94a1b..feab6987d 100755 --- a/ports/nrf/common-hal/supervisor/Runtime.c +++ b/ports/nrf/common-hal/supervisor/Runtime.c @@ -32,3 +32,7 @@ bool common_hal_get_serial_connected(void) { return (bool) serial_connected(); } +bool common_hal_get_serial_bytes_available(void) { + return (bool) serial_bytes_available(); +} + diff --git a/ports/nrf/common-hal/usb_hid/Device.h b/ports/nrf/common-hal/usb_hid/Device.h deleted file mode 100644 index 612423715..000000000 --- a/ports/nrf/common-hal/usb_hid/Device.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2018 hathach 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 COMMON_HAL_USB_HID_DEVICE_H -#define COMMON_HAL_USB_HID_DEVICE_H - -#include <stdint.h> -#include <stdbool.h> - -#include "py/obj.h" - -#ifdef __cplusplus - extern "C" { -#endif - -// 1 to enable device, 0 to disable -#define USB_HID_DEVICE_KEYBOARD 1 -#define USB_HID_DEVICE_MOUSE 1 -#define USB_HID_DEVICE_CONSUMER 1 -#define USB_HID_DEVICE_SYS_CONTROL 1 -#define USB_HID_DEVICE_GAMEPAD 1 -#define USB_HID_DEVICE_DIGITIZER 0 // not supported yet - -enum { - USB_HID_REPORT_ID_UNUSED = 0, - -#if USB_HID_DEVICE_KEYBOARD - USB_HID_REPORT_ID_KEYBOARD, -#endif - -#if USB_HID_DEVICE_MOUSE - USB_HID_REPORT_ID_MOUSE, -#endif - -#if USB_HID_DEVICE_CONSUMER - USB_HID_REPORT_ID_CONSUMER, -#endif - -#if USB_HID_DEVICE_SYS_CONTROL - USB_HID_REPORT_ID_SYS_CONTROL, -#endif - -#if USB_HID_DEVICE_GAMEPAD - USB_HID_REPORT_ID_GAMEPAD, -#endif - -#if USB_HID_DEVICE_DIGITIZER - USB_HID_REPORT_ID_DIGITIZER, -#endif -}; - -#define USB_HID_NUM_DEVICES (USB_HID_DEVICE_KEYBOARD + USB_HID_DEVICE_MOUSE + USB_HID_DEVICE_CONSUMER + \ - USB_HID_DEVICE_SYS_CONTROL + USB_HID_DEVICE_GAMEPAD + USB_HID_DEVICE_DIGITIZER ) - -typedef struct { - mp_obj_base_t base; - uint8_t* report_buffer; - uint8_t report_id; - uint8_t report_length; - uint8_t usage_page; - uint8_t usage; -} usb_hid_device_obj_t; - - -extern usb_hid_device_obj_t usb_hid_devices[]; - -#ifdef __cplusplus - } -#endif - -#endif /* COMMON_HAL_USB_HID_DEVICE_H */ diff --git a/ports/nrf/drivers/bluetooth/ble_drv.c b/ports/nrf/drivers/bluetooth/ble_drv.c deleted file mode 100644 index 7e95c2eab..000000000 --- a/ports/nrf/drivers/bluetooth/ble_drv.c +++ /dev/null @@ -1,1117 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2016 Glenn Ruben Bakke - * - * 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. - */ - -#if BLUETOOTH_SD - -#include <stdio.h> -#include <string.h> -#include <stdbool.h> - -#if (BLUETOOTH_SD == 132) -#define NRF52 // Needed for SD132 v2 -#endif - -#include "py/runtime.h" -#include "supervisor/shared/translate.h" -#include "ble_drv.h" -#include "mpconfigport.h" -#include "nrf_sdm.h" -#include "nrfx_power.h" -#include "ble_gap.h" -#include "ble.h" // sd_ble_uuid_encode - - -#define BLE_DRIVER_VERBOSE 0 -#if BLE_DRIVER_VERBOSE -#define BLE_DRIVER_LOG printf -#else -#define BLE_DRIVER_LOG(...) -#endif - -#define BLE_ADV_LENGTH_FIELD_SIZE 1 -#define BLE_ADV_AD_TYPE_FIELD_SIZE 1 -#define BLE_AD_TYPE_FLAGS_DATA_SIZE 1 - -#define MSEC_TO_UNITS(TIME, RESOLUTION) (((TIME) * 1000) / (RESOLUTION)) -#define UNIT_0_625_MS (625) -#define UNIT_10_MS (10000) -#define APP_CFG_NON_CONN_ADV_TIMEOUT 0 // Disable timeout. -#define NON_CONNECTABLE_ADV_INTERVAL MSEC_TO_UNITS(100, UNIT_0_625_MS) - -#define BLE_MIN_CONN_INTERVAL MSEC_TO_UNITS(12, UNIT_0_625_MS) -#define BLE_MAX_CONN_INTERVAL MSEC_TO_UNITS(12, UNIT_0_625_MS) -#define BLE_SLAVE_LATENCY 0 -#define BLE_CONN_SUP_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS) - -#ifndef BLE_GAP_ADV_MAX_SIZE -#define BLE_GAP_ADV_MAX_SIZE 31 -#endif - -#define SD_TEST_OR_ENABLE() \ -if (ble_drv_stack_enabled() == 0) { \ - (void)ble_drv_stack_enable(); \ -} - -static volatile bool m_adv_in_progress; -static volatile bool m_tx_in_progress; - -static ble_drv_gap_evt_callback_t gap_event_handler; -static ble_drv_gatts_evt_callback_t gatts_event_handler; - -static mp_obj_t mp_gap_observer; -static mp_obj_t mp_gatts_observer; - -static volatile bool m_primary_service_found; -static volatile bool m_characteristic_found; -static volatile bool m_write_done; - -static volatile ble_drv_adv_evt_callback_t adv_event_handler; -static volatile ble_drv_gattc_evt_callback_t gattc_event_handler; -static volatile ble_drv_disc_add_service_callback_t disc_add_service_handler; -static volatile ble_drv_disc_add_char_callback_t disc_add_char_handler; -static volatile ble_drv_gattc_char_data_callback_t gattc_char_data_handle; - -static mp_obj_t mp_adv_observer; -static mp_obj_t mp_gattc_observer; -static mp_obj_t mp_gattc_disc_service_observer; -static mp_obj_t mp_gattc_disc_char_observer; -static mp_obj_t mp_gattc_char_data_observer; - -#if (BLUETOOTH_SD == 140) -static uint8_t m_adv_handle = BLE_GAP_ADV_SET_HANDLE_NOT_SET; -static uint8_t m_scan_buffer_data[BLE_GAP_SCAN_BUFFER_MIN]; - -static ble_data_t m_scan_buffer = -{ - m_scan_buffer_data, - BLE_GAP_SCAN_BUFFER_MIN -}; -#endif - -#include "nrf_nvic.h" - -nrf_nvic_state_t nrf_nvic_state = {0}; - -void softdevice_assert_handler(uint32_t id, uint32_t pc, uint32_t info) { - BLE_DRIVER_LOG("ERROR: SoftDevice assert!!!"); -} - -uint32_t ble_drv_stack_enable(void) { - m_adv_in_progress = false; - m_tx_in_progress = false; - -#if BLUETOOTH_LFCLK_RC - nrf_clock_lf_cfg_t clock_config = { - .source = NRF_CLOCK_LF_SRC_RC, - .rc_ctiv = 16, - .rc_temp_ctiv = 2, -#if (BLE_API_VERSION == 4) - .accuracy = 0 -#else - .xtal_accuracy = 0 -#endif - }; -#else - nrf_clock_lf_cfg_t clock_config = { - .source = NRF_CLOCK_LF_SRC_XTAL, - .rc_ctiv = 0, - .rc_temp_ctiv = 0, -#if (BLE_API_VERSION == 4) - .accuracy = NRF_CLOCK_LF_ACCURACY_20_PPM -#else - .xtal_accuracy = NRF_CLOCK_LF_XTAL_ACCURACY_20_PPM -#endif - }; -#endif - -#if (BLUETOOTH_SD == 140) - // The SD takes over the POWER IRQ and will fail if the IRQ is already in use - nrfx_power_uninit(); -#endif - - uint32_t err_code = sd_softdevice_enable(&clock_config, - softdevice_assert_handler); - - BLE_DRIVER_LOG("SoftDevice enable status: " UINT_FMT "\n", (uint16_t)err_code); - - err_code = sd_nvic_EnableIRQ(SWI2_EGU2_IRQn); - - BLE_DRIVER_LOG("IRQ enable status: " UINT_FMT "\n", (uint16_t)err_code); - - // Enable BLE stack. -#if (BLE_API_VERSION == 2) - ble_enable_params_t ble_enable_params; - memset(&ble_enable_params, 0x00, sizeof(ble_enable_params)); - ble_enable_params.gatts_enable_params.attr_tab_size = BLE_GATTS_ATTR_TAB_SIZE_DEFAULT; - ble_enable_params.gatts_enable_params.service_changed = 0; - ble_enable_params.gap_enable_params.periph_conn_count = 1; - ble_enable_params.gap_enable_params.central_conn_count = 1; -#endif - -#if (BLE_API_VERSION == 2) - uint32_t app_ram_start = 0x200039c0; - err_code = sd_ble_enable(&ble_enable_params, &app_ram_start); // 8K SD headroom from linker script. - BLE_DRIVER_LOG("BLE ram size: " UINT_FMT "\n", (uint16_t)app_ram_start); -#else - uint32_t app_ram_start = 0x20004000; - err_code = sd_ble_enable(&app_ram_start); - BLE_DRIVER_LOG("BLE ram size: " UINT_FMT "\n", (uint16_t)app_ram_start); -#endif - - - BLE_DRIVER_LOG("BLE enable status: " UINT_FMT "\n", (uint16_t)err_code); - - // set up security mode - ble_gap_conn_params_t gap_conn_params; - ble_gap_conn_sec_mode_t sec_mode; - - BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); - - const char device_name[] = "micr"; - - if ((err_code = sd_ble_gap_device_name_set(&sec_mode, - (const uint8_t *)device_name, - strlen(device_name))) != 0) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - translate("Cannot apply GAP parameters."))); - } - - // set connection parameters - memset(&gap_conn_params, 0, sizeof(gap_conn_params)); - - gap_conn_params.min_conn_interval = BLE_MIN_CONN_INTERVAL; - gap_conn_params.max_conn_interval = BLE_MAX_CONN_INTERVAL; - gap_conn_params.slave_latency = BLE_SLAVE_LATENCY; - gap_conn_params.conn_sup_timeout = BLE_CONN_SUP_TIMEOUT; - - if (sd_ble_gap_ppcp_set(&gap_conn_params) != 0) { - - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - translate("Cannot set PPCP parameters."))); - } - - return err_code; -} - -void ble_drv_stack_disable(void) { - sd_softdevice_disable(); -} - -uint8_t ble_drv_stack_enabled(void) { - uint8_t is_enabled; - uint32_t err_code = sd_softdevice_is_enabled(&is_enabled); - (void)err_code; - - BLE_DRIVER_LOG("Is enabled status: " UINT_FMT "\n", (uint16_t)err_code); - - return is_enabled; -} - -void ble_drv_address_get(ble_drv_addr_t * p_addr) { - SD_TEST_OR_ENABLE(); - - ble_gap_addr_t local_ble_addr; -#if (BLE_API_VERSION == 2) - uint32_t err_code = sd_ble_gap_address_get(&local_ble_addr); -#else - uint32_t err_code = sd_ble_gap_addr_get(&local_ble_addr); -#endif - - if (err_code != 0) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - translate("Can not query for the device address."))); - } - - BLE_DRIVER_LOG("ble address, type: " HEX2_FMT ", " \ - "address: " HEX2_FMT ":" HEX2_FMT ":" HEX2_FMT ":" \ - HEX2_FMT ":" HEX2_FMT ":" HEX2_FMT "\n", \ - local_ble_addr.addr_type, \ - local_ble_addr.addr[5], local_ble_addr.addr[4], local_ble_addr.addr[3], \ - local_ble_addr.addr[2], local_ble_addr.addr[1], local_ble_addr.addr[0]); - - p_addr->addr_type = local_ble_addr.addr_type; - memcpy(p_addr->addr, local_ble_addr.addr, 6); -} - -bool ble_drv_uuid_add_vs(uint8_t * p_uuid, uint8_t * idx) { - SD_TEST_OR_ENABLE(); - - if (sd_ble_uuid_vs_add((ble_uuid128_t const *)p_uuid, idx) != 0) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - translate("Can not add Vendor Specific 128-bit UUID."))); - } - - return true; -} - -bool ble_drv_service_add(ubluepy_service_obj_t * p_service_obj) { - SD_TEST_OR_ENABLE(); - - if (p_service_obj->p_uuid->type > BLE_UUID_TYPE_BLE) { - - ble_uuid_t uuid; - uuid.type = p_service_obj->p_uuid->uuid_vs_idx; - uuid.uuid = p_service_obj->p_uuid->value[0]; - uuid.uuid += p_service_obj->p_uuid->value[1] << 8; - - if (sd_ble_gatts_service_add(p_service_obj->type, - &uuid, - &p_service_obj->handle) != 0) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - translate("Can not add Service."))); - } - } else if (p_service_obj->p_uuid->type == BLE_UUID_TYPE_BLE) { - BLE_DRIVER_LOG("adding service\n"); - - ble_uuid_t uuid; - uuid.type = p_service_obj->p_uuid->type; - uuid.uuid = p_service_obj->p_uuid->value[0]; - uuid.uuid += p_service_obj->p_uuid->value[1] << 8; - - if (sd_ble_gatts_service_add(p_service_obj->type, - &uuid, - &p_service_obj->handle) != 0) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - translate("Can not add Service."))); - } - } - return true; -} - -bool ble_drv_characteristic_add(ubluepy_characteristic_obj_t * p_char_obj) { - ble_gatts_char_md_t char_md; - ble_gatts_attr_md_t cccd_md; - ble_gatts_attr_t attr_char_value; - ble_uuid_t uuid; - ble_gatts_attr_md_t attr_md; - - memset(&char_md, 0, sizeof(char_md)); - - char_md.char_props.broadcast = (p_char_obj->props & UBLUEPY_PROP_BROADCAST) ? 1 : 0; - char_md.char_props.read = (p_char_obj->props & UBLUEPY_PROP_READ) ? 1 : 0; - char_md.char_props.write_wo_resp = (p_char_obj->props & UBLUEPY_PROP_WRITE_WO_RESP) ? 1 : 0; - char_md.char_props.write = (p_char_obj->props & UBLUEPY_PROP_WRITE) ? 1 : 0; - char_md.char_props.notify = (p_char_obj->props & UBLUEPY_PROP_NOTIFY) ? 1 : 0; - char_md.char_props.indicate = (p_char_obj->props & UBLUEPY_PROP_INDICATE) ? 1 : 0; -#if 0 - char_md.char_props.auth_signed_wr = (p_char_obj->props & UBLUEPY_PROP_NOTIFY) ? 1 : 0; -#endif - - - char_md.p_char_user_desc = NULL; - char_md.p_char_pf = NULL; - char_md.p_user_desc_md = NULL; - char_md.p_sccd_md = NULL; - - // if cccd - if (p_char_obj->attrs & UBLUEPY_ATTR_CCCD) { - memset(&cccd_md, 0, sizeof(cccd_md)); - BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm); - BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm); - cccd_md.vloc = BLE_GATTS_VLOC_STACK; - char_md.p_cccd_md = &cccd_md; - } else { - char_md.p_cccd_md = NULL; - } - - uuid.type = p_char_obj->p_uuid->type; - uuid.uuid = p_char_obj->p_uuid->value[0]; - uuid.uuid += p_char_obj->p_uuid->value[1] << 8; - - memset(&attr_md, 0, sizeof(attr_md)); - - BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm); - BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm); - - attr_md.vloc = BLE_GATTS_VLOC_STACK; - attr_md.rd_auth = 0; - attr_md.wr_auth = 0; - attr_md.vlen = 1; - - memset(&attr_char_value, 0, sizeof(attr_char_value)); - - attr_char_value.p_uuid = &uuid; - attr_char_value.p_attr_md = &attr_md; - attr_char_value.init_len = sizeof(uint8_t); - attr_char_value.init_offs = 0; -#if (BLE_API_VERSION == 2) - attr_char_value.max_len = (GATT_MTU_SIZE_DEFAULT - 3); -#else - attr_char_value.max_len = (BLE_GATT_ATT_MTU_DEFAULT - 3); -#endif - - ble_gatts_char_handles_t handles; - - if (sd_ble_gatts_characteristic_add(p_char_obj->service_handle, - &char_md, - &attr_char_value, - &handles) != 0) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - translate("Can not add Characteristic."))); - } - - // apply handles to object instance - p_char_obj->handle = handles.value_handle; - p_char_obj->user_desc_handle = handles.user_desc_handle; - p_char_obj->cccd_handle = handles.cccd_handle; - p_char_obj->sccd_handle = handles.sccd_handle; - - return true; -} - -bool ble_drv_advertise_data(ubluepy_advertise_data_t * p_adv_params) { - SD_TEST_OR_ENABLE(); - - uint8_t byte_pos = 0; - uint8_t adv_data[BLE_GAP_ADV_MAX_SIZE]; - - if (p_adv_params->device_name_len > 0) { - ble_gap_conn_sec_mode_t sec_mode; - - BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); - - if (sd_ble_gap_device_name_set(&sec_mode, - p_adv_params->p_device_name, - p_adv_params->device_name_len) != 0) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - translate("Can not apply device name in the stack."))); - } - - BLE_DRIVER_LOG("Device name applied\n"); - - adv_data[byte_pos] = (BLE_ADV_AD_TYPE_FIELD_SIZE + p_adv_params->device_name_len); - byte_pos += BLE_ADV_LENGTH_FIELD_SIZE; - adv_data[byte_pos] = BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME; - byte_pos += BLE_ADV_AD_TYPE_FIELD_SIZE; - memcpy(&adv_data[byte_pos], p_adv_params->p_device_name, p_adv_params->device_name_len); - // increment position counter to see if it fits, and in case more content should - // follow in this adv packet. - byte_pos += p_adv_params->device_name_len; - } - - // Add FLAGS only if manually controlled data has not been used. - if (p_adv_params->data_len == 0) { - // set flags, default to disc mode - adv_data[byte_pos] = (BLE_ADV_AD_TYPE_FIELD_SIZE + BLE_AD_TYPE_FLAGS_DATA_SIZE); - byte_pos += BLE_ADV_LENGTH_FIELD_SIZE; - adv_data[byte_pos] = BLE_GAP_AD_TYPE_FLAGS; - byte_pos += BLE_AD_TYPE_FLAGS_DATA_SIZE; - adv_data[byte_pos] = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE; - byte_pos += 1; - } - - if (p_adv_params->num_of_services > 0) { - - bool type_16bit_present = false; - bool type_128bit_present = false; - - for (uint8_t i = 0; i < p_adv_params->num_of_services; i++) { - ubluepy_service_obj_t * p_service = (ubluepy_service_obj_t *)p_adv_params->p_services[i]; - if (p_service->p_uuid->type == UBLUEPY_UUID_16_BIT) { - type_16bit_present = true; - } - - if (p_service->p_uuid->type == UBLUEPY_UUID_128_BIT) { - type_128bit_present = true; - } - } - - if (type_16bit_present) { - uint8_t size_byte_pos = byte_pos; - - // skip length byte for now, apply total length post calculation - byte_pos += BLE_ADV_LENGTH_FIELD_SIZE; - - adv_data[byte_pos] = BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE; - byte_pos += BLE_ADV_AD_TYPE_FIELD_SIZE; - - uint8_t uuid_total_size = 0; - uint8_t encoded_size = 0; - - for (uint8_t i = 0; i < p_adv_params->num_of_services; i++) { - ubluepy_service_obj_t * p_service = (ubluepy_service_obj_t *)p_adv_params->p_services[i]; - - ble_uuid_t uuid; - uuid.type = p_service->p_uuid->type; - uuid.uuid = p_service->p_uuid->value[0]; - uuid.uuid += p_service->p_uuid->value[1] << 8; - // calculate total size of uuids - if (sd_ble_uuid_encode(&uuid, &encoded_size, NULL) != 0) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - translate("Can not encode UUID, to check length."))); - } - - // do encoding into the adv buffer - if (sd_ble_uuid_encode(&uuid, &encoded_size, &adv_data[byte_pos]) != 0) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - translate("Can encode UUID into the advertisment packet."))); - } - - BLE_DRIVER_LOG("encoded uuid for service %u: ", 0); - for (uint8_t j = 0; j < encoded_size; j++) { - BLE_DRIVER_LOG(HEX2_FMT " ", adv_data[byte_pos + j]); - } - BLE_DRIVER_LOG("\n"); - - uuid_total_size += encoded_size; // size of entry - byte_pos += encoded_size; // relative to adv data packet - BLE_DRIVER_LOG("ADV: uuid size: %u, type: %u, uuid: %x%x, vs_idx: %u\n", - encoded_size, p_service->p_uuid->type, - p_service->p_uuid->value[1], - p_service->p_uuid->value[0], - p_service->p_uuid->uuid_vs_idx); - } - - adv_data[size_byte_pos] = (BLE_ADV_AD_TYPE_FIELD_SIZE + uuid_total_size); - } - - if (type_128bit_present) { - uint8_t size_byte_pos = byte_pos; - - // skip length byte for now, apply total length post calculation - byte_pos += BLE_ADV_LENGTH_FIELD_SIZE; - - adv_data[byte_pos] = BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE; - byte_pos += BLE_ADV_AD_TYPE_FIELD_SIZE; - - uint8_t uuid_total_size = 0; - uint8_t encoded_size = 0; - - for (uint8_t i = 0; i < p_adv_params->num_of_services; i++) { - ubluepy_service_obj_t * p_service = (ubluepy_service_obj_t *)p_adv_params->p_services[i]; - - ble_uuid_t uuid; - uuid.type = p_service->p_uuid->uuid_vs_idx; - uuid.uuid = p_service->p_uuid->value[0]; - uuid.uuid += p_service->p_uuid->value[1] << 8; - - // calculate total size of uuids - if (sd_ble_uuid_encode(&uuid, &encoded_size, NULL) != 0) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - translate("Can not encode UUID, to check length."))); - } - - // do encoding into the adv buffer - if (sd_ble_uuid_encode(&uuid, &encoded_size, &adv_data[byte_pos]) != 0) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - translate("Can encode UUID into the advertisment packet."))); - } - - BLE_DRIVER_LOG("encoded uuid for service %u: ", 0); - for (uint8_t j = 0; j < encoded_size; j++) { - BLE_DRIVER_LOG(HEX2_FMT " ", adv_data[byte_pos + j]); - } - BLE_DRIVER_LOG("\n"); - - uuid_total_size += encoded_size; // size of entry - byte_pos += encoded_size; // relative to adv data packet - BLE_DRIVER_LOG("ADV: uuid size: %u, type: %x%x, uuid: %u, vs_idx: %u\n", - encoded_size, p_service->p_uuid->type, - p_service->p_uuid->value[1], - p_service->p_uuid->value[0], - p_service->p_uuid->uuid_vs_idx); - } - - adv_data[size_byte_pos] = (BLE_ADV_AD_TYPE_FIELD_SIZE + uuid_total_size); - } - } - - if ((p_adv_params->data_len > 0) && (p_adv_params->p_data != NULL)) { - if (p_adv_params->data_len + byte_pos > BLE_GAP_ADV_MAX_SIZE) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - translate("Can not fit data into the advertisment packet."))); - } - - memcpy(adv_data, p_adv_params->p_data, p_adv_params->data_len); - byte_pos += p_adv_params->data_len; - } - - // scan response data not set - uint32_t err_code; -#if (BLUETOOTH_SD == 132) - if ((err_code = sd_ble_gap_adv_data_set(adv_data, byte_pos, NULL, 0)) != 0) { - - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - translate("Can not apply advertisment data. status: 0x%02x"), (uint16_t)err_code)); - } - BLE_DRIVER_LOG("Set Adv data size: " UINT_FMT "\n", byte_pos); -#endif - - static ble_gap_adv_params_t m_adv_params; - - // initialize advertising params - memset(&m_adv_params, 0, sizeof(m_adv_params)); - if (p_adv_params->connectable) { -#if (BLUETOOTH_SD == 140) - m_adv_params.properties.type = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED; -#else - m_adv_params.type = BLE_GAP_ADV_TYPE_ADV_IND; -#endif - } else { -#if (BLUETOOTH_SD == 140) - m_adv_params.properties.type = BLE_GAP_ADV_TYPE_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED; -#else - m_adv_params.type = BLE_GAP_ADV_TYPE_ADV_NONCONN_IND; -#endif - } - - m_adv_params.p_peer_addr = NULL; // undirected advertisement - m_adv_params.interval = MSEC_TO_UNITS(100, UNIT_0_625_MS); // approx 8 ms -#if (BLUETOOTH_SD == 140) - m_adv_params.duration = BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED; - m_adv_params.filter_policy = BLE_GAP_ADV_FP_ANY; - m_adv_params.primary_phy = BLE_GAP_PHY_1MBPS; -#else - m_adv_params.fp = BLE_GAP_ADV_FP_ANY; - m_adv_params.timeout = 0; // infinite advertisment -#endif - - ble_drv_advertise_stop(); - -#if (BLUETOOTH_SD == 140) - const ble_gap_adv_data_t ble_gap_adv_data = { - .adv_data = { - .p_data = adv_data, - .len = byte_pos - } - }; - - if ((err_code = sd_ble_gap_adv_set_configure(&m_adv_handle, &ble_gap_adv_data, &m_adv_params)) != 0) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - translate("Can not apply advertisment data. status: 0x%02x"), (uint16_t)err_code)); - } - err_code = sd_ble_gap_adv_start(m_adv_handle, BLE_CONN_CFG_TAG_DEFAULT); -#elif (BLUETOOTH_SD == 132 && BLE_API_VERSION == 4) - err_code = sd_ble_gap_adv_start(&m_adv_params, BLE_CONN_CFG_TAG_DEFAULT); -#else - err_code = sd_ble_gap_adv_start(&m_adv_params); -#endif - if (err_code != 0) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - translate("Can not start advertisment. status: 0x%02x"), (uint16_t)err_code)); - } - - m_adv_in_progress = true; - - return true; -} - -void ble_drv_advertise_stop(void) { - if (m_adv_in_progress == true) { - uint32_t err_code; -#if (BLUETOOTH_SD == 140) - if ((err_code = sd_ble_gap_adv_stop(m_adv_handle)) != 0) { -#else - if ((err_code = sd_ble_gap_adv_stop()) != 0) { -#endif - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - translate("Can not stop advertisment. status: 0x%02x"), (uint16_t)err_code)); - } - } - m_adv_in_progress = false; -} - -void ble_drv_attr_s_read(uint16_t conn_handle, uint16_t handle, uint16_t len, uint8_t * p_data) { - ble_gatts_value_t gatts_value; - memset(&gatts_value, 0, sizeof(gatts_value)); - - gatts_value.len = len; - gatts_value.offset = 0; - gatts_value.p_value = p_data; - - uint32_t err_code = sd_ble_gatts_value_get(conn_handle, - handle, - &gatts_value); - if (err_code != 0) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - translate("Can not read attribute value. status: 0x%02x"), (uint16_t)err_code)); - } - -} - -void ble_drv_attr_s_write(uint16_t conn_handle, uint16_t handle, uint16_t len, uint8_t * p_data) { - ble_gatts_value_t gatts_value; - memset(&gatts_value, 0, sizeof(gatts_value)); - - gatts_value.len = len; - gatts_value.offset = 0; - gatts_value.p_value = p_data; - - uint32_t err_code = sd_ble_gatts_value_set(conn_handle, handle, &gatts_value); - - if (err_code != 0) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - translate("Can not write attribute value. status: 0x%02x"), (uint16_t)err_code)); - } -} - -void ble_drv_attr_s_notify(uint16_t conn_handle, uint16_t handle, uint16_t len, uint8_t * p_data) { - uint16_t hvx_len = len; - ble_gatts_hvx_params_t hvx_params; - - memset(&hvx_params, 0, sizeof(hvx_params)); - - hvx_params.handle = handle; - hvx_params.type = BLE_GATT_HVX_NOTIFICATION; - hvx_params.offset = 0; - hvx_params.p_len = &hvx_len; - hvx_params.p_data = p_data; - - while (m_tx_in_progress) { - ; - } - - m_tx_in_progress = true; - uint32_t err_code; - if ((err_code = sd_ble_gatts_hvx(conn_handle, &hvx_params)) != 0) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - translate("Can not notify attribute value. status: 0x%02x"), (uint16_t)err_code)); - } -} - -void ble_drv_gap_event_handler_set(mp_obj_t obj, ble_drv_gap_evt_callback_t evt_handler) { - mp_gap_observer = obj; - gap_event_handler = evt_handler; -} - -void ble_drv_gatts_event_handler_set(mp_obj_t obj, ble_drv_gatts_evt_callback_t evt_handler) { - mp_gatts_observer = obj; - gatts_event_handler = evt_handler; -} - -void ble_drv_gattc_event_handler_set(mp_obj_t obj, ble_drv_gattc_evt_callback_t evt_handler) { - mp_gattc_observer = obj; - gattc_event_handler = evt_handler; -} - -void ble_drv_adv_report_handler_set(mp_obj_t obj, ble_drv_adv_evt_callback_t evt_handler) { - mp_adv_observer = obj; - adv_event_handler = evt_handler; -} - - -void ble_drv_attr_c_read(uint16_t conn_handle, uint16_t handle, mp_obj_t obj, ble_drv_gattc_char_data_callback_t cb) { - - mp_gattc_char_data_observer = obj; - gattc_char_data_handle = cb; - - uint32_t err_code = sd_ble_gattc_read(conn_handle, - handle, - 0); - if (err_code != 0) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - translate("Can not read attribute value. status: 0x%02x"), (uint16_t)err_code)); - } - - while (gattc_char_data_handle != NULL) { - ; - } -} - -void ble_drv_attr_c_write(uint16_t conn_handle, uint16_t handle, uint16_t len, uint8_t * p_data, bool w_response) { - - ble_gattc_write_params_t write_params; - - if (w_response) { - write_params.write_op = BLE_GATT_OP_WRITE_REQ; - } else { - write_params.write_op = BLE_GATT_OP_WRITE_CMD; - } - - write_params.flags = BLE_GATT_EXEC_WRITE_FLAG_PREPARED_CANCEL; - write_params.handle = handle; - write_params.offset = 0; - write_params.len = len; - write_params.p_value = p_data; - - m_write_done = !w_response; - - uint32_t err_code = sd_ble_gattc_write(conn_handle, &write_params); - - if (err_code != 0) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - translate("Can not write attribute value. status: 0x%02x"), (uint16_t)err_code)); - } - - while (m_write_done != true) { - ; - } -} -void ble_drv_scan_start(void) { - SD_TEST_OR_ENABLE(); - - ble_gap_scan_params_t scan_params; - memset(&scan_params, 0, sizeof(ble_gap_scan_params_t)); - - scan_params.active = 1; - scan_params.interval = MSEC_TO_UNITS(100, UNIT_0_625_MS); - scan_params.window = MSEC_TO_UNITS(100, UNIT_0_625_MS); -#if (BLUETOOTH_SD == 140) - scan_params.scan_phys = BLE_GAP_PHY_1MBPS; -#endif - scan_params.timeout = 0; // Infinite - - uint32_t err_code; -#if (BLUETOOTH_SD == 140) - if ((err_code = sd_ble_gap_scan_start(&scan_params, &m_scan_buffer)) != 0) { -#else - if ((err_code = sd_ble_gap_scan_start(&scan_params)) != 0) { -#endif - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - translate("Can not start scanning. status: 0x%02x"), (uint16_t)err_code)); - } -} - -void ble_drv_scan_stop(void) { - sd_ble_gap_scan_stop(); -} - -void ble_drv_connect(uint8_t * p_addr, uint8_t addr_type) { - SD_TEST_OR_ENABLE(); - - ble_gap_scan_params_t scan_params; - scan_params.active = 1; - scan_params.interval = MSEC_TO_UNITS(100, UNIT_0_625_MS); - scan_params.window = MSEC_TO_UNITS(100, UNIT_0_625_MS); - scan_params.timeout = 0; // Infinite - - ble_gap_addr_t addr; - memset(&addr, 0, sizeof(addr)); - - addr.addr_type = addr_type; - memcpy(addr.addr, p_addr, 6); - - BLE_DRIVER_LOG("GAP CONNECTING: "HEX2_FMT":"HEX2_FMT":"HEX2_FMT":"HEX2_FMT":"HEX2_FMT":"HEX2_FMT", type: %d\n", - addr.addr[0], addr.addr[1], addr.addr[2], addr.addr[3], addr.addr[4], addr.addr[5], addr.addr_type); - - ble_gap_conn_params_t conn_params; - -// (void)sd_ble_gap_ppcp_get(&conn_params); - - // set connection parameters - memset(&conn_params, 0, sizeof(conn_params)); - - conn_params.min_conn_interval = BLE_MIN_CONN_INTERVAL; - conn_params.max_conn_interval = BLE_MAX_CONN_INTERVAL; - conn_params.slave_latency = BLE_SLAVE_LATENCY; - conn_params.conn_sup_timeout = BLE_CONN_SUP_TIMEOUT; - - uint32_t err_code; -#if (BLE_API_VERSION == 2) - if ((err_code = sd_ble_gap_connect(&addr, &scan_params, &conn_params)) != 0) { -#else - if ((err_code = sd_ble_gap_connect(&addr, &scan_params, &conn_params, BLE_CONN_CFG_TAG_DEFAULT)) != 0) { -#endif - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - translate("Can not connect. status: 0x%02x"), (uint16_t)err_code)); - } -} - -bool ble_drv_discover_services(mp_obj_t obj, uint16_t conn_handle, uint16_t start_handle, ble_drv_disc_add_service_callback_t cb) { - BLE_DRIVER_LOG("Discover primary services. Conn handle: 0x" HEX2_FMT "\n", - conn_handle); - - mp_gattc_disc_service_observer = obj; - disc_add_service_handler = cb; - - m_primary_service_found = false; - - uint32_t err_code; - err_code = sd_ble_gattc_primary_services_discover(conn_handle, - start_handle, - NULL); - if (err_code != 0) { - return false; - } - - // busy loop until last service has been iterated - while (disc_add_service_handler != NULL) { - ; - } - - if (m_primary_service_found) { - return true; - } else { - return false; - } -} - -bool ble_drv_discover_characteristic(mp_obj_t obj, - uint16_t conn_handle, - uint16_t start_handle, - uint16_t end_handle, - ble_drv_disc_add_char_callback_t cb) { - BLE_DRIVER_LOG("Discover characteristicts. Conn handle: 0x" HEX2_FMT "\n", - conn_handle); - - mp_gattc_disc_char_observer = obj; - disc_add_char_handler = cb; - - ble_gattc_handle_range_t handle_range; - handle_range.start_handle = start_handle; - handle_range.end_handle = end_handle; - - m_characteristic_found = false; - - uint32_t err_code; - err_code = sd_ble_gattc_characteristics_discover(conn_handle, &handle_range); - if (err_code != 0) { - return false; - } - - // busy loop until last service has been iterated - while (disc_add_char_handler != NULL) { - ; - } - - if (m_characteristic_found) { - return true; - } else { - return false; - } -} - -void ble_drv_discover_descriptors(void) { - -} - -static void ble_evt_handler(ble_evt_t * p_ble_evt) { -// S132 event ranges. -// Common 0x01 -> 0x0F -// GAP 0x10 -> 0x2F -// GATTC 0x30 -> 0x4F -// GATTS 0x50 -> 0x6F -// L2CAP 0x70 -> 0x8F - switch (p_ble_evt->header.evt_id) { - case BLE_GAP_EVT_CONNECTED: - BLE_DRIVER_LOG("GAP CONNECT\n"); - m_adv_in_progress = false; - gap_event_handler(mp_gap_observer, p_ble_evt->header.evt_id, p_ble_evt->evt.gap_evt.conn_handle, p_ble_evt->header.evt_len - (2 * sizeof(uint16_t)), NULL); - - ble_gap_conn_params_t conn_params; - (void)sd_ble_gap_ppcp_get(&conn_params); - (void)sd_ble_gap_conn_param_update(p_ble_evt->evt.gap_evt.conn_handle, &conn_params); - break; - - case BLE_GAP_EVT_DISCONNECTED: - BLE_DRIVER_LOG("GAP DISCONNECT\n"); - gap_event_handler(mp_gap_observer, p_ble_evt->header.evt_id, p_ble_evt->evt.gap_evt.conn_handle, p_ble_evt->header.evt_len - (2 * sizeof(uint16_t)), NULL); - break; - - case BLE_GATTS_EVT_HVC: - gatts_event_handler(mp_gatts_observer, p_ble_evt->header.evt_id, p_ble_evt->evt.gatts_evt.params.hvc.handle, p_ble_evt->header.evt_len - (2 * sizeof(uint16_t)), NULL); - break; - - case BLE_GATTS_EVT_WRITE: - BLE_DRIVER_LOG("GATTS write\n"); - - uint16_t handle = p_ble_evt->evt.gatts_evt.params.write.handle; - uint16_t data_len = p_ble_evt->evt.gatts_evt.params.write.len; - uint8_t * p_data = &p_ble_evt->evt.gatts_evt.params.write.data[0]; - - gatts_event_handler(mp_gatts_observer, p_ble_evt->header.evt_id, handle, data_len, p_data); - break; - - case BLE_GAP_EVT_CONN_PARAM_UPDATE: - BLE_DRIVER_LOG("GAP CONN PARAM UPDATE\n"); - break; - - case BLE_GATTS_EVT_SYS_ATTR_MISSING: - // No system attributes have been stored. - (void)sd_ble_gatts_sys_attr_set(p_ble_evt->evt.gatts_evt.conn_handle, NULL, 0, 0); - break; - -#if (BLE_API_VERSION == 4) - case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST: - BLE_DRIVER_LOG("GATTS EVT EXCHANGE MTU REQUEST\n"); - (void)sd_ble_gatts_exchange_mtu_reply(p_ble_evt->evt.gatts_evt.conn_handle, 23); // MAX MTU size - break; -#endif - -#if (BLE_API_VERSION == 4) - case BLE_GATTS_EVT_HVN_TX_COMPLETE: -#else - case BLE_EVT_TX_COMPLETE: -#endif - BLE_DRIVER_LOG("BLE EVT TX COMPLETE\n"); - m_tx_in_progress = false; - break; - - case BLE_GAP_EVT_SEC_PARAMS_REQUEST: - BLE_DRIVER_LOG("BLE EVT SEC PARAMS REQUEST\n"); - // pairing not supported - (void)sd_ble_gap_sec_params_reply(p_ble_evt->evt.gatts_evt.conn_handle, - BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, - NULL, NULL); - break; - - case BLE_GAP_EVT_ADV_REPORT: - BLE_DRIVER_LOG("BLE EVT ADV REPORT\n"); - ble_drv_adv_data_t adv_data = { - .p_peer_addr = p_ble_evt->evt.gap_evt.params.adv_report.peer_addr.addr, - .addr_type = p_ble_evt->evt.gap_evt.params.adv_report.peer_addr.addr_type, -#if (BLUETOOTH_SD == 140) - .is_scan_resp = p_ble_evt->evt.gap_evt.params.adv_report.type.scannable, -#else - .is_scan_resp = p_ble_evt->evt.gap_evt.params.adv_report.scan_rsp, -#endif - .rssi = p_ble_evt->evt.gap_evt.params.adv_report.rssi, -#if (BLUETOOTH_SD == 140) - .data_len = p_ble_evt->evt.gap_evt.params.adv_report.data.len, - .p_data = p_ble_evt->evt.gap_evt.params.adv_report.data.p_data, -#else - .data_len = p_ble_evt->evt.gap_evt.params.adv_report.dlen, - .p_data = p_ble_evt->evt.gap_evt.params.adv_report.data, -#endif -#if (BLUETOOTH_SD == 132) - .adv_type = p_ble_evt->evt.gap_evt.params.adv_report.type -#endif - }; - - // TODO: Fix unsafe callback to possible undefined callback... - adv_event_handler(mp_adv_observer, - p_ble_evt->header.evt_id, - &adv_data); - break; - - case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST: - BLE_DRIVER_LOG("BLE EVT CONN PARAM UPDATE REQUEST\n"); - - (void)sd_ble_gap_conn_param_update(p_ble_evt->evt.gap_evt.conn_handle, - &p_ble_evt->evt.gap_evt.params.conn_param_update_request.conn_params); - break; - - case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP: - BLE_DRIVER_LOG("BLE EVT PRIMARY SERVICE DISCOVERY RESPONSE\n"); - BLE_DRIVER_LOG(">>> service count: %d\n", p_ble_evt->evt.gattc_evt.params.prim_srvc_disc_rsp.count); - - for (uint16_t i = 0; i < p_ble_evt->evt.gattc_evt.params.prim_srvc_disc_rsp.count; i++) { - ble_gattc_service_t * p_service = &p_ble_evt->evt.gattc_evt.params.prim_srvc_disc_rsp.services[i]; - - ble_drv_service_data_t service; - service.uuid_type = p_service->uuid.type; - service.uuid = p_service->uuid.uuid; - service.start_handle = p_service->handle_range.start_handle; - service.end_handle = p_service->handle_range.end_handle; - - disc_add_service_handler(mp_gattc_disc_service_observer, &service); - } - - if (p_ble_evt->evt.gattc_evt.params.prim_srvc_disc_rsp.count > 0) { - m_primary_service_found = true; - } - - // mark end of service discovery - disc_add_service_handler = NULL; - - break; - - case BLE_GATTC_EVT_CHAR_DISC_RSP: - BLE_DRIVER_LOG("BLE EVT CHAR DISCOVERY RESPONSE\n"); - BLE_DRIVER_LOG(">>> characteristic count: %d\n", p_ble_evt->evt.gattc_evt.params.char_disc_rsp.count); - - for (uint16_t i = 0; i < p_ble_evt->evt.gattc_evt.params.char_disc_rsp.count; i++) { - ble_gattc_char_t * p_char = &p_ble_evt->evt.gattc_evt.params.char_disc_rsp.chars[i]; - - ble_drv_char_data_t char_data; - char_data.uuid_type = p_char->uuid.type; - char_data.uuid = p_char->uuid.uuid; - char_data.decl_handle = p_char->handle_decl; - char_data.value_handle = p_char->handle_value; - - char_data.props |= (p_char->char_props.broadcast) ? UBLUEPY_PROP_BROADCAST : 0; - char_data.props |= (p_char->char_props.read) ? UBLUEPY_PROP_READ : 0; - char_data.props |= (p_char->char_props.write_wo_resp) ? UBLUEPY_PROP_WRITE_WO_RESP : 0; - char_data.props |= (p_char->char_props.write) ? UBLUEPY_PROP_WRITE : 0; - char_data.props |= (p_char->char_props.notify) ? UBLUEPY_PROP_NOTIFY : 0; - char_data.props |= (p_char->char_props.indicate) ? UBLUEPY_PROP_INDICATE : 0; - #if 0 - char_data.props |= (p_char->char_props.auth_signed_wr) ? UBLUEPY_PROP_NOTIFY : 0; - #endif - - disc_add_char_handler(mp_gattc_disc_char_observer, &char_data); - } - - if (p_ble_evt->evt.gattc_evt.params.char_disc_rsp.count > 0) { - m_characteristic_found = true; - } - - // mark end of characteristic discovery - disc_add_char_handler = NULL; - - break; - - case BLE_GATTC_EVT_READ_RSP: - BLE_DRIVER_LOG("BLE EVT READ RESPONSE, offset: 0x"HEX2_FMT", length: 0x"HEX2_FMT"\n", - p_ble_evt->evt.gattc_evt.params.read_rsp.offset, - p_ble_evt->evt.gattc_evt.params.read_rsp.len); - - gattc_char_data_handle(mp_gattc_char_data_observer, - p_ble_evt->evt.gattc_evt.params.read_rsp.len, - p_ble_evt->evt.gattc_evt.params.read_rsp.data); - - // mark end of read - gattc_char_data_handle = NULL; - - break; - - case BLE_GATTC_EVT_WRITE_RSP: - BLE_DRIVER_LOG("BLE EVT WRITE RESPONSE\n"); - m_write_done = true; - break; - - case BLE_GATTC_EVT_HVX: - BLE_DRIVER_LOG("BLE EVT HVX RESPONSE\n"); - break; - - default: - BLE_DRIVER_LOG(">>> unhandled evt: 0x" HEX2_FMT "\n", p_ble_evt->header.evt_id); - break; - } -} - -#if (BLE_API_VERSION == 2) -static uint8_t m_ble_evt_buf[sizeof(ble_evt_t) + (GATT_MTU_SIZE_DEFAULT)] __attribute__ ((aligned (4))); -#else -static uint8_t m_ble_evt_buf[sizeof(ble_evt_t) + (BLE_GATT_ATT_MTU_DEFAULT)] __attribute__ ((aligned (4))); -#endif - -void SWI2_EGU2_IRQHandler(void) { - uint32_t evt_id; - uint32_t err_code; - do { - err_code = sd_evt_get(&evt_id); - // TODO: handle non ble events - } while (err_code != NRF_ERROR_NOT_FOUND && err_code != NRF_SUCCESS); - - uint16_t evt_len = sizeof(m_ble_evt_buf); - do { - err_code = sd_ble_evt_get(m_ble_evt_buf, &evt_len); - ble_evt_handler((ble_evt_t *)m_ble_evt_buf); - } while (err_code != NRF_ERROR_NOT_FOUND && err_code != NRF_SUCCESS); -} - -#endif // BLUETOOTH_SD diff --git a/ports/nrf/drivers/bluetooth/ble_drv.h b/ports/nrf/drivers/bluetooth/ble_drv.h deleted file mode 100644 index d8b715467..000000000 --- a/ports/nrf/drivers/bluetooth/ble_drv.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2016 Glenn Ruben Bakke - * - * 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 BLUETOOTH_LE_DRIVER_H__ -#define BLUETOOTH_LE_DRIVER_H__ - -#if BLUETOOTH_SD - -#include <stdint.h> -#include <stdbool.h> - -#include "modubluepy.h" - -typedef struct { - uint8_t addr[6]; - uint8_t addr_type; -} ble_drv_addr_t; - -typedef struct { - uint8_t * p_peer_addr; - uint8_t addr_type; - bool is_scan_resp; - int8_t rssi; - uint8_t data_len; - uint8_t * p_data; - uint8_t adv_type; -} ble_drv_adv_data_t; - -typedef struct { - uint16_t uuid; - uint8_t uuid_type; - uint16_t start_handle; - uint16_t end_handle; -} ble_drv_service_data_t; - -typedef struct { - uint16_t uuid; - uint8_t uuid_type; - uint8_t props; - uint16_t decl_handle; - uint16_t value_handle; -} ble_drv_char_data_t; - -typedef void (*ble_drv_gap_evt_callback_t)(mp_obj_t self, uint16_t event_id, uint16_t conn_handle, uint16_t length, uint8_t * data); -typedef void (*ble_drv_gatts_evt_callback_t)(mp_obj_t self, uint16_t event_id, uint16_t attr_handle, uint16_t length, uint8_t * data); -typedef void (*ble_drv_gattc_evt_callback_t)(mp_obj_t self, uint16_t event_id, uint16_t attr_handle, uint16_t length, uint8_t * data); -typedef void (*ble_drv_adv_evt_callback_t)(mp_obj_t self, uint16_t event_id, ble_drv_adv_data_t * data); -typedef void (*ble_drv_disc_add_service_callback_t)(mp_obj_t self, ble_drv_service_data_t * p_service_data); -typedef void (*ble_drv_disc_add_char_callback_t)(mp_obj_t self, ble_drv_char_data_t * p_desc_data); -typedef void (*ble_drv_gattc_char_data_callback_t)(mp_obj_t self, uint16_t length, uint8_t * p_data); - -uint32_t ble_drv_stack_enable(void); - -void ble_drv_stack_disable(void); - -uint8_t ble_drv_stack_enabled(void); - -void ble_drv_address_get(ble_drv_addr_t * p_addr); - -bool ble_drv_uuid_add_vs(uint8_t * p_uuid, uint8_t * idx); - -bool ble_drv_service_add(ubluepy_service_obj_t * p_service_obj); - -bool ble_drv_characteristic_add(ubluepy_characteristic_obj_t * p_char_obj); - -bool ble_drv_advertise_data(ubluepy_advertise_data_t * p_adv_params); - -void ble_drv_advertise_stop(void); - -void ble_drv_gap_event_handler_set(mp_obj_t obs, ble_drv_gap_evt_callback_t evt_handler); - -void ble_drv_gatts_event_handler_set(mp_obj_t obj, ble_drv_gatts_evt_callback_t evt_handler); - -void ble_drv_gattc_event_handler_set(mp_obj_t obj, ble_drv_gattc_evt_callback_t evt_handler); - -void ble_drv_attr_s_read(uint16_t conn_handle, uint16_t handle, uint16_t len, uint8_t * p_data); - -void ble_drv_attr_c_read(uint16_t conn_handle, uint16_t handle, mp_obj_t obj, ble_drv_gattc_char_data_callback_t cb); - -void ble_drv_attr_s_write(uint16_t conn_handle, uint16_t handle, uint16_t len, uint8_t * p_data); - -void ble_drv_attr_s_notify(uint16_t conn_handle, uint16_t handle, uint16_t len, uint8_t * p_data); - -void ble_drv_attr_c_write(uint16_t conn_handle, uint16_t handle, uint16_t len, uint8_t * p_data, bool w_response); - -void ble_drv_scan_start(void); - -void ble_drv_scan_stop(void); - -void ble_drv_adv_report_handler_set(mp_obj_t obj, ble_drv_adv_evt_callback_t evt_handler); - -void ble_drv_connect(uint8_t * p_addr, uint8_t addr_type); - -bool ble_drv_discover_services(mp_obj_t obj, uint16_t conn_handle, uint16_t start_handle, ble_drv_disc_add_service_callback_t cb); - -bool ble_drv_discover_characteristic(mp_obj_t obj, - uint16_t conn_handle, - uint16_t start_handle, - uint16_t end_handle, - ble_drv_disc_add_char_callback_t cb); - -void ble_drv_discover_descriptors(void); - -#endif // BLUETOOTH_SD - -#endif // BLUETOOTH_LE_DRIVER_H__ diff --git a/ports/nrf/drivers/bluetooth/ble_uart.c b/ports/nrf/drivers/bluetooth/ble_uart.c deleted file mode 100644 index 52c042f7b..000000000 --- a/ports/nrf/drivers/bluetooth/ble_uart.c +++ /dev/null @@ -1,275 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2017 Glenn Ruben Bakke - * - * 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. - */ - -#if BLUETOOTH_SD - -#include <string.h> -#include "ble_uart.h" -#include "ringbuffer.h" -#include "py/mphal.h" -#include "lib/utils/interrupt_char.h" - -#if MICROPY_PY_BLE_NUS - -static ubluepy_uuid_obj_t uuid_obj_service = { - .base.type = &ubluepy_uuid_type, - .type = UBLUEPY_UUID_128_BIT, - .value = {0x01, 0x00} -}; - -static ubluepy_uuid_obj_t uuid_obj_char_tx = { - .base.type = &ubluepy_uuid_type, - .type = UBLUEPY_UUID_128_BIT, - .value = {0x03, 0x00} -}; - -static ubluepy_uuid_obj_t uuid_obj_char_rx = { - .base.type = &ubluepy_uuid_type, - .type = UBLUEPY_UUID_128_BIT, - .value = {0x02, 0x00} -}; - -static ubluepy_service_obj_t ble_uart_service = { - .base.type = &ubluepy_service_type, - .p_uuid = &uuid_obj_service, - .type = UBLUEPY_SERVICE_PRIMARY -}; - -static ubluepy_characteristic_obj_t ble_uart_char_rx = { - .base.type = &ubluepy_characteristic_type, - .p_uuid = &uuid_obj_char_rx, - .props = UBLUEPY_PROP_WRITE | UBLUEPY_PROP_WRITE_WO_RESP, - .attrs = 0, -}; - -static ubluepy_characteristic_obj_t ble_uart_char_tx = { - .base.type = &ubluepy_characteristic_type, - .p_uuid = &uuid_obj_char_tx, - .props = UBLUEPY_PROP_NOTIFY, - .attrs = UBLUEPY_ATTR_CCCD, -}; - -static ubluepy_peripheral_obj_t ble_uart_peripheral = { - .base.type = &ubluepy_peripheral_type, - .conn_handle = 0xFFFF, -}; - -static volatile bool m_cccd_enabled; -static volatile bool m_connected; - -ringBuffer_typedef(uint8_t, ringbuffer_t); - -static ringbuffer_t m_rx_ring_buffer; -static ringbuffer_t * mp_rx_ring_buffer = &m_rx_ring_buffer; -static uint8_t m_rx_ring_buffer_data[128]; - -static ubluepy_advertise_data_t m_adv_data_uart_service; - -#if BLUETOOTH_WEBBLUETOOTH_REPL -static ubluepy_advertise_data_t m_adv_data_eddystone_url; -#endif // BLUETOOTH_WEBBLUETOOTH_REPL - -int mp_hal_stdin_rx_chr(void) { - while (isBufferEmpty(mp_rx_ring_buffer)) { - ; - } - - uint8_t byte; - bufferRead(mp_rx_ring_buffer, byte); - return (int)byte; -} - -bool mp_hal_stdin_any(void) { - return !isBufferEmpty(mp_rx_ring_buffer); -} - -void mp_hal_stdout_tx_strn(const char *str, size_t len) { - uint8_t *buf = (uint8_t *)str; - size_t send_len; - - while (len > 0) { - if (len >= 20) { - send_len = 20; // (GATT_MTU_SIZE_DEFAULT - 3) - } else { - send_len = len; - } - - ubluepy_characteristic_obj_t * p_char = &ble_uart_char_tx; - - ble_drv_attr_s_notify(p_char->p_service->p_periph->conn_handle, - p_char->handle, - send_len, - buf); - - len -= send_len; - buf += send_len; - } -} - -void mp_hal_stdout_tx_strn_cooked(const char *str, mp_uint_t len) { - mp_hal_stdout_tx_strn(str, len); -} - -STATIC void gap_event_handler(mp_obj_t self_in, uint16_t event_id, uint16_t conn_handle, uint16_t length, uint8_t * data) { - ubluepy_peripheral_obj_t * self = MP_OBJ_TO_PTR(self_in); - - if (event_id == 16) { // connect event - self->conn_handle = conn_handle; - m_connected = true; - } else if (event_id == 17) { // disconnect event - self->conn_handle = 0xFFFF; // invalid connection handle - m_connected = false; - ble_uart_advertise(); - } -} - -STATIC void gatts_event_handler(mp_obj_t self_in, uint16_t event_id, uint16_t attr_handle, uint16_t length, uint8_t * data) { - ubluepy_peripheral_obj_t * self = MP_OBJ_TO_PTR(self_in); - (void)self; - - if (event_id == 80) { // gatts write - if (ble_uart_char_tx.cccd_handle == attr_handle) { - m_cccd_enabled = true; - } else if (ble_uart_char_rx.handle == attr_handle) { - for (uint16_t i = 0; i < length; i++) { - #if MICROPY_KBD_EXCEPTION - if (data[i] == mp_interrupt_char) { - mp_keyboard_interrupt(); - } else - #endif - { - bufferWrite(mp_rx_ring_buffer, data[i]); - } - } - } - } -} - -void ble_uart_init0(void) { - uint8_t base_uuid[] = {0x9E, 0xCA, 0xDC, 0x24, 0x0E, 0xE5, 0xA9, 0xE0, 0x93, 0xF3, 0xA3, 0xB5, 0x00, 0x00, 0x40, 0x6E}; - uint8_t uuid_vs_idx; - - (void)ble_drv_uuid_add_vs(base_uuid, &uuid_vs_idx); - - uuid_obj_service.uuid_vs_idx = uuid_vs_idx; - uuid_obj_char_tx.uuid_vs_idx = uuid_vs_idx; - uuid_obj_char_rx.uuid_vs_idx = uuid_vs_idx; - - (void)ble_drv_service_add(&ble_uart_service); - ble_uart_service.char_list = mp_obj_new_list(0, NULL); - - // add TX characteristic - ble_uart_char_tx.service_handle = ble_uart_service.handle; - bool retval = ble_drv_characteristic_add(&ble_uart_char_tx); - if (retval) { - ble_uart_char_tx.p_service = &ble_uart_service; - } - mp_obj_list_append(ble_uart_service.char_list, MP_OBJ_FROM_PTR(&ble_uart_char_tx)); - - // add RX characteristic - ble_uart_char_rx.service_handle = ble_uart_service.handle; - retval = ble_drv_characteristic_add(&ble_uart_char_rx); - if (retval) { - ble_uart_char_rx.p_service = &ble_uart_service; - } - mp_obj_list_append(ble_uart_service.char_list, MP_OBJ_FROM_PTR(&ble_uart_char_rx)); - - // setup the peripheral - ble_uart_peripheral.service_list = mp_obj_new_list(0, NULL); - mp_obj_list_append(ble_uart_peripheral.service_list, MP_OBJ_FROM_PTR(&ble_uart_service)); - ble_uart_service.p_periph = &ble_uart_peripheral; - - ble_drv_gap_event_handler_set(MP_OBJ_FROM_PTR(&ble_uart_peripheral), gap_event_handler); - ble_drv_gatts_event_handler_set(MP_OBJ_FROM_PTR(&ble_uart_peripheral), gatts_event_handler); - - ble_uart_peripheral.conn_handle = 0xFFFF; - - char device_name[] = "mpus"; - - mp_obj_t service_list = mp_obj_new_list(0, NULL); - mp_obj_list_append(service_list, MP_OBJ_FROM_PTR(&ble_uart_service)); - - mp_obj_t * services = NULL; - mp_uint_t num_services; - mp_obj_get_array(service_list, &num_services, &services); - - m_adv_data_uart_service.p_services = services; - m_adv_data_uart_service.num_of_services = num_services; - m_adv_data_uart_service.p_device_name = (uint8_t *)device_name; - m_adv_data_uart_service.device_name_len = strlen(device_name); - m_adv_data_uart_service.connectable = true; - m_adv_data_uart_service.p_data = NULL; - -#if BLUETOOTH_WEBBLUETOOTH_REPL - // for now point eddystone URL to https://goo.gl/x46FES => https://glennrub.github.io/webbluetooth/micropython/repl/ - static uint8_t eddystone_url_data[27] = {0x2, 0x1, 0x6, - 0x3, 0x3, 0xaa, 0xfe, - 19, 0x16, 0xaa, 0xfe, 0x10, 0xee, 0x3, 'g', 'o', 'o', '.', 'g', 'l', '/', 'x', '4', '6', 'F', 'E', 'S'}; - // eddystone url adv data - m_adv_data_eddystone_url.p_data = eddystone_url_data; - m_adv_data_eddystone_url.data_len = sizeof(eddystone_url_data); - m_adv_data_eddystone_url.connectable = false; -#endif - - m_cccd_enabled = false; - - // initialize ring buffer - m_rx_ring_buffer.size = sizeof(m_rx_ring_buffer_data) + 1; - m_rx_ring_buffer.start = 0; - m_rx_ring_buffer.end = 0; - m_rx_ring_buffer.elems = m_rx_ring_buffer_data; - - m_connected = false; - - ble_uart_advertise(); -} - -void ble_uart_advertise(void) { -#if BLUETOOTH_WEBBLUETOOTH_REPL - while (!m_connected) { - (void)ble_drv_advertise_data(&m_adv_data_uart_service); - mp_hal_delay_ms(500); - (void)ble_drv_advertise_data(&m_adv_data_eddystone_url); - mp_hal_delay_ms(500); - } - - ble_drv_advertise_stop(); -#else - (void)ble_drv_advertise_data(&m_adv_data_uart_service); -#endif // BLUETOOTH_WEBBLUETOOTH_REPL -} - -bool ble_uart_connected(void) { - return (m_connected); -} - -bool ble_uart_enabled(void) { - return (m_cccd_enabled); -} - -#endif // MICROPY_PY_BLE_NUS - -#endif // BLUETOOTH_SD diff --git a/ports/nrf/examples/ubluepy_eddystone.py b/ports/nrf/examples/ubluepy_eddystone.py index c8abd5aea..baf25ba4b 100644 --- a/ports/nrf/examples/ubluepy_eddystone.py +++ b/ports/nrf/examples/ubluepy_eddystone.py @@ -44,7 +44,7 @@ def generate_eddystone_adv_packet(url): service_data = uuid + eddystone_data packet_service_data = gen_ad_type_content(constants.ad_types.AD_TYPE_SERVICE_DATA, service_data) - # generate advertisment packet + # generate advertisement packet packet = bytearray([]) packet.extend(packet_flags) packet.extend(packet_uuid16) diff --git a/ports/nrf/examples/ubluepy_temp.py b/ports/nrf/examples/ubluepy_temp.py index fac091bc1..e5c157dbb 100644 --- a/ports/nrf/examples/ubluepy_temp.py +++ b/ports/nrf/examples/ubluepy_temp.py @@ -41,7 +41,7 @@ def event_handler(id, handle, data): rtc.stop() # indicate 'disconnected' LED(1).off() - # restart advertisment + # restart advertisement periph.advertise(device_name="micr_temp", services=[serv_env_sense]) elif id == constants.EVT_GATTS_WRITE: diff --git a/ports/nrf/internal_flash.c b/ports/nrf/internal_flash.c deleted file mode 100644 index 812ef4d3f..000000000 --- a/ports/nrf/internal_flash.c +++ /dev/null @@ -1,226 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2013, 2014 Damien P. George - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include "internal_flash.h" - -#include <stdint.h> -#include <string.h> - -#include "extmod/vfs.h" -#include "extmod/vfs_fat.h" -#include "py/mphal.h" -#include "py/obj.h" -#include "py/runtime.h" -#include "lib/oofatfs/ff.h" -#include "supervisor/shared/rgb_led_status.h" - -#include "nrf_nvmc.h" - -#ifdef BLUETOOTH_SD -#include "nrf_sdm.h" -#endif - -// defined in linker -extern uint32_t __fatfs_flash_start_addr[]; -extern uint32_t __fatfs_flash_length[]; - -#define NO_CACHE 0xffffffff -#define FL_PAGE_SZ 4096 - -uint8_t _flash_cache[FL_PAGE_SZ] __attribute__((aligned(4))); -uint32_t _flash_page_addr = NO_CACHE; - - -/*------------------------------------------------------------------*/ -/* Internal Flash API - *------------------------------------------------------------------*/ -static inline uint32_t lba2addr(uint32_t block) { - return ((uint32_t)__fatfs_flash_start_addr) + block * FILESYSTEM_BLOCK_SIZE; -} - -void internal_flash_init(void) { - // Activity LED for flash writes. -#ifdef MICROPY_HW_LED_MSC - struct port_config pin_conf; - port_get_config_defaults(&pin_conf); - - pin_conf.direction = PORT_PIN_DIR_OUTPUT; - port_pin_set_config(MICROPY_HW_LED_MSC, &pin_conf); - port_pin_set_output_level(MICROPY_HW_LED_MSC, false); -#endif -} - -uint32_t internal_flash_get_block_size(void) { - return FILESYSTEM_BLOCK_SIZE; -} - -uint32_t internal_flash_get_block_count(void) { - return ((uint32_t) __fatfs_flash_length) / FILESYSTEM_BLOCK_SIZE ; -} - -// TODO support flashing with SD enabled -void internal_flash_flush(void) { - if (_flash_page_addr == NO_CACHE) return; - - // Skip if data is the same - if (memcmp(_flash_cache, (void *)_flash_page_addr, FL_PAGE_SZ) != 0) { -// _is_flashing = true; - nrf_nvmc_page_erase(_flash_page_addr); - nrf_nvmc_write_words(_flash_page_addr, (uint32_t *)_flash_cache, FL_PAGE_SZ / sizeof(uint32_t)); - } - - _flash_page_addr = NO_CACHE; -} - -mp_uint_t internal_flash_read_blocks(uint8_t *dest, uint32_t block, uint32_t num_blocks) { - uint32_t src = lba2addr(block); - memcpy(dest, (uint8_t*) src, FILESYSTEM_BLOCK_SIZE*num_blocks); - return 0; // success -} - -mp_uint_t internal_flash_write_blocks(const uint8_t *src, uint32_t lba, uint32_t num_blocks) { - -#ifdef MICROPY_HW_LED_MSC - port_pin_set_output_level(MICROPY_HW_LED_MSC, true); -#endif - - while (num_blocks) { - uint32_t const addr = lba2addr(lba); - uint32_t const page_addr = addr & ~(FL_PAGE_SZ - 1); - - uint32_t count = 8 - (lba % 8); // up to page boundary - count = MIN(num_blocks, count); - - if (page_addr != _flash_page_addr) { - internal_flash_flush(); - - // writing previous cached data, skip current data until flashing is done - // tinyusb stack will invoke write_block() with the same parameters later on - // if ( _is_flashing ) return; - - _flash_page_addr = page_addr; - memcpy(_flash_cache, (void *)page_addr, FL_PAGE_SZ); - } - - memcpy(_flash_cache + (addr & (FL_PAGE_SZ - 1)), src, count * FILESYSTEM_BLOCK_SIZE); - - // adjust for next run - lba += count; - src += count * FILESYSTEM_BLOCK_SIZE; - num_blocks -= count; - } - -#ifdef MICROPY_HW_LED_MSC - port_pin_set_output_level(MICROPY_HW_LED_MSC, false); -#endif - - return 0; // success -} - -/******************************************************************************/ -// MicroPython bindings -// -// Expose the flash as an object with the block protocol. - -// there is a singleton Flash object -STATIC const mp_obj_base_t internal_flash_obj = {&internal_flash_type}; - -STATIC mp_obj_t internal_flash_obj_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - // check arguments - mp_arg_check_num(n_args, n_kw, 0, 0, false); - - // return singleton object - return (mp_obj_t)&internal_flash_obj; -} - -STATIC mp_obj_t internal_flash_obj_readblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) { - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_WRITE); - mp_uint_t ret = internal_flash_read_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / FILESYSTEM_BLOCK_SIZE); - return MP_OBJ_NEW_SMALL_INT(ret); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_3(internal_flash_obj_readblocks_obj, internal_flash_obj_readblocks); - -STATIC mp_obj_t internal_flash_obj_writeblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) { - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ); - mp_uint_t ret = internal_flash_write_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / FILESYSTEM_BLOCK_SIZE); - return MP_OBJ_NEW_SMALL_INT(ret); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_3(internal_flash_obj_writeblocks_obj, internal_flash_obj_writeblocks); - -STATIC mp_obj_t internal_flash_obj_ioctl(mp_obj_t self, mp_obj_t cmd_in, mp_obj_t arg_in) { - mp_int_t cmd = mp_obj_get_int(cmd_in); - switch (cmd) { - case BP_IOCTL_INIT: internal_flash_init(); return MP_OBJ_NEW_SMALL_INT(0); - case BP_IOCTL_DEINIT: internal_flash_flush(); return MP_OBJ_NEW_SMALL_INT(0); // TODO properly - case BP_IOCTL_SYNC: internal_flash_flush(); return MP_OBJ_NEW_SMALL_INT(0); - case BP_IOCTL_SEC_COUNT: return MP_OBJ_NEW_SMALL_INT(internal_flash_get_block_count()); - case BP_IOCTL_SEC_SIZE: return MP_OBJ_NEW_SMALL_INT(internal_flash_get_block_size()); - default: return mp_const_none; - } -} -STATIC MP_DEFINE_CONST_FUN_OBJ_3(internal_flash_obj_ioctl_obj, internal_flash_obj_ioctl); - -STATIC const mp_rom_map_elem_t internal_flash_obj_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&internal_flash_obj_readblocks_obj) }, - { MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&internal_flash_obj_writeblocks_obj) }, - { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&internal_flash_obj_ioctl_obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(internal_flash_obj_locals_dict, internal_flash_obj_locals_dict_table); - -const mp_obj_type_t internal_flash_type = { - { &mp_type_type }, - .name = MP_QSTR_InternalFlash, - .make_new = internal_flash_obj_make_new, - .locals_dict = (mp_obj_t)&internal_flash_obj_locals_dict, -}; - -/*------------------------------------------------------------------*/ -/* Flash API - *------------------------------------------------------------------*/ - -void flash_init_vfs(fs_user_mount_t *vfs) { - vfs->base.type = &mp_fat_vfs_type; - vfs->flags |= FSUSER_NATIVE | FSUSER_HAVE_IOCTL; - vfs->fatfs.drv = vfs; - -// vfs->fatfs.part = 1; // flash filesystem lives on first partition - vfs->readblocks[0] = (mp_obj_t)&internal_flash_obj_readblocks_obj; - vfs->readblocks[1] = (mp_obj_t)&internal_flash_obj; - vfs->readblocks[2] = (mp_obj_t)internal_flash_read_blocks; // native version - - vfs->writeblocks[0] = (mp_obj_t)&internal_flash_obj_writeblocks_obj; - vfs->writeblocks[1] = (mp_obj_t)&internal_flash_obj; - vfs->writeblocks[2] = (mp_obj_t)internal_flash_write_blocks; // native version - - vfs->u.ioctl[0] = (mp_obj_t)&internal_flash_obj_ioctl_obj; - vfs->u.ioctl[1] = (mp_obj_t)&internal_flash_obj; -} - -void flash_flush(void) { - internal_flash_flush(); -} diff --git a/ports/nrf/modules/ubluepy/modubluepy.c b/ports/nrf/modules/ubluepy/modubluepy.c deleted file mode 100644 index b306c065b..000000000 --- a/ports/nrf/modules/ubluepy/modubluepy.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2017 Glenn Ruben Bakke - * - * 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/obj.h" - -#if MICROPY_PY_UBLUEPY - -extern const mp_obj_type_t ubluepy_peripheral_type; -extern const mp_obj_type_t ubluepy_service_type; -extern const mp_obj_type_t ubluepy_uuid_type; -extern const mp_obj_type_t ubluepy_characteristic_type; -extern const mp_obj_type_t ubluepy_delegate_type; -extern const mp_obj_type_t ubluepy_constants_type; -extern const mp_obj_type_t ubluepy_scanner_type; -extern const mp_obj_type_t ubluepy_scan_entry_type; - -STATIC const mp_rom_map_elem_t mp_module_ubluepy_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ubluepy) }, -#if MICROPY_PY_UBLUEPY_PERIPHERAL - { MP_ROM_QSTR(MP_QSTR_Peripheral), MP_ROM_PTR(&ubluepy_peripheral_type) }, -#endif -#if 0 // MICROPY_PY_UBLUEPY_CENTRAL - { MP_ROM_QSTR(MP_QSTR_Central), MP_ROM_PTR(&ubluepy_central_type) }, -#endif -#if MICROPY_PY_UBLUEPY_CENTRAL - { MP_ROM_QSTR(MP_QSTR_Scanner), MP_ROM_PTR(&ubluepy_scanner_type) }, - { MP_ROM_QSTR(MP_QSTR_ScanEntry), MP_ROM_PTR(&ubluepy_scan_entry_type) }, -#endif - { MP_ROM_QSTR(MP_QSTR_DefaultDelegate), MP_ROM_PTR(&ubluepy_delegate_type) }, - { MP_ROM_QSTR(MP_QSTR_UUID), MP_ROM_PTR(&ubluepy_uuid_type) }, - { MP_ROM_QSTR(MP_QSTR_Service), MP_ROM_PTR(&ubluepy_service_type) }, - { MP_ROM_QSTR(MP_QSTR_Characteristic), MP_ROM_PTR(&ubluepy_characteristic_type) }, - { MP_ROM_QSTR(MP_QSTR_constants), MP_ROM_PTR(&ubluepy_constants_type) }, -#if MICROPY_PY_UBLUEPY_DESCRIPTOR - { MP_ROM_QSTR(MP_QSTR_Descriptor), MP_ROM_PTR(&ubluepy_descriptor_type) }, -#endif -}; - - -STATIC MP_DEFINE_CONST_DICT(mp_module_ubluepy_globals, mp_module_ubluepy_globals_table); - -const mp_obj_module_t mp_module_ubluepy = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t*)&mp_module_ubluepy_globals, -}; - -#endif // MICROPY_PY_UBLUEPY diff --git a/ports/nrf/modules/ubluepy/modubluepy.h b/ports/nrf/modules/ubluepy/modubluepy.h deleted file mode 100644 index 83d86c5df..000000000 --- a/ports/nrf/modules/ubluepy/modubluepy.h +++ /dev/null @@ -1,200 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2017 Glenn Ruben Bakke - * - * 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 UBLUEPY_H__ -#define UBLUEPY_H__ - -/* Examples: - -Advertisment: - -from ubluepy import Peripheral -p = Peripheral() -p.advertise(device_name="MicroPython") - -DB setup: - -from ubluepy import Service, Characteristic, UUID, Peripheral, constants -from pyb import LED - -def event_handler(id, handle, data): - print("BLE event:", id, "handle:", handle) - print(data) - - if id == constants.EVT_GAP_CONNECTED: - # connected - LED(2).on() - elif id == constants.EVT_GAP_DISCONNECTED: - # disconnect - LED(2).off() - elif id == 80: - print("id 80, data:", data) - -# u0 = UUID("0x180D") # HRM service -# u1 = UUID("0x2A37") # HRM measurement - -u0 = UUID("6e400001-b5a3-f393-e0a9-e50e24dcca9e") -u1 = UUID("6e400002-b5a3-f393-e0a9-e50e24dcca9e") -u2 = UUID("6e400003-b5a3-f393-e0a9-e50e24dcca9e") -s = Service(u0) -c0 = Characteristic(u1, props = Characteristic.PROP_WRITE | Characteristic.PROP_WRITE_WO_RESP) -c1 = Characteristic(u2, props = Characteristic.PROP_NOTIFY, attrs = Characteristic.ATTR_CCCD) -s.addCharacteristic(c0) -s.addCharacteristic(c1) -p = Peripheral() -p.addService(s) -p.setConnectionHandler(event_handler) -p.advertise(device_name="micr", services=[s]) - -*/ - -#include "py/obj.h" - -extern const mp_obj_type_t ubluepy_uuid_type; -extern const mp_obj_type_t ubluepy_service_type; -extern const mp_obj_type_t ubluepy_characteristic_type; -extern const mp_obj_type_t ubluepy_peripheral_type; -extern const mp_obj_type_t ubluepy_scanner_type; -extern const mp_obj_type_t ubluepy_scan_entry_type; -extern const mp_obj_type_t ubluepy_constants_type; -extern const mp_obj_type_t ubluepy_constants_ad_types_type; - -typedef enum { - UBLUEPY_UUID_16_BIT = 1, - UBLUEPY_UUID_128_BIT -} ubluepy_uuid_type_t; - -typedef enum { - UBLUEPY_SERVICE_PRIMARY = 1, - UBLUEPY_SERVICE_SECONDARY = 2 -} ubluepy_service_type_t; - -typedef enum { - UBLUEPY_ADDR_TYPE_PUBLIC = 0, - UBLUEPY_ADDR_TYPE_RANDOM_STATIC = 1, -#if 0 - UBLUEPY_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE = 2, - UBLUEPY_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE = 3, -#endif -} ubluepy_addr_type_t; - -typedef enum { - UBLUEPY_ROLE_PERIPHERAL, - UBLUEPY_ROLE_CENTRAL -} ubluepy_role_type_t; - -typedef struct _ubluepy_uuid_obj_t { - mp_obj_base_t base; - ubluepy_uuid_type_t type; - uint8_t value[2]; - uint8_t uuid_vs_idx; -} ubluepy_uuid_obj_t; - -typedef struct _ubluepy_peripheral_obj_t { - mp_obj_base_t base; - ubluepy_role_type_t role; - volatile uint16_t conn_handle; - mp_obj_t delegate; - mp_obj_t notif_handler; - mp_obj_t conn_handler; - mp_obj_t service_list; -} ubluepy_peripheral_obj_t; - -typedef struct _ubluepy_service_obj_t { - mp_obj_base_t base; - uint16_t handle; - uint8_t type; - ubluepy_uuid_obj_t * p_uuid; - ubluepy_peripheral_obj_t * p_periph; - mp_obj_t char_list; - uint16_t start_handle; - uint16_t end_handle; -} ubluepy_service_obj_t; - -typedef struct _ubluepy_characteristic_obj_t { - mp_obj_base_t base; - uint16_t handle; - ubluepy_uuid_obj_t * p_uuid; - uint16_t service_handle; - uint16_t user_desc_handle; - uint16_t cccd_handle; - uint16_t sccd_handle; - uint8_t props; - uint8_t attrs; - ubluepy_service_obj_t * p_service; - mp_obj_t value_data; -} ubluepy_characteristic_obj_t; - -typedef struct _ubluepy_descriptor_obj_t { - mp_obj_base_t base; - uint16_t handle; - ubluepy_uuid_obj_t * p_uuid; -} ubluepy_descriptor_obj_t; - -typedef struct _ubluepy_delegate_obj_t { - mp_obj_base_t base; -} ubluepy_delegate_obj_t; - -typedef struct _ubluepy_advertise_data_t { - uint8_t * p_device_name; - uint8_t device_name_len; - mp_obj_t * p_services; - uint8_t num_of_services; - uint8_t * p_data; - uint8_t data_len; - bool connectable; -} ubluepy_advertise_data_t; - -typedef struct _ubluepy_scanner_obj_t { - mp_obj_base_t base; - mp_obj_t adv_reports; -} ubluepy_scanner_obj_t; - -typedef struct _ubluepy_scan_entry_obj_t { - mp_obj_base_t base; - mp_obj_t addr; - uint8_t addr_type; - bool connectable; - int8_t rssi; - mp_obj_t data; -} ubluepy_scan_entry_obj_t; - -typedef enum _ubluepy_prop_t { - UBLUEPY_PROP_BROADCAST = 0x01, - UBLUEPY_PROP_READ = 0x02, - UBLUEPY_PROP_WRITE_WO_RESP = 0x04, - UBLUEPY_PROP_WRITE = 0x08, - UBLUEPY_PROP_NOTIFY = 0x10, - UBLUEPY_PROP_INDICATE = 0x20, - UBLUEPY_PROP_AUTH_SIGNED_WR = 0x40, -} ubluepy_prop_t; - -typedef enum _ubluepy_attr_t { - UBLUEPY_ATTR_CCCD = 0x01, - UBLUEPY_ATTR_SCCD = 0x02, -} ubluepy_attr_t; - -#endif // UBLUEPY_H__ diff --git a/ports/nrf/modules/ubluepy/ubluepy_characteristic.c b/ports/nrf/modules/ubluepy/ubluepy_characteristic.c deleted file mode 100644 index 0935615a5..000000000 --- a/ports/nrf/modules/ubluepy/ubluepy_characteristic.c +++ /dev/null @@ -1,223 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2017 Glenn Ruben Bakke - * - * 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/obj.h" -#include "py/runtime.h" -#include "supervisor/shared/translate.h" - -#if MICROPY_PY_UBLUEPY_PERIPHERAL || MICROPY_PY_UBLUEPY_CENTRAL - -#include "modubluepy.h" -#include "ble_drv.h" - -STATIC void ubluepy_characteristic_print(const mp_print_t *print, mp_obj_t o, mp_print_kind_t kind) { - ubluepy_characteristic_obj_t * self = (ubluepy_characteristic_obj_t *)o; - - mp_printf(print, "Characteristic(handle: 0x" HEX2_FMT ", conn_handle: " HEX2_FMT ")", - self->handle, self->p_service->p_periph->conn_handle); -} - -STATIC mp_obj_t ubluepy_characteristic_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - static const mp_arg_t allowed_args[] = { - { MP_QSTR_uuid, MP_ARG_REQUIRED| MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_props, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = UBLUEPY_PROP_READ | UBLUEPY_PROP_WRITE} }, - { MP_QSTR_attrs, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, - }; - - // parse args - 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); - - ubluepy_characteristic_obj_t *s = m_new_obj(ubluepy_characteristic_obj_t); - s->base.type = type; - - mp_obj_t uuid_obj = args[0].u_obj; - - if (uuid_obj == mp_const_none) { - return MP_OBJ_FROM_PTR(s); - } - - if (MP_OBJ_IS_TYPE(uuid_obj, &ubluepy_uuid_type)) { - s->p_uuid = MP_OBJ_TO_PTR(uuid_obj); - // (void)sd_characterstic_add(s); - } else { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, - translate("Invalid UUID parameter"))); - } - - if (args[1].u_int > 0) { - s->props = (uint8_t)args[1].u_int; - } - - if (args[2].u_int > 0) { - s->attrs = (uint8_t)args[2].u_int; - } - - // clear pointer to service - s->p_service = NULL; - - // clear pointer to char value data - s->value_data = NULL; - - return MP_OBJ_FROM_PTR(s); -} - -void char_data_callback(mp_obj_t self_in, uint16_t length, uint8_t * p_data) { - ubluepy_characteristic_obj_t * self = MP_OBJ_TO_PTR(self_in); - self->value_data = mp_obj_new_bytearray(length, p_data); -} - -/// \method read() -/// Read Characteristic value. -/// -STATIC mp_obj_t char_read(mp_obj_t self_in) { - ubluepy_characteristic_obj_t * self = MP_OBJ_TO_PTR(self_in); - -#if MICROPY_PY_UBLUEPY_CENTRAL - // TODO: free any previous allocation of value_data - - ble_drv_attr_c_read(self->p_service->p_periph->conn_handle, - self->handle, - self_in, - char_data_callback); - - return self->value_data; -#else - (void)self; - return mp_const_none; -#endif -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(ubluepy_characteristic_read_obj, char_read); - -/// \method write(data, [with_response=False]) -/// Write Characteristic value. -/// -STATIC mp_obj_t char_write(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - ubluepy_characteristic_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - mp_obj_t data = pos_args[1]; - - static const mp_arg_t allowed_args[] = { - { MP_QSTR_with_response, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false } }, - }; - - // parse args - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 2, pos_args + 2, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ); - - // figure out mode of the Peripheral - ubluepy_role_type_t role = self->p_service->p_periph->role; - - if (role == UBLUEPY_ROLE_PERIPHERAL) { - if (self->props & UBLUEPY_PROP_NOTIFY) { - ble_drv_attr_s_notify(self->p_service->p_periph->conn_handle, - self->handle, - bufinfo.len, - bufinfo.buf); - } else { - ble_drv_attr_s_write(self->p_service->p_periph->conn_handle, - self->handle, - bufinfo.len, - bufinfo.buf); - } - } else { -#if MICROPY_PY_UBLUEPY_CENTRAL - bool with_response = args[0].u_bool; - - ble_drv_attr_c_write(self->p_service->p_periph->conn_handle, - self->handle, - bufinfo.len, - bufinfo.buf, - with_response); -#endif - } - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(ubluepy_characteristic_write_obj, 2, char_write); - -/// \method properties() -/// Read Characteristic value properties. -/// -STATIC mp_obj_t char_properties(mp_obj_t self_in) { - ubluepy_characteristic_obj_t * self = MP_OBJ_TO_PTR(self_in); - return MP_OBJ_NEW_SMALL_INT(self->props); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(ubluepy_characteristic_get_properties_obj, char_properties); - -/// \method uuid() -/// Get UUID instance of the characteristic. -/// -STATIC mp_obj_t char_uuid(mp_obj_t self_in) { - ubluepy_characteristic_obj_t * self = MP_OBJ_TO_PTR(self_in); - return MP_OBJ_FROM_PTR(self->p_uuid); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(ubluepy_characteristic_get_uuid_obj, char_uuid); - - -STATIC const mp_rom_map_elem_t ubluepy_characteristic_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&ubluepy_characteristic_read_obj) }, - { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&ubluepy_characteristic_write_obj) }, -#if 0 - { MP_ROM_QSTR(MP_QSTR_supportsRead), MP_ROM_PTR(&ubluepy_characteristic_supports_read_obj) }, - { MP_ROM_QSTR(MP_QSTR_propertiesToString), MP_ROM_PTR(&ubluepy_characteristic_properties_to_str_obj) }, - { MP_ROM_QSTR(MP_QSTR_getHandle), MP_ROM_PTR(&ubluepy_characteristic_get_handle_obj) }, - - // Properties - { MP_ROM_QSTR(MP_QSTR_peripheral), MP_ROM_PTR(&ubluepy_characteristic_get_peripheral_obj) }, -#endif - { MP_ROM_QSTR(MP_QSTR_uuid), MP_ROM_PTR(&ubluepy_characteristic_get_uuid_obj) }, - { MP_ROM_QSTR(MP_QSTR_properties), MP_ROM_PTR(&ubluepy_characteristic_get_properties_obj) }, - - { MP_ROM_QSTR(MP_QSTR_PROP_BROADCAST), MP_ROM_INT(UBLUEPY_PROP_BROADCAST) }, - { MP_ROM_QSTR(MP_QSTR_PROP_READ), MP_ROM_INT(UBLUEPY_PROP_READ) }, - { MP_ROM_QSTR(MP_QSTR_PROP_WRITE_WO_RESP), MP_ROM_INT(UBLUEPY_PROP_WRITE_WO_RESP) }, - { MP_ROM_QSTR(MP_QSTR_PROP_WRITE), MP_ROM_INT(UBLUEPY_PROP_WRITE) }, - { MP_ROM_QSTR(MP_QSTR_PROP_NOTIFY), MP_ROM_INT(UBLUEPY_PROP_NOTIFY) }, - { MP_ROM_QSTR(MP_QSTR_PROP_INDICATE), MP_ROM_INT(UBLUEPY_PROP_INDICATE) }, - { MP_ROM_QSTR(MP_QSTR_PROP_AUTH_SIGNED_WR), MP_ROM_INT(UBLUEPY_PROP_AUTH_SIGNED_WR) }, - -#if MICROPY_PY_UBLUEPY_PERIPHERAL - { MP_ROM_QSTR(MP_QSTR_ATTR_CCCD), MP_ROM_INT(UBLUEPY_ATTR_CCCD) }, -#endif - -#if MICROPY_PY_UBLUEPY_CENTRAL - { MP_ROM_QSTR(MP_QSTR_PROP_AUTH_SIGNED_WR), MP_ROM_INT(UBLUEPY_ATTR_SCCD) }, -#endif -}; - -STATIC MP_DEFINE_CONST_DICT(ubluepy_characteristic_locals_dict, ubluepy_characteristic_locals_dict_table); - -const mp_obj_type_t ubluepy_characteristic_type = { - { &mp_type_type }, - .name = MP_QSTR_Characteristic, - .print = ubluepy_characteristic_print, - .make_new = ubluepy_characteristic_make_new, - .locals_dict = (mp_obj_dict_t*)&ubluepy_characteristic_locals_dict -}; - -#endif // MICROPY_PY_UBLUEPY_PERIPHERAL || MICROPY_PY_UBLUEPY_CENTRAL diff --git a/ports/nrf/modules/ubluepy/ubluepy_constants.c b/ports/nrf/modules/ubluepy/ubluepy_constants.c deleted file mode 100644 index 14e433e6e..000000000 --- a/ports/nrf/modules/ubluepy/ubluepy_constants.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2017 Glenn Ruben Bakke - * - * 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/obj.h" -#include "py/runtime.h" - -#if MICROPY_PY_UBLUEPY - -#include "modubluepy.h" - -STATIC const mp_rom_map_elem_t ubluepy_constants_ad_types_locals_dict_table[] = { - // GAP AD Types - { MP_ROM_QSTR(MP_QSTR_AD_TYPE_FLAGS), MP_ROM_INT(0x01) }, - { MP_ROM_QSTR(MP_QSTR_AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE), MP_ROM_INT(0x02) }, - { MP_ROM_QSTR(MP_QSTR_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE), MP_ROM_INT(0x03) }, - { MP_ROM_QSTR(MP_QSTR_AD_TYPE_32BIT_SERVICE_UUID_MORE_AVAILABLE), MP_ROM_INT(0x04) }, - { MP_ROM_QSTR(MP_QSTR_AD_TYPE_32BIT_SERVICE_UUID_COMPLETE), MP_ROM_INT(0x05) }, - { MP_ROM_QSTR(MP_QSTR_AD_TYPE_128BIT_SERVICE_UUID_MORE_AVAILABLE), MP_ROM_INT(0x06) }, - { MP_ROM_QSTR(MP_QSTR_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE), MP_ROM_INT(0x07) }, - { MP_ROM_QSTR(MP_QSTR_AD_TYPE_SHORT_LOCAL_NAME), MP_ROM_INT(0x08) }, - { MP_ROM_QSTR(MP_QSTR_AD_TYPE_COMPLETE_LOCAL_NAME), MP_ROM_INT(0x09) }, - { MP_ROM_QSTR(MP_QSTR_AD_TYPE_TX_POWER_LEVEL), MP_ROM_INT(0x0A) }, - { MP_ROM_QSTR(MP_QSTR_AD_TYPE_CLASS_OF_DEVICE), MP_ROM_INT(0x0D) }, - { MP_ROM_QSTR(MP_QSTR_AD_TYPE_SIMPLE_PAIRING_HASH_C), MP_ROM_INT(0x0E) }, - { MP_ROM_QSTR(MP_QSTR_AD_TYPE_SIMPLE_PAIRING_RANDOMIZER_R), MP_ROM_INT(0x0F) }, - { MP_ROM_QSTR(MP_QSTR_AD_TYPE_SECURITY_MANAGER_TK_VALUE), MP_ROM_INT(0x10) }, - { MP_ROM_QSTR(MP_QSTR_AD_TYPE_SECURITY_MANAGER_OOB_FLAGS), MP_ROM_INT(0x11) }, - { MP_ROM_QSTR(MP_QSTR_AD_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE), MP_ROM_INT(0x12) }, - { MP_ROM_QSTR(MP_QSTR_AD_TYPE_SOLICITED_SERVICE_UUIDS_16BIT), MP_ROM_INT(0x14) }, - { MP_ROM_QSTR(MP_QSTR_AD_TYPE_SOLICITED_SERVICE_UUIDS_128BIT), MP_ROM_INT(0x15) }, - { MP_ROM_QSTR(MP_QSTR_AD_TYPE_SERVICE_DATA), MP_ROM_INT(0x16) }, - { MP_ROM_QSTR(MP_QSTR_AD_TYPE_PUBLIC_TARGET_ADDRESS), MP_ROM_INT(0x17) }, - { MP_ROM_QSTR(MP_QSTR_AD_TYPE_RANDOM_TARGET_ADDRESS), MP_ROM_INT(0x18) }, - { MP_ROM_QSTR(MP_QSTR_AD_TYPE_APPEARANCE), MP_ROM_INT(0x19) }, - { MP_ROM_QSTR(MP_QSTR_AD_TYPE_ADVERTISING_INTERVAL), MP_ROM_INT(0x1A) }, - { MP_ROM_QSTR(MP_QSTR_AD_TYPE_LE_BLUETOOTH_DEVICE_ADDRESS), MP_ROM_INT(0x1B) }, - { MP_ROM_QSTR(MP_QSTR_AD_TYPE_LE_ROLE), MP_ROM_INT(0x1C) }, - { MP_ROM_QSTR(MP_QSTR_AD_TYPE_SIMPLE_PAIRING_HASH_C256), MP_ROM_INT(0x1D) }, - { MP_ROM_QSTR(MP_QSTR_AD_TYPE_SIMPLE_PAIRING_RANDOMIZER_R256), MP_ROM_INT(0x1E) }, - { MP_ROM_QSTR(MP_QSTR_AD_TYPE_SERVICE_DATA_32BIT_UUID), MP_ROM_INT(0x20) }, - { MP_ROM_QSTR(MP_QSTR_AD_TYPE_SERVICE_DATA_128BIT_UUID), MP_ROM_INT(0x21) }, - { MP_ROM_QSTR(MP_QSTR_AD_TYPE_URI), MP_ROM_INT(0x24) }, - { MP_ROM_QSTR(MP_QSTR_AD_TYPE_3D_INFORMATION_DATA), MP_ROM_INT(0x3D) }, - { MP_ROM_QSTR(MP_QSTR_AD_TYPE_MANUFACTURER_SPECIFIC_DATA), MP_ROM_INT(0xFF) }, -}; - -STATIC MP_DEFINE_CONST_DICT(ubluepy_constants_ad_types_locals_dict, ubluepy_constants_ad_types_locals_dict_table); - -const mp_obj_type_t ubluepy_constants_ad_types_type = { - { &mp_type_type }, - .name = MP_QSTR_ad_types, - .locals_dict = (mp_obj_dict_t*)&ubluepy_constants_ad_types_locals_dict -}; - -STATIC const mp_rom_map_elem_t ubluepy_constants_locals_dict_table[] = { - // GAP events - { MP_ROM_QSTR(MP_QSTR_EVT_GAP_CONNECTED), MP_ROM_INT(16) }, - { MP_ROM_QSTR(MP_QSTR_EVT_GAP_DISCONNECTED), MP_ROM_INT(17) }, - { MP_ROM_QSTR(MP_QSTR_EVT_GATTS_WRITE), MP_ROM_INT(80) }, - { MP_ROM_QSTR(MP_QSTR_UUID_CCCD), MP_ROM_INT(0x2902) }, - - { MP_ROM_QSTR(MP_QSTR_ADDR_TYPE_PUBLIC), MP_ROM_INT(UBLUEPY_ADDR_TYPE_PUBLIC) }, - { MP_ROM_QSTR(MP_QSTR_ADDR_TYPE_RANDOM_STATIC), MP_ROM_INT(UBLUEPY_ADDR_TYPE_RANDOM_STATIC) }, - - { MP_ROM_QSTR(MP_QSTR_ad_types), MP_ROM_PTR(&ubluepy_constants_ad_types_type) }, -}; - -STATIC MP_DEFINE_CONST_DICT(ubluepy_constants_locals_dict, ubluepy_constants_locals_dict_table); - -const mp_obj_type_t ubluepy_constants_type = { - { &mp_type_type }, - .name = MP_QSTR_constants, - .locals_dict = (mp_obj_dict_t*)&ubluepy_constants_locals_dict -}; - -#endif // MICROPY_PY_UBLUEPY diff --git a/ports/nrf/modules/ubluepy/ubluepy_delegate.c b/ports/nrf/modules/ubluepy/ubluepy_delegate.c deleted file mode 100644 index 07bb7f492..000000000 --- a/ports/nrf/modules/ubluepy/ubluepy_delegate.c +++ /dev/null @@ -1,89 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2017 Glenn Ruben Bakke - * - * 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/obj.h" -#include "py/runtime.h" - -#if MICROPY_PY_UBLUEPY_PERIPHERAL || MICROPY_PY_UBLUEPY_CENTRAL - -#include "modubluepy.h" - -STATIC void ubluepy_delegate_print(const mp_print_t *print, mp_obj_t o, mp_print_kind_t kind) { - ubluepy_delegate_obj_t * self = (ubluepy_delegate_obj_t *)o; - (void)self; - mp_printf(print, "DefaultDelegate()"); -} - -STATIC mp_obj_t ubluepy_delegate_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - ubluepy_delegate_obj_t *s = m_new_obj(ubluepy_delegate_obj_t); - s->base.type = type; - - return MP_OBJ_FROM_PTR(s); -} - -/// \method handleConnection() -/// Handle connection events. -/// -STATIC mp_obj_t delegate_handle_conn(mp_obj_t self_in) { - ubluepy_delegate_obj_t *self = MP_OBJ_TO_PTR(self_in); - - (void)self; - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(ubluepy_delegate_handle_conn_obj, delegate_handle_conn); - -/// \method handleNotification() -/// Handle notification events. -/// -STATIC mp_obj_t delegate_handle_notif(mp_obj_t self_in) { - ubluepy_delegate_obj_t *self = MP_OBJ_TO_PTR(self_in); - - (void)self; - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(ubluepy_delegate_handle_notif_obj, delegate_handle_notif); - -STATIC const mp_rom_map_elem_t ubluepy_delegate_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_handleConnection), MP_ROM_PTR(&ubluepy_delegate_handle_conn_obj) }, - { MP_ROM_QSTR(MP_QSTR_handleNotification), MP_ROM_PTR(&ubluepy_delegate_handle_notif_obj) }, -#if 0 - { MP_ROM_QSTR(MP_QSTR_handleDiscovery), MP_ROM_PTR(&ubluepy_delegate_handle_disc_obj) }, -#endif -}; - -STATIC MP_DEFINE_CONST_DICT(ubluepy_delegate_locals_dict, ubluepy_delegate_locals_dict_table); - -const mp_obj_type_t ubluepy_delegate_type = { - { &mp_type_type }, - .name = MP_QSTR_DefaultDelegate, - .print = ubluepy_delegate_print, - .make_new = ubluepy_delegate_make_new, - .locals_dict = (mp_obj_dict_t*)&ubluepy_delegate_locals_dict -}; - -#endif // MICROPY_PY_UBLUEPY_PERIPHERAL || MICROPY_PY_UBLUEPY_CENTRAL diff --git a/ports/nrf/modules/ubluepy/ubluepy_descriptor.c b/ports/nrf/modules/ubluepy/ubluepy_descriptor.c deleted file mode 100644 index b15301954..000000000 --- a/ports/nrf/modules/ubluepy/ubluepy_descriptor.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2017 Glenn Ruben Bakke - * - * 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/obj.h" -#include "py/runtime.h" -#include "py/objstr.h" -#include "py/misc.h" - -#if MICROPY_PY_UBLUEPY - -#include "modubluepy.h" -#include "ble_drv.h" - -STATIC void ubluepy_descriptor_print(const mp_print_t *print, mp_obj_t o, mp_print_kind_t kind) { - ubluepy_descriptor_obj_t * self = (ubluepy_descriptor_obj_t *)o; - - mp_printf(print, "Descriptor(uuid: 0x" HEX2_FMT HEX2_FMT ")", - self->p_uuid->value[1], self->p_uuid->value[0]); -} - -STATIC mp_obj_t ubluepy_descriptor_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - - enum { ARG_NEW_UUID }; - - static const mp_arg_t allowed_args[] = { - { ARG_NEW_UUID, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - }; - - // parse args - 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); - - ubluepy_descriptor_obj_t * s = m_new_obj(ubluepy_descriptor_obj_t); - s->base.type = type; - - mp_obj_t uuid_obj = args[ARG_NEW_UUID].u_obj; - - (void)uuid_obj; - - return MP_OBJ_FROM_PTR(s); -} - -STATIC const mp_rom_map_elem_t ubluepy_descriptor_locals_dict_table[] = { -#if 0 - { MP_ROM_QSTR(MP_QSTR_binVal), MP_ROM_PTR(&ubluepy_descriptor_bin_val_obj) }, -#endif -}; - -STATIC MP_DEFINE_CONST_DICT(ubluepy_descriptor_locals_dict, ubluepy_descriptor_locals_dict_table); - -const mp_obj_type_t ubluepy_descriptor_type = { - { &mp_type_type }, - .name = MP_QSTR_Descriptor, - .print = ubluepy_descriptor_print, - .make_new = ubluepy_descriptor_make_new, - .locals_dict = (mp_obj_dict_t*)&ubluepy_descriptor_locals_dict -}; - -#endif // MICROPY_PY_UBLUEPY diff --git a/ports/nrf/modules/ubluepy/ubluepy_peripheral.c b/ports/nrf/modules/ubluepy/ubluepy_peripheral.c deleted file mode 100644 index 48e467374..000000000 --- a/ports/nrf/modules/ubluepy/ubluepy_peripheral.c +++ /dev/null @@ -1,498 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2017 Glenn Ruben Bakke - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include <string.h> -#include "py/obj.h" -#include "py/runtime.h" -#include "py/objstr.h" -#include "py/objlist.h" - -#if MICROPY_PY_UBLUEPY - -#include "ble_drv.h" - -STATIC void ubluepy_peripheral_print(const mp_print_t *print, mp_obj_t o, mp_print_kind_t kind) { - ubluepy_peripheral_obj_t * self = (ubluepy_peripheral_obj_t *)o; - (void)self; - mp_printf(print, "Peripheral(conn_handle: " HEX2_FMT ")", - self->conn_handle); -} - -STATIC void gap_event_handler(mp_obj_t self_in, uint16_t event_id, uint16_t conn_handle, uint16_t length, uint8_t * data) { - ubluepy_peripheral_obj_t *self = MP_OBJ_TO_PTR(self_in); - - if (event_id == 16) { // connect event - self->conn_handle = conn_handle; - } else if (event_id == 17) { // disconnect event - self->conn_handle = 0xFFFF; // invalid connection handle - } - - if (self->conn_handler != mp_const_none) { - mp_obj_t args[3]; - mp_uint_t num_of_args = 3; - args[0] = MP_OBJ_NEW_SMALL_INT(event_id); - args[1] = MP_OBJ_NEW_SMALL_INT(conn_handle); - if (data != NULL) { - args[2] = mp_obj_new_bytearray_by_ref(length, data); - } else { - args[2] = mp_const_none; - } - - // for now hard-code all events to conn_handler - mp_call_function_n_kw(self->conn_handler, num_of_args, 0, args); - } - - (void)self; -} - -STATIC void gatts_event_handler(mp_obj_t self_in, uint16_t event_id, uint16_t attr_handle, uint16_t length, uint8_t * data) { - ubluepy_peripheral_obj_t *self = MP_OBJ_TO_PTR(self_in); - - if (self->conn_handler != mp_const_none) { - mp_obj_t args[3]; - mp_uint_t num_of_args = 3; - args[0] = MP_OBJ_NEW_SMALL_INT(event_id); - args[1] = MP_OBJ_NEW_SMALL_INT(attr_handle); - if (data != NULL) { - args[2] = mp_obj_new_bytearray_by_ref(length, data); - } else { - args[2] = mp_const_none; - } - - // for now hard-code all events to conn_handler - mp_call_function_n_kw(self->conn_handler, num_of_args, 0, args); - } - -} - -#if MICROPY_PY_UBLUEPY_CENTRAL - -static volatile bool m_disc_evt_received; - -STATIC void gattc_event_handler(mp_obj_t self_in, uint16_t event_id, uint16_t attr_handle, uint16_t length, uint8_t * data) { - ubluepy_peripheral_obj_t *self = MP_OBJ_TO_PTR(self_in); - (void)self; - m_disc_evt_received = true; -} -#endif - -STATIC mp_obj_t ubluepy_peripheral_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - enum { - ARG_NEW_DEVICE_ADDR, - ARG_NEW_ADDR_TYPE - }; - - static const mp_arg_t allowed_args[] = { - { ARG_NEW_DEVICE_ADDR, MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { ARG_NEW_ADDR_TYPE, MP_ARG_OBJ, {.u_obj = mp_const_none} }, - }; - - // parse args - 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); - - ubluepy_peripheral_obj_t *s = m_new_obj(ubluepy_peripheral_obj_t); - s->base.type = type; - - s->delegate = mp_const_none; - s->conn_handler = mp_const_none; - s->notif_handler = mp_const_none; - s->conn_handle = 0xFFFF; - - s->service_list = mp_obj_new_list(0, NULL); - - return MP_OBJ_FROM_PTR(s); -} - -/// \method withDelegate(DefaultDelegate) -/// Set delegate instance for handling Bluetooth LE events. -/// -STATIC mp_obj_t peripheral_with_delegate(mp_obj_t self_in, mp_obj_t delegate) { - ubluepy_peripheral_obj_t *self = MP_OBJ_TO_PTR(self_in); - - self->delegate = delegate; - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(ubluepy_peripheral_with_delegate_obj, peripheral_with_delegate); - -/// \method setNotificationHandler(func) -/// Set handler for Bluetooth LE notification events. -/// -STATIC mp_obj_t peripheral_set_notif_handler(mp_obj_t self_in, mp_obj_t func) { - ubluepy_peripheral_obj_t *self = MP_OBJ_TO_PTR(self_in); - - self->notif_handler = func; - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(ubluepy_peripheral_set_notif_handler_obj, peripheral_set_notif_handler); - -/// \method setConnectionHandler(func) -/// Set handler for Bluetooth LE connection events. -/// -STATIC mp_obj_t peripheral_set_conn_handler(mp_obj_t self_in, mp_obj_t func) { - ubluepy_peripheral_obj_t *self = MP_OBJ_TO_PTR(self_in); - - self->conn_handler = func; - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(ubluepy_peripheral_set_conn_handler_obj, peripheral_set_conn_handler); - -#if MICROPY_PY_UBLUEPY_PERIPHERAL - -/// \method advertise(device_name, [service=[service1, service2, ...]], [data=bytearray], [connectable=True]) -/// Start advertising. Connectable advertisment type by default. -/// -STATIC mp_obj_t peripheral_advertise(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - static const mp_arg_t allowed_args[] = { - { MP_QSTR_device_name, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_services, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_data, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_connectable, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, - }; - - ubluepy_peripheral_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - - self->role = UBLUEPY_ROLE_PERIPHERAL; - - // parse args - 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); - - // ubluepy_peripheral_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - mp_obj_t device_name_obj = args[0].u_obj; - mp_obj_t service_obj = args[1].u_obj; - mp_obj_t data_obj = args[2].u_obj; - mp_obj_t connectable_obj = args[3].u_obj; - - ubluepy_advertise_data_t adv_data; - memset(&adv_data, 0, sizeof(ubluepy_advertise_data_t)); - - if (device_name_obj != mp_const_none && MP_OBJ_IS_STR(device_name_obj)) { - GET_STR_DATA_LEN(device_name_obj, str_data, str_len); - - adv_data.p_device_name = (uint8_t *)str_data; - adv_data.device_name_len = str_len; - } - - if (service_obj != mp_const_none) { - mp_obj_t * services = NULL; - mp_uint_t num_services; - mp_obj_get_array(service_obj, &num_services, &services); - - if (num_services > 0) { - adv_data.p_services = services; - adv_data.num_of_services = num_services; - } - } - - if (data_obj != mp_const_none) { - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(data_obj, &bufinfo, MP_BUFFER_READ); - - if (bufinfo.len > 0) { - adv_data.p_data = bufinfo.buf; - adv_data.data_len = bufinfo.len; - } - } - - adv_data.connectable = true; - if (connectable_obj != mp_const_none && !(mp_obj_is_true(connectable_obj))) { - adv_data.connectable = false; - } else { - ble_drv_gap_event_handler_set(MP_OBJ_FROM_PTR(self), gap_event_handler); - ble_drv_gatts_event_handler_set(MP_OBJ_FROM_PTR(self), gatts_event_handler); - } - - (void)ble_drv_advertise_data(&adv_data); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(ubluepy_peripheral_advertise_obj, 0, peripheral_advertise); - -/// \method advertise_stop() -/// Stop advertisment if any onging advertisment. -/// -STATIC mp_obj_t peripheral_advertise_stop(mp_obj_t self_in) { - ubluepy_peripheral_obj_t *self = MP_OBJ_TO_PTR(self_in); - - (void)self; - - ble_drv_advertise_stop(); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(ubluepy_peripheral_advertise_stop_obj, peripheral_advertise_stop); - -#endif // MICROPY_PY_UBLUEPY_PERIPHERAL - -/// \method disconnect() -/// disconnect connection. -/// -STATIC mp_obj_t peripheral_disconnect(mp_obj_t self_in) { - ubluepy_peripheral_obj_t *self = MP_OBJ_TO_PTR(self_in); - - (void)self; - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(ubluepy_peripheral_disconnect_obj, peripheral_disconnect); - -/// \method addService(Service) -/// Add service to the Peripheral. -/// -STATIC mp_obj_t peripheral_add_service(mp_obj_t self_in, mp_obj_t service) { - ubluepy_peripheral_obj_t * self = MP_OBJ_TO_PTR(self_in); - ubluepy_service_obj_t * p_service = MP_OBJ_TO_PTR(service); - - p_service->p_periph = self; - - mp_obj_list_append(self->service_list, service); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(ubluepy_peripheral_add_service_obj, peripheral_add_service); - -/// \method getServices() -/// Return list with all service registered in the Peripheral. -/// -STATIC mp_obj_t peripheral_get_services(mp_obj_t self_in) { - ubluepy_peripheral_obj_t * self = MP_OBJ_TO_PTR(self_in); - - return self->service_list; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(ubluepy_peripheral_get_services_obj, peripheral_get_services); - -#if MICROPY_PY_UBLUEPY_CENTRAL - -void static disc_add_service(mp_obj_t self, ble_drv_service_data_t * p_service_data) { - ubluepy_service_obj_t * p_service = m_new_obj(ubluepy_service_obj_t); - p_service->base.type = &ubluepy_service_type; - - ubluepy_uuid_obj_t * p_uuid = m_new_obj(ubluepy_uuid_obj_t); - p_uuid->base.type = &ubluepy_uuid_type; - - p_service->p_uuid = p_uuid; - - p_uuid->type = p_service_data->uuid_type; - p_uuid->value[0] = p_service_data->uuid & 0xFF; - p_uuid->value[1] = p_service_data->uuid >> 8; - - p_service->handle = p_service_data->start_handle; - p_service->start_handle = p_service_data->start_handle; - p_service->end_handle = p_service_data->end_handle; - - p_service->char_list = mp_obj_new_list(0, NULL); - - peripheral_add_service(self, MP_OBJ_FROM_PTR(p_service)); -} - -void static disc_add_char(mp_obj_t service_in, ble_drv_char_data_t * p_desc_data) { - ubluepy_service_obj_t * p_service = MP_OBJ_TO_PTR(service_in); - ubluepy_characteristic_obj_t * p_char = m_new_obj(ubluepy_characteristic_obj_t); - p_char->base.type = &ubluepy_characteristic_type; - - ubluepy_uuid_obj_t * p_uuid = m_new_obj(ubluepy_uuid_obj_t); - p_uuid->base.type = &ubluepy_uuid_type; - - p_char->p_uuid = p_uuid; - - p_uuid->type = p_desc_data->uuid_type; - p_uuid->value[0] = p_desc_data->uuid & 0xFF; - p_uuid->value[1] = p_desc_data->uuid >> 8; - - // add characteristic specific data from discovery - p_char->props = p_desc_data->props; - p_char->handle = p_desc_data->value_handle; - - // equivalent to ubluepy_service.c - service_add_characteristic() - // except the registration of the characteristic towards the bluetooth stack - p_char->service_handle = p_service->handle; - p_char->p_service = p_service; - - mp_obj_list_append(p_service->char_list, MP_OBJ_FROM_PTR(p_char)); -} - -/// \method connect(device_address [, addr_type=ADDR_TYPE_PUBLIC]) -/// Connect to device peripheral with the given device address. -/// addr_type can be either ADDR_TYPE_PUBLIC (default) or -/// ADDR_TYPE_RANDOM_STATIC. -/// -STATIC mp_obj_t peripheral_connect(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - ubluepy_peripheral_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - mp_obj_t dev_addr = pos_args[1]; - - self->role = UBLUEPY_ROLE_CENTRAL; - - static const mp_arg_t allowed_args[] = { - { MP_QSTR_addr_type, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = UBLUEPY_ADDR_TYPE_PUBLIC } }, - }; - - // parse args - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 2, pos_args + 2, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - uint8_t addr_type = args[0].u_int; - - ble_drv_gap_event_handler_set(MP_OBJ_FROM_PTR(self), gap_event_handler); - - if (MP_OBJ_IS_STR(dev_addr)) { - GET_STR_DATA_LEN(dev_addr, str_data, str_len); - if (str_len == 17) { // Example "11:22:33:aa:bb:cc" - - uint8_t * p_addr = m_new(uint8_t, 6); - - p_addr[0] = unichar_xdigit_value(str_data[16]); - p_addr[0] += unichar_xdigit_value(str_data[15]) << 4; - p_addr[1] = unichar_xdigit_value(str_data[13]); - p_addr[1] += unichar_xdigit_value(str_data[12]) << 4; - p_addr[2] = unichar_xdigit_value(str_data[10]); - p_addr[2] += unichar_xdigit_value(str_data[9]) << 4; - p_addr[3] = unichar_xdigit_value(str_data[7]); - p_addr[3] += unichar_xdigit_value(str_data[6]) << 4; - p_addr[4] = unichar_xdigit_value(str_data[4]); - p_addr[4] += unichar_xdigit_value(str_data[3]) << 4; - p_addr[5] = unichar_xdigit_value(str_data[1]); - p_addr[5] += unichar_xdigit_value(str_data[0]) << 4; - - ble_drv_connect(p_addr, addr_type); - - m_del(uint8_t, p_addr, 6); - } - } - - // block until connected - while (self->conn_handle == 0xFFFF) { - ; - } - - ble_drv_gattc_event_handler_set(MP_OBJ_FROM_PTR(self), gattc_event_handler); - - bool service_disc_retval = ble_drv_discover_services(self, self->conn_handle, 0x0001, disc_add_service); - - // continue discovery of primary services ... - while (service_disc_retval) { - // locate the last added service - mp_obj_t * services = NULL; - mp_uint_t num_services; - mp_obj_get_array(self->service_list, &num_services, &services); - - ubluepy_service_obj_t * p_service = (ubluepy_service_obj_t *)services[num_services - 1]; - - service_disc_retval = ble_drv_discover_services(self, - self->conn_handle, - p_service->end_handle + 1, - disc_add_service); - } - - // For each service perform a characteristic discovery - mp_obj_t * services = NULL; - mp_uint_t num_services; - mp_obj_get_array(self->service_list, &num_services, &services); - - for (uint16_t s = 0; s < num_services; s++) { - ubluepy_service_obj_t * p_service = (ubluepy_service_obj_t *)services[s]; - bool char_disc_retval = ble_drv_discover_characteristic(p_service, - self->conn_handle, - p_service->start_handle, - p_service->end_handle, - disc_add_char); - // continue discovery of characteristics ... - while (char_disc_retval) { - mp_obj_t * characteristics = NULL; - mp_uint_t num_chars; - mp_obj_get_array(p_service->char_list, &num_chars, &characteristics); - - ubluepy_characteristic_obj_t * p_char = (ubluepy_characteristic_obj_t *)characteristics[num_chars - 1]; - uint16_t next_handle = p_char->handle + 1; - if ((next_handle) < p_service->end_handle) { - char_disc_retval = ble_drv_discover_characteristic(p_service, - self->conn_handle, - next_handle, - p_service->end_handle, - disc_add_char); - } else { - break; - } - } - } - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(ubluepy_peripheral_connect_obj, 2, peripheral_connect); - -#endif - -STATIC const mp_rom_map_elem_t ubluepy_peripheral_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_withDelegate), MP_ROM_PTR(&ubluepy_peripheral_with_delegate_obj) }, - { MP_ROM_QSTR(MP_QSTR_setNotificationHandler), MP_ROM_PTR(&ubluepy_peripheral_set_notif_handler_obj) }, - { MP_ROM_QSTR(MP_QSTR_setConnectionHandler), MP_ROM_PTR(&ubluepy_peripheral_set_conn_handler_obj) }, - { MP_ROM_QSTR(MP_QSTR_getServices), MP_ROM_PTR(&ubluepy_peripheral_get_services_obj) }, -#if MICROPY_PY_UBLUEPY_CENTRAL - { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&ubluepy_peripheral_connect_obj) }, -#if 0 - { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&ubluepy_peripheral_disconnect_obj) }, - { MP_ROM_QSTR(MP_QSTR_getServiceByUUID), MP_ROM_PTR(&ubluepy_peripheral_get_service_by_uuid_obj) }, - { MP_ROM_QSTR(MP_QSTR_getCharacteristics), MP_ROM_PTR(&ubluepy_peripheral_get_chars_obj) }, - { MP_ROM_QSTR(MP_QSTR_getDescriptors), MP_ROM_PTR(&ubluepy_peripheral_get_descs_obj) }, - { MP_ROM_QSTR(MP_QSTR_waitForNotifications), MP_ROM_PTR(&ubluepy_peripheral_wait_for_notif_obj) }, - { MP_ROM_QSTR(MP_QSTR_writeCharacteristic), MP_ROM_PTR(&ubluepy_peripheral_write_char_obj) }, - { MP_ROM_QSTR(MP_QSTR_readCharacteristic), MP_ROM_PTR(&ubluepy_peripheral_read_char_obj) }, -#endif // 0 -#endif // MICROPY_PY_UBLUEPY_CENTRAL -#if MICROPY_PY_UBLUEPY_PERIPHERAL - { MP_ROM_QSTR(MP_QSTR_advertise), MP_ROM_PTR(&ubluepy_peripheral_advertise_obj) }, - { MP_ROM_QSTR(MP_QSTR_advertise_stop), MP_ROM_PTR(&ubluepy_peripheral_advertise_stop_obj) }, - { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&ubluepy_peripheral_disconnect_obj) }, - { MP_ROM_QSTR(MP_QSTR_addService), MP_ROM_PTR(&ubluepy_peripheral_add_service_obj) }, -#if 0 - { MP_ROM_QSTR(MP_QSTR_addCharacteristic), MP_ROM_PTR(&ubluepy_peripheral_add_char_obj) }, - { MP_ROM_QSTR(MP_QSTR_addDescriptor), MP_ROM_PTR(&ubluepy_peripheral_add_desc_obj) }, - { MP_ROM_QSTR(MP_QSTR_writeCharacteristic), MP_ROM_PTR(&ubluepy_peripheral_write_char_obj) }, - { MP_ROM_QSTR(MP_QSTR_readCharacteristic), MP_ROM_PTR(&ubluepy_peripheral_read_char_obj) }, -#endif -#endif -#if MICROPY_PY_UBLUEPY_BROADCASTER - { MP_ROM_QSTR(MP_QSTR_advertise), MP_ROM_PTR(&ubluepy_peripheral_advertise_obj) }, -#endif -#if MICROPY_PY_UBLUEPY_OBSERVER - // Nothing yet. -#endif -}; - -STATIC MP_DEFINE_CONST_DICT(ubluepy_peripheral_locals_dict, ubluepy_peripheral_locals_dict_table); - -const mp_obj_type_t ubluepy_peripheral_type = { - { &mp_type_type }, - .name = MP_QSTR_Peripheral, - .print = ubluepy_peripheral_print, - .make_new = ubluepy_peripheral_make_new, - .locals_dict = (mp_obj_dict_t*)&ubluepy_peripheral_locals_dict -}; - -#endif // MICROPY_PY_UBLUEPY diff --git a/ports/nrf/modules/ubluepy/ubluepy_scan_entry.c b/ports/nrf/modules/ubluepy/ubluepy_scan_entry.c deleted file mode 100644 index 773070b08..000000000 --- a/ports/nrf/modules/ubluepy/ubluepy_scan_entry.c +++ /dev/null @@ -1,146 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2017 Glenn Ruben Bakke - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include <string.h> -#include "py/obj.h" -#include "py/runtime.h" -#include "py/objstr.h" -#include "py/objlist.h" -#include "py/objarray.h" -#include "py/objtuple.h" -#include "py/qstr.h" - -#if MICROPY_PY_UBLUEPY_CENTRAL - -#include "ble_drv.h" - -STATIC void ubluepy_scan_entry_print(const mp_print_t *print, mp_obj_t o, mp_print_kind_t kind) { - ubluepy_scan_entry_obj_t * self = (ubluepy_scan_entry_obj_t *)o; - (void)self; - mp_printf(print, "ScanEntry"); -} - -/// \method addr() -/// Return address as text string. -/// -STATIC mp_obj_t scan_entry_get_addr(mp_obj_t self_in) { - ubluepy_scan_entry_obj_t *self = MP_OBJ_TO_PTR(self_in); - return self->addr; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(bluepy_scan_entry_get_addr_obj, scan_entry_get_addr); - -/// \method addr_type() -/// Return address type value. -/// -STATIC mp_obj_t scan_entry_get_addr_type(mp_obj_t self_in) { - ubluepy_scan_entry_obj_t *self = MP_OBJ_TO_PTR(self_in); - return mp_obj_new_int(self->addr_type); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(bluepy_scan_entry_get_addr_type_obj, scan_entry_get_addr_type); - -/// \method rssi() -/// Return RSSI value. -/// -STATIC mp_obj_t scan_entry_get_rssi(mp_obj_t self_in) { - ubluepy_scan_entry_obj_t *self = MP_OBJ_TO_PTR(self_in); - return mp_obj_new_int(self->rssi); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(bluepy_scan_entry_get_rssi_obj, scan_entry_get_rssi); - -/// \method getScanData() -/// Return list of the scan data tupples (ad_type, description, value) -/// -STATIC mp_obj_t scan_entry_get_scan_data(mp_obj_t self_in) { - ubluepy_scan_entry_obj_t * self = MP_OBJ_TO_PTR(self_in); - - mp_obj_t retval_list = mp_obj_new_list(0, NULL); - - // TODO: check if self->data is set - mp_obj_array_t * data = MP_OBJ_TO_PTR(self->data); - - uint16_t byte_index = 0; - - while (byte_index < data->len) { - mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(3, NULL)); - - uint8_t adv_item_len = ((uint8_t * )data->items)[byte_index]; - uint8_t adv_item_type = ((uint8_t * )data->items)[byte_index + 1]; - - mp_obj_t description = mp_const_none; - - mp_map_t *constant_map = mp_obj_dict_get_map(ubluepy_constants_ad_types_type.locals_dict); - mp_map_elem_t *ad_types_table = MP_OBJ_TO_PTR(constant_map->table); - - uint16_t num_of_elements = constant_map->used; - - for (uint16_t i = 0; i < num_of_elements; i++) { - mp_map_elem_t element = (mp_map_elem_t)*ad_types_table; - ad_types_table++; - uint16_t element_value = mp_obj_get_int(element.value); - - if (adv_item_type == element_value) { - qstr key_qstr = MP_OBJ_QSTR_VALUE(element.key); - const char * text = qstr_str(key_qstr); - size_t len = qstr_len(key_qstr); - - vstr_t vstr; - vstr_init(&vstr, len); - vstr_printf(&vstr, "%s", text); - description = mp_obj_new_str(vstr.buf, vstr.len); - vstr_clear(&vstr); - } - } - - t->items[0] = MP_OBJ_NEW_SMALL_INT(adv_item_type); - t->items[1] = description; - t->items[2] = mp_obj_new_bytearray(adv_item_len - 1, - &((uint8_t * )data->items)[byte_index + 2]); - mp_obj_list_append(retval_list, MP_OBJ_FROM_PTR(t)); - - byte_index += adv_item_len + 1; - } - - return retval_list; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(ubluepy_scan_entry_get_scan_data_obj, scan_entry_get_scan_data); - -STATIC const mp_rom_map_elem_t ubluepy_scan_entry_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_addr), MP_ROM_PTR(&bluepy_scan_entry_get_addr_obj) }, - { MP_ROM_QSTR(MP_QSTR_addr_type), MP_ROM_PTR(&bluepy_scan_entry_get_addr_type_obj) }, - { MP_ROM_QSTR(MP_QSTR_rssi), MP_ROM_PTR(&bluepy_scan_entry_get_rssi_obj) }, - { MP_ROM_QSTR(MP_QSTR_getScanData), MP_ROM_PTR(&ubluepy_scan_entry_get_scan_data_obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(ubluepy_scan_entry_locals_dict, ubluepy_scan_entry_locals_dict_table); - -const mp_obj_type_t ubluepy_scan_entry_type = { - { &mp_type_type }, - .name = MP_QSTR_ScanEntry, - .print = ubluepy_scan_entry_print, - .locals_dict = (mp_obj_dict_t*)&ubluepy_scan_entry_locals_dict -}; - -#endif // MICROPY_PY_UBLUEPY_CENTRAL diff --git a/ports/nrf/modules/ubluepy/ubluepy_scanner.c b/ports/nrf/modules/ubluepy/ubluepy_scanner.c deleted file mode 100644 index 1cde3d551..000000000 --- a/ports/nrf/modules/ubluepy/ubluepy_scanner.c +++ /dev/null @@ -1,124 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2017 Glenn Ruben Bakke - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include <string.h> -#include "py/obj.h" -#include "py/runtime.h" -#include "py/objstr.h" -#include "py/objlist.h" -#include "py/mphal.h" - -#if MICROPY_PY_UBLUEPY_CENTRAL - -#include "ble_drv.h" - -STATIC void adv_event_handler(mp_obj_t self_in, uint16_t event_id, ble_drv_adv_data_t * data) { - ubluepy_scanner_obj_t *self = MP_OBJ_TO_PTR(self_in); - - ubluepy_scan_entry_obj_t * item = m_new_obj(ubluepy_scan_entry_obj_t); - item->base.type = &ubluepy_scan_entry_type; - - vstr_t vstr; - vstr_init(&vstr, 17); - - vstr_printf(&vstr, ""HEX2_FMT":"HEX2_FMT":"HEX2_FMT":" \ - HEX2_FMT":"HEX2_FMT":"HEX2_FMT"", - data->p_peer_addr[5], data->p_peer_addr[4], data->p_peer_addr[3], - data->p_peer_addr[2], data->p_peer_addr[1], data->p_peer_addr[0]); - - item->addr = mp_obj_new_str(vstr.buf, vstr.len); - - vstr_clear(&vstr); - - item->addr_type = data->addr_type; - item->rssi = data->rssi; - item->data = mp_obj_new_bytearray(data->data_len, data->p_data); - - mp_obj_list_append(self->adv_reports, item); -} - -STATIC void ubluepy_scanner_print(const mp_print_t *print, mp_obj_t o, mp_print_kind_t kind) { - ubluepy_scanner_obj_t * self = (ubluepy_scanner_obj_t *)o; - (void)self; - mp_printf(print, "Scanner"); -} - -STATIC mp_obj_t ubluepy_scanner_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - static const mp_arg_t allowed_args[] = { - - }; - - // parse args - 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); - - ubluepy_scanner_obj_t * s = m_new_obj(ubluepy_scanner_obj_t); - s->base.type = type; - - return MP_OBJ_FROM_PTR(s); -} - -/// \method scan(timeout) -/// Scan for devices. Timeout is in milliseconds and will set the duration -/// of the scanning. -/// -STATIC mp_obj_t scanner_scan(mp_obj_t self_in, mp_obj_t timeout_in) { - ubluepy_scanner_obj_t * self = MP_OBJ_TO_PTR(self_in); - mp_int_t timeout = mp_obj_get_int(timeout_in); - - self->adv_reports = mp_obj_new_list(0, NULL); - - ble_drv_adv_report_handler_set(MP_OBJ_FROM_PTR(self), adv_event_handler); - - // start - ble_drv_scan_start(); - - // sleep - mp_hal_delay_ms(timeout); - - // stop - ble_drv_scan_stop(); - - return self->adv_reports; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(ubluepy_scanner_scan_obj, scanner_scan); - -STATIC const mp_rom_map_elem_t ubluepy_scanner_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&ubluepy_scanner_scan_obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(ubluepy_scanner_locals_dict, ubluepy_scanner_locals_dict_table); - - -const mp_obj_type_t ubluepy_scanner_type = { - { &mp_type_type }, - .name = MP_QSTR_Scanner, - .print = ubluepy_scanner_print, - .make_new = ubluepy_scanner_make_new, - .locals_dict = (mp_obj_dict_t*)&ubluepy_scanner_locals_dict -}; - -#endif // MICROPY_PY_UBLUEPY_CENTRAL diff --git a/ports/nrf/modules/ubluepy/ubluepy_service.c b/ports/nrf/modules/ubluepy/ubluepy_service.c deleted file mode 100644 index 59b81234f..000000000 --- a/ports/nrf/modules/ubluepy/ubluepy_service.c +++ /dev/null @@ -1,187 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2017 Glenn Ruben Bakke - * - * 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/obj.h" -#include "py/runtime.h" -#include "py/objlist.h" -#include "supervisor/shared/translate.h" - -#if MICROPY_PY_UBLUEPY_PERIPHERAL || MICROPY_PY_UBLUEPY_CENTRAL - -#include "modubluepy.h" -#include "ble_drv.h" - -STATIC void ubluepy_service_print(const mp_print_t *print, mp_obj_t o, mp_print_kind_t kind) { - ubluepy_service_obj_t * self = (ubluepy_service_obj_t *)o; - - mp_printf(print, "Service(handle: 0x" HEX2_FMT ")", self->handle); -} - -STATIC mp_obj_t ubluepy_service_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - - enum { ARG_NEW_UUID, ARG_NEW_TYPE }; - - static const mp_arg_t allowed_args[] = { - { ARG_NEW_UUID, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - { ARG_NEW_TYPE, MP_ARG_INT, {.u_int = UBLUEPY_SERVICE_PRIMARY} }, - }; - - // parse args - 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); - - ubluepy_service_obj_t *s = m_new_obj(ubluepy_service_obj_t); - s->base.type = type; - - mp_obj_t uuid_obj = args[ARG_NEW_UUID].u_obj; - - if (uuid_obj == MP_OBJ_NULL) { - return MP_OBJ_FROM_PTR(s); - } - - if (MP_OBJ_IS_TYPE(uuid_obj, &ubluepy_uuid_type)) { - s->p_uuid = MP_OBJ_TO_PTR(uuid_obj); - - uint8_t type = args[ARG_NEW_TYPE].u_int; - if (type > 0 && type <= UBLUEPY_SERVICE_PRIMARY) { - s->type = type; - } else { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, - translate("Invalid Service type"))); - } - - (void)ble_drv_service_add(s); - - } else { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, - translate("Invalid UUID parameter"))); - } - - // clear reference to peripheral - s->p_periph = NULL; - s->char_list = mp_obj_new_list(0, NULL); - - return MP_OBJ_FROM_PTR(s); -} - -/// \method addCharacteristic(Characteristic) -/// Add Characteristic to the Service. -/// -STATIC mp_obj_t service_add_characteristic(mp_obj_t self_in, mp_obj_t characteristic) { - ubluepy_service_obj_t * self = MP_OBJ_TO_PTR(self_in); - ubluepy_characteristic_obj_t * p_char = MP_OBJ_TO_PTR(characteristic); - - p_char->service_handle = self->handle; - - bool retval = ble_drv_characteristic_add(p_char); - - if (retval) { - p_char->p_service = self; - } - - mp_obj_list_append(self->char_list, characteristic); - - // return mp_obj_new_bool(retval); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(ubluepy_service_add_char_obj, service_add_characteristic); - -/// \method getCharacteristics() -/// Return list with all characteristics registered in the Service. -/// -STATIC mp_obj_t service_get_chars(mp_obj_t self_in) { - ubluepy_service_obj_t * self = MP_OBJ_TO_PTR(self_in); - - return self->char_list; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(ubluepy_service_get_chars_obj, service_get_chars); - -/// \method getCharacteristic(UUID) -/// Return Characteristic with the given UUID. -/// -STATIC mp_obj_t service_get_characteristic(mp_obj_t self_in, mp_obj_t uuid) { - ubluepy_service_obj_t * self = MP_OBJ_TO_PTR(self_in); - ubluepy_uuid_obj_t * p_uuid = MP_OBJ_TO_PTR(uuid); - - // validate that there is an UUID object passed in as parameter - if (!(MP_OBJ_IS_TYPE(uuid, &ubluepy_uuid_type))) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, - translate("Invalid UUID parameter"))); - } - - mp_obj_t * chars = NULL; - mp_uint_t num_chars = 0; - mp_obj_get_array(self->char_list, &num_chars, &chars); - - for (uint8_t i = 0; i < num_chars; i++) { - ubluepy_characteristic_obj_t * p_char = (ubluepy_characteristic_obj_t *)chars[i]; - - bool type_match = p_char->p_uuid->type == p_uuid->type; - bool uuid_match = ((uint16_t)(*(uint16_t *)&p_char->p_uuid->value[0]) == - (uint16_t)(*(uint16_t *)&p_uuid->value[0])); - - if (type_match && uuid_match) { - return MP_OBJ_FROM_PTR(p_char); - } - } - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(ubluepy_service_get_char_obj, service_get_characteristic); - -/// \method uuid() -/// Get UUID instance of the Service. -/// -STATIC mp_obj_t service_uuid(mp_obj_t self_in) { - ubluepy_service_obj_t * self = MP_OBJ_TO_PTR(self_in); - return MP_OBJ_FROM_PTR(self->p_uuid); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(ubluepy_service_get_uuid_obj, service_uuid); - -STATIC const mp_rom_map_elem_t ubluepy_service_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_getCharacteristic), MP_ROM_PTR(&ubluepy_service_get_char_obj) }, - { MP_ROM_QSTR(MP_QSTR_addCharacteristic), MP_ROM_PTR(&ubluepy_service_add_char_obj) }, - { MP_ROM_QSTR(MP_QSTR_getCharacteristics), MP_ROM_PTR(&ubluepy_service_get_chars_obj) }, -#if 0 - // Properties - { MP_ROM_QSTR(MP_QSTR_peripheral), MP_ROM_PTR(&ubluepy_service_get_peripheral_obj) }, -#endif - { MP_ROM_QSTR(MP_QSTR_uuid), MP_ROM_PTR(&ubluepy_service_get_uuid_obj) }, - { MP_ROM_QSTR(MP_QSTR_PRIMARY), MP_ROM_INT(UBLUEPY_SERVICE_PRIMARY) }, - { MP_ROM_QSTR(MP_QSTR_SECONDARY), MP_ROM_INT(UBLUEPY_SERVICE_SECONDARY) }, -}; - -STATIC MP_DEFINE_CONST_DICT(ubluepy_service_locals_dict, ubluepy_service_locals_dict_table); - -const mp_obj_type_t ubluepy_service_type = { - { &mp_type_type }, - .name = MP_QSTR_Service, - .print = ubluepy_service_print, - .make_new = ubluepy_service_make_new, - .locals_dict = (mp_obj_dict_t*)&ubluepy_service_locals_dict -}; - -#endif // MICROPY_PY_UBLUEPY_PERIPHERAL || MICROPY_PY_UBLUEPY_CENTRAL diff --git a/ports/nrf/modules/ubluepy/ubluepy_uuid.c b/ports/nrf/modules/ubluepy/ubluepy_uuid.c deleted file mode 100644 index b45494e41..000000000 --- a/ports/nrf/modules/ubluepy/ubluepy_uuid.c +++ /dev/null @@ -1,174 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2017 Glenn Ruben Bakke - * - * 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/obj.h" -#include "py/runtime.h" -#include "py/objstr.h" -#include "py/misc.h" -#include "supervisor/shared/translate.h" - -#if MICROPY_PY_UBLUEPY - -#include "modubluepy.h" -#include "ble_drv.h" - -STATIC void ubluepy_uuid_print(const mp_print_t *print, mp_obj_t o, mp_print_kind_t kind) { - ubluepy_uuid_obj_t * self = (ubluepy_uuid_obj_t *)o; - if (self->type == UBLUEPY_UUID_16_BIT) { - mp_printf(print, "UUID(uuid: 0x" HEX2_FMT HEX2_FMT ")", - self->value[1], self->value[0]); - } else { - mp_printf(print, "UUID(uuid: 0x" HEX2_FMT HEX2_FMT ", VS idx: " HEX2_FMT ")", - self->value[1], self->value[0], self->uuid_vs_idx); - } -} - -STATIC mp_obj_t ubluepy_uuid_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - - enum { ARG_NEW_UUID }; - - static const mp_arg_t allowed_args[] = { - { ARG_NEW_UUID, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - }; - - // parse args - 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); - - ubluepy_uuid_obj_t *s = m_new_obj(ubluepy_uuid_obj_t); - s->base.type = type; - - mp_obj_t uuid_obj = args[ARG_NEW_UUID].u_obj; - - if (uuid_obj == MP_OBJ_NULL) { - return MP_OBJ_FROM_PTR(s); - } - - if (MP_OBJ_IS_INT(uuid_obj)) { - s->type = UBLUEPY_UUID_16_BIT; - s->value[1] = (((uint16_t)mp_obj_get_int(uuid_obj)) >> 8) & 0xFF; - s->value[0] = ((uint8_t)mp_obj_get_int(uuid_obj)) & 0xFF; - } else if (MP_OBJ_IS_STR(uuid_obj)) { - GET_STR_DATA_LEN(uuid_obj, str_data, str_len); - if (str_len == 6) { // Assume hex digit prefixed with 0x - s->type = UBLUEPY_UUID_16_BIT; - s->value[0] = unichar_xdigit_value(str_data[5]); - s->value[0] += unichar_xdigit_value(str_data[4]) << 4; - s->value[1] = unichar_xdigit_value(str_data[3]); - s->value[1] += unichar_xdigit_value(str_data[2]) << 4; - } else if (str_len == 36) { - s->type = UBLUEPY_UUID_128_BIT; - uint8_t buffer[16]; - buffer[0] = unichar_xdigit_value(str_data[35]); - buffer[0] += unichar_xdigit_value(str_data[34]) << 4; - buffer[1] = unichar_xdigit_value(str_data[33]); - buffer[1] += unichar_xdigit_value(str_data[32]) << 4; - buffer[2] = unichar_xdigit_value(str_data[31]); - buffer[2] += unichar_xdigit_value(str_data[30]) << 4; - buffer[3] = unichar_xdigit_value(str_data[29]); - buffer[3] += unichar_xdigit_value(str_data[28]) << 4; - buffer[4] = unichar_xdigit_value(str_data[27]); - buffer[4] += unichar_xdigit_value(str_data[26]) << 4; - buffer[5] = unichar_xdigit_value(str_data[25]); - buffer[5] += unichar_xdigit_value(str_data[24]) << 4; - // 23 '-' - buffer[6] = unichar_xdigit_value(str_data[22]); - buffer[6] += unichar_xdigit_value(str_data[21]) << 4; - buffer[7] = unichar_xdigit_value(str_data[20]); - buffer[7] += unichar_xdigit_value(str_data[19]) << 4; - // 18 '-' - buffer[8] = unichar_xdigit_value(str_data[17]); - buffer[8] += unichar_xdigit_value(str_data[16]) << 4; - buffer[9] = unichar_xdigit_value(str_data[15]); - buffer[9] += unichar_xdigit_value(str_data[14]) << 4; - // 13 '-' - buffer[10] = unichar_xdigit_value(str_data[12]); - buffer[10] += unichar_xdigit_value(str_data[11]) << 4; - buffer[11] = unichar_xdigit_value(str_data[10]); - buffer[11] += unichar_xdigit_value(str_data[9]) << 4; - // 8 '-' - // 16-bit field - s->value[0] = unichar_xdigit_value(str_data[7]); - s->value[0] += unichar_xdigit_value(str_data[6]) << 4; - s->value[1] = unichar_xdigit_value(str_data[5]); - s->value[1] += unichar_xdigit_value(str_data[4]) << 4; - - buffer[14] = unichar_xdigit_value(str_data[3]); - buffer[14] += unichar_xdigit_value(str_data[2]) << 4; - buffer[15] = unichar_xdigit_value(str_data[1]); - buffer[15] += unichar_xdigit_value(str_data[0]) << 4; - - ble_drv_uuid_add_vs(buffer, &s->uuid_vs_idx); - } else { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, - translate("Invalid UUID string length"))); - } - } else if (MP_OBJ_IS_TYPE(uuid_obj, &ubluepy_uuid_type)) { - // deep copy instance - ubluepy_uuid_obj_t * p_old = MP_OBJ_TO_PTR(uuid_obj); - s->type = p_old->type; - s->value[0] = p_old->value[0]; - s->value[1] = p_old->value[1]; - } else { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, - translate("Invalid UUID parameter"))); - } - - return MP_OBJ_FROM_PTR(s); -} - -/// \method binVal() -/// Get binary value of the 16 or 128 bit UUID. Returned as bytearray type. -/// -STATIC mp_obj_t uuid_bin_val(mp_obj_t self_in) { - ubluepy_uuid_obj_t * self = MP_OBJ_TO_PTR(self_in); - - // TODO: Extend the uint16 byte value to 16 byte if 128-bit, - // also encapsulate it in a bytearray. For now, return - // the uint16_t field of the UUID. - return MP_OBJ_NEW_SMALL_INT(self->value[0] | self->value[1] << 8); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(ubluepy_uuid_bin_val_obj, uuid_bin_val); - -STATIC const mp_rom_map_elem_t ubluepy_uuid_locals_dict_table[] = { -#if 0 - { MP_ROM_QSTR(MP_QSTR_getCommonName), MP_ROM_PTR(&ubluepy_uuid_get_common_name_obj) }, -#endif - // Properties - { MP_ROM_QSTR(MP_QSTR_binVal), MP_ROM_PTR(&ubluepy_uuid_bin_val_obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(ubluepy_uuid_locals_dict, ubluepy_uuid_locals_dict_table); - -const mp_obj_type_t ubluepy_uuid_type = { - { &mp_type_type }, - .name = MP_QSTR_UUID, - .print = ubluepy_uuid_print, - .make_new = ubluepy_uuid_make_new, - .locals_dict = (mp_obj_dict_t*)&ubluepy_uuid_locals_dict -}; - -#endif // MICROPY_PY_UBLUEPY diff --git a/ports/nrf/mpconfigport.h b/ports/nrf/mpconfigport.h index b710808b9..86f5af20a 100644 --- a/ports/nrf/mpconfigport.h +++ b/ports/nrf/mpconfigport.h @@ -58,7 +58,7 @@ #define MICROPY_FATFS_LFN_CODE_PAGE (437) /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */ #define MICROPY_FATFS_USE_LABEL (1) #define MICROPY_FATFS_RPATH (2) -#define MICROPY_FATFS_MULTI_PARTITION (0) +#define MICROPY_FATFS_MULTI_PARTITION (1) #define MICROPY_FATFS_NUM_PERSISTENT (1) //#define MICROPY_FATFS_MAX_SS (4096) @@ -90,7 +90,6 @@ #define MICROPY_PY_BUILTINS_COMPILE (1) #define MICROPY_PY_BUILTINS_HELP (1) #define MICROPY_PY_BUILTINS_HELP_MODULES (1) -#define MICROPY_PY_BUILTINS_HELP_TEXT circuitpython_help_text #define MICROPY_PY_BUILTINS_INPUT (1) #define MICROPY_MODULE_BUILTIN_INIT (1) #define MICROPY_PY_ALL_SPECIAL_METHODS (0) @@ -113,7 +112,7 @@ #define MICROPY_PY_URANDOM_EXTRA_FUNCS (0) #define MICROPY_PY_UCTYPES (0) #define MICROPY_PY_UZLIB (0) -#define MICROPY_PY_UJSON (0) +#define MICROPY_PY_UJSON (1) #define MICROPY_PY_URE (0) #define MICROPY_PY_UHEAPQ (0) #define MICROPY_PY_UHASHLIB (1) @@ -129,21 +128,14 @@ #define CIRCUITPY_GAMEPAD_TICKS 0x1f #if BLUETOOTH_SD -#define MICROPY_PY_BLEIO (1) -#define MICROPY_PY_BLE_NUS (0) -#define MICROPY_PY_UBLUEPY (1) -#define MICROPY_PY_UBLUEPY_PERIPHERAL (1) -#define MICROPY_PY_UBLUEPY_CENTRAL (1) -#define BLUETOOTH_WEBBLUETOOTH_REPL (0) + #define MICROPY_PY_BLEIO (1) + #define MICROPY_PY_BLE_NUS (0) +#else + #ifndef MICROPY_PY_BLEIO + #define MICROPY_PY_BLEIO (0) + #endif #endif -#ifndef MICROPY_PY_BLEIO -#define MICROPY_PY_BLEIO (0) -#endif - -#ifndef MICROPY_PY_UBLUEPY -#define MICROPY_PY_UBLUEPY (0) -#endif // type definitions for the specific machine @@ -184,16 +176,8 @@ extern const struct _mp_obj_module_t neopixel_write_module; extern const struct _mp_obj_module_t usb_hid_module; extern const struct _mp_obj_module_t bleio_module; -extern const struct _mp_obj_module_t mp_module_ubluepy; - -#if MICROPY_PY_UBLUEPY -#define UBLUEPY_MODULE { MP_ROM_QSTR(MP_QSTR_ubluepy), MP_ROM_PTR(&mp_module_ubluepy) }, -#else -#define UBLUEPY_MODULE -#endif - #if MICROPY_PY_BLEIO -#define BLEIO_MODULE { MP_ROM_QSTR(MP_QSTR_bleio), MP_ROM_PTR(&bleio_module) }, +#define BLEIO_MODULE { MP_ROM_QSTR(MP_QSTR_bleio), MP_ROM_PTR(&bleio_module) }, #else #define BLEIO_MODULE #endif @@ -220,9 +204,9 @@ extern const struct _mp_obj_module_t mp_module_ubluepy; { MP_OBJ_NEW_QSTR (MP_QSTR_supervisor ), (mp_obj_t)&supervisor_module }, \ { MP_OBJ_NEW_QSTR (MP_QSTR_gamepad ), (mp_obj_t)&gamepad_module }, \ { MP_OBJ_NEW_QSTR (MP_QSTR_time ), (mp_obj_t)&time_module }, \ + { MP_OBJ_NEW_QSTR (MP_QSTR_json ), (mp_obj_t)&mp_module_ujson }, \ USBHID_MODULE \ - BLEIO_MODULE \ - UBLUEPY_MODULE \ + BLEIO_MODULE // extra built in names to add to the global namespace #define MICROPY_PORT_BUILTINS \ @@ -232,9 +216,12 @@ extern const struct _mp_obj_module_t mp_module_ubluepy; #define MP_STATE_PORT MP_STATE_VM +#include "supervisor/flash_root_pointers.h" + #define MICROPY_PORT_ROOT_POINTERS \ const char *readline_hist[8]; \ mp_obj_t gamepad_singleton; \ + FLASH_ROOT_POINTERS \ // We need to provide a declaration/definition of alloca() #include <alloca.h> diff --git a/ports/nrf/mpconfigport.mk b/ports/nrf/mpconfigport.mk index 17304b783..f43e29fce 100644 --- a/ports/nrf/mpconfigport.mk +++ b/ports/nrf/mpconfigport.mk @@ -5,3 +5,4 @@ MPY_TOOL_LONGINT_IMPL = -mlongint-impl=mpz INTERNAL_LIBM = (1) +USB_SERIAL_NUMBER_LENGTH = 16 diff --git a/ports/nrf/mphalport.c b/ports/nrf/mphalport.c index 1e1ebf32e..73f38bada 100644 --- a/ports/nrf/mphalport.c +++ b/ports/nrf/mphalport.c @@ -27,86 +27,9 @@ #include <string.h> -#include "mphalport.h" +#include "py/mphal.h" #include "py/mpstate.h" - - -#if (MICROPY_PY_BLE_NUS == 0) - -#if !defined( NRF52840_XXAA) || ( defined(CFG_HWUART_FOR_SERIAL) && CFG_HWUART_FOR_SERIAL == 1 ) -int mp_hal_stdin_rx_chr(void) { - uint8_t data = 0; - - while (!nrfx_uart_rx_ready(&serial_instance)); - - const nrfx_err_t err = nrfx_uart_rx(&serial_instance, &data, sizeof(data)); - if (err == NRFX_SUCCESS) - NRFX_ASSERT(err); - - return data; -} - -bool mp_hal_stdin_any(void) { - return nrfx_uart_rx_ready(&serial_instance); -} - -void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { - if (len == 0) - return; - - const nrfx_err_t err = nrfx_uart_tx(&serial_instance, (uint8_t*)str, len); - if (err == NRFX_SUCCESS) - NRFX_ASSERT(err); -} - -#else - -#include "tusb.h" - -int mp_hal_stdin_rx_chr(void) { - for (;;) { - #ifdef MICROPY_VM_HOOK_LOOP - MICROPY_VM_HOOK_LOOP - #endif - // if (reload_requested) { - // return CHAR_CTRL_D; - // } - - if (tud_cdc_available()) { - #ifdef MICROPY_HW_LED_RX - gpio_toggle_pin_level(MICROPY_HW_LED_RX); - #endif - return tud_cdc_read_char(); - } - } - - return 0; -} - -bool mp_hal_stdin_any(void) { - return tud_cdc_available() > 0; -} - -void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { - - #ifdef MICROPY_HW_LED_TX - gpio_toggle_pin_level(MICROPY_HW_LED_TX); - #endif - - #ifdef CIRCUITPY_BOOT_OUTPUT_FILE - if (boot_output_file != NULL) { - UINT bytes_written = 0; - f_write(boot_output_file, str, len, &bytes_written); - } - #endif - - tud_cdc_write(str, len); -} - -#endif // USB - -#endif // NUS - +#include "py/gc.h" /*------------------------------------------------------------------*/ /* delay @@ -126,4 +49,3 @@ void mp_hal_delay_ms(mp_uint_t delay) { // TODO(tannewt): Go to sleep for a little while while we wait. } } - diff --git a/ports/nrf/mphalport.h b/ports/nrf/mphalport.h index f283cf38d..a1929a4ac 100644 --- a/ports/nrf/mphalport.h +++ b/ports/nrf/mphalport.h @@ -31,21 +31,16 @@ #include <stdint.h> #include "lib/utils/interrupt_char.h" -#include "nrfx_uart.h" +#include "nrfx_uarte.h" #include "py/mpconfig.h" -extern nrfx_uart_t serial_instance; +extern nrfx_uarte_t serial_instance; extern volatile uint64_t ticks_ms; -static inline mp_uint_t mp_hal_ticks_ms(void) { - return ticks_ms; -} +#define mp_hal_ticks_ms() ((mp_uint_t) ticks_ms) +#define mp_hal_delay_us(us) NRFX_DELAY_US((uint32_t) (us)) -int mp_hal_stdin_rx_chr(void); -void mp_hal_stdout_tx_str(const char *str); bool mp_hal_stdin_any(void); -void mp_hal_delay_ms(mp_uint_t ms); -#define mp_hal_delay_us(us) NRFX_DELAY_US((uint32_t) (us)) #endif diff --git a/ports/nrf/nrfx b/ports/nrf/nrfx -Subproject 293f553ed9551c1fdfd05eac48e75bbdeb4e729 +Subproject b96950abf27229c2a3b1719d60691321246bfc9 diff --git a/ports/nrf/nrfx_config.h b/ports/nrf/nrfx_config.h index cc4d19327..1d3085e2b 100644 --- a/ports/nrf/nrfx_config.h +++ b/ports/nrf/nrfx_config.h @@ -27,14 +27,19 @@ // Enable SPIM2 and SPIM3 (if available) #define NRFX_SPIM2_ENABLED 1 -#ifdef NRF52840_XXAA +#ifdef NRF_SPIM3 #define NRFX_SPIM3_ENABLED 1 +#else + #define NRFX_SPIM3_ENABLED 0 #endif #define NRFX_SPIM_DEFAULT_CONFIG_IRQ_PRIORITY 7 #define NRFX_SPIM_MISO_PULL_CFG 1 +// QSPI +#define NRFX_QSPI_ENABLED 1 + // TWI aka. I2C; enable TWIM0 and TWIM1 (no conflict with SPIM choices) #define NRFX_TWIM_ENABLED 1 #define NRFX_TWIM0_ENABLED 1 @@ -45,13 +50,8 @@ #define NRFX_TWIM_DEFAULT_CONFIG_HOLD_BUS_UNINIT 0 // UART -#define NRFX_UART_ENABLED 1 -#define NRFX_UART0_ENABLED 1 - -#define NRFX_UART_DEFAULT_CONFIG_IRQ_PRIORITY 7 -#define NRFX_UART_DEFAULT_CONFIG_HWFC NRF_UART_HWFC_DISABLED -#define NRFX_UART_DEFAULT_CONFIG_PARITY NRF_UART_PARITY_EXCLUDED -#define NRFX_UART_DEFAULT_CONFIG_BAUDRATE NRF_UART_BAUDRATE_115200 +#define NRFX_UARTE_ENABLED 1 +#define NRFX_UARTE0_ENABLED 1 // PWM #define NRFX_PWM0_ENABLED 1 @@ -64,4 +64,24 @@ #define NRFX_PWM3_ENABLED 0 #endif +// TIMERS +#define NRFX_TIMER_ENABLED 1 +// Don't enable TIMER0: it's used by the SoftDevice. +#define NRFX_TIMER1_ENABLED 1 +#define NRFX_TIMER2_ENABLED 1 + +#ifdef NRFX_TIMER3 +#define NRFX_TIMER3_ENABLED 1 +#else +#define NRFX_TIMER3_ENABLED 0 +#endif + +#ifdef NRFX_TIMER4 +#define NRFX_TIMER4_ENABLED 1 +#else +#define NRFX_TIMER4_ENABLED 0 +#endif + +#define NRFX_TIMER_DEFAULT_CONFIG_IRQ_PRIORITY 7 + #endif // NRFX_CONFIG_H__ diff --git a/ports/nrf/peripherals/nrf/pins.h b/ports/nrf/peripherals/nrf/pins.h index 01aa9e956..33462d711 100644 --- a/ports/nrf/peripherals/nrf/pins.h +++ b/ports/nrf/peripherals/nrf/pins.h @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2018 Dan Halbert 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 diff --git a/ports/nrf/peripherals/nrf/timers.c b/ports/nrf/peripherals/nrf/timers.c new file mode 100644 index 000000000..7f7a003d3 --- /dev/null +++ b/ports/nrf/peripherals/nrf/timers.c @@ -0,0 +1,88 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Dan Halbert 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. + */ + +#include "common-hal/pulseio/PulseOut.h" + +#include <stdint.h> + +#include "nrfx.h" +#include "nrfx_timer.h" + +#include "py/mpconfig.h" +#include "py/runtime.h" + +STATIC nrfx_timer_t nrfx_timers[] = { +#if NRFX_CHECK(NRFX_TIMER0_ENABLED) + // Note that TIMER0 is reserved for use by the SoftDevice, so it should not usually be enabled. + NRFX_TIMER_INSTANCE(0), +#endif +#if NRFX_CHECK(NRFX_TIMER1_ENABLED) + NRFX_TIMER_INSTANCE(1), +#endif +#if NRFX_CHECK(NRFX_TIMER2_ENABLED) + NRFX_TIMER_INSTANCE(2), +#endif +#if NRFX_CHECK(NRFX_TIMER3_ENABLED) + NRFX_TIMER_INSTANCE(3), +#endif +#if NRFX_CHECK(NRFX_TIMER4_ENABLED) + NRFX_TIMER_INSTANCE(4), +#endif +}; + +static bool nrfx_timer_allocated[ARRAY_SIZE(nrfx_timers)]; + +void timers_reset(void) { + for (size_t i = 0; i < ARRAY_SIZE(nrfx_timers); i ++) { + nrfx_timer_uninit(&nrfx_timers[i]); + nrfx_timer_allocated[i] = false; + } +} + +// Returns a free nrfx_timer instance, and marks it as allocated. +// The caller should init as with the desired config. +// Returns NULL if no timer is available. +nrfx_timer_t* nrf_peripherals_allocate_timer(void) { + for (size_t i = 0; i < ARRAY_SIZE(nrfx_timers); i ++) { + if (!nrfx_timer_allocated[i]) { + nrfx_timer_allocated[i] = true; + return &nrfx_timers[i]; + } + } + return NULL; +} + +// Free a timer, which may or may not have been initialized. +void nrf_peripherals_free_timer(nrfx_timer_t* timer) { + for (size_t i = 0; i < ARRAY_SIZE(nrfx_timers); i ++) { + if (timer == &nrfx_timers[i]) { + nrfx_timer_allocated[i] = false; + // Safe to call even if not initialized. + nrfx_timer_uninit(timer); + return; + } + } +} diff --git a/ports/nrf/peripherals/nrf/timers.h b/ports/nrf/peripherals/nrf/timers.h new file mode 100644 index 000000000..7d3815579 --- /dev/null +++ b/ports/nrf/peripherals/nrf/timers.h @@ -0,0 +1,32 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Dan Halbert 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. + */ + +#include "nrfx.h" +#include "nrfx_timer.h" + +void timers_reset(void); +nrfx_timer_t* nrf_peripherals_allocate_timer(void); +void nrf_peripherals_free_timer(nrfx_timer_t* timer); diff --git a/ports/nrf/supervisor/filesystem.c b/ports/nrf/supervisor/filesystem.c deleted file mode 100644 index 1a3165a2d..000000000 --- a/ports/nrf/supervisor/filesystem.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2017 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. - */ - -#include "extmod/vfs_fat.h" -#include "lib/oofatfs/ff.h" -#include "lib/oofatfs/diskio.h" - -#include "py/mpstate.h" - -#include "internal_flash.h" - -static mp_vfs_mount_t _mp_vfs; -static fs_user_mount_t _internal_vfs; - - -void filesystem_init(bool create_allowed) { - // init the vfs object - fs_user_mount_t *int_vfs = &_internal_vfs; - int_vfs->flags = 0; - flash_init_vfs(int_vfs); - - // try to mount the flash - FRESULT res = f_mount(&int_vfs->fatfs); - - if (res == FR_NO_FILESYSTEM && create_allowed) { - // no filesystem so create a fresh one - uint8_t working_buf[_MAX_SS]; - res = f_mkfs(&int_vfs->fatfs, FM_FAT | FM_SFD, 4096, working_buf, sizeof(working_buf)); - // Flush the new file system to make sure its repaired immediately. - flash_flush(); - if (res != FR_OK) { - return; - } - - // set label - f_setlabel(&int_vfs->fatfs, "CIRCUITPY"); - - // create lib folder - f_mkdir(&int_vfs->fatfs, "/lib"); - - flash_flush(); - } else if (res != FR_OK) { - return; - } - - mp_vfs_mount_t *mp_vfs = &_mp_vfs; - mp_vfs->str = "/"; - mp_vfs->len = 1; - mp_vfs->obj = MP_OBJ_FROM_PTR(int_vfs); - mp_vfs->next = NULL; - MP_STATE_VM(vfs_mount_table) = mp_vfs; - - // The current directory is used as the boot up directory. - // It is set to the internal flash filesystem by default. - MP_STATE_PORT(vfs_cur) = mp_vfs; -} - -void filesystem_flush(void) { - flash_flush(); -} - -void filesystem_writable_by_python(bool writable) { - fs_user_mount_t *vfs = &_internal_vfs; - - if (writable) { - vfs->flags |= FSUSER_USB_WRITABLE; - } else { - vfs->flags &= ~FSUSER_USB_WRITABLE; - } -} - -bool filesystem_present(void) { - return true; -} diff --git a/ports/nrf/supervisor/internal_flash.c b/ports/nrf/supervisor/internal_flash.c new file mode 100644 index 000000000..a648afa17 --- /dev/null +++ b/ports/nrf/supervisor/internal_flash.c @@ -0,0 +1,121 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "supervisor/flash.h" + +#include <stdint.h> +#include <string.h> + +#include "extmod/vfs.h" +#include "extmod/vfs_fat.h" +#include "py/mphal.h" +#include "py/obj.h" +#include "py/runtime.h" +#include "lib/oofatfs/ff.h" + +#include "nrf_nvmc.h" + +#ifdef BLUETOOTH_SD +#include "nrf_sdm.h" +#endif + +// defined in linker +extern uint32_t __fatfs_flash_start_addr[]; +extern uint32_t __fatfs_flash_length[]; + +#define NO_CACHE 0xffffffff +#define FL_PAGE_SZ 4096 + +uint8_t _flash_cache[FL_PAGE_SZ] __attribute__((aligned(4))); +uint32_t _flash_page_addr = NO_CACHE; + + +/*------------------------------------------------------------------*/ +/* Internal Flash API + *------------------------------------------------------------------*/ +static inline uint32_t lba2addr(uint32_t block) { + return ((uint32_t)__fatfs_flash_start_addr) + block * FILESYSTEM_BLOCK_SIZE; +} + +void supervisor_flash_init(void) { +} + +uint32_t supervisor_flash_get_block_size(void) { + return FILESYSTEM_BLOCK_SIZE; +} + +uint32_t supervisor_flash_get_block_count(void) { + return ((uint32_t) __fatfs_flash_length) / FILESYSTEM_BLOCK_SIZE ; +} + +// TODO support flashing with SD enabled +void supervisor_flash_flush(void) { + if (_flash_page_addr == NO_CACHE) return; + + // Skip if data is the same + if (memcmp(_flash_cache, (void *)_flash_page_addr, FL_PAGE_SZ) != 0) { +// _is_flashing = true; + nrf_nvmc_page_erase(_flash_page_addr); + nrf_nvmc_write_words(_flash_page_addr, (uint32_t *)_flash_cache, FL_PAGE_SZ / sizeof(uint32_t)); + } + + _flash_page_addr = NO_CACHE; +} + +mp_uint_t supervisor_flash_read_blocks(uint8_t *dest, uint32_t block, uint32_t num_blocks) { + uint32_t src = lba2addr(block); + memcpy(dest, (uint8_t*) src, FILESYSTEM_BLOCK_SIZE*num_blocks); + return 0; // success +} + +mp_uint_t supervisor_flash_write_blocks(const uint8_t *src, uint32_t lba, uint32_t num_blocks) { + while (num_blocks) { + uint32_t const addr = lba2addr(lba); + uint32_t const page_addr = addr & ~(FL_PAGE_SZ - 1); + + uint32_t count = 8 - (lba % 8); // up to page boundary + count = MIN(num_blocks, count); + + if (page_addr != _flash_page_addr) { + supervisor_flash_flush(); + + // writing previous cached data, skip current data until flashing is done + // tinyusb stack will invoke write_block() with the same parameters later on + // if ( _is_flashing ) return; + + _flash_page_addr = page_addr; + memcpy(_flash_cache, (void *)page_addr, FL_PAGE_SZ); + } + + memcpy(_flash_cache + (addr & (FL_PAGE_SZ - 1)), src, count * FILESYSTEM_BLOCK_SIZE); + + // adjust for next run + lba += count; + src += count * FILESYSTEM_BLOCK_SIZE; + num_blocks -= count; + } + + return 0; // success +} diff --git a/ports/nrf/internal_flash.h b/ports/nrf/supervisor/internal_flash.h index 3811815e2..cf1dc91b5 100644 --- a/ports/nrf/internal_flash.h +++ b/ports/nrf/supervisor/internal_flash.h @@ -29,9 +29,7 @@ #include <stdbool.h> #include <stdint.h> -#include "mpconfigport.h" - -#define FLASH_ROOT_POINTERS +#include "py/mpconfig.h" #define FLASH_PAGE_SIZE 0x1000 #define CIRCUITPY_INTERNAL_NVM_SIZE 0 @@ -39,21 +37,4 @@ #define INTERNAL_FLASH_SYSTICK_MASK (0x1ff) // 512ms #define INTERNAL_FLASH_IDLE_TICK(tick) (((tick) & INTERNAL_FLASH_SYSTICK_MASK) == 2) -void internal_flash_init(void); -uint32_t internal_flash_get_block_size(void); -uint32_t internal_flash_get_block_count(void); -void internal_flash_irq_handler(void); -void internal_flash_flush(void); - -// these return 0 on success, non-zero on error -mp_uint_t internal_flash_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks); -mp_uint_t internal_flash_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks); - -extern const struct _mp_obj_type_t internal_flash_type; - -struct _fs_user_mount_t; - -void flash_init_vfs(struct _fs_user_mount_t *vfs); -void flash_flush(void); - #endif // MICROPY_INCLUDED_NRF_INTERNAL_FLASH_H diff --git a/ports/nrf/supervisor/internal_flash_root_pointers.h b/ports/nrf/supervisor/internal_flash_root_pointers.h new file mode 100644 index 000000000..cc6074585 --- /dev/null +++ b/ports/nrf/supervisor/internal_flash_root_pointers.h @@ -0,0 +1,31 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries LLC + * + * 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_NRF_INTERNAL_FLASH_ROOT_POINTERS_H +#define MICROPY_INCLUDED_NRF_INTERNAL_FLASH_ROOT_POINTERS_H + +#define FLASH_ROOT_POINTERS + +#endif // MICROPY_INCLUDED_NRF_INTERNAL_FLASH_ROOT_POINTERS_H diff --git a/ports/nrf/supervisor/port.c b/ports/nrf/supervisor/port.c index c858a3648..fcb3ae55c 100644 --- a/ports/nrf/supervisor/port.c +++ b/ports/nrf/supervisor/port.c @@ -31,12 +31,14 @@ #include "nrf/cache.h" #include "nrf/clocks.h" #include "nrf/power.h" +#include "nrf/timers.h" #include "shared-module/gamepad/__init__.h" #include "common-hal/microcontroller/Pin.h" #include "common-hal/busio/I2C.h" #include "common-hal/busio/SPI.h" #include "common-hal/pulseio/PWMOut.h" +#include "common-hal/pulseio/PulseOut.h" #include "tick.h" safe_mode_t port_init(void) { @@ -81,23 +83,23 @@ void reset_port(void) { i2c_reset(); spi_reset(); pwmout_reset(); + pulseout_reset(); + timers_reset(); reset_all_pins(); } +void reset_to_bootloader(void) { + enum { DFU_MAGIC_SERIAL = 0x4e }; + + NRF_POWER->GPREGRET = DFU_MAGIC_SERIAL; + NVIC_SystemReset(); +} + void HardFault_Handler(void) { -// static volatile uint32_t reg; -// static volatile uint32_t reg2; -// static volatile uint32_t bfar; -// reg = SCB->HFSR; -// reg2 = SCB->CFSR; -// bfar = SCB->BFAR; -// for (int i = 0; i < 0; i++) -// { -// (void)reg; -// (void)reg2; -// (void)bfar; -// } + while (true) { + asm(""); + } } diff --git a/ports/nrf/supervisor/qspi_flash.c b/ports/nrf/supervisor/qspi_flash.c new file mode 100644 index 000000000..048db06f2 --- /dev/null +++ b/ports/nrf/supervisor/qspi_flash.c @@ -0,0 +1,158 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 hathach for Adafruit Industries + * Copyright (c) 2018 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. + */ + +#include "supervisor/spi_flash_api.h" + +#include <stdint.h> +#include <string.h> + +#include "py/mpconfig.h" // for EXTERNAL_FLASH_QSPI_DUAL +#include "nrfx_qspi.h" + +#include "shared-bindings/microcontroller/__init__.h" + +#include "supervisor/shared/external_flash/common_commands.h" +#include "supervisor/shared/external_flash/qspi_flash.h" + +bool spi_flash_command(uint8_t command) { + nrf_qspi_cinstr_conf_t cinstr_cfg = { + .opcode = 0, + .length = 0, + .io2_level = true, + .io3_level = true, + .wipwait = false, + .wren = false + }; + cinstr_cfg.opcode = command; + cinstr_cfg.length = 1; + nrfx_qspi_cinstr_xfer(&cinstr_cfg, NULL, NULL); + return true; +} + +bool spi_flash_read_command(uint8_t command, uint8_t* response, uint32_t length) { + nrf_qspi_cinstr_conf_t cinstr_cfg = { + .opcode = command, + .length = length + 1, + .io2_level = true, + .io3_level = true, + .wipwait = false, + .wren = false + }; + nrfx_qspi_cinstr_xfer(&cinstr_cfg, NULL, response); + return true; +} + +bool spi_flash_write_command(uint8_t command, uint8_t* data, uint32_t length) { + nrf_qspi_cinstr_conf_t cinstr_cfg = { + .opcode = command, + .length = length + 1, + .io2_level = true, + .io3_level = true, + .wipwait = false, + .wren = false // We do this manually. + }; + nrfx_qspi_cinstr_xfer(&cinstr_cfg, data, NULL); + return true; +} + +bool spi_flash_sector_command(uint8_t command, uint32_t address) { + if (command != CMD_SECTOR_ERASE) { + return false; + } + return nrfx_qspi_erase(NRF_QSPI_ERASE_LEN_4KB, address) == NRFX_SUCCESS; +} + +bool spi_flash_write_data(uint32_t address, uint8_t* data, uint32_t length) { + return nrfx_qspi_write(data, length, address) == NRFX_SUCCESS; +} + +bool spi_flash_read_data(uint32_t address, uint8_t* data, uint32_t length) { + nrfx_qspi_read(data, length, address); + return true; +} + +void spi_flash_init(void) { + // Init QSPI flash + nrfx_qspi_config_t qspi_cfg = { + .xip_offset = 0, + .pins = { + .sck_pin = MICROPY_QSPI_SCK, + .csn_pin = MICROPY_QSPI_CS, + .io0_pin = MICROPY_QSPI_DATA0, + .io1_pin = NRF_QSPI_PIN_NOT_CONNECTED, + .io2_pin = NRF_QSPI_PIN_NOT_CONNECTED, + .io3_pin = NRF_QSPI_PIN_NOT_CONNECTED, + + }, + .prot_if = { + .readoc = NRF_QSPI_READOC_FASTREAD, + .writeoc = NRF_QSPI_WRITEOC_PP, + .addrmode = NRF_QSPI_ADDRMODE_24BIT, + .dpmconfig = false + }, + .phy_if = { + .sck_freq = NRF_QSPI_FREQ_32MDIV16, // Start at a slow 2mhz and speed up once we know what we're talking to. + .sck_delay = 10, // min time CS must stay high before going low again. in unit of 62.5 ns + .spi_mode = NRF_QSPI_MODE_0, + .dpmen = false + }, + .irq_priority = 7, + }; + +#if EXTERNAL_FLASH_QSPI_DUAL + qspi_cfg.pins.io1_pin = MICROPY_QSPI_DATA1; + qspi_cfg.prot_if.readoc = NRF_QSPI_READOC_READ2O; + qspi_cfg.prot_if.writeoc = NRF_QSPI_WRITEOC_PP2O; +#else + qspi_cfg.pins.io1_pin = MICROPY_QSPI_DATA1; + qspi_cfg.pins.io2_pin = MICROPY_QSPI_DATA2; + qspi_cfg.pins.io3_pin = MICROPY_QSPI_DATA3; + qspi_cfg.prot_if.readoc = NRF_QSPI_READOC_READ4IO; + qspi_cfg.prot_if.writeoc = NRF_QSPI_WRITEOC_PP4O; +#endif + + // No callback for blocking API + nrfx_qspi_init(&qspi_cfg, NULL, NULL); +} + +void spi_flash_init_device(const external_flash_device* device) { + check_quad_enable(device); + + // Switch to single output line if the device doesn't support quad programs. + if (!device->supports_qspi_writes) { + NRF_QSPI->IFCONFIG0 &= ~QSPI_IFCONFIG0_WRITEOC_Msk; + NRF_QSPI->IFCONFIG0 |= QSPI_IFCONFIG0_WRITEOC_PP; + } + + // Speed up as much as we can. + uint8_t sckfreq = 0; + while (32000000 / (sckfreq + 1) > device->max_clock_speed_mhz * 1000000 && sckfreq < 16) { + sckfreq += 1; + } + NRF_QSPI->IFCONFIG1 &= ~QSPI_IFCONFIG1_SCKFREQ_Msk; + NRF_QSPI->IFCONFIG1 |= sckfreq << QSPI_IFCONFIG1_SCKDELAY_Pos; +} diff --git a/ports/nrf/supervisor/serial.c b/ports/nrf/supervisor/serial.c index da7fe07fd..6fd89eb3e 100644 --- a/ports/nrf/supervisor/serial.c +++ b/ports/nrf/supervisor/serial.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * Copyright (c) 2017, 2018 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 @@ -24,85 +24,104 @@ * THE SOFTWARE. */ -#include "mphalport.h" +#include "py/mphal.h" -#if MICROPY_PY_BLE_NUS +#include "supervisor/serial.h" + +#if (MICROPY_PY_BLE_NUS == 1) #include "ble_uart.h" #else +#include <string.h> #include "nrf_gpio.h" +#include "nrfx_uarte.h" #endif -#if !defined( NRF52840_XXAA) || ( defined(CFG_HWUART_FOR_SERIAL) && CFG_HWUART_FOR_SERIAL == 1 ) - -#define INST_NO 0 - -nrfx_uart_t serial_instance = NRFX_UART_INSTANCE(INST_NO); +#if (MICROPY_PY_BLE_NUS == 1) void serial_init(void) { -#if MICROPY_PY_BLE_NUS - ble_uart_init0(); - while (!ble_uart_enabled()) { - ; - } -#else - nrfx_uart_config_t config = NRFX_UART_DEFAULT_CONFIG; - config.pseltxd = MICROPY_HW_UART_TX; - config.pselrxd = MICROPY_HW_UART_RX; - config.hwfc = MICROPY_HW_UART_HWFC ? NRF_UART_HWFC_ENABLED : NRF_UART_HWFC_DISABLED; -#ifdef MICROPY_HW_UART_CTS - config.pselcts = MICROPY_HW_UART_CTS; -#endif -#ifdef MICROPY_HW_UART_RTS - config.pselrts = MICROPY_HW_UART_RTS; -#endif - - const nrfx_err_t err = nrfx_uart_init(&serial_instance, &config, NULL); - if (err == NRFX_SUCCESS) - NRFX_ASSERT(err); - - nrfx_uart_rx_enable(&serial_instance); -#endif + ble_uart_init(); } bool serial_connected(void) { - return true; + return ble_uart_connected(); } char serial_read(void) { - return (char) mp_hal_stdin_rx_chr(); + return (char) ble_uart_rx_chr(); } bool serial_bytes_available(void) { - return mp_hal_stdin_any(); + return ble_uart_stdin_any(); } void serial_write(const char *text) { - mp_hal_stdout_tx_str(text); + ble_uart_stdout_tx_str(text); } -#else +#elif !defined(NRF52840_XXAA) -#include "tusb.h" +uint8_t serial_received_char; +nrfx_uarte_t serial_instance = NRFX_UARTE_INSTANCE(0); void serial_init(void) { - // usb is already initialized in board_init() -} + nrfx_uarte_config_t config = { + .pseltxd = MICROPY_HW_UART_TX, + .pselrxd = MICROPY_HW_UART_RX, + .pselcts = NRF_UARTE_PSEL_DISCONNECTED, + .pselrts = NRF_UARTE_PSEL_DISCONNECTED, + .p_context = NULL, + .hwfc = NRF_UARTE_HWFC_DISABLED, + .parity = NRF_UARTE_PARITY_EXCLUDED, + .baudrate = NRF_UARTE_BAUDRATE_115200, + .interrupt_priority = 7 + }; + + nrfx_uarte_uninit(&serial_instance); + const nrfx_err_t err = nrfx_uarte_init(&serial_instance, &config, NULL); // no callback for blocking mode + + if (err != NRFX_SUCCESS) { + NRFX_ASSERT(err); + } + // enabled receiving + nrf_uarte_task_trigger(serial_instance.p_reg, NRF_UARTE_TASK_STARTRX); +} bool serial_connected(void) { - return tud_cdc_connected(); + return true; } char serial_read(void) { - return (char) tud_cdc_read_char(); + uint8_t data; + nrfx_uarte_rx(&serial_instance, &data, 1); + return data; } bool serial_bytes_available(void) { - return tud_cdc_available() > 0; + return nrf_uarte_event_check(serial_instance.p_reg, NRF_UARTE_EVENT_RXDRDY); } void serial_write(const char* text) { - tud_cdc_write(text, strlen(text)); + serial_write_substring(text, strlen(text)); +} + +void serial_write_substring(const char *text, uint32_t len) { + if (len == 0) { + return; + } + + // EasyDMA can only access SRAM + uint8_t * tx_buf = (uint8_t*) text; + if ( !nrfx_is_in_ram(text) ) { + tx_buf = (uint8_t *) m_malloc(len, false); + memcpy(tx_buf, text, len); + } + + nrfx_uarte_tx(&serial_instance, tx_buf, len); + + if ( !nrfx_is_in_ram(text) ) { + m_free(tx_buf); + } } #endif diff --git a/ports/nrf/supervisor/usb.c b/ports/nrf/supervisor/usb.c new file mode 100644 index 000000000..a67c9311a --- /dev/null +++ b/ports/nrf/supervisor/usb.c @@ -0,0 +1,83 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 hathach 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. + */ + +#include "nrfx.h" +#include "nrfx_power.h" +#include "tick.h" +#include "supervisor/usb.h" +#include "lib/utils/interrupt_char.h" +#include "lib/mp-readline/readline.h" + +#ifdef SOFTDEVICE_PRESENT +#include "nrf_sdm.h" +#include "nrf_soc.h" +#endif + +/* tinyusb function that handles power event (detected, ready, removed) + * We must call it within SD's SOC event handler, or set it as power event handler if SD is not enabled. + */ +extern void tusb_hal_nrf_power_event(uint32_t event); + +void init_usb_hardware(void) { + + // USB power may already be ready at this time -> no event generated + // We need to invoke the handler based on the status initially + uint32_t usb_reg; + +#ifdef SOFTDEVICE_PRESENT + uint8_t sd_en = false; + (void) sd_softdevice_is_enabled(&sd_en); + + if ( sd_en ) { + sd_power_usbdetected_enable(true); + sd_power_usbpwrrdy_enable(true); + sd_power_usbremoved_enable(true); + + sd_power_usbregstatus_get(&usb_reg); + }else +#endif + { + // Power module init + const nrfx_power_config_t pwr_cfg = { 0 }; + nrfx_power_init(&pwr_cfg); + + // Register tusb function as USB power handler + const nrfx_power_usbevt_config_t config = { .handler = (nrfx_power_usb_event_handler_t) tusb_hal_nrf_power_event }; + nrfx_power_usbevt_init(&config); + + nrfx_power_usbevt_enable(); + + usb_reg = NRF_POWER->USBREGSTATUS; + } + + if ( usb_reg & POWER_USBREGSTATUS_VBUSDETECT_Msk ) { + tusb_hal_nrf_power_event(NRFX_POWER_USB_EVT_DETECTED); + } + + if ( usb_reg & POWER_USBREGSTATUS_OUTPUTRDY_Msk ) { + tusb_hal_nrf_power_event(NRFX_POWER_USB_EVT_READY); + } +} diff --git a/ports/nrf/tick.h b/ports/nrf/tick.h index 73f17d703..838e9fbea 100644 --- a/ports/nrf/tick.h +++ b/ports/nrf/tick.h @@ -26,7 +26,7 @@ #ifndef MICROPY_INCLUDED_NRF_TICK_H #define MICROPY_INCLUDED_NRF_TICK_H -#include "mpconfigport.h" +#include "py/mpconfig.h" #include <stdint.h> diff --git a/ports/nrf/usb/usb_desc.c b/ports/nrf/usb/usb_desc.c deleted file mode 100644 index 10d603528..000000000 --- a/ports/nrf/usb/usb_desc.c +++ /dev/null @@ -1,393 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2018 hathach 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. - */ - -#include "usb_desc.h" -#include "common-hal/usb_hid/Device.h" - -//--------------------------------------------------------------------+ -// MACRO TYPEDEF CONSTANT ENUM DECLARATION -//--------------------------------------------------------------------+ -#define USB_VID 0x239A - -/* Note: different class combination e.g CDC and (CDC + MSC) should have different - * PID since Host OS will "remembered" device driver after the first plug */ -#define USB_PID 0x802A - -/*------------- Interface Numbering -------------*/ -enum { - ITF_NUM_CDC = 0 , - ITF_NUM_CDC_DATA , - ITF_NUM_MSC , - ITF_NUM_HID_GEN , - ITF_NUM_TOTAL -}; - -enum { - ITF_STR_LANGUAGE = 0 , - ITF_STR_MANUFACTURER , - ITF_STR_PRODUCT , - ITF_STR_SERIAL , - ITF_STR_CDC , - ITF_STR_MSC , - ITF_STR_HID -}; - -/*------------- Endpoint Numbering & Size -------------*/ -#define _EP_IN(x) (0x80 | (x)) -#define _EP_OUT(x) (x) - -// CDC -#define EP_CDC_NOTIF _EP_IN ( ITF_NUM_CDC+1 ) -#define EP_CDC_NOTIF_SIZE 8 - -#define EP_CDC_OUT _EP_OUT( ITF_NUM_CDC+2 ) -#define EP_CDC_IN _EP_IN ( ITF_NUM_CDC+2 ) - -// Mass Storage -#define EP_MSC_OUT _EP_OUT( ITF_NUM_MSC+1 ) -#define EP_MSC_IN _EP_IN ( ITF_NUM_MSC+1 ) - -// HID composite = keyboard + mouse + gamepad + etc ... -#define EP_HID_GEN _EP_IN ( ITF_NUM_HID_GEN+1 ) -#define EP_HID_GEN_SIZE 16 - -//--------------------------------------------------------------------+ -// STRING DESCRIPTORS -//--------------------------------------------------------------------+ - -uint16_t usb_desc_str_serial[1+16] = { TUD_DESC_STR_HEADER(16) }; - -// array of pointer to string descriptors -uint16_t const * const string_desc_arr [] = -{ - // 0 index is supported language = English - TUD_DESC_STRCONV(0x0409), - - // 1 Manufacturer - TUD_DESC_STRCONV('A','d','a','f','r','u','i','t',' ','I','n','d','u','s','t','r','i','e','s'), - - // 2 Product - TUD_DESC_STRCONV('C','i','r','c','u','i','t','P','y',' ','n','R','F','5','2'), - - // 3 Serials TODO use chip ID - usb_desc_str_serial, - - // 4 CDC Interface - TUD_DESC_STRCONV('C','i','r','c','u','i','t','P','y',' ','S','e','r','i','a','l'), - - // 5 MSC Interface - TUD_DESC_STRCONV('C','i','r','c','u','i','t','P','y',' ','S','t','o','r','a','g','e'), - - // 6 HID Interface - TUD_DESC_STRCONV('C','i','r','c','u','i','t','P','y',' ','H','I','D'), - - // Custom Interface -// TUD_DESC_STRCONV('C','i','r','c','u','i','t','P','y',' ','C','u','s','t','o','m') -}; - - -//--------------------------------------------------------------------+ -// Device Descriptor -//--------------------------------------------------------------------+ -tusb_desc_device_t const usb_desc_dev = -{ - .bLength = sizeof(tusb_desc_device_t), - .bDescriptorType = TUSB_DESC_DEVICE, - .bcdUSB = 0x0200, - - #if CFG_TUD_CDC - // Use Interface Association Descriptor (IAD) for CDC - // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1) - .bDeviceClass = TUSB_CLASS_MISC, - .bDeviceSubClass = MISC_SUBCLASS_COMMON, - .bDeviceProtocol = MISC_PROTOCOL_IAD, - #else - .bDeviceClass = 0x00, - .bDeviceSubClass = 0x00, - .bDeviceProtocol = 0x00, - #endif - - .bMaxPacketSize0 = CFG_TUD_ENDOINT0_SIZE, - - .idVendor = USB_VID, - .idProduct = USB_PID, - .bcdDevice = 0x0100, - - .iManufacturer = 0x01, - .iProduct = 0x02, - .iSerialNumber = 0x03, - - .bNumConfigurations = 0x01 // TODO multiple configurations -}; - -//--------------------------------------------------------------------+ -// HID Report Descriptor -//--------------------------------------------------------------------+ -uint8_t const usb_desc_hid_generic_report[] = -{ -#if USB_HID_DEVICE_KEYBOARD - HID_REPORT_DESC_KEYBOARD( HID_REPORT_ID(USB_HID_REPORT_ID_KEYBOARD), ), -#endif - -#if USB_HID_DEVICE_MOUSE - HID_REPORT_DESC_MOUSE( HID_REPORT_ID(USB_HID_REPORT_ID_MOUSE), ), -#endif - -#if USB_HID_DEVICE_CONSUMER - HID_REPORT_DESC_CONSUMER( HID_REPORT_ID(USB_HID_REPORT_ID_CONSUMER), ), -#endif - -#if USB_HID_DEVICE_SYS_CONTROL - HID_REPORT_DESC_SYSTEM_CONTROL( HID_REPORT_ID(USB_HID_REPORT_ID_SYS_CONTROL ), ), -#endif - -#if USB_HID_DEVICE_GAMEPAD - HID_REPORT_DESC_GAMEPAD( HID_REPORT_ID(USB_HID_REPORT_ID_GAMEPAD ), ) -#endif - -}; - -//--------------------------------------------------------------------+ -// Configuration Descriptor -//--------------------------------------------------------------------+ -usb_desc_cfg_t const usb_desc_cfg = -{ - .config = - { - .bLength = sizeof(tusb_desc_configuration_t), - .bDescriptorType = TUSB_DESC_CONFIGURATION, - .wTotalLength = sizeof(usb_desc_cfg_t), - .bNumInterfaces = ITF_NUM_TOTAL, - .bConfigurationValue = 1, - .iConfiguration = 0x00, - .bmAttributes = TUSB_DESC_CONFIG_ATT_BUS_POWER, - .bMaxPower = TUSB_DESC_CONFIG_POWER_MA(100) - }, - - // IAD points to CDC Interfaces - .cdc = - { - .iad = - { - .bLength = sizeof(tusb_desc_interface_assoc_t), - .bDescriptorType = TUSB_DESC_INTERFACE_ASSOCIATION, - - .bFirstInterface = ITF_NUM_CDC, - .bInterfaceCount = 2, - - .bFunctionClass = TUSB_CLASS_CDC, - .bFunctionSubClass = CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, - .bFunctionProtocol = CDC_COMM_PROTOCOL_ATCOMMAND, - .iFunction = 0 - }, - - //------------- CDC Communication Interface -------------// - .comm_itf = - { - .bLength = sizeof(tusb_desc_interface_t), - .bDescriptorType = TUSB_DESC_INTERFACE, - .bInterfaceNumber = ITF_NUM_CDC, - .bAlternateSetting = 0, - .bNumEndpoints = 1, - .bInterfaceClass = TUSB_CLASS_CDC, - .bInterfaceSubClass = CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, - .bInterfaceProtocol = CDC_COMM_PROTOCOL_ATCOMMAND, - .iInterface = ITF_STR_CDC - }, - - .header = - { - .bLength = sizeof(cdc_desc_func_header_t), - .bDescriptorType = TUSB_DESC_CLASS_SPECIFIC, - .bDescriptorSubType = CDC_FUNC_DESC_HEADER, - .bcdCDC = 0x0120 - }, - - .call = - { - .bLength = sizeof(cdc_desc_func_call_management_t), - .bDescriptorType = TUSB_DESC_CLASS_SPECIFIC, - .bDescriptorSubType = CDC_FUNC_DESC_CALL_MANAGEMENT, - .bmCapabilities = { 0 }, - .bDataInterface = ITF_NUM_CDC+1, - }, - - .acm = - { - .bLength = sizeof(cdc_desc_func_acm_t), - .bDescriptorType = TUSB_DESC_CLASS_SPECIFIC, - .bDescriptorSubType = CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, - .bmCapabilities = { // 0x02 - .support_line_request = 1, - } - }, - - .union_func = - { - .bLength = sizeof(cdc_desc_func_union_t), // plus number of - .bDescriptorType = TUSB_DESC_CLASS_SPECIFIC, - .bDescriptorSubType = CDC_FUNC_DESC_UNION, - .bControlInterface = ITF_NUM_CDC, - .bSubordinateInterface = ITF_NUM_CDC+1, - }, - - .ep_notif = - { - .bLength = sizeof(tusb_desc_endpoint_t), - .bDescriptorType = TUSB_DESC_ENDPOINT, - .bEndpointAddress = EP_CDC_NOTIF, - .bmAttributes = { .xfer = TUSB_XFER_INTERRUPT }, - .wMaxPacketSize = { .size = EP_CDC_NOTIF_SIZE }, - .bInterval = 0x10 - }, - - //------------- CDC Data Interface -------------// - .data_itf = - { - .bLength = sizeof(tusb_desc_interface_t), - .bDescriptorType = TUSB_DESC_INTERFACE, - .bInterfaceNumber = ITF_NUM_CDC+1, - .bAlternateSetting = 0x00, - .bNumEndpoints = 2, - .bInterfaceClass = TUSB_CLASS_CDC_DATA, - .bInterfaceSubClass = 0, - .bInterfaceProtocol = 0, - .iInterface = 0x00 - }, - - .ep_out = - { - .bLength = sizeof(tusb_desc_endpoint_t), - .bDescriptorType = TUSB_DESC_ENDPOINT, - .bEndpointAddress = EP_CDC_OUT, - .bmAttributes = { .xfer = TUSB_XFER_BULK }, - .wMaxPacketSize = { .size = CFG_TUD_CDC_EPSIZE }, - .bInterval = 0 - }, - - .ep_in = - { - .bLength = sizeof(tusb_desc_endpoint_t), - .bDescriptorType = TUSB_DESC_ENDPOINT, - .bEndpointAddress = EP_CDC_IN, - .bmAttributes = { .xfer = TUSB_XFER_BULK }, - .wMaxPacketSize = { .size = CFG_TUD_CDC_EPSIZE }, - .bInterval = 0 - }, - }, - - //------------- Mass Storage-------------// - .msc = - { - .itf = - { - .bLength = sizeof(tusb_desc_interface_t), - .bDescriptorType = TUSB_DESC_INTERFACE, - .bInterfaceNumber = ITF_NUM_MSC, - .bAlternateSetting = 0x00, - .bNumEndpoints = 2, - .bInterfaceClass = TUSB_CLASS_MSC, - .bInterfaceSubClass = MSC_SUBCLASS_SCSI, - .bInterfaceProtocol = MSC_PROTOCOL_BOT, - .iInterface = ITF_STR_MSC - }, - - .ep_out = - { - .bLength = sizeof(tusb_desc_endpoint_t), - .bDescriptorType = TUSB_DESC_ENDPOINT, - .bEndpointAddress = EP_MSC_OUT, - .bmAttributes = { .xfer = TUSB_XFER_BULK }, - .wMaxPacketSize = { .size = CFG_TUD_MSC_EPSIZE}, - .bInterval = 1 - }, - - .ep_in = - { - .bLength = sizeof(tusb_desc_endpoint_t), - .bDescriptorType = TUSB_DESC_ENDPOINT, - .bEndpointAddress = EP_MSC_IN, - .bmAttributes = { .xfer = TUSB_XFER_BULK }, - .wMaxPacketSize = { .size = CFG_TUD_MSC_EPSIZE}, - .bInterval = 1 - } - }, - - //------------- HID Generic Multiple report -------------// - .hid_generic = - { - .itf = - { - .bLength = sizeof(tusb_desc_interface_t), - .bDescriptorType = TUSB_DESC_INTERFACE, - .bInterfaceNumber = ITF_NUM_HID_GEN, - .bAlternateSetting = 0x00, - .bNumEndpoints = 1, - .bInterfaceClass = TUSB_CLASS_HID, - .bInterfaceSubClass = 0, - .bInterfaceProtocol = 0, - .iInterface = ITF_STR_HID - }, - - .hid_desc = - { - .bLength = sizeof(tusb_hid_descriptor_hid_t), - .bDescriptorType = HID_DESC_TYPE_HID, - .bcdHID = 0x0111, - .bCountryCode = HID_Local_NotSupported, - .bNumDescriptors = 1, - .bReportType = HID_DESC_TYPE_REPORT, - .wReportLength = sizeof(usb_desc_hid_generic_report) - }, - - .ep_in = - { - .bLength = sizeof(tusb_desc_endpoint_t), - .bDescriptorType = TUSB_DESC_ENDPOINT, - .bEndpointAddress = EP_HID_GEN, - .bmAttributes = { .xfer = TUSB_XFER_INTERRUPT }, - .wMaxPacketSize = { .size = EP_HID_GEN_SIZE }, - .bInterval = 0x0A - } - } -}; - - -// tud_desc_set is required by tinyusb stack -tud_desc_set_t tud_desc_set = -{ - .device = &usb_desc_dev, - .config = &usb_desc_cfg, - .string_arr = (uint8_t const **) string_desc_arr, - .string_count = sizeof(string_desc_arr)/sizeof(string_desc_arr[0]), - - .hid_report = - { - .generic = usb_desc_hid_generic_report, - .boot_keyboard = NULL, - .boot_mouse = NULL - } -}; diff --git a/ports/nrf/usb/usb_desc.h b/ports/nrf/usb/usb_desc.h deleted file mode 100644 index 19f3f6d5b..000000000 --- a/ports/nrf/usb/usb_desc.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2018 hathach 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 USB_DESC_H_ -#define USB_DESC_H_ - -#include "tusb.h" - -#ifdef __cplusplus - extern "C" { -#endif - -/*------------- Configuration Descriptor -------------*/ -typedef struct ATTR_PACKED -{ - tusb_desc_configuration_t config; - - //------------- CDC -------------// - struct ATTR_PACKED - { - tusb_desc_interface_assoc_t iad; - - //CDC Control Interface - tusb_desc_interface_t comm_itf; - cdc_desc_func_header_t header; - cdc_desc_func_call_management_t call; - cdc_desc_func_acm_t acm; - cdc_desc_func_union_t union_func; - tusb_desc_endpoint_t ep_notif; - - //CDC Data Interface - tusb_desc_interface_t data_itf; - tusb_desc_endpoint_t ep_out; - tusb_desc_endpoint_t ep_in; - }cdc; - - //------------- Mass Storage -------------// - struct ATTR_PACKED - { - tusb_desc_interface_t itf; - tusb_desc_endpoint_t ep_out; - tusb_desc_endpoint_t ep_in; - } msc; - - //------------- HID -------------// - struct ATTR_PACKED - { - tusb_desc_interface_t itf; - tusb_hid_descriptor_hid_t hid_desc; - tusb_desc_endpoint_t ep_in; - } hid_generic; - -} usb_desc_cfg_t; - - -// Descriptors set used by tinyusb stack -extern tud_desc_set_t tud_desc_set; - - -#ifdef __cplusplus - } -#endif - -#endif /* USB_DESC_H_ */ diff --git a/py/builtinhelp.c b/py/builtinhelp.c index 4cea7e6d5..9a3407a16 100644 --- a/py/builtinhelp.c +++ b/py/builtinhelp.c @@ -27,6 +27,7 @@ #include <stdio.h> #include <string.h> +#include "genhdr/mpversion.h" #include "py/builtin.h" #include "py/mpconfig.h" #include "py/objmodule.h" @@ -133,7 +134,10 @@ STATIC void mp_help_print_modules(void) { } // let the user know there may be other modules available from the filesystem - mp_print_str(MP_PYTHON_PRINTER, "Plus any modules on the filesystem\n"); + const compressed_string_t* compressed = translate("Plus any modules on the filesystem\n"); + char decompressed[compressed->length]; + decompress(compressed, decompressed); + mp_print_str(MP_PYTHON_PRINTER, decompressed); } #endif @@ -174,8 +178,12 @@ STATIC void mp_help_print_obj(const mp_obj_t obj) { STATIC mp_obj_t mp_builtin_help(size_t n_args, const mp_obj_t *args) { if (n_args == 0) { - // print a general help message - mp_print_str(MP_PYTHON_PRINTER, MICROPY_PY_BUILTINS_HELP_TEXT); + // print a general help message. Translate only works on single strings on one line. + const compressed_string_t* compressed = + translate("Welcome to Adafruit CircuitPython %s!\n\nPlease visit learn.adafruit.com/category/circuitpython for project guides.\n\nTo list built-in modules please do `help(\"modules\")`.\n"); + char decompressed[compressed->length]; + decompress(compressed, decompressed); + mp_printf(MP_PYTHON_PRINTER, decompressed, MICROPY_GIT_TAG); } else { // try to print something sensible about the given object mp_help_print_obj(args[0]); diff --git a/py/builtinimport.c b/py/builtinimport.c index fee875b60..6ed0a7594 100755..100644 --- a/py/builtinimport.c +++ b/py/builtinimport.c @@ -155,11 +155,9 @@ STATIC void do_load_from_lexer(mp_obj_t module_obj, mp_lexer_t *lex) { #endif #if MICROPY_PERSISTENT_CODE_LOAD || MICROPY_MODULE_FROZEN_MPY -STATIC void do_execute_raw_code(mp_obj_t module_obj, mp_raw_code_t *raw_code) { +STATIC void do_execute_raw_code(mp_obj_t module_obj, mp_raw_code_t *raw_code, const char *filename) { #if MICROPY_PY___FILE__ - // TODO - //qstr source_name = lex->source_name; - //mp_store_attr(module_obj, MP_QSTR___file__, MP_OBJ_NEW_QSTR(source_name)); + mp_store_attr(module_obj, MP_QSTR___file__, MP_OBJ_NEW_QSTR(qstr_from_str(filename))); #endif // execute the module in its context @@ -222,7 +220,7 @@ STATIC void do_load(mp_obj_t module_obj, vstr_t *file) { // its data) in the list of frozen files, execute it. #if MICROPY_MODULE_FROZEN_MPY if (frozen_type == MP_FROZEN_MPY) { - do_execute_raw_code(module_obj, modref); + do_execute_raw_code(module_obj, modref, file_str); return; } #endif @@ -235,7 +233,7 @@ STATIC void do_load(mp_obj_t module_obj, vstr_t *file) { #if MICROPY_PERSISTENT_CODE_LOAD if (file_str[file->len - 3] == 'm') { mp_raw_code_t *raw_code = mp_raw_code_load_file(file_str); - do_execute_raw_code(module_obj, raw_code); + do_execute_raw_code(module_obj, raw_code, file_str); return; } #endif diff --git a/py/emitinlinethumb.c b/py/emitinlinethumb.c index 577f65672..7f0ec6659 100644 --- a/py/emitinlinethumb.c +++ b/py/emitinlinethumb.c @@ -59,7 +59,7 @@ struct _emit_inline_asm_t { qstr *label_lookup; }; -STATIC void emit_inline_thumb_error_msg(emit_inline_asm_t *emit, const char *msg) { +STATIC void emit_inline_thumb_error_msg(emit_inline_asm_t *emit, const compressed_string_t *msg) { *emit->error_slot = mp_obj_new_exception_msg(&mp_type_SyntaxError, msg); } @@ -99,17 +99,17 @@ STATIC void emit_inline_thumb_end_pass(emit_inline_asm_t *emit, mp_uint_t type_s STATIC mp_uint_t emit_inline_thumb_count_params(emit_inline_asm_t *emit, mp_uint_t n_params, mp_parse_node_t *pn_params) { if (n_params > 4) { - emit_inline_thumb_error_msg(emit, "can only have up to 4 parameters to Thumb assembly"); + emit_inline_thumb_error_msg(emit, translate("can only have up to 4 parameters to Thumb assembly")); return 0; } for (mp_uint_t i = 0; i < n_params; i++) { if (!MP_PARSE_NODE_IS_ID(pn_params[i])) { - emit_inline_thumb_error_msg(emit, "parameters must be registers in sequence r0 to r3"); + emit_inline_thumb_error_msg(emit, translate("parameters must be registers in sequence r0 to r3")); return 0; } const char *p = qstr_str(MP_PARSE_NODE_LEAF_ARG(pn_params[i])); if (!(strlen(p) == 2 && p[0] == 'r' && p[1] == '0' + i)) { - emit_inline_thumb_error_msg(emit, "parameters must be registers in sequence r0 to r3"); + emit_inline_thumb_error_msg(emit, translate("parameters must be registers in sequence r0 to r3")); return 0; } } @@ -185,7 +185,7 @@ STATIC mp_uint_t get_arg_reg(emit_inline_asm_t *emit, const char *op, mp_parse_n if (r->reg > max_reg) { emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, - "'%s' expects at most r%d", op, max_reg)); + translate("'%s' expects at most r%d"), op, max_reg)); return 0; } else { return r->reg; @@ -194,7 +194,7 @@ STATIC mp_uint_t get_arg_reg(emit_inline_asm_t *emit, const char *op, mp_parse_n } emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, - "'%s' expects a register", op)); + translate("'%s' expects a register"), op)); return 0; } @@ -208,7 +208,7 @@ STATIC mp_uint_t get_arg_special_reg(emit_inline_asm_t *emit, const char *op, mp } emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, - "'%s' expects a special register", op)); + translate("'%s' expects a special register"), op)); return 0; } @@ -227,7 +227,7 @@ STATIC mp_uint_t get_arg_vfpreg(emit_inline_asm_t *emit, const char *op, mp_pars if (regno > 31) { emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, - "'%s' expects at most r%d", op, 31)); + translate("'%s' expects at most r%d"), op, 31)); return 0; } else { return regno; @@ -236,7 +236,7 @@ STATIC mp_uint_t get_arg_vfpreg(emit_inline_asm_t *emit, const char *op, mp_pars malformed: emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, - "'%s' expects an FPU register", op)); + translate("'%s' expects an FPU register"), op)); return 0; } #endif @@ -289,19 +289,19 @@ STATIC mp_uint_t get_arg_reglist(emit_inline_asm_t *emit, const char *op, mp_par return reglist; bad_arg: - emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, "'%s' expects {r0, r1, ...}", op)); + emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, translate("'%s' expects {r0, r1, ...}"), op)); return 0; } STATIC uint32_t get_arg_i(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn, uint32_t fit_mask) { mp_obj_t o; if (!mp_parse_node_get_int_maybe(pn, &o)) { - emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, "'%s' expects an integer", op)); + emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, translate("'%s' expects an integer"), op)); return 0; } uint32_t i = mp_obj_get_int_truncated(o); if ((i & (~fit_mask)) != 0) { - emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, "'%s' integer 0x%x does not fit in mask 0x%x", op, i, fit_mask)); + emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, translate("'%s' integer 0x%x does not fit in mask 0x%x"), op, i, fit_mask)); return 0; } return i; @@ -325,13 +325,13 @@ STATIC bool get_arg_addr(emit_inline_asm_t *emit, const char *op, mp_parse_node_ return true; bad_arg: - emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, "'%s' expects an address of the form [a, b]", op)); + emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, translate("'%s' expects an address of the form [a, b]"), op)); return false; } STATIC int get_arg_label(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn) { if (!MP_PARSE_NODE_IS_ID(pn)) { - emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, "'%s' expects a label", op)); + emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, translate("'%s' expects a label"), op)); return 0; } qstr label_qstr = MP_PARSE_NODE_LEAF_ARG(pn); @@ -342,7 +342,7 @@ STATIC int get_arg_label(emit_inline_asm_t *emit, const char *op, mp_parse_node_ } // only need to have the labels on the last pass if (emit->pass == MP_PASS_EMIT) { - emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, "label '%q' not defined", label_qstr)); + emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, translate("label '%q' not defined"), label_qstr)); } return 0; } @@ -803,11 +803,11 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_a return; unknown_op: - emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, "unsupported Thumb instruction '%s' with %d arguments", op_str, n_args)); + emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, translate("unsupported Thumb instruction '%s' with %d arguments"), op_str, n_args)); return; branch_not_in_range: - emit_inline_thumb_error_msg(emit, "branch not in range"); + emit_inline_thumb_error_msg(emit, translate("branch not in range")); return; } diff --git a/py/makeqstrdata.py b/py/makeqstrdata.py index b0a043ee3..5b5ec1c37 100644 --- a/py/makeqstrdata.py +++ b/py/makeqstrdata.py @@ -349,8 +349,7 @@ def print_qstr_data(encoding_table, qcfgs, qstrs, i18ns): total_text_compressed_size += len(compressed) decompressed = decompress(encoding_table, len(translation_encoded), compressed).decode("utf-8") for c in C_ESCAPES: - decompressed.replace(c, C_ESCAPES[c]) - #print("// \"{}\"".format(translation)) + decompressed = decompressed.replace(c, C_ESCAPES[c]) print("TRANSLATION(\"{}\", {}, {{ {} }}) // {}".format(original, len(translation_encoded)+1, ", ".join(["0x{:02x}".format(x) for x in compressed]), decompressed)) total_text_size += len(translation.encode("utf-8")) diff --git a/py/mkenv.mk b/py/mkenv.mk index facb8a3c2..b76dd60f8 100644 --- a/py/mkenv.mk +++ b/py/mkenv.mk @@ -72,7 +72,7 @@ endif MAKE_FROZEN = $(PYTHON) $(TOP)/tools/make-frozen.py MPY_CROSS = $(TOP)/mpy-cross/mpy-cross -MPY_TOOL = $(PYTHON) $(TOP)/tools/mpy-tool.py +MPY_TOOL = $(PYTHON3) $(TOP)/tools/mpy-tool.py PREPROCESS_FROZEN_MODULES = PYTHONPATH=$(TOP)/tools/python-semver $(TOP)/tools/preprocess_frozen_modules.py all: diff --git a/py/mkrules.mk b/py/mkrules.mk index e619f2bdd..aa94ba412 100644 --- a/py/mkrules.mk +++ b/py/mkrules.mk @@ -130,7 +130,7 @@ xargs -n1 "$(abspath $(MPY_CROSS))" $(MPY_CROSS_FLAGS) # to build frozen_mpy.c from all .mpy files # You need to define MPY_TOOL_LONGINT_IMPL in mpconfigport.mk # if the default will not work (mpz is the default). -$(BUILD)/frozen_mpy.c: $(BUILD)/frozen_mpy $(BUILD)/genhdr/qstrdefs.generated.h +$(BUILD)/frozen_mpy.c: $(BUILD)/frozen_mpy $(BUILD)/genhdr/qstrdefs.generated.h $(TOP)/tools/mpy-tool.py $(STEPECHO) "Creating $@" $(Q)$(MPY_TOOL) $(MPY_TOOL_LONGINT_IMPL) -f -q $(BUILD)/genhdr/qstrdefs.preprocessed.h $(shell $(FIND) -L $(BUILD)/frozen_mpy -type f -name '*.mpy') > $@ endif diff --git a/py/modsys.c b/py/modsys.c index e32841923..68e048d91 100644 --- a/py/modsys.c +++ b/py/modsys.c @@ -135,7 +135,7 @@ STATIC mp_obj_t mp_sys_exc_info(void) { t->items[0] = MP_OBJ_FROM_PTR(mp_obj_get_type(cur_exc)); t->items[1] = cur_exc; - t->items[2] = mp_const_none; + t->items[2] = mp_obj_exception_get_traceback_obj(cur_exc); return MP_OBJ_FROM_PTR(t); } MP_DEFINE_CONST_FUN_OBJ_0(mp_sys_exc_info_obj, mp_sys_exc_info); diff --git a/py/moduerrno.c b/py/moduerrno.c index 255c1a73e..c1feafaa1 100644 --- a/py/moduerrno.c +++ b/py/moduerrno.c @@ -136,19 +136,28 @@ const char* mp_errno_to_str(mp_obj_t errno_val) { #endif //MICROPY_PY_UERRNO -// For commonly encountered errors, return human readable strings -const compressed_string_t* mp_common_errno_to_str(mp_obj_t errno_val) { - if (MP_OBJ_IS_SMALL_INT(errno_val)) { - switch (MP_OBJ_SMALL_INT_VALUE(errno_val)) { - case EPERM: return translate("Permission denied"); - case ENOENT: return translate("No such file/directory"); - case EIO: return translate("Input/output error"); - case EACCES: return translate("Permission denied"); - case EEXIST: return translate("File exists"); - case ENODEV: return translate("Unsupported operation"); - case EINVAL: return translate("Invalid argument"); - case EROFS: return translate("Read-only filesystem"); - } +// For commonly encountered errors, return human readable strings, otherwise try errno name +const char *mp_common_errno_to_str(mp_obj_t errno_val, char *buf, size_t len) { + if (!MP_OBJ_IS_SMALL_INT(errno_val)) { + return NULL; + } + + const compressed_string_t* desc = NULL; + switch (MP_OBJ_SMALL_INT_VALUE(errno_val)) { + case EPERM: desc = translate("Permission denied"); break; + case ENOENT: desc = translate("No such file/directory"); break; + case EIO: desc = translate("Input/output error"); break; + case EACCES: desc = translate("Permission denied"); break; + case EEXIST: desc = translate("File exists"); break; + case ENODEV: desc = translate("Unsupported operation"); break; + case EINVAL: desc = translate("Invalid argument"); break; + case EROFS: desc = translate("Read-only filesystem"); break; } - return NULL; + if (desc != NULL && desc->length <= len) { + decompress(desc, buf); + return buf; + } + + const char *msg = mp_errno_to_str(errno_val); + return msg[0] != '\0' ? msg : NULL; } diff --git a/py/mperrno.h b/py/mperrno.h index 876b090b5..911a9b413 100644 --- a/py/mperrno.h +++ b/py/mperrno.h @@ -141,7 +141,6 @@ #endif const char* mp_errno_to_str(mp_obj_t errno_val); -// For commonly encountered errors, return compressed human readable strings -const compressed_string_t* mp_common_errno_to_str(mp_obj_t errno_val); +const char *mp_common_errno_to_str(mp_obj_t errno_val, char *buf, size_t len); #endif // MICROPY_INCLUDED_PY_MPERRNO_H @@ -717,6 +717,7 @@ bool mp_obj_exception_match(mp_obj_t exc, mp_const_obj_t exc_type); void mp_obj_exception_clear_traceback(mp_obj_t self_in); void mp_obj_exception_add_traceback(mp_obj_t self_in, qstr file, size_t line, qstr block); void mp_obj_exception_get_traceback(mp_obj_t self_in, size_t *n, size_t **values); +mp_obj_t mp_obj_exception_get_traceback_obj(mp_obj_t self_in); mp_obj_t mp_obj_exception_get_value(mp_obj_t self_in); mp_obj_t mp_obj_exception_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args); mp_obj_t mp_alloc_emergency_exception_buf(mp_obj_t size_in); diff --git a/py/objboundmeth.c b/py/objboundmeth.c index b0df6a68a..a05680d41 100644 --- a/py/objboundmeth.c +++ b/py/objboundmeth.c @@ -92,6 +92,9 @@ STATIC void bound_meth_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { if (attr == MP_QSTR___name__) { mp_obj_bound_meth_t *o = MP_OBJ_TO_PTR(self_in); dest[0] = MP_OBJ_NEW_QSTR(mp_obj_fun_get_name(o->meth)); + } else if (attr == MP_QSTR___func__) { + mp_obj_bound_meth_t *o = MP_OBJ_TO_PTR(self_in); + dest[0] = o->meth; } } #endif diff --git a/py/objexcept.c b/py/objexcept.c index 8bd6245a4..c54e5fd4a 100644 --- a/py/objexcept.c +++ b/py/objexcept.c @@ -30,6 +30,7 @@ #include <stdio.h> #include "py/objlist.h" +#include "py/objnamedtuple.h" #include "py/objstr.h" #include "py/objtuple.h" #include "py/objtype.h" @@ -113,17 +114,11 @@ void mp_obj_exception_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kin return; } else if (o->args->len == 1) { // try to provide a nice OSError error message - if (o->base.type == &mp_type_OSError && MP_OBJ_IS_SMALL_INT(o->args->items[0])) { - const compressed_string_t* common = mp_common_errno_to_str(o->args->items[0]); - const char* msg; + if (MP_OBJ_IS_SMALL_INT(o->args->items[0]) && + mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(o->base.type), MP_OBJ_FROM_PTR(&mp_type_OSError))) { char decompressed[50]; - if (common != NULL && common->length <= 50) { - decompress(common, decompressed); - msg = decompressed; - } else { - msg = mp_errno_to_str(o->args->items[0]); - } - if (msg[0] != '\0') { + const char *msg = mp_common_errno_to_str(o->args->items[0], decompressed, sizeof(decompressed)); + if (msg != NULL) { mp_printf(print, "[Errno " INT_FMT "] %s", MP_OBJ_SMALL_INT_VALUE(o->args->items[0]), msg); return; } @@ -214,6 +209,31 @@ void mp_obj_exception_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { dest[0] = MP_OBJ_FROM_PTR(self->args); } else if (self->base.type == &mp_type_StopIteration && attr == MP_QSTR_value) { dest[0] = mp_obj_exception_get_value(self_in); + #if MICROPY_CPYTHON_COMPAT + } else if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(self->base.type), MP_OBJ_FROM_PTR(&mp_type_OSError))) { + if (attr == MP_QSTR_errno) { + dest[0] = mp_obj_exception_get_value(self_in); + } else if (attr == MP_QSTR_strerror) { + if (self->args->len > 1) { + dest[0] = self->args->items[1]; + } else if (self->args->len > 0) { + char decompressed[50]; + const char *msg = mp_common_errno_to_str(self->args->items[0], decompressed, sizeof(decompressed)); + if (msg != NULL) { + dest[0] = mp_obj_new_str(msg, strlen(msg)); + } else { + dest[0] = mp_const_none; + } + } else { + dest[0] = mp_const_none; + } + } else if (attr == MP_QSTR_filename) { + dest[0] = self->args->len > 2 ? self->args->items[2] : mp_const_none; + // skip winerror + } else if (attr == MP_QSTR_filename2) { + dest[0] = self->args->len > 4 ? self->args->items[4] : mp_const_none; + } + #endif } } @@ -531,3 +551,164 @@ void mp_obj_exception_get_traceback(mp_obj_t self_in, size_t *n, size_t **values *values = self->traceback_data; } } + +#if MICROPY_PY_SYS_EXC_INFO +STATIC const mp_obj_namedtuple_type_t code_type_obj = { + .base = { + .base = { + .type = &mp_type_type + }, + .name = MP_QSTR_code, + .print = namedtuple_print, + .make_new = namedtuple_make_new, + .unary_op = mp_obj_tuple_unary_op, + .binary_op = mp_obj_tuple_binary_op, + .attr = namedtuple_attr, + .subscr = mp_obj_tuple_subscr, + .getiter = mp_obj_tuple_getiter, + .parent = &mp_type_tuple, + }, + .n_fields = 15, + .fields = { + MP_QSTR_co_argcount, + MP_QSTR_co_kwonlyargcount, + MP_QSTR_co_nlocals, + MP_QSTR_co_stacksize, + MP_QSTR_co_flags, + MP_QSTR_co_code, + MP_QSTR_co_consts, + MP_QSTR_co_names, + MP_QSTR_co_varnames, + MP_QSTR_co_freevars, + MP_QSTR_co_cellvars, + MP_QSTR_co_filename, + MP_QSTR_co_name, + MP_QSTR_co_firstlineno, + MP_QSTR_co_lnotab, + }, +}; + +STATIC mp_obj_t code_make_new(qstr file, qstr block) { + mp_obj_t elems[15] = { + mp_obj_new_int(0), // co_argcount + mp_obj_new_int(0), // co_kwonlyargcount + mp_obj_new_int(0), // co_nlocals + mp_obj_new_int(0), // co_stacksize + mp_obj_new_int(0), // co_flags + mp_obj_new_bytearray(0, NULL), // co_code + mp_obj_new_tuple(0, NULL), // co_consts + mp_obj_new_tuple(0, NULL), // co_names + mp_obj_new_tuple(0, NULL), // co_varnames + mp_obj_new_tuple(0, NULL), // co_freevars + mp_obj_new_tuple(0, NULL), // co_cellvars + MP_OBJ_NEW_QSTR(file), // co_filename + MP_OBJ_NEW_QSTR(block), // co_name + mp_obj_new_int(1), // co_firstlineno + mp_obj_new_bytearray(0, NULL), // co_lnotab + }; + + return namedtuple_make_new((const mp_obj_type_t*)&code_type_obj, 15, 0, elems); +} + +STATIC const mp_obj_namedtuple_type_t frame_type_obj = { + .base = { + .base = { + .type = &mp_type_type + }, + .name = MP_QSTR_frame, + .print = namedtuple_print, + .make_new = namedtuple_make_new, + .unary_op = mp_obj_tuple_unary_op, + .binary_op = mp_obj_tuple_binary_op, + .attr = namedtuple_attr, + .subscr = mp_obj_tuple_subscr, + .getiter = mp_obj_tuple_getiter, + .parent = &mp_type_tuple, + }, + .n_fields = 8, + .fields = { + MP_QSTR_f_back, + MP_QSTR_f_builtins, + MP_QSTR_f_code, + MP_QSTR_f_globals, + MP_QSTR_f_lasti, + MP_QSTR_f_lineno, + MP_QSTR_f_locals, + MP_QSTR_f_trace, + }, +}; + +STATIC mp_obj_t frame_make_new(mp_obj_t f_code, int f_lineno) { + mp_obj_t elems[8] = { + mp_const_none, // f_back + mp_obj_new_dict(0), // f_builtins + f_code, // f_code + mp_obj_new_dict(0), // f_globals + mp_obj_new_int(0), // f_lasti + mp_obj_new_int(f_lineno), // f_lineno + mp_obj_new_dict(0), // f_locals + mp_const_none, // f_trace + }; + + return namedtuple_make_new((const mp_obj_type_t*)&frame_type_obj, 8, 0, elems); +} + +STATIC const mp_obj_namedtuple_type_t traceback_type_obj = { + .base = { + .base = { + .type = &mp_type_type + }, + .name = MP_QSTR_traceback, + .print = namedtuple_print, + .make_new = namedtuple_make_new, + .unary_op = mp_obj_tuple_unary_op, + .binary_op = mp_obj_tuple_binary_op, + .attr = namedtuple_attr, + .subscr = mp_obj_tuple_subscr, + .getiter = mp_obj_tuple_getiter, + .parent = &mp_type_tuple, + }, + .n_fields = 4, + .fields = { + MP_QSTR_tb_frame, + MP_QSTR_tb_lasti, + MP_QSTR_tb_lineno, + MP_QSTR_tb_next, + }, +}; + +STATIC mp_obj_t traceback_from_values(size_t *values, mp_obj_t tb_next) { + int lineno = values[1]; + + mp_obj_t elems[4] = { + frame_make_new(code_make_new(values[0], values[2]), lineno), + mp_obj_new_int(0), + mp_obj_new_int(lineno), + tb_next, + }; + + return namedtuple_make_new((const mp_obj_type_t*)&traceback_type_obj, 4, 0, elems); +}; + +mp_obj_t mp_obj_exception_get_traceback_obj(mp_obj_t self_in) { + mp_obj_exception_t *self = MP_OBJ_TO_PTR(self_in); + + if (!mp_obj_is_exception_instance(self)) { + return mp_const_none; + } + + size_t n, *values; + mp_obj_exception_get_traceback(self, &n, &values); + if (n == 0) { + return mp_const_none; + } + + mp_obj_t tb_next = mp_const_none; + + for (size_t i = 0; i < n; i += 3) { + tb_next = traceback_from_values(&values[i], tb_next); + } + + return tb_next; +} +#endif @@ -307,7 +307,7 @@ $(HEADER_BUILD)/qstrdefs.preprocessed.h: $(PY_QSTR_DEFS) $(QSTR_DEFS) $(QSTR_DEF # qstr data $(HEADER_BUILD)/qstrdefs.enum.h: $(PY_SRC)/makeqstrdata.py $(HEADER_BUILD)/qstrdefs.preprocessed.h $(STEPECHO) "GEN $@" - $(PYTHON3) $(PY_SRC)/makeqstrdata.py $(HEADER_BUILD)/qstrdefs.preprocessed.h > $@ + $(Q)$(PYTHON3) $(PY_SRC)/makeqstrdata.py $(HEADER_BUILD)/qstrdefs.preprocessed.h > $@ # Adding an order only dependency on $(HEADER_BUILD) causes $(HEADER_BUILD) to get # created before we run the script to generate the .h @@ -315,7 +315,7 @@ $(HEADER_BUILD)/qstrdefs.enum.h: $(PY_SRC)/makeqstrdata.py $(HEADER_BUILD)/qstrd # the lines in "" and then unwrap after the preprocessor is finished. $(HEADER_BUILD)/qstrdefs.generated.h: $(PY_SRC)/makeqstrdata.py $(HEADER_BUILD)/$(TRANSLATION).mo $(HEADER_BUILD)/qstrdefs.preprocessed.h $(STEPECHO) "GEN $@" - $(PYTHON3) $(PY_SRC)/makeqstrdata.py --compression_filename $(HEADER_BUILD)/compression.generated.h --translation $(HEADER_BUILD)/$(TRANSLATION).mo $(HEADER_BUILD)/qstrdefs.preprocessed.h > $@ + $(Q)$(PYTHON3) $(PY_SRC)/makeqstrdata.py --compression_filename $(HEADER_BUILD)/compression.generated.h --translation $(HEADER_BUILD)/$(TRANSLATION).mo $(HEADER_BUILD)/qstrdefs.preprocessed.h > $@ $(PY_BUILD)/qstr.o: $(HEADER_BUILD)/qstrdefs.generated.h diff --git a/shared-bindings/audioio/AudioOut.c b/shared-bindings/audioio/AudioOut.c index db5b371e2..18d908eef 100644 --- a/shared-bindings/audioio/AudioOut.c +++ b/shared-bindings/audioio/AudioOut.c @@ -43,13 +43,15 @@ //| //| AudioOut can be used to output an analog audio signal on a given pin. //| -//| .. class:: AudioOut(left_channel, right_channel=None) +//| .. class:: AudioOut(left_channel, *, right_channel=None, quiescent_value=0x8000) //| //| Create a AudioOut object associated with the given pin(s). This allows you to //| play audio signals out on the given pin(s). //| //| :param ~microcontroller.Pin left_channel: The pin to output the left channel to //| :param ~microcontroller.Pin right_channel: The pin to output the right channel to +//| :param int quiescent_value: The output value when no signal is present. Samples should start +//| and end with this value to prevent audible popping. //| //| Simple 8ksps 440 Hz sin wave:: //| @@ -95,10 +97,11 @@ STATIC mp_obj_t audioio_audioout_make_new(const mp_obj_type_t *type, size_t n_ar mp_arg_check_num(n_args, n_kw, 1, 2, true); mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args); - enum { ARG_left_channel, ARG_right_channel }; + enum { ARG_left_channel, ARG_right_channel, ARG_quiescent_value }; static const mp_arg_t allowed_args[] = { { MP_QSTR_left_channel, MP_ARG_OBJ | MP_ARG_REQUIRED }, { MP_QSTR_right_channel, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_rom_obj = mp_const_none} }, + { MP_QSTR_quiescent_value, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_int = 0x8000} }, }; 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); @@ -117,7 +120,7 @@ STATIC mp_obj_t audioio_audioout_make_new(const mp_obj_type_t *type, size_t n_ar // create AudioOut object from the given pin audioio_audioout_obj_t *self = m_new_obj(audioio_audioout_obj_t); self->base.type = &audioio_audioout_type; - common_hal_audioio_audioout_construct(self, left_channel_pin, right_channel_pin); + common_hal_audioio_audioout_construct(self, left_channel_pin, right_channel_pin, args[ARG_quiescent_value].u_int); return MP_OBJ_FROM_PTR(self); } diff --git a/shared-bindings/audioio/AudioOut.h b/shared-bindings/audioio/AudioOut.h index 751473605..d09a5c9ca 100644 --- a/shared-bindings/audioio/AudioOut.h +++ b/shared-bindings/audioio/AudioOut.h @@ -35,7 +35,7 @@ extern const mp_obj_type_t audioio_audioout_type; // left_channel will always be non-NULL but right_channel may be for mono output. void common_hal_audioio_audioout_construct(audioio_audioout_obj_t* self, - const mcu_pin_obj_t* left_channel, const mcu_pin_obj_t* right_channel); + const mcu_pin_obj_t* left_channel, const mcu_pin_obj_t* right_channel, uint16_t default_value); void common_hal_audioio_audioout_deinit(audioio_audioout_obj_t* self); bool common_hal_audioio_audioout_deinited(audioio_audioout_obj_t* self); diff --git a/shared-bindings/audioio/Mixer.c b/shared-bindings/audioio/Mixer.c new file mode 100644 index 000000000..dc7a12ebc --- /dev/null +++ b/shared-bindings/audioio/Mixer.c @@ -0,0 +1,249 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 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. + */ +#include "shared-bindings/audioio/Mixer.h" + +#include <stdint.h> + +#include "lib/utils/context_manager_helpers.h" +#include "py/binary.h" +#include "py/objproperty.h" +#include "py/runtime.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/audioio/RawSample.h" +#include "shared-bindings/util.h" +#include "supervisor/shared/translate.h" + +//| .. currentmodule:: audioio +//| +//| :class:`Mixer` -- Mixes one or more audio samples together +//| =========================================================== +//| +//| Mixer mixes multiple samples into one sample. +//| +//| .. class:: Mixer(channel_count=2, buffer_size=1024) +//| +//| Create a Mixer object that can mix multiple channels with the same sample rate. +//| +//| :param int channel_count: The maximum number of samples to mix at once +//| :param int buffer_size: The total size in bytes of the buffers to mix into +//| +//| Playing a wave file from flash:: +//| +//| import board +//| import audioio +//| import digitalio +//| +//| # Required for CircuitPlayground Express +//| speaker_enable = digitalio.DigitalInOut(board.SPEAKER_ENABLE) +//| speaker_enable.switch_to_output(value=True) +//| +//| music = audioio.WaveFile(open("cplay-5.1-16bit-16khz.wav", "rb")) +//| drum = audioio.WaveFile(open("drum.wav", "rb")) +//| mixer = audioio.Mixer(voice_count=2, sample_rate=16000, channel_count=1, bits_per_sample=16, samples_signed=True) +//| a = audioio.AudioOut(board.A0) +//| +//| print("playing") +//| a.play(mixer) +//| mixer.play(music, voice=0) +//| while mixer.playing: +//| mixer.play(drum, voice=1) +//| time.sleep(1) +//| print("stopped") +//| +STATIC mp_obj_t audioio_mixer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) { + mp_arg_check_num(n_args, n_kw, 0, 2, true); + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args); + enum { ARG_voice_count, ARG_buffer_size, ARG_channel_count, ARG_bits_per_sample, ARG_samples_signed, ARG_sample_rate }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_voice_count, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 2} }, + { MP_QSTR_buffer_size, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 1024} }, + { MP_QSTR_channel_count, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 2} }, + { MP_QSTR_bits_per_sample, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 16} }, + { MP_QSTR_samples_signed, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = true} }, + { MP_QSTR_sample_rate, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 8000} }, + }; + 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_int_t voice_count = args[ARG_voice_count].u_int; + if (voice_count < 1 || voice_count > 255) { + mp_raise_ValueError(translate("Invalid voice count")); + } + + mp_int_t channel_count = args[ARG_channel_count].u_int; + if (channel_count < 1 || channel_count > 2) { + mp_raise_ValueError(translate("Invalid channel count")); + } + mp_int_t sample_rate = args[ARG_sample_rate].u_int; + if (sample_rate < 1) { + mp_raise_ValueError(translate("Sample rate must be positive")); + } + mp_int_t bits_per_sample = args[ARG_bits_per_sample].u_int; + if (bits_per_sample != 8 && bits_per_sample != 16) { + mp_raise_ValueError(translate("bits_per_sample must be 8 or 16")); + } + audioio_mixer_obj_t *self = m_new_obj_var(audioio_mixer_obj_t, audioio_mixer_voice_t, voice_count); + self->base.type = &audioio_mixer_type; + common_hal_audioio_mixer_construct(self, voice_count, args[ARG_buffer_size].u_int, bits_per_sample, args[ARG_samples_signed].u_bool, channel_count, sample_rate); + + return MP_OBJ_FROM_PTR(self); +} + +//| .. method:: deinit() +//| +//| Deinitialises the Mixer and releases any hardware resources for reuse. +//| +STATIC mp_obj_t audioio_mixer_deinit(mp_obj_t self_in) { + audioio_mixer_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audioio_mixer_deinit(self); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(audioio_mixer_deinit_obj, audioio_mixer_deinit); + +//| .. method:: __enter__() +//| +//| No-op used by Context Managers. +//| +// Provided by context manager helper. + +//| .. method:: __exit__() +//| +//| Automatically deinitializes the hardware when exiting a context. See +//| :ref:`lifetime-and-contextmanagers` for more info. +//| +STATIC mp_obj_t audioio_mixer_obj___exit__(size_t n_args, const mp_obj_t *args) { + (void)n_args; + common_hal_audioio_mixer_deinit(args[0]); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audioio_mixer___exit___obj, 4, 4, audioio_mixer_obj___exit__); + + +//| .. method:: play(sample, *, voice=0, loop=False) +//| +//| Plays the sample once when loop=False and continuously when loop=True. +//| Does not block. Use `playing` to block. +//| +//| Sample must be an `audioio.WaveFile`, `audioio.Mixer` or `audioio.RawSample`. +//| +//| The sample must match the Mixer's encoding settings given in the constructor. +//| +STATIC mp_obj_t audioio_mixer_obj_play(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_sample, ARG_voice, ARG_loop }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_sample, MP_ARG_OBJ | MP_ARG_REQUIRED }, + { MP_QSTR_voice, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0} }, + { MP_QSTR_loop, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} }, + }; + audioio_mixer_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + raise_error_if_deinited(common_hal_audioio_mixer_deinited(self)); + 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); + + mp_obj_t sample = args[ARG_sample].u_obj; + common_hal_audioio_mixer_play(self, sample, args[ARG_voice].u_int, args[ARG_loop].u_bool); + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(audioio_mixer_play_obj, 1, audioio_mixer_obj_play); + +//| .. method:: stop_voice(voice=0) +//| +//| Stops playback of the sample on the given voice. +//| +STATIC mp_obj_t audioio_mixer_obj_stop_voice(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_voice }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_voice, MP_ARG_INT, {.u_int = 0} }, + }; + audioio_mixer_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + raise_error_if_deinited(common_hal_audioio_mixer_deinited(self)); + 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); + + common_hal_audioio_mixer_stop_voice(self, args[ARG_voice].u_int); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(audioio_mixer_stop_voice_obj, 1, audioio_mixer_obj_stop_voice); + +//| .. attribute:: playing +//| +//| True when any voice is being output. (read-only) +//| +STATIC mp_obj_t audioio_mixer_obj_get_playing(mp_obj_t self_in) { + audioio_mixer_obj_t *self = MP_OBJ_TO_PTR(self_in); + raise_error_if_deinited(common_hal_audioio_mixer_deinited(self)); + return mp_obj_new_bool(common_hal_audioio_mixer_get_playing(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(audioio_mixer_get_playing_obj, audioio_mixer_obj_get_playing); + +const mp_obj_property_t audioio_mixer_playing_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&audioio_mixer_get_playing_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj}, +}; + +//| .. attribute:: sample_rate +//| +//| 32 bit value that dictates how quickly samples are played in Hertz (cycles per second). +//| +STATIC mp_obj_t audioio_mixer_obj_get_sample_rate(mp_obj_t self_in) { + audioio_mixer_obj_t *self = MP_OBJ_TO_PTR(self_in); + raise_error_if_deinited(common_hal_audioio_mixer_deinited(self)); + return MP_OBJ_NEW_SMALL_INT(common_hal_audioio_mixer_get_sample_rate(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(audioio_mixer_get_sample_rate_obj, audioio_mixer_obj_get_sample_rate); + + +const mp_obj_property_t audioio_mixer_sample_rate_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&audioio_mixer_get_sample_rate_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj}, +}; + +STATIC const mp_rom_map_elem_t audioio_mixer_locals_dict_table[] = { + // Methods + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&audioio_mixer_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&audioio_mixer___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR_play), MP_ROM_PTR(&audioio_mixer_play_obj) }, + { MP_ROM_QSTR(MP_QSTR_stop_voice), MP_ROM_PTR(&audioio_mixer_stop_voice_obj) }, + + // Properties + { MP_ROM_QSTR(MP_QSTR_playing), MP_ROM_PTR(&audioio_mixer_playing_obj) }, + { MP_ROM_QSTR(MP_QSTR_sample_rate), MP_ROM_PTR(&audioio_mixer_sample_rate_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(audioio_mixer_locals_dict, audioio_mixer_locals_dict_table); + +const mp_obj_type_t audioio_mixer_type = { + { &mp_type_type }, + .name = MP_QSTR_Mixer, + .make_new = audioio_mixer_make_new, + .locals_dict = (mp_obj_dict_t*)&audioio_mixer_locals_dict, +}; diff --git a/shared-bindings/audioio/Mixer.h b/shared-bindings/audioio/Mixer.h new file mode 100644 index 000000000..832072b8f --- /dev/null +++ b/shared-bindings/audioio/Mixer.h @@ -0,0 +1,52 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 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_AUDIOIO_MIXER_H +#define MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOIO_MIXER_H + +#include "common-hal/microcontroller/Pin.h" +#include "shared-module/audioio/Mixer.h" +#include "shared-bindings/audioio/RawSample.h" + +extern const mp_obj_type_t audioio_mixer_type; + +void common_hal_audioio_mixer_construct(audioio_mixer_obj_t* self, + uint8_t voice_count, + uint32_t buffer_size, + uint8_t bits_per_sample, + bool samples_signed, + uint8_t channel_count, + uint32_t sample_rate); + +void common_hal_audioio_mixer_deinit(audioio_mixer_obj_t* self); +bool common_hal_audioio_mixer_deinited(audioio_mixer_obj_t* self); +void common_hal_audioio_mixer_play(audioio_mixer_obj_t* self, mp_obj_t sample, uint8_t voice, bool loop); +void common_hal_audioio_mixer_stop_voice(audioio_mixer_obj_t* self, uint8_t voice); + +bool common_hal_audioio_mixer_get_playing(audioio_mixer_obj_t* self); +uint32_t common_hal_audioio_mixer_get_sample_rate(audioio_mixer_obj_t* self); + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOIO_MIXER_H diff --git a/shared-bindings/audioio/WaveFile.c b/shared-bindings/audioio/WaveFile.c index 4ff0abdda..2d2ef578b 100644 --- a/shared-bindings/audioio/WaveFile.c +++ b/shared-bindings/audioio/WaveFile.c @@ -138,6 +138,43 @@ const mp_obj_property_t audioio_wavefile_sample_rate_obj = { (mp_obj_t)&mp_const_none_obj}, }; +//| .. attribute:: bits_per_sample +//| +//| Bits per sample. (read only) +//| +STATIC mp_obj_t audioio_wavefile_obj_get_bits_per_sample(mp_obj_t self_in) { + audioio_wavefile_obj_t *self = MP_OBJ_TO_PTR(self_in); + raise_error_if_deinited(common_hal_audioio_wavefile_deinited(self)); + return MP_OBJ_NEW_SMALL_INT(common_hal_audioio_wavefile_get_bits_per_sample(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(audioio_wavefile_get_bits_per_sample_obj, audioio_wavefile_obj_get_bits_per_sample); + +const mp_obj_property_t audioio_wavefile_bits_per_sample_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&audioio_wavefile_get_bits_per_sample_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj}, +}; + +//| .. attribute:: channel_count +//| +//| Number of audio channels. (read only) +//| +STATIC mp_obj_t audioio_wavefile_obj_get_channel_count(mp_obj_t self_in) { + audioio_wavefile_obj_t *self = MP_OBJ_TO_PTR(self_in); + raise_error_if_deinited(common_hal_audioio_wavefile_deinited(self)); + return MP_OBJ_NEW_SMALL_INT(common_hal_audioio_wavefile_get_channel_count(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(audioio_wavefile_get_channel_count_obj, audioio_wavefile_obj_get_channel_count); + +const mp_obj_property_t audioio_wavefile_channel_count_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&audioio_wavefile_get_channel_count_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj}, +}; + + STATIC const mp_rom_map_elem_t audioio_wavefile_locals_dict_table[] = { // Methods { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&audioio_wavefile_deinit_obj) }, @@ -146,6 +183,8 @@ STATIC const mp_rom_map_elem_t audioio_wavefile_locals_dict_table[] = { // Properties { MP_ROM_QSTR(MP_QSTR_sample_rate), MP_ROM_PTR(&audioio_wavefile_sample_rate_obj) }, + { MP_ROM_QSTR(MP_QSTR_bits_per_sample), MP_ROM_PTR(&audioio_wavefile_bits_per_sample_obj) }, + { MP_ROM_QSTR(MP_QSTR_channel_count), MP_ROM_PTR(&audioio_wavefile_channel_count_obj) }, }; STATIC MP_DEFINE_CONST_DICT(audioio_wavefile_locals_dict, audioio_wavefile_locals_dict_table); diff --git a/shared-bindings/audioio/WaveFile.h b/shared-bindings/audioio/WaveFile.h index 255ffbcd5..62a4200dc 100644 --- a/shared-bindings/audioio/WaveFile.h +++ b/shared-bindings/audioio/WaveFile.h @@ -40,5 +40,7 @@ void common_hal_audioio_wavefile_deinit(audioio_wavefile_obj_t* self); bool common_hal_audioio_wavefile_deinited(audioio_wavefile_obj_t* self); uint32_t common_hal_audioio_wavefile_get_sample_rate(audioio_wavefile_obj_t* self); void common_hal_audioio_wavefile_set_sample_rate(audioio_wavefile_obj_t* self, uint32_t sample_rate); +uint8_t common_hal_audioio_wavefile_get_bits_per_sample(audioio_wavefile_obj_t* self); +uint8_t common_hal_audioio_wavefile_get_channel_count(audioio_wavefile_obj_t* self); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOIO_WAVEFILE_H diff --git a/shared-bindings/audioio/__init__.c b/shared-bindings/audioio/__init__.c index 8a00b43d8..4786b6425 100644 --- a/shared-bindings/audioio/__init__.c +++ b/shared-bindings/audioio/__init__.c @@ -32,6 +32,8 @@ #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/audioio/__init__.h" #include "shared-bindings/audioio/AudioOut.h" +#include "shared-bindings/audioio/Mixer.h" +#include "shared-bindings/audioio/RawSample.h" #include "shared-bindings/audioio/WaveFile.h" //| :mod:`audioio` --- Support for audio input and output @@ -49,6 +51,7 @@ //| :maxdepth: 3 //| //| AudioOut +//| Mixer //| RawSample //| WaveFile //| @@ -61,6 +64,7 @@ STATIC const mp_rom_map_elem_t audioio_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_audioio) }, { MP_ROM_QSTR(MP_QSTR_AudioOut), MP_ROM_PTR(&audioio_audioout_type) }, + { MP_ROM_QSTR(MP_QSTR_Mixer), MP_ROM_PTR(&audioio_mixer_type) }, { MP_ROM_QSTR(MP_QSTR_RawSample), MP_ROM_PTR(&audioio_rawsample_type) }, { MP_ROM_QSTR(MP_QSTR_WaveFile), MP_ROM_PTR(&audioio_wavefile_type) }, }; diff --git a/shared-bindings/bleio/Adapter.c b/shared-bindings/bleio/Adapter.c index bfe87071d..d9449d3ab 100644 --- a/shared-bindings/bleio/Adapter.c +++ b/shared-bindings/bleio/Adapter.c @@ -25,6 +25,7 @@ */ #include "py/objproperty.h" +#include "shared-bindings/bleio/Address.h" #include "shared-bindings/bleio/Adapter.h" //| .. currentmodule:: bleio @@ -57,8 +58,6 @@ //| MAC address of the BLE adapter. (read-only) //| -#define BLE_ADDRESS_LEN 17 - STATIC mp_obj_t bleio_adapter_get_enabled(mp_obj_t self) { return mp_obj_new_bool(common_hal_bleio_adapter_get_enabled()); } @@ -81,16 +80,12 @@ const mp_obj_property_t bleio_adapter_enabled_obj = { }; STATIC mp_obj_t bleio_adapter_get_address(mp_obj_t self) { - vstr_t vstr; - vstr_init(&vstr, BLE_ADDRESS_LEN); - - common_hal_bleio_adapter_get_address(&vstr); - - const mp_obj_t mac_str = mp_obj_new_str(vstr.buf, vstr.len); + mp_obj_t obj = bleio_address_type.make_new(&bleio_address_type, 1, 0, mp_const_none); + bleio_address_obj_t *address = MP_OBJ_TO_PTR(obj); - vstr_clear(&vstr); + common_hal_bleio_adapter_get_address(address); - return mac_str; + return obj; } MP_DEFINE_CONST_FUN_OBJ_1(bleio_adapter_get_address_obj, bleio_adapter_get_address); diff --git a/shared-bindings/bleio/Adapter.h b/shared-bindings/bleio/Adapter.h index 6c5d56948..fe3886e59 100644 --- a/shared-bindings/bleio/Adapter.h +++ b/shared-bindings/bleio/Adapter.h @@ -27,12 +27,12 @@ #ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADAPTER_H #define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADAPTER_H -#include "py/obj.h" +#include "shared-module/bleio/Address.h" const mp_obj_type_t bleio_adapter_type; extern bool common_hal_bleio_adapter_get_enabled(void); extern void common_hal_bleio_adapter_set_enabled(bool enabled); -extern void common_hal_bleio_adapter_get_address(vstr_t *address); +extern void common_hal_bleio_adapter_get_address(bleio_address_obj_t *address); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADAPTER_H diff --git a/shared-bindings/bleio/Address.c b/shared-bindings/bleio/Address.c new file mode 100644 index 000000000..ec23ff207 --- /dev/null +++ b/shared-bindings/bleio/Address.c @@ -0,0 +1,167 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Artur Pacholec + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include <string.h> +#include <stdio.h> + +#include "py/objproperty.h" +#include "py/objstr.h" +#include "py/runtime.h" +#include "shared-bindings/bleio/Address.h" +#include "shared-module/bleio/Address.h" + +#define ADDRESS_LONG_LEN 17 // XX:XX:XX:XX:XX:XX +#define ADDRESS_SHORT_LEN 12 // XXXXXXXXXXXX + +//| .. currentmodule:: bleio +//| +//| :class:`Address` -- BLE address +//| ========================================================= +//| +//| Encapsulates the address of a BLE device. +//| + +//| .. class:: Address(address) +//| +//| Create a new Address object encapsulating the address value. +//| The value itself can be one of: +//| +//| - a `str` value in the format of 'XXXXXXXXXXXX' or 'XX:XX:XX:XX:XX' +//| - a `bytes` or `bytearray` containing 6 bytes +//| - another Address object +//| +//| :param address: The address to encapsulate +//| + +//| .. attribute:: type +//| +//| The address type. One of: +//| +//| - `bleio.AddressType.PUBLIC` +//| - `bleio.AddressType.RANDOM_STATIC` +//| - `bleio.AddressType.RANDOM_PRIVATE_RESOLVABLE` +//| - `bleio.AddressType.RANDOM_PRIVATE_NON_RESOLVABLE` +//| +STATIC mp_obj_t bleio_address_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) { + mp_arg_check_num(n_args, n_kw, 1, 1, true); + bleio_address_obj_t *self = m_new_obj(bleio_address_obj_t); + self->base.type = &bleio_address_type; + self->type = ADDRESS_PUBLIC; + + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args); + + enum { ARG_address }; + static const mp_arg_t allowed_args[] = { + { ARG_address, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + }; + + 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); + + const mp_obj_t address = args[ARG_address].u_obj; + + if (MP_OBJ_IS_STR(address)) { + GET_STR_DATA_LEN(address, str_data, str_len); + const bool is_long = (str_len == ADDRESS_LONG_LEN); + const bool is_short = (str_len == ADDRESS_SHORT_LEN); + + if (is_long || is_short) { + size_t i = str_len - 1; + for (size_t b = 0; b < BLEIO_ADDRESS_BYTES; ++b) { + self->value[b] = unichar_xdigit_value(str_data[i]) | + unichar_xdigit_value(str_data[i - 1]) << 4; + + i -= is_long ? 3 : 2; + } + } else { + mp_raise_ValueError(translate("Wrong address length")); + } + } else if (MP_OBJ_IS_TYPE(address, &mp_type_bytearray) || MP_OBJ_IS_TYPE(address, &mp_type_bytes)) { + mp_buffer_info_t buf_info; + mp_get_buffer_raise(address, &buf_info, MP_BUFFER_READ); + if (buf_info.len != BLEIO_ADDRESS_BYTES) { + mp_raise_ValueError(translate("Wrong number of bytes provided")); + } + + for (size_t b = 0; b < BLEIO_ADDRESS_BYTES; ++b) { + self->value[BLEIO_ADDRESS_BYTES - b - 1] = ((uint8_t*)buf_info.buf)[b]; + } + } else if (MP_OBJ_IS_TYPE(address, &bleio_address_type)) { + // deep copy + bleio_address_obj_t *other = MP_OBJ_TO_PTR(address); + self->type = other->type; + memcpy(self->value, other->value, BLEIO_ADDRESS_BYTES); + } + + return MP_OBJ_FROM_PTR(self); +} + +STATIC void bleio_address_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + bleio_address_obj_t *self = MP_OBJ_TO_PTR(self_in); + + mp_printf(print, "Address('"HEX2_FMT":"HEX2_FMT":"HEX2_FMT":"HEX2_FMT":"HEX2_FMT":"HEX2_FMT"')", + self->value[5], self->value[4], self->value[3], + self->value[2], self->value[1], self->value[0]); +} + +STATIC mp_obj_t bleio_address_get_type(mp_obj_t self_in) { + bleio_address_obj_t *self = MP_OBJ_TO_PTR(self_in); + + if (self->type == ADDRESS_PUBLIC) { + return (mp_obj_t)&bleio_addresstype_public_obj; + } else if (self->type == ADDRESS_RANDOM_STATIC) { + return (mp_obj_t)&bleio_addresstype_random_static_obj; + } else if (self->type == ADDRESS_RANDOM_PRIVATE_RESOLVABLE) { + return (mp_obj_t)&bleio_addresstype_random_private_resolvable_obj; + } else if (self->type == ADDRESS_RANDOM_PRIVATE_NON_RESOLVABLE) { + return (mp_obj_t)&bleio_addresstype_random_private_non_resolvable_obj; + } + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(bleio_address_get_type_obj, bleio_address_get_type); + +const mp_obj_property_t bleio_address_type_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&bleio_address_get_type_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj}, +}; + +STATIC const mp_rom_map_elem_t bleio_address_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_type), MP_ROM_PTR(&bleio_address_type_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(bleio_address_locals_dict, bleio_address_locals_dict_table); + +const mp_obj_type_t bleio_address_type = { + { &mp_type_type }, + .name = MP_QSTR_Address, + .print = bleio_address_print, + .make_new = bleio_address_make_new, + .locals_dict = (mp_obj_dict_t*)&bleio_address_locals_dict +}; diff --git a/shared-bindings/bleio/Address.h b/shared-bindings/bleio/Address.h new file mode 100644 index 000000000..9c9e20968 --- /dev/null +++ b/shared-bindings/bleio/Address.h @@ -0,0 +1,34 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Artur Pacholec + * + * 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_BLEIO_ADDRESS_H +#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADDRESS_H + +#include "py/objtype.h" + +extern const mp_obj_type_t bleio_address_type; + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADDRESS_H diff --git a/shared-bindings/bleio/AddressType.c b/shared-bindings/bleio/AddressType.c new file mode 100644 index 000000000..cf2151c94 --- /dev/null +++ b/shared-bindings/bleio/AddressType.c @@ -0,0 +1,99 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Artur Pacholec + * + * 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 "shared-bindings/bleio/AddressType.h" + +//| .. currentmodule:: bleio +//| +//| :class:`AddressType` -- defines the type of a BLE address +//| ============================================================= +//| +//| .. class:: bleio.AddressType +//| +//| Enum-like class to define the type of a BLE address, see also `bleio.Address`. +//| +//| .. data:: PUBLIC +//| +//| The address is public +//| +//| .. data:: RANDOM_STATIC +//| +//| The address is random static +//| +//| .. data:: RANDOM_PRIVATE_RESOLVABLE +//| +//| The address is random private resolvable +//| +//| .. data:: RANDOM_PRIVATE_NON_RESOLVABLE +//| +//| The address is private non-resolvable +//| +const mp_obj_type_t bleio_addresstype_type; + +const bleio_addresstype_obj_t bleio_addresstype_public_obj = { + { &bleio_addresstype_type }, +}; + +const bleio_addresstype_obj_t bleio_addresstype_random_static_obj = { + { &bleio_addresstype_type }, +}; + +const bleio_addresstype_obj_t bleio_addresstype_random_private_resolvable_obj = { + { &bleio_addresstype_type }, +}; + +const bleio_addresstype_obj_t bleio_addresstype_random_private_non_resolvable_obj = { + { &bleio_addresstype_type }, +}; + +STATIC const mp_rom_map_elem_t bleio_addresstype_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_PUBLIC), MP_ROM_PTR(&bleio_addresstype_public_obj) }, + { MP_ROM_QSTR(MP_QSTR_RANDOM_STATIC), MP_ROM_PTR(&bleio_addresstype_random_static_obj) }, + { MP_ROM_QSTR(MP_QSTR_RANDOM_PRIVATE_RESOLVABLE), MP_ROM_PTR(&bleio_addresstype_random_private_resolvable_obj) }, + { MP_ROM_QSTR(MP_QSTR_RANDOM_PRIVATE_NON_RESOLVABLE), MP_ROM_PTR(&bleio_addresstype_random_private_non_resolvable_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(bleio_addresstype_locals_dict, bleio_addresstype_locals_dict_table); + +STATIC void bleio_addresstype_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + qstr type = MP_QSTR_PUBLIC; + + if (MP_OBJ_TO_PTR(self_in) == MP_ROM_PTR(&bleio_addresstype_random_static_obj)) { + type = MP_QSTR_RANDOM_STATIC; + } else if (MP_OBJ_TO_PTR(self_in) == MP_ROM_PTR(&bleio_addresstype_random_private_resolvable_obj)) { + type = MP_QSTR_RANDOM_PRIVATE_RESOLVABLE; + } else if (MP_OBJ_TO_PTR(self_in) == MP_ROM_PTR(&bleio_addresstype_random_private_non_resolvable_obj)) { + type = MP_QSTR_RANDOM_PRIVATE_NON_RESOLVABLE; + } + + mp_printf(print, "%q.%q.%q", MP_QSTR_bleio, MP_QSTR_AddressType, type); +} + +const mp_obj_type_t bleio_addresstype_type = { + { &mp_type_type }, + .name = MP_QSTR_AddressType, + .print = bleio_addresstype_print, + .locals_dict = (mp_obj_t)&bleio_addresstype_locals_dict, +}; diff --git a/shared-bindings/bleio/AddressType.h b/shared-bindings/bleio/AddressType.h new file mode 100644 index 000000000..e69caffab --- /dev/null +++ b/shared-bindings/bleio/AddressType.h @@ -0,0 +1,50 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Artur Pacholec + * + * 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_BLEIO_ADDRESSTYPE_H +#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADDRESSTYPE_H + +#include "py/obj.h" + +typedef enum { + ADDRESS_PUBLIC, + ADDRESS_RANDOM_STATIC, + ADDRESS_RANDOM_PRIVATE_RESOLVABLE, + ADDRESS_RANDOM_PRIVATE_NON_RESOLVABLE +} bleio_address_type_t; + +extern const mp_obj_type_t bleio_addresstype_type; + +typedef struct { + mp_obj_base_t base; +} bleio_addresstype_obj_t; + +extern const bleio_addresstype_obj_t bleio_addresstype_public_obj; +extern const bleio_addresstype_obj_t bleio_addresstype_random_static_obj; +extern const bleio_addresstype_obj_t bleio_addresstype_random_private_resolvable_obj; +extern const bleio_addresstype_obj_t bleio_addresstype_random_private_non_resolvable_obj; + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADDRESSTYPE_H diff --git a/shared-bindings/bleio/AdvertisementData.c b/shared-bindings/bleio/AdvertisementData.c new file mode 100644 index 000000000..9cfdd74e9 --- /dev/null +++ b/shared-bindings/bleio/AdvertisementData.c @@ -0,0 +1,90 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Artur Pacholec + * + * 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/obj.h" +#include "shared-module/bleio/AdvertisementData.h" + +//| .. currentmodule:: bleio +//| +//| :class:`AdvertisementData` -- data used during BLE advertising +//| ============================================================== +//| +//| Represents the data to be broadcast during BLE advertising. +//| + +STATIC const mp_rom_map_elem_t bleio_advertisementdata_locals_dict_table[] = { + // Static variables + { MP_ROM_QSTR(MP_QSTR_FLAGS), MP_ROM_INT(AdFlags) }, + { MP_ROM_QSTR(MP_QSTR_INCOMPLETE_LIST_OF_16BIT_SERVICE_CLASS_UUIDS), MP_ROM_INT(AdIncompleteListOf16BitServiceClassUUIDs) }, + { MP_ROM_QSTR(MP_QSTR_COMPLETE_LIST_OF_16BIT_SERVICE_CLASS_UUIDS), MP_ROM_INT(AdCompleteListOf16BitServiceClassUUIDs) }, + { MP_ROM_QSTR(MP_QSTR_INCOMPLETE_LIST_OF_32BIT_SERVICE_CLASS_UUIDS), MP_ROM_INT(AdIncompleteListOf32BitServiceClassUUIDs) }, + { MP_ROM_QSTR(MP_QSTR_COMPLETE_LIST_OF_32BIT_SERVICE_CLASS_UUIDS), MP_ROM_INT(AdCompleteListOf32BitServiceClassUUIDs) }, + { MP_ROM_QSTR(MP_QSTR_INCOMPLETE_LIST_OF_128BIT_SERVICE_CLASS_UUIDS), MP_ROM_INT(AdIncompleteListOf128BitServiceClassUUIDs) }, + { MP_ROM_QSTR(MP_QSTR_COMPLETE_LIST_OF_128BIT_SERVICE_CLASS_UUIDS), MP_ROM_INT(AdCompleteListOf128BitServiceClassUUIDs) }, + { MP_ROM_QSTR(MP_QSTR_SHORTENED_LOCAL_NAME), MP_ROM_INT(AdShortenedLocalName) }, + { MP_ROM_QSTR(MP_QSTR_COMPLETE_LOCAL_NAME), MP_ROM_INT(AdCompleteLocalName) }, + { MP_ROM_QSTR(MP_QSTR_TX_POWER_LEVEL), MP_ROM_INT(AdTxPowerLevel) }, + { MP_ROM_QSTR(MP_QSTR_CLASS_OF_DEVICE), MP_ROM_INT(AdClassOfDevice) }, + { MP_ROM_QSTR(MP_QSTR_SIMPLE_PAIRING_HASH_C), MP_ROM_INT(AdSimplePairingHashC) }, + { MP_ROM_QSTR(MP_QSTR_SIMPLE_PAIRING_RANDOMIZER_R), MP_ROM_INT(AdSimplePairingRandomizerR) }, + { MP_ROM_QSTR(MP_QSTR_SECURITY_MANAGER_TK_VALUE), MP_ROM_INT(AdSecurityManagerTKValue) }, + { MP_ROM_QSTR(MP_QSTR_SECURITY_MANAGER_OOB_FLAGS), MP_ROM_INT(AdSecurityManagerOOBFlags) }, + { MP_ROM_QSTR(MP_QSTR_SLAVE_CONNECTION_INTERVAL_RANGE), MP_ROM_INT(AdSlaveConnectionIntervalRange) }, + { MP_ROM_QSTR(MP_QSTR_LIST_OF_16BIT_SERVICE_SOLICITATION_UUIDS), MP_ROM_INT(AdListOf16BitServiceSolicitationUUIDs) }, + { MP_ROM_QSTR(MP_QSTR_LIST_OF_128BIT_SERVICE_SOLICITATION_UUIDS), MP_ROM_INT(AdListOf128BitServiceSolicitationUUIDs) }, + { MP_ROM_QSTR(MP_QSTR_SERVICE_DATA), MP_ROM_INT(AdServiceData) }, + { MP_ROM_QSTR(MP_QSTR_PUBLIC_TARGET_ADDRESS), MP_ROM_INT(AdPublicTargetAddress) }, + { MP_ROM_QSTR(MP_QSTR_RANDOM_TARGET_ADDRESS), MP_ROM_INT(AdRandomTargetAddress) }, + { MP_ROM_QSTR(MP_QSTR_APPEARANCE), MP_ROM_INT(AdAppearance) }, + { MP_ROM_QSTR(MP_QSTR_ADVERTISING_INTERNAL), MP_ROM_INT(AdAdvertisingInterval) }, + { MP_ROM_QSTR(MP_QSTR_LE_BLUETOOTH_DEVICE_ADDRESS), MP_ROM_INT(AdLEBluetoothDeviceAddress) }, + { MP_ROM_QSTR(MP_QSTR_LE_ROLE), MP_ROM_INT(AdLERole) }, + { MP_ROM_QSTR(MP_QSTR_SIMPLE_PAIRING_HASH_C256), MP_ROM_INT(AdSimplePairingHashC256) }, + { MP_ROM_QSTR(MP_QSTR_SIMPLE_PAIRING_RANDOMIZER_R256), MP_ROM_INT(AdSimplePairingRandomizerR256) }, + { MP_ROM_QSTR(MP_QSTR_LIST_OF_32BIT_SERVICE_SOLICITATION_UUIDS), MP_ROM_INT(AdListOf32BitServiceSolicitationUUIDs) }, + { MP_ROM_QSTR(MP_QSTR_SERVICE_DATA_32BIT_UUID), MP_ROM_INT(AdServiceData32BitUUID) }, + { MP_ROM_QSTR(MP_QSTR_SERVICE_DATA_128BIT_UUID), MP_ROM_INT(AdServiceData128BitUUID) }, + { MP_ROM_QSTR(MP_QSTR_LE_SECURE_CONNECTIONS_CONFIRMATION_VALUE), MP_ROM_INT(AdLESecureConnectionsConfirmationValue) }, + { MP_ROM_QSTR(MP_QSTR_LE_SECURE_CONNECTIONS_RANDOM_VALUE), MP_ROM_INT(AdLESecureConnectionsRandomValue) }, + { MP_ROM_QSTR(MP_QSTR_URI), MP_ROM_INT(AdURI) }, + { MP_ROM_QSTR(MP_QSTR_INDOOR_POSITIONING), MP_ROM_INT(AdIndoorPositioning) }, + { MP_ROM_QSTR(MP_QSTR_TRANSPORT_DISCOVERY_DATA), MP_ROM_INT(AdTransportDiscoveryData) }, + { MP_ROM_QSTR(MP_QSTR_LE_SUPPORTED_FEATURES), MP_ROM_INT(AdLESupportedFeatures) }, + { MP_ROM_QSTR(MP_QSTR_CHANNEL_MAP_UPDATE_INDICATION), MP_ROM_INT(AdChannelMapUpdateIndication) }, + { MP_ROM_QSTR(MP_QSTR_PB_ADV), MP_ROM_INT(AdPBADV) }, + { MP_ROM_QSTR(MP_QSTR_MESH_MESSAGE), MP_ROM_INT(AdMeshMessage) }, + { MP_ROM_QSTR(MP_QSTR_MESH_BEACON), MP_ROM_INT(AdMeshBeacon) }, + { MP_ROM_QSTR(MP_QSTR_3D_INFORMATION_DATA), MP_ROM_INT(Ad3DInformationData) }, + { MP_ROM_QSTR(MP_QSTR_MANUFACTURER_SPECIFIC_DATA), MP_ROM_INT(AdManufacturerSpecificData) }, +}; + +STATIC MP_DEFINE_CONST_DICT(bleio_advertisementdata_locals_dict, bleio_advertisementdata_locals_dict_table); + +const mp_obj_type_t bleio_advertisementdata_type = { + { &mp_type_type }, + .name = MP_QSTR_AdvertisementData, + .locals_dict = (mp_obj_dict_t*)&bleio_advertisementdata_locals_dict +}; diff --git a/shared-bindings/bleio/AdvertisementData.h b/shared-bindings/bleio/AdvertisementData.h new file mode 100644 index 000000000..05b5a2c8d --- /dev/null +++ b/shared-bindings/bleio/AdvertisementData.h @@ -0,0 +1,34 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Artur Pacholec + * + * 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_BLEIO_ADVERTISEMENTDATA_H +#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADVERTISEMENTDATA_H + +#include "py/obj.h" + +extern const mp_obj_type_t bleio_advertisementdata_type; + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADVERTISEMENTDATA_H diff --git a/shared-bindings/bleio/Characteristic.c b/shared-bindings/bleio/Characteristic.c new file mode 100644 index 000000000..369f3f991 --- /dev/null +++ b/shared-bindings/bleio/Characteristic.c @@ -0,0 +1,332 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Glenn Ruben Bakke + * Copyright (c) 2018 Artur Pacholec + * + * 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/objproperty.h" +#include "py/runtime.h" +#include "shared-bindings/bleio/Characteristic.h" +#include "shared-bindings/bleio/UUID.h" + +//| .. currentmodule:: bleio +//| +//| :class:`Characteristic` -- BLE service characteristic +//| ========================================================= +//| +//| Stores information about a BLE service characteristic and allows to read +//| and write the characteristic's value. +//| + +//| .. class:: Characteristic(uuid) +//| +//| Create a new Characteristic object identified by the specified UUID. +//| +//| :param bleio.UUID uuid: The uuid of the characteristic +//| + +//| .. attribute:: broadcast +//| +//| A `bool` specifying if the characteristic allows broadcasting its value. +//| + +//| .. attribute:: indicate +//| +//| A `bool` specifying if the characteristic allows indicating its value. +//| + +//| .. attribute:: notify +//| +//| A `bool` specifying if the characteristic allows notifying its value. +//| + +//| .. attribute:: read +//| +//| A `bool` specifying if the characteristic allows reading its value. +//| + +//| .. attribute:: uuid +//| +//| The UUID of this characteristic. (read-only) +//| + +//| .. attribute:: value +//| +//| The value of this characteristic. The value can be written to if the `write` property allows it. +//| If the `read` property allows it, the value can be read. If the `notify` property is set, writting +//| to the value will generate a BLE notification. +//| + +//| .. attribute:: write +//| +//| A `bool` specifying if the characteristic allows writting to its value. +//| + +//| .. attribute:: write_no_resp +//| +//| A `bool` specifying if the characteristic allows writting to its value without response. +//| +STATIC void bleio_characteristic_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + + mp_printf(print, "Characteristic(uuid: 0x"HEX2_FMT""HEX2_FMT" handle: 0x" HEX2_FMT ")", + self->uuid->value[1], self->uuid->value[0], self->handle); +} + +STATIC mp_obj_t bleio_characteristic_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) { + mp_arg_check_num(n_args, n_kw, 1, 1, true); + bleio_characteristic_obj_t *self = m_new_obj(bleio_characteristic_obj_t); + self->base.type = &bleio_characteristic_type; + self->service = NULL; + self->value_data = NULL; + + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args); + + enum { ARG_uuid }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_uuid, MP_ARG_REQUIRED| 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); + + const mp_obj_t uuid = args[ARG_uuid].u_obj; + + if (uuid == mp_const_none) { + return MP_OBJ_FROM_PTR(self); + } + + if (MP_OBJ_IS_TYPE(uuid, &bleio_uuid_type)) { + self->uuid = MP_OBJ_TO_PTR(uuid); + } else { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, + translate("Invalid UUID parameter"))); + } + + common_hal_bleio_characteristic_construct(self); + + return MP_OBJ_FROM_PTR(self); +} + +STATIC mp_obj_t bleio_characteristic_get_broadcast(mp_obj_t self_in) { + bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + + return mp_obj_new_bool(self->props.broadcast); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_broadcast_obj, bleio_characteristic_get_broadcast); + +STATIC mp_obj_t bleio_characteristic_set_broadcast(mp_obj_t self_in, mp_obj_t broadcast_in) { + bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + + self->props.broadcast = mp_obj_is_true(broadcast_in); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_characteristic_set_broadcast_obj, bleio_characteristic_set_broadcast); + +const mp_obj_property_t bleio_characteristic_broadcast_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_characteristic_get_broadcast_obj, + (mp_obj_t)&bleio_characteristic_set_broadcast_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +STATIC mp_obj_t bleio_characteristic_get_indicate(mp_obj_t self_in) { + bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + + return mp_obj_new_bool(self->props.indicate); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_indicate_obj, bleio_characteristic_get_indicate); + +STATIC mp_obj_t bleio_characteristic_set_indicate(mp_obj_t self_in, mp_obj_t indicate_in) { + bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + + self->props.indicate = mp_obj_is_true(indicate_in); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_characteristic_set_indicate_obj, bleio_characteristic_set_indicate); + +const mp_obj_property_t bleio_characteristic_indicate_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_characteristic_get_indicate_obj, + (mp_obj_t)&bleio_characteristic_set_indicate_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +STATIC mp_obj_t bleio_characteristic_get_notify(mp_obj_t self_in) { + bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + + return mp_obj_new_bool(self->props.notify); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_notify_obj, bleio_characteristic_get_notify); + +STATIC mp_obj_t bleio_characteristic_set_notify(mp_obj_t self_in, mp_obj_t notify_in) { + bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + + self->props.notify = mp_obj_is_true(notify_in); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_characteristic_set_notify_obj, bleio_characteristic_set_notify); + +const mp_obj_property_t bleio_characteristic_notify_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_characteristic_get_notify_obj, + (mp_obj_t)&bleio_characteristic_set_notify_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +STATIC mp_obj_t bleio_characteristic_get_read(mp_obj_t self_in) { + bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + + return mp_obj_new_bool(self->props.read); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_read_obj, bleio_characteristic_get_read); + +STATIC mp_obj_t bleio_characteristic_set_read(mp_obj_t self_in, mp_obj_t read_in) { + bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + + self->props.read = mp_obj_is_true(read_in); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_characteristic_set_read_obj, bleio_characteristic_set_read); + +const mp_obj_property_t bleio_characteristic_read_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_characteristic_get_read_obj, + (mp_obj_t)&bleio_characteristic_set_read_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +STATIC mp_obj_t bleio_characteristic_get_write(mp_obj_t self_in) { + bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + + return mp_obj_new_bool(self->props.write); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_write_obj, bleio_characteristic_get_write); + +STATIC mp_obj_t bleio_characteristic_set_write(mp_obj_t self_in, mp_obj_t write_in) { + bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + + self->props.write = mp_obj_is_true(write_in); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_characteristic_set_write_obj, bleio_characteristic_set_write); + +const mp_obj_property_t bleio_characteristic_write_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_characteristic_get_write_obj, + (mp_obj_t)&bleio_characteristic_set_write_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +STATIC mp_obj_t bleio_characteristic_get_write_wo_resp(mp_obj_t self_in) { + bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + + return mp_obj_new_bool(self->props.write_wo_resp); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_write_wo_resp_obj, bleio_characteristic_get_write_wo_resp); + +STATIC mp_obj_t bleio_characteristic_set_write_wo_resp(mp_obj_t self_in, mp_obj_t write_wo_resp_in) { + bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + + self->props.write_wo_resp = mp_obj_is_true(write_wo_resp_in); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_characteristic_set_write_wo_resp_obj, bleio_characteristic_set_write_wo_resp); + +const mp_obj_property_t bleio_characteristic_write_wo_resp_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_characteristic_get_write_wo_resp_obj, + (mp_obj_t)&bleio_characteristic_set_write_wo_resp_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +STATIC mp_obj_t bleio_characteristic_get_uuid(mp_obj_t self_in) { + bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + + return MP_OBJ_FROM_PTR(self->uuid); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_uuid_obj, bleio_characteristic_get_uuid); + +const mp_obj_property_t bleio_characteristic_uuid_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_characteristic_get_uuid_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +STATIC mp_obj_t bleio_characteristic_get_value(mp_obj_t self_in) { + bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + + common_hal_bleio_characteristic_read_value(self); + + return self->value_data; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_value_obj, bleio_characteristic_get_value); + +STATIC mp_obj_t bleio_characteristic_set_value(mp_obj_t self_in, mp_obj_t value_in) { + bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(value_in, &bufinfo, MP_BUFFER_READ); + + common_hal_bleio_characteristic_write_value(self, &bufinfo); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_characteristic_set_value_obj, bleio_characteristic_set_value); + +const mp_obj_property_t bleio_characteristic_value_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_characteristic_get_value_obj, + (mp_obj_t)&bleio_characteristic_set_value_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +STATIC const mp_rom_map_elem_t bleio_characteristic_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_broadcast), MP_ROM_PTR(&bleio_characteristic_broadcast_obj) }, + { MP_ROM_QSTR(MP_QSTR_indicate), MP_ROM_PTR(&bleio_characteristic_indicate_obj) }, + { MP_ROM_QSTR(MP_QSTR_notify), MP_ROM_PTR(&bleio_characteristic_notify_obj) }, + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&bleio_characteristic_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_uuid), MP_ROM_PTR(&bleio_characteristic_uuid_obj) }, + { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&bleio_characteristic_value_obj) }, + { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&bleio_characteristic_write_obj) }, + { MP_ROM_QSTR(MP_QSTR_write_wo_resp), MP_ROM_PTR(&bleio_characteristic_write_wo_resp_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(bleio_characteristic_locals_dict, bleio_characteristic_locals_dict_table); + +const mp_obj_type_t bleio_characteristic_type = { + { &mp_type_type }, + .name = MP_QSTR_Characteristic, + .print = bleio_characteristic_print, + .make_new = bleio_characteristic_make_new, + .locals_dict = (mp_obj_dict_t*)&bleio_characteristic_locals_dict +}; diff --git a/shared-bindings/bleio/Characteristic.h b/shared-bindings/bleio/Characteristic.h new file mode 100644 index 000000000..0e99e97cc --- /dev/null +++ b/shared-bindings/bleio/Characteristic.h @@ -0,0 +1,38 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Artur Pacholec + * + * 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_BLEIO_CHARACTERISTIC_H +#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CHARACTERISTIC_H + +#include "shared-module/bleio/Characteristic.h" + +extern const mp_obj_type_t bleio_characteristic_type; + +extern void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self); +extern void common_hal_bleio_characteristic_read_value(bleio_characteristic_obj_t *self); +extern void common_hal_bleio_characteristic_write_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo); + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CHARACTERISTIC_H diff --git a/shared-bindings/bleio/Descriptor.c b/shared-bindings/bleio/Descriptor.c new file mode 100644 index 000000000..df32a00e7 --- /dev/null +++ b/shared-bindings/bleio/Descriptor.c @@ -0,0 +1,171 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Glenn Ruben Bakke + * Copyright (c) 2018 Artur Pacholec + * + * 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/objproperty.h" +#include "py/runtime.h" +#include "shared-bindings/bleio/Descriptor.h" +#include "shared-bindings/bleio/UUID.h" + +enum { + DescriptorUuidCharacteristicExtendedProperties = 0x2900, + DescriptorUuidCharacteristicUserDescription = 0x2901, + DescriptorUuidClientCharacteristicConfiguration = 0x2902, + DescriptorUuidServerCharacteristicConfiguration = 0x2903, + DescriptorUuidCharacteristicPresentationFormat = 0x2904, + DescriptorUuidCharacteristicAggregateFormat = 0x2905, + DescriptorUuidValidRange = 0x2906, + DescriptorUuidExternalReportReference = 0x2907, + DescriptorUuidReportReference = 0x2908, + DescriptorUuidNumberOfDigitals = 0x2909, + DescriptorUuidValueTriggerSetting = 0x290A, + DescriptorUuidEnvironmentalSensingConfiguration = 0x290B, + DescriptorUuidEnvironmentalSensingMeasurement = 0x290C, + DescriptorUuidEnvironmentalSensingTriggerSetting = 0x290D, + DescriptorUuidTimeTriggerSetting = 0x290E, +}; + +//| .. currentmodule:: bleio +//| +//| :class:`Descriptor` -- BLE descriptor +//| ========================================================= +//| +//| Stores information about a BLE descriptor. +//| Descriptors are encapsulated by BLE characteristics and provide contextual +//| information about the characteristic. +//| + +//| .. class:: Descriptor(uuid) +//| +//| Create a new descriptor object with the UUID uuid. +//| The value can be either of type `bleio.UUID` or any value allowed by the `bleio.UUID` constructor. + +//| .. attribute:: handle +//| +//| The descriptor handle. (read-only) +//| + +//| .. attribute:: uuid +//| +//| The descriptor uuid. (read-only) +//| +STATIC mp_obj_t bleio_descriptor_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) { + mp_arg_check_num(n_args, n_kw, 0, 1, true); + bleio_descriptor_obj_t *self = m_new_obj(bleio_descriptor_obj_t); + self->base.type = type; + + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args); + + enum { ARG_uuid }; + static const mp_arg_t allowed_args[] = { + { ARG_uuid, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + }; + + 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); + + const mp_obj_t uuid_arg = args[ARG_uuid].u_obj; + + bleio_uuid_obj_t *uuid; + if (MP_OBJ_IS_TYPE(uuid_arg, &bleio_uuid_type)) { + uuid = MP_OBJ_TO_PTR(uuid_arg); + } else { + uuid = MP_OBJ_TO_PTR(bleio_uuid_type.make_new(&bleio_uuid_type, 1, 0, &uuid_arg)); + } + + common_hal_bleio_descriptor_construct(self, uuid); + + return MP_OBJ_FROM_PTR(self); +} + +STATIC void bleio_descriptor_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + bleio_descriptor_obj_t *self = MP_OBJ_TO_PTR(self_in); + + common_hal_bleio_descriptor_print(self, print); +} + +STATIC mp_obj_t bleio_descriptor_get_handle(mp_obj_t self_in) { + bleio_descriptor_obj_t *self = MP_OBJ_TO_PTR(self_in); + + return mp_obj_new_int(common_hal_bleio_descriptor_get_handle(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(bleio_descriptor_get_handle_obj, bleio_descriptor_get_handle); + +const mp_obj_property_t bleio_descriptor_handle_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&bleio_descriptor_get_handle_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj}, +}; + +STATIC mp_obj_t bleio_descriptor_get_uuid(mp_obj_t self_in) { + bleio_descriptor_obj_t *self = MP_OBJ_TO_PTR(self_in); + const mp_obj_t uuid = mp_obj_new_int(common_hal_bleio_descriptor_get_uuid(self)); + + return bleio_uuid_type.make_new(&bleio_uuid_type, 1, 0, &uuid); +} +MP_DEFINE_CONST_FUN_OBJ_1(bleio_descriptor_get_uuid_obj, bleio_descriptor_get_uuid); + +const mp_obj_property_t bleio_descriptor_uuid_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&bleio_descriptor_get_uuid_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj}, +}; + +STATIC const mp_rom_map_elem_t bleio_descriptor_locals_dict_table[] = { + // Properties + { MP_ROM_QSTR(MP_QSTR_handle), MP_ROM_PTR(&bleio_descriptor_handle_obj) }, + { MP_ROM_QSTR(MP_QSTR_uuid), MP_ROM_PTR(&bleio_descriptor_uuid_obj) }, + + // Static variables + { MP_ROM_QSTR(MP_QSTR_CHARACTERISTIC_EXTENDED_PROPERTIES), MP_ROM_INT(DescriptorUuidCharacteristicExtendedProperties) }, + { MP_ROM_QSTR(MP_QSTR_CHARACTERISTIC_USER_DESCRIPTION), MP_ROM_INT(DescriptorUuidCharacteristicUserDescription) }, + { MP_ROM_QSTR(MP_QSTR_CLIENT_CHARACTERISTIC_CONFIGURATION), MP_ROM_INT(DescriptorUuidClientCharacteristicConfiguration) }, + { MP_ROM_QSTR(MP_QSTR_SERVER_CHARACTERISTIC_CONFIGURATION), MP_ROM_INT(DescriptorUuidServerCharacteristicConfiguration) }, + { MP_ROM_QSTR(MP_QSTR_CHARACTERISTIC_PRESENTATION_FORMAT), MP_ROM_INT(DescriptorUuidCharacteristicPresentationFormat) }, + { MP_ROM_QSTR(MP_QSTR_CHARACTERISTIC_AGGREGATE_FORMAT), MP_ROM_INT(DescriptorUuidCharacteristicAggregateFormat) }, + { MP_ROM_QSTR(MP_QSTR_VALID_RANGE), MP_ROM_INT(DescriptorUuidValidRange) }, + { MP_ROM_QSTR(MP_QSTR_EXTERNAL_REPORT_REFERENCE), MP_ROM_INT(DescriptorUuidExternalReportReference) }, + { MP_ROM_QSTR(MP_QSTR_REPORT_REFERENCE), MP_ROM_INT(DescriptorUuidReportReference) }, + { MP_ROM_QSTR(MP_QSTR_NUMBER_OF_DIGITALS), MP_ROM_INT(DescriptorUuidNumberOfDigitals) }, + { MP_ROM_QSTR(MP_QSTR_VALUE_TRIGGER_SETTING), MP_ROM_INT(DescriptorUuidValueTriggerSetting) }, + { MP_ROM_QSTR(MP_QSTR_ENVIRONMENTAL_SENSING_CONFIGURATION), MP_ROM_INT(DescriptorUuidEnvironmentalSensingConfiguration) }, + { MP_ROM_QSTR(MP_QSTR_ENVIRONMENTAL_SENSING_MEASUREMENT ), MP_ROM_INT(DescriptorUuidEnvironmentalSensingMeasurement) }, + { MP_ROM_QSTR(MP_QSTR_ENVIRONMENTAL_SENSING_TRIGGER_SETTING), MP_ROM_INT(DescriptorUuidEnvironmentalSensingTriggerSetting) }, + { MP_ROM_QSTR(MP_QSTR_TIME_TRIGGER_SETTING), MP_ROM_INT(DescriptorUuidTimeTriggerSetting) } +}; + +STATIC MP_DEFINE_CONST_DICT(bleio_descriptor_locals_dict, bleio_descriptor_locals_dict_table); + +const mp_obj_type_t bleio_descriptor_type = { + { &mp_type_type }, + .name = MP_QSTR_Descriptor, + .print = bleio_descriptor_print, + .make_new = bleio_descriptor_make_new, + .locals_dict = (mp_obj_dict_t*)&bleio_descriptor_locals_dict +}; diff --git a/shared-bindings/bleio/Descriptor.h b/shared-bindings/bleio/Descriptor.h new file mode 100644 index 000000000..85310d304 --- /dev/null +++ b/shared-bindings/bleio/Descriptor.h @@ -0,0 +1,40 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Artur Pacholec + * + * 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_BLEIO_DESCRIPTOR_H +#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_DESCRIPTOR_H + +#include "common-hal/bleio/Descriptor.h" +#include "common-hal/bleio/UUID.h" + +extern const mp_obj_type_t bleio_descriptor_type; + +extern void common_hal_bleio_descriptor_construct(bleio_descriptor_obj_t *self, bleio_uuid_obj_t *uuid); +extern void common_hal_bleio_descriptor_print(bleio_descriptor_obj_t *self, const mp_print_t *print); +extern mp_int_t common_hal_bleio_descriptor_get_handle(bleio_descriptor_obj_t *self); +extern mp_int_t common_hal_bleio_descriptor_get_uuid(bleio_descriptor_obj_t *self); + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_DESCRIPTOR_H diff --git a/shared-bindings/bleio/Device.c b/shared-bindings/bleio/Device.c new file mode 100644 index 000000000..94834ef7c --- /dev/null +++ b/shared-bindings/bleio/Device.c @@ -0,0 +1,357 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Glenn Ruben Bakke + * Copyright (c) 2018 Artur Pacholec + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include <string.h> +#include <stdio.h> + +#include "ble_drv.h" +#include "py/objarray.h" +#include "py/objproperty.h" +#include "py/objstr.h" +#include "py/runtime.h" +#include "shared-bindings/bleio/Adapter.h" +#include "shared-bindings/bleio/AddressType.h" +#include "shared-bindings/bleio/Characteristic.h" +#include "shared-bindings/bleio/Device.h" +#include "shared-bindings/bleio/Service.h" +#include "shared-bindings/bleio/UUID.h" +#include "shared-module/bleio/AdvertisementData.h" +#include "shared-module/bleio/Device.h" +#include "shared-module/bleio/ScanEntry.h" + +//| .. currentmodule:: bleio +//| +//| :class:`Device` -- BLE device +//| ========================================================= +//| +//| Provides access a to BLE device, either in a Peripheral or Central role. +//| When a device is created without any parameter passed to the constructor, +//| it will be set to the Peripheral role. If a address is passed, the device +//| will be a Central. For a Peripheral you can set the `name`, add services +//| via `add_service` and then start and stop advertising via `start_advertising` +//| and `stop_advertising`. For the Central, you can `bleio.Device.connect` and `bleio.Device.disconnect` +//| to the device, once a connection is established, the device's services can +//| be accessed using `services`. +//| +//| Usage:: +//| +//| import bleio +//| +//| # Peripheral +//| periph = bleio.Device() +//| +//| serv = bleio.Service(bleio.UUID(0x180f)) +//| p.add_service(serv) +//| +//| chara = bleio.Characteristic(bleio.UUID(0x2919)) +//| chara.read = True +//| chara.notify = True +//| serv.add_characteristic(chara) +//| +//| periph.start_advertising() +//| +//| # Central +//| scanner = bleio.Scanner() +//| entries = scanner.scan(2500) +//| +//| my_entry = None +//| for entry in entries: +//| if entry.name is not None and entry.name == 'MyDevice': +//| my_entry = entry +//| break +//| +//| central = bleio.Device(my_entry.address) +//| central.connect() +//| + +//| .. class:: Device(address=None, scan_entry=None) +//| +//| Create a new Device object. If the `address` or :py:data:`scan_entry` parameters are not `None`, +//| the role is set to Central, otherwise it's set to Peripheral. +//| +//| :param bleio.Address address: The address of the device to connect to +//| :param bleio.ScanEntry scan_entry: The scan entry returned from `bleio.Scanner` +//| + +//| .. attribute:: name +//| +//| For the Peripheral role, this property can be used to read and write the device's name. +//| For the Central role, this property will equal the name of the remote device, if one was +//| advertised by the device. In the Central role this property is read-only. +//| + +//| .. attribute:: services +//| +//| A `list` of `bleio.Service` that are offered by this device. (read-only) +//| For a Peripheral device, this list will contain services added using `add_service`, +//| for a Central, this list will be empty until a connection is established, at which point +//| it will be filled with the remote device's services. +//| + +//| .. method:: add_service(service) +//| +//| Appends the :py:data:`service` to the list of this devices's services. +//| This method can only be called for Peripheral devices. +//| +//| :param bleio.Service service: the service to append +//| + +//| .. method:: connect() +//| +//| Attempts a connection to the remote device. If the connection is successful, +//| the device's services are available via `services`. +//| This method can only be called for Central devices. +//| + +//| .. method:: disconnect() +//| +//| Disconnects from the remote device. +//| This method can only be called for Central devices. +//| + +//| .. method:: start_advertising(connectable=True) +//| +//| Starts advertising the device. The device's name and +//| services are put into the advertisement packets. +//| If :py:data:`connectable` is `True` then other devices are allowed to conncet to this device. +//| This method can only be called for Peripheral devices. +//| + +//| .. method:: stop_advertising() +//| +//| Disconnects from the remote device. +//| This method can only be called for Peripheral devices. +//| + +// TODO: Add unique MAC address part to name +static const char default_name[] = "CIRCUITPY"; + +STATIC void bleio_device_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + bleio_device_obj_t *self = MP_OBJ_TO_PTR(self_in); + + mp_printf(print, "Device(role: %s)", self->is_peripheral ? "Peripheral" : "Central"); +} + +STATIC mp_obj_t bleio_device_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) { + mp_arg_check_num(n_args, n_kw, 0, 1, true); + bleio_device_obj_t *self = m_new_obj(bleio_device_obj_t); + self->base.type = &bleio_device_type; + self->service_list = mp_obj_new_list(0, NULL); + self->notif_handler = mp_const_none; + self->conn_handler = mp_const_none; + self->conn_handle = 0xFFFF; + self->is_peripheral = true; + + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args); + + enum { ARG_address, ARG_scan_entry }; + static const mp_arg_t allowed_args[] = { + { ARG_address, MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_scan_entry, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.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); + + const mp_obj_t address_obj = args[ARG_address].u_obj; + const mp_obj_t scan_entry_obj = args[ARG_scan_entry].u_obj; + + if (address_obj != mp_const_none) { + bleio_address_obj_t *address = MP_OBJ_TO_PTR(address_obj); + + self->is_peripheral = false; + self->address.type = address->type; + memcpy(self->address.value, address->value, BLEIO_ADDRESS_BYTES); + } else if (scan_entry_obj != mp_const_none) { + bleio_scanentry_obj_t *scan_entry = MP_OBJ_TO_PTR(scan_entry_obj); + + self->is_peripheral = false; + self->address.type = scan_entry->address.type; + memcpy(self->address.value, scan_entry->address.value, BLEIO_ADDRESS_BYTES); + } else { + self->name = mp_obj_new_str(default_name, strlen(default_name)); + common_hal_bleio_adapter_get_address(&self->address); + } + + return MP_OBJ_FROM_PTR(self); +} + +STATIC mp_obj_t bleio_device_add_service(mp_obj_t self_in, mp_obj_t service_in) { + bleio_device_obj_t *self = MP_OBJ_TO_PTR(self_in); + bleio_service_obj_t *service = MP_OBJ_TO_PTR(service_in); + + if (!self->is_peripheral) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, + translate("Can't add services in Central mode"))); + } + + service->device = self; + + mp_obj_list_append(self->service_list, service); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_device_add_service_obj, bleio_device_add_service); + +STATIC mp_obj_t bleio_device_connect(mp_obj_t self_in) { + bleio_device_obj_t *self = MP_OBJ_TO_PTR(self_in); + + if (self->is_peripheral) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, + translate("Can't connect in Peripheral mode"))); + } + + common_hal_bleio_device_connect(self); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_device_connect_obj, bleio_device_connect); + +STATIC mp_obj_t bleio_device_disconnect(mp_obj_t self_in) { + bleio_device_obj_t *self = MP_OBJ_TO_PTR(self_in); + + common_hal_bleio_device_disconnect(self); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_device_disconnect_obj, bleio_device_disconnect); + +STATIC mp_obj_t bleio_device_get_name(mp_obj_t self_in) { + bleio_device_obj_t *self = MP_OBJ_TO_PTR(self_in); + + return self->name; +} +MP_DEFINE_CONST_FUN_OBJ_1(bleio_device_get_name_obj, bleio_device_get_name); + +static mp_obj_t bleio_device_set_name(mp_obj_t self_in, mp_obj_t value) { + bleio_device_obj_t *self = MP_OBJ_TO_PTR(self_in); + + if (!self->is_peripheral) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, + translate("Can't change the name in Central mode"))); + } + + self->name = value; + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_device_set_name_obj, bleio_device_set_name); + +const mp_obj_property_t bleio_device_name_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_device_get_name_obj, + (mp_obj_t)&bleio_device_set_name_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +STATIC mp_obj_t bleio_device_start_advertising(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + bleio_device_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + + if (!self->is_peripheral) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, + translate("Can't advertise in Central mode"))); + } + + enum { ARG_connectable, ARG_data }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_connectable, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} }, + { MP_QSTR_data, 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 - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_buffer_info_t bufinfo = { 0 }; + if (args[ARG_data].u_obj != mp_const_none) { + mp_get_buffer_raise(args[ARG_data].u_obj, &bufinfo, MP_BUFFER_READ); + } + + const mp_obj_list_t *service_list = MP_OBJ_TO_PTR(self->service_list); + for (size_t i = 0; i < service_list->len; ++i) { + bleio_service_obj_t *service = service_list->items[i]; + if (service->handle == 0xFFFF) { + common_hal_bleio_device_add_service(self, service); + } + } + + common_hal_bleio_device_start_advertising(self, args[ARG_connectable].u_bool, &bufinfo); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_device_start_advertising_obj, 0, bleio_device_start_advertising); + +STATIC mp_obj_t bleio_device_stop_advertising(mp_obj_t self_in) { + bleio_device_obj_t *self = MP_OBJ_TO_PTR(self_in); + + if (!self->is_peripheral) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, + translate("Can't advertise in Central mode"))); + } + + common_hal_bleio_device_stop_advertising(self); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_device_stop_advertising_obj, bleio_device_stop_advertising); + +STATIC mp_obj_t bleio_device_get_services(mp_obj_t self_in) { + bleio_device_obj_t *self = MP_OBJ_TO_PTR(self_in); + + return self->service_list; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_device_get_services_obj, bleio_device_get_services); + +const mp_obj_property_t bleio_device_services_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_device_get_services_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +STATIC const mp_rom_map_elem_t bleio_device_locals_dict_table[] = { + // Methods + { MP_ROM_QSTR(MP_QSTR_add_service), MP_ROM_PTR(&bleio_device_add_service_obj) }, + { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&bleio_device_connect_obj) }, + { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&bleio_device_disconnect_obj) }, + { MP_ROM_QSTR(MP_QSTR_start_advertising), MP_ROM_PTR(&bleio_device_start_advertising_obj) }, + { MP_ROM_QSTR(MP_QSTR_stop_advertising), MP_ROM_PTR(&bleio_device_stop_advertising_obj) }, + + // Properties + { MP_ROM_QSTR(MP_QSTR_name), MP_ROM_PTR(&bleio_device_name_obj) }, + { MP_ROM_QSTR(MP_QSTR_services), MP_ROM_PTR(&bleio_device_services_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(bleio_device_locals_dict, bleio_device_locals_dict_table); + +const mp_obj_type_t bleio_device_type = { + { &mp_type_type }, + .name = MP_QSTR_Device, + .print = bleio_device_print, + .make_new = bleio_device_make_new, + .locals_dict = (mp_obj_dict_t*)&bleio_device_locals_dict +}; diff --git a/shared-bindings/bleio/Device.h b/shared-bindings/bleio/Device.h new file mode 100644 index 000000000..aebf1d639 --- /dev/null +++ b/shared-bindings/bleio/Device.h @@ -0,0 +1,42 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Artur Pacholec + * + * 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_BLEIO_DEVICE_H +#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_DEVICE_H + +#include "shared-module/bleio/AdvertisementData.h" +#include "shared-module/bleio/Device.h" +#include "shared-module/bleio/Service.h" + +extern const mp_obj_type_t bleio_device_type; + +extern void common_hal_bleio_device_add_service(bleio_device_obj_t *device, bleio_service_obj_t *service); +extern void common_hal_bleio_device_start_advertising(bleio_device_obj_t *device, bool connectable, mp_buffer_info_t *raw_data); +extern void common_hal_bleio_device_stop_advertising(bleio_device_obj_t *device); +extern void common_hal_bleio_device_connect(bleio_device_obj_t *device); +extern void common_hal_bleio_device_disconnect(bleio_device_obj_t *device); + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_DEVICE_H diff --git a/shared-bindings/bleio/ScanEntry.c b/shared-bindings/bleio/ScanEntry.c new file mode 100644 index 000000000..e452c7267 --- /dev/null +++ b/shared-bindings/bleio/ScanEntry.c @@ -0,0 +1,308 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Artur Pacholec + * Copyright (c) 2017 Glenn Ruben Bakke + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include <string.h> + +#include "py/objarray.h" +#include "py/objproperty.h" +#include "py/objstr.h" +#include "py/objtuple.h" +#include "shared-bindings/bleio/Address.h" +#include "shared-bindings/bleio/ScanEntry.h" +#include "shared-bindings/bleio/UUID.h" +#include "shared-module/bleio/AdvertisementData.h" +#include "shared-module/bleio/ScanEntry.h" + +//| .. currentmodule:: bleio +//| +//| :class:`ScanEntry` -- BLE scan response entry +//| ========================================================= +//| +//| Encapsulates information about a device that was received as a +//| response to a BLE scan request. +//| + +//| .. attribute:: address +//| +//| The address of the device. (read-only) +//| This attribute is of type `bleio.Address`. +//| + +//| .. attribute:: manufacturer_specific_data +//| +//| The manufacturer-specific data present in the advertisement packet. (read-only) +//| + +//| .. attribute:: name +//| +//| The name of the device. (read-only) +//| This attribute might be `None` if the data was missing from the advertisement packet. +//| + +//| .. attribute:: raw_data +//| +//| All the advertisement data present in the packet. (read-only) +//| + +//| .. attribute:: rssi +//| +//| The signal strength of the device at the time of the scan. (read-only) +//| + +//| .. attribute:: service_uuids +//| +//| The address of the device. (read-only) +//| This attribute is a list of `bleio.UUID`. +//| This attribute might be empty or incomplete, depending on the advertisement packet. +//| Currently only 16-bit UUIDS are listed. +//| + +//| .. attribute:: tx_power_level +//| +//| The transmit power level of the device. (read-only) +//| This attribute might be `None` if the data was missing from the advertisement packet. +//| +static uint8_t find_data_item(mp_obj_array_t *data_in, uint8_t type, uint8_t **data_out) { + uint16_t i = 0; + while (i < data_in->len) { + const uint8_t item_len = ((uint8_t*)data_in->items)[i]; + const uint8_t item_type = ((uint8_t*)data_in->items)[i + 1]; + if (item_type != type) { + i += (item_len + 1); + continue; + } + + *data_out = &((uint8_t*)data_in->items)[i + 2]; + + return item_len; + } + + return 0; +} + +STATIC mp_obj_t scanentry_get_name(mp_obj_t self_in); + +STATIC void bleio_scanentry_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + bleio_scanentry_obj_t *self = (bleio_scanentry_obj_t *)self_in; + mp_printf(print, "ScanEntry(address: "HEX2_FMT":"HEX2_FMT":"HEX2_FMT":"HEX2_FMT":"HEX2_FMT":"HEX2_FMT"", + self->address.value[5], self->address.value[4], self->address.value[3], + self->address.value[1], self->address.value[1], self->address.value[0]); + + const mp_obj_t name_obj = scanentry_get_name(self_in); + if (name_obj != mp_const_none) { + mp_obj_str_t *str = MP_OBJ_TO_PTR(name_obj); + mp_printf(print, " name: %s", str->data); + } + + mp_print_str(print, ")"); +} + +STATIC mp_obj_t bleio_scanentry_get_address(mp_obj_t self_in) { + bleio_scanentry_obj_t *self = MP_OBJ_TO_PTR(self_in); + + mp_obj_t obj = bleio_address_type.make_new(&bleio_address_type, 1, 0, (mp_obj_t)&mp_const_none_obj); + bleio_address_obj_t *address = MP_OBJ_TO_PTR(obj); + + address->type = self->address.type; + memcpy(address->value, self->address.value, BLEIO_ADDRESS_BYTES); + + return obj; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bluepy_scanentry_get_address_obj, bleio_scanentry_get_address); + +const mp_obj_property_t bleio_scanentry_address_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bluepy_scanentry_get_address_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +STATIC mp_obj_t scanentry_get_manufacturer_specific_data(mp_obj_t self_in) { + bleio_scanentry_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_obj_array_t *data = MP_OBJ_TO_PTR(self->data); + uint8_t *manuf_data; + + const uint8_t manuf_data_len = find_data_item(data, AdManufacturerSpecificData, &manuf_data); + if (manuf_data_len == 0) { + return mp_const_none; + } + + return mp_obj_new_bytearray_by_ref(manuf_data_len, manuf_data); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(scanentry_get_manufacturer_specific_data_obj, scanentry_get_manufacturer_specific_data); + +const mp_obj_property_t bleio_scanentry_manufacturer_specific_data_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&scanentry_get_manufacturer_specific_data_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +STATIC mp_obj_t scanentry_get_name(mp_obj_t self_in) { + bleio_scanentry_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_obj_array_t *data = MP_OBJ_TO_PTR(self->data); + uint8_t *name; + + // Try for Complete but settle for Shortened + uint8_t name_len = find_data_item(data, AdCompleteLocalName, &name); + if (name_len == 0) { + name_len = find_data_item(data, AdShortenedLocalName, &name); + } + + if (name_len == 0) { + return mp_const_none; + } + + return mp_obj_new_str((const char*)name, name_len - 1); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bluepy_scanentry_get_name_obj, scanentry_get_name); + +const mp_obj_property_t bleio_scanentry_name_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bluepy_scanentry_get_name_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +STATIC mp_obj_t scanentry_get_raw_data(mp_obj_t self_in) { + bleio_scanentry_obj_t *self = MP_OBJ_TO_PTR(self_in); + + mp_obj_t entries = mp_obj_new_list(0, NULL); + + mp_obj_array_t *data = MP_OBJ_TO_PTR(self->data); + + uint16_t i = 0; + while (i < data->len) { + mp_obj_tuple_t *entry = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL)); + + const uint8_t item_len = ((uint8_t*)data->items)[i]; + const uint8_t item_type = ((uint8_t*)data->items)[i + 1]; + + entry->items[0] = MP_OBJ_NEW_SMALL_INT(item_type); + entry->items[1] = mp_obj_new_bytearray(item_len - 1, &((uint8_t*)data->items)[i + 2]); + mp_obj_list_append(entries, MP_OBJ_FROM_PTR(entry)); + + i += (item_len + 1); + } + + return entries; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_scanentry_get_raw_data_obj, scanentry_get_raw_data); + +const mp_obj_property_t bleio_scanentry_raw_data_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_scanentry_get_raw_data_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +STATIC mp_obj_t scanentry_get_rssi(mp_obj_t self_in) { + bleio_scanentry_obj_t *self = MP_OBJ_TO_PTR(self_in); + + return mp_obj_new_int(self->rssi); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bluepy_scanentry_get_rssi_obj, scanentry_get_rssi); + +const mp_obj_property_t bleio_scanentry_rssi_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bluepy_scanentry_get_rssi_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +STATIC mp_obj_t scanentry_get_service_uuids(mp_obj_t self_in) { + bleio_scanentry_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_obj_array_t *data = MP_OBJ_TO_PTR(self->data); + uint8_t *uuids; + + // Try for Complete but settle for Incomplete + uint8_t uuids_len = find_data_item(data, AdCompleteListOf16BitServiceClassUUIDs, &uuids); + if (uuids_len == 0) { + uuids_len = find_data_item(data, AdIncompleteListOf16BitServiceClassUUIDs, &uuids); + } + + mp_obj_t entries = mp_obj_new_list(0, NULL); + for (size_t i = 0; i < uuids_len / sizeof(uint16_t); ++i) { + const mp_obj_t uuid_int = mp_obj_new_int(uuids[sizeof(uint16_t) * i] | (uuids[sizeof(uint16_t) * i + 1] << 8)); + const mp_obj_t uuid_obj = bleio_uuid_type.make_new(&bleio_uuid_type, 1, 0, &uuid_int); + + mp_obj_list_append(entries, uuid_obj); + } + + // TODO: 32-bit UUIDs + // TODO: 128-bit UUIDs + + return entries; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(scanentry_get_service_uuids_obj, scanentry_get_service_uuids); + +const mp_obj_property_t bleio_scanentry_service_uuids_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&scanentry_get_service_uuids_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +STATIC mp_obj_t scanentry_get_tx_power_level(mp_obj_t self_in) { + bleio_scanentry_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_obj_array_t *data = MP_OBJ_TO_PTR(self->data); + uint8_t *tx_power; + + const uint8_t tx_power_len = find_data_item(data, AdTxPowerLevel, &tx_power); + if (tx_power_len == 0) { + return mp_const_none; + } + + return mp_obj_new_int((int8_t)(*tx_power)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(scanentry_get_tx_power_level_obj, scanentry_get_tx_power_level); + +const mp_obj_property_t bleio_scanentry_tx_power_level_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&scanentry_get_tx_power_level_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +STATIC const mp_rom_map_elem_t bleio_scanentry_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_address), MP_ROM_PTR(&bleio_scanentry_address_obj) }, + { MP_ROM_QSTR(MP_QSTR_manufacturer_specific_data), MP_ROM_PTR(&bleio_scanentry_manufacturer_specific_data_obj) }, + { MP_ROM_QSTR(MP_QSTR_name), MP_ROM_PTR(&bleio_scanentry_name_obj) }, + { MP_ROM_QSTR(MP_QSTR_raw_data), MP_ROM_PTR(&bleio_scanentry_raw_data_obj) }, + { MP_ROM_QSTR(MP_QSTR_rssi), MP_ROM_PTR(&bleio_scanentry_rssi_obj) }, + { MP_ROM_QSTR(MP_QSTR_service_uuids), MP_ROM_PTR(&bleio_scanentry_service_uuids_obj) }, + { MP_ROM_QSTR(MP_QSTR_tx_power_level), MP_ROM_PTR(&bleio_scanentry_tx_power_level_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(bleio_scanentry_locals_dict, bleio_scanentry_locals_dict_table); + +const mp_obj_type_t bleio_scanentry_type = { + { &mp_type_type }, + .name = MP_QSTR_ScanEntry, + .print = bleio_scanentry_print, + .locals_dict = (mp_obj_dict_t*)&bleio_scanentry_locals_dict +}; diff --git a/shared-bindings/bleio/ScanEntry.h b/shared-bindings/bleio/ScanEntry.h new file mode 100644 index 000000000..2b44ba3f4 --- /dev/null +++ b/shared-bindings/bleio/ScanEntry.h @@ -0,0 +1,35 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Artur Pacholec + * Copyright (c) 2017 Glenn Ruben Bakke + * + * 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_BLEIO_SCANENTRY_H +#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SCANENTRY_H + +#include "py/obj.h" + +extern const mp_obj_type_t bleio_scanentry_type; + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SCANENTRY_H diff --git a/shared-bindings/bleio/Scanner.c b/shared-bindings/bleio/Scanner.c new file mode 100644 index 000000000..5d19778f6 --- /dev/null +++ b/shared-bindings/bleio/Scanner.c @@ -0,0 +1,162 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Artur Pacholec + * + * 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/objproperty.h" +#include "shared-bindings/bleio/ScanEntry.h" +#include "shared-bindings/bleio/Scanner.h" + +#define DEFAULT_INTERVAL 100 +#define DEFAULT_WINDOW 100 + +//| .. currentmodule:: bleio +//| +//| :class:`Scanner` -- scan for nearby BLE devices +//| ========================================================= +//| +//| Allows scanning for nearby BLE devices. +//| +//| Usage:: +//| +//| import bleio +//| scanner = bleio.Scanner() +//| entries = scanner.scan(2500) +//| print(entries) +//| + +//| .. class:: Scanner() +//| +//| Create a new Scanner object. +//| + +//| .. attribute:: interval +//| +//| The interval (in ms) between the start of two consecutive scan windows. +//| Allowed values are between 10ms and 10.24 sec. +//| + +//| .. attribute:: window +//| +//| The duration (in ms) in which a single BLE channel is scanned. +//| Allowed values are between 10ms and 10.24 sec. +//| + +//| .. method:: scan(timeout) +//| +//| Performs a BLE scan. +//| +//| :param int timeout: the scan timeout in ms +//| :returns: advertising packets found +//| :rtype: list of :py:class:`bleio.ScanEntry` +//| +STATIC void bleio_scanner_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + bleio_scanner_obj_t *self = MP_OBJ_TO_PTR(self_in); + + mp_printf(print, "Scanner(interval: %d window: %d)", self->interval, self->window); +} + +STATIC mp_obj_t bleio_scanner_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + bleio_scanner_obj_t *self = m_new_obj(bleio_scanner_obj_t); + self->base.type = type; + + self->interval = DEFAULT_INTERVAL; + self->window = DEFAULT_WINDOW; + + return MP_OBJ_FROM_PTR(self); +} + +STATIC mp_obj_t bleio_scanner_get_interval(mp_obj_t self_in) { + bleio_scanner_obj_t *self = MP_OBJ_TO_PTR(self_in); + + return mp_obj_new_int(self->interval); +} +MP_DEFINE_CONST_FUN_OBJ_1(bleio_scanner_get_interval_obj, bleio_scanner_get_interval); + +static mp_obj_t bleio_scanner_set_interval(mp_obj_t self_in, mp_obj_t value) { + bleio_scanner_obj_t *self = MP_OBJ_TO_PTR(self_in); + + self->interval = mp_obj_get_int(value); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_scanner_set_interval_obj, bleio_scanner_set_interval); + +const mp_obj_property_t bleio_scanner_interval_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_scanner_get_interval_obj, + (mp_obj_t)&bleio_scanner_set_interval_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +STATIC mp_obj_t scanner_scan(mp_obj_t self_in, mp_obj_t timeout_in) { + bleio_scanner_obj_t *self = MP_OBJ_TO_PTR(self_in); + const mp_int_t timeout = mp_obj_get_int(timeout_in); + + self->adv_reports = mp_obj_new_list(0, NULL); + + common_hal_bleio_scanner_scan(self, timeout); + + return self->adv_reports; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_scanner_scan_obj, scanner_scan); + +STATIC mp_obj_t bleio_scanner_get_window(mp_obj_t self_in) { + bleio_scanner_obj_t *self = MP_OBJ_TO_PTR(self_in); + + return mp_obj_new_int(self->window); +} +MP_DEFINE_CONST_FUN_OBJ_1(bleio_scanner_get_window_obj, bleio_scanner_get_window); + +static mp_obj_t bleio_scanner_set_window(mp_obj_t self_in, mp_obj_t value) { + bleio_scanner_obj_t *self = MP_OBJ_TO_PTR(self_in); + + self->window = mp_obj_get_int(value); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_scanner_set_window_obj, bleio_scanner_set_window); + +const mp_obj_property_t bleio_scanner_window_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_scanner_get_window_obj, + (mp_obj_t)&bleio_scanner_set_window_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +STATIC const mp_rom_map_elem_t bleio_scanner_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_interval), MP_ROM_PTR(&bleio_scanner_interval_obj) }, + { MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&bleio_scanner_scan_obj) }, + { MP_ROM_QSTR(MP_QSTR_window), MP_ROM_PTR(&bleio_scanner_window_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(bleio_scanner_locals_dict, bleio_scanner_locals_dict_table); + +const mp_obj_type_t bleio_scanner_type = { + { &mp_type_type }, + .name = MP_QSTR_Scanner, + .print = bleio_scanner_print, + .make_new = bleio_scanner_make_new, + .locals_dict = (mp_obj_dict_t*)&bleio_scanner_locals_dict +}; diff --git a/shared-bindings/bleio/Scanner.h b/shared-bindings/bleio/Scanner.h new file mode 100644 index 000000000..9bd071747 --- /dev/null +++ b/shared-bindings/bleio/Scanner.h @@ -0,0 +1,39 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Glenn Ruben Bakke + * Copyright (c) 2018 Artur Pacholec + * + * 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_BLEIO_SCANNER_H +#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SCANNER_H + +#include "py/objtype.h" +#include "shared-module/bleio/Scanner.h" + +extern const mp_obj_type_t bleio_scanner_type; + +extern void common_hal_bleio_scanner_scan(bleio_scanner_obj_t *self, mp_int_t timeout); +extern void common_hal_bleio_scanner_stop(bleio_scanner_obj_t *self); + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SCANNER_H diff --git a/shared-bindings/bleio/Service.c b/shared-bindings/bleio/Service.c new file mode 100644 index 000000000..2d09cbc3c --- /dev/null +++ b/shared-bindings/bleio/Service.c @@ -0,0 +1,170 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Glenn Ruben Bakke + * Copyright (c) 2018 Artur Pacholec + * + * 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/objproperty.h" +#include "py/runtime.h" +#include "shared-bindings/bleio/Service.h" +#include "shared-bindings/bleio/UUID.h" + +//| .. currentmodule:: bleio +//| +//| :class:`Service` -- BLE service +//| ========================================================= +//| +//| Stores information about a BLE service and its characteristics. +//| + +//| .. class:: Service(uuid, secondary=False) +//| +//| Create a new Service object identified by the specified UUID. +//| To mark the service as secondary, pass `True` as :py:data:`secondary`. +//| +//| :param bleio.UUID uuid: The uuid of the service +//| :param bool secondary: If the service is a secondary one +//| + +//| .. method:: add_characteristic(characteristic) +//| +//| Appends the :py:data:`characteristic` to the list of this service's characteristics. +//| +//| :param bleio.Characteristic characteristic: the characteristic to append +//| + +//| .. attribute:: characteristics +//| +//| A `list` of `bleio.Characteristic` that are offered by this service. (read-only) +//| + +//| .. attribute:: uuid +//| +//| The UUID of this service. (read-only) +//| +STATIC void bleio_service_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + bleio_service_obj_t *self = MP_OBJ_TO_PTR(self_in); + + mp_printf(print, "Service(uuid: 0x"HEX2_FMT""HEX2_FMT")", + self->uuid->value[1], self->uuid->value[0]); +} + +STATIC mp_obj_t bleio_service_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) { + mp_arg_check_num(n_args, n_kw, 1, 1, true); + bleio_service_obj_t *self = m_new_obj(bleio_service_obj_t); + self->base.type = &bleio_service_type; + self->device = NULL; + self->char_list = mp_obj_new_list(0, NULL); + self->handle = 0xFFFF; + + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args); + + enum { ARG_uuid, ARG_secondary }; + static const mp_arg_t allowed_args[] = { + { ARG_uuid, MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_secondary, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, + }; + + 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); + + self->is_secondary = args[ARG_secondary].u_bool; + + const mp_obj_t uuid = args[ARG_uuid].u_obj; + + if (uuid == mp_const_none) { + return MP_OBJ_FROM_PTR(self); + } + + if (MP_OBJ_IS_TYPE(uuid, &bleio_uuid_type)) { + self->uuid = MP_OBJ_TO_PTR(uuid); + } else { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, + translate("Invalid UUID parameter"))); + } + + return MP_OBJ_FROM_PTR(self); +} + +STATIC mp_obj_t bleio_service_add_characteristic(mp_obj_t self_in, mp_obj_t characteristic_in) { + bleio_service_obj_t *self = MP_OBJ_TO_PTR(self_in); + bleio_characteristic_obj_t *characteristic = MP_OBJ_TO_PTR(characteristic_in); + + if (self->uuid->type == UUID_TYPE_128BIT) { + characteristic->uuid->type = UUID_TYPE_128BIT; + characteristic->uuid->uuid_vs_idx = self->uuid->uuid_vs_idx; + } + + characteristic->service = self; + + mp_obj_list_append(self->char_list, characteristic); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_service_add_characteristic_obj, bleio_service_add_characteristic); + +STATIC mp_obj_t bleio_service_get_characteristics(mp_obj_t self_in) { + bleio_service_obj_t *self = MP_OBJ_TO_PTR(self_in); + + return self->char_list; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_service_get_characteristics_obj, bleio_service_get_characteristics); + +const mp_obj_property_t bleio_service_characteristics_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_service_get_characteristics_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +STATIC mp_obj_t bleio_service_get_uuid(mp_obj_t self_in) { + bleio_service_obj_t *self = MP_OBJ_TO_PTR(self_in); + + return MP_OBJ_FROM_PTR(self->uuid); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_service_get_uuid_obj, bleio_service_get_uuid); + +const mp_obj_property_t bleio_service_uuid_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_service_get_uuid_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +STATIC const mp_rom_map_elem_t bleio_service_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_add_characteristic), MP_ROM_PTR(&bleio_service_add_characteristic_obj) }, + { MP_ROM_QSTR(MP_QSTR_characteristics), MP_ROM_PTR(&bleio_service_characteristics_obj) }, + { MP_ROM_QSTR(MP_QSTR_uuid), MP_ROM_PTR(&bleio_service_uuid_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(bleio_service_locals_dict, bleio_service_locals_dict_table); + +const mp_obj_type_t bleio_service_type = { + { &mp_type_type }, + .name = MP_QSTR_Service, + .print = bleio_service_print, + .make_new = bleio_service_make_new, + .locals_dict = (mp_obj_dict_t*)&bleio_service_locals_dict +}; diff --git a/shared-bindings/bleio/Service.h b/shared-bindings/bleio/Service.h new file mode 100644 index 000000000..77c751829 --- /dev/null +++ b/shared-bindings/bleio/Service.h @@ -0,0 +1,37 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Artur Pacholec + * + * 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_BLEIO_SERVICE_H +#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SERVICE_H + +#include "shared-module/bleio/Characteristic.h" +#include "shared-module/bleio/Service.h" + +const mp_obj_type_t bleio_service_type; + +extern void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self, bleio_characteristic_obj_t *characteristic); + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SERVICE_H diff --git a/shared-bindings/bleio/UUID.c b/shared-bindings/bleio/UUID.c new file mode 100644 index 000000000..7cef9a26f --- /dev/null +++ b/shared-bindings/bleio/UUID.c @@ -0,0 +1,146 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Glenn Ruben Bakke + * Copyright (c) 2018 Artur Pacholec + * + * 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/objproperty.h" +#include "py/runtime.h" +#include "shared-bindings/bleio/UUID.h" + +//| .. currentmodule:: bleio +//| +//| :class:`UUID` -- BLE UUID +//| ========================================================= +//| +//| Encapsulates both 16-bit and 128-bit UUIDs. Can be used for services, +//| characteristics, descriptors and more. +//| + +//| .. class:: UUID(uuid) +//| +//| Create a new UUID object encapsulating the uuid value. +//| The value itself can be one of: +//| +//| - a `int` value in range of 0 to 0xFFFF +//| - a `str` value in the format of '0xXXXX' for 16-bit or 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' for 128-bit +//| +//| :param int/str uuid: The uuid to encapsulate +//| + +//| .. method:: __len__() +//| +//| Returns the uuid length in bits +//| +//| This allows you to: +//| +//| uuid = bleio.UUID(0x1801) +//| print(len(uuid)) +//| + +//| .. attribute:: type +//| +//| The UUID type. One of: +//| +//| - `bleio.UUIDType.TYPE_16BIT` +//| - `bleio.UUIDType.TYPE_128BIT` +//| +STATIC mp_obj_t bleio_uuid_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) { + mp_arg_check_num(n_args, n_kw, 1, 1, true); + bleio_uuid_obj_t *self = m_new_obj(bleio_uuid_obj_t); + self->base.type = &bleio_uuid_type; + + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args); + + enum { ARG_uuid }; + static const mp_arg_t allowed_args[] = { + { ARG_uuid, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + }; + + 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); + + const mp_obj_t uuid = args[ARG_uuid].u_obj; + + common_hal_bleio_uuid_construct(self, &uuid); + + return MP_OBJ_FROM_PTR(self); +} + +STATIC mp_obj_t bleio_uuid_unary_op(mp_unary_op_t op, mp_obj_t self_in) { + bleio_uuid_obj_t *self = MP_OBJ_TO_PTR(self_in); + + const bleio_uuid_type_t type = common_hal_bleio_uuid_get_type(self); + const uint8_t len = (type == UUID_TYPE_16BIT) ? 16 : 128; + 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 void bleio_uuid_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + bleio_uuid_obj_t *self = MP_OBJ_TO_PTR(self_in); + + common_hal_bleio_uuid_print(self, print); +} + +STATIC mp_obj_t bleio_uuid_get_type(mp_obj_t self_in) { + bleio_uuid_obj_t *self = MP_OBJ_TO_PTR(self_in); + + const bleio_uuid_type_t type = common_hal_bleio_uuid_get_type(self); + if (type == UUID_TYPE_16BIT) { + return (mp_obj_t)&bleio_uuidtype_16bit_obj; + } + + if (type == UUID_TYPE_128BIT) { + return (mp_obj_t)&bleio_uuidtype_128bit_obj; + } + + return (mp_obj_t)&mp_const_none_obj; +} +MP_DEFINE_CONST_FUN_OBJ_1(bleio_uuid_get_type_obj, bleio_uuid_get_type); + +const mp_obj_property_t bleio_uuid_type_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&bleio_uuid_get_type_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj}, +}; + +STATIC const mp_rom_map_elem_t bleio_uuid_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_type), MP_ROM_PTR(&bleio_uuid_type_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(bleio_uuid_locals_dict, bleio_uuid_locals_dict_table); + +const mp_obj_type_t bleio_uuid_type = { + { &mp_type_type }, + .name = MP_QSTR_UUID, + .print = bleio_uuid_print, + .make_new = bleio_uuid_make_new, + .unary_op = bleio_uuid_unary_op, + .locals_dict = (mp_obj_dict_t*)&bleio_uuid_locals_dict +}; diff --git a/shared-bindings/bleio/UUID.h b/shared-bindings/bleio/UUID.h new file mode 100644 index 000000000..d6fcbac1b --- /dev/null +++ b/shared-bindings/bleio/UUID.h @@ -0,0 +1,39 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Artur Pacholec + * + * 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_BLEIO_UUID_H +#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_UUID_H + +#include "common-hal/bleio/UUID.h" +#include "shared-bindings/bleio/UUIDType.h" + +extern const mp_obj_type_t bleio_uuid_type; + +extern void common_hal_bleio_uuid_construct(bleio_uuid_obj_t *self, const mp_obj_t *uuid); +extern void common_hal_bleio_uuid_print(bleio_uuid_obj_t *self, const mp_print_t *print); +extern bleio_uuid_type_t common_hal_bleio_uuid_get_type(bleio_uuid_obj_t *self); + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_UUID_H diff --git a/shared-bindings/bleio/UUIDType.c b/shared-bindings/bleio/UUIDType.c new file mode 100644 index 000000000..e36d1f06d --- /dev/null +++ b/shared-bindings/bleio/UUIDType.c @@ -0,0 +1,75 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Artur Pacholec + * + * 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 "shared-bindings/bleio/UUIDType.h" + +//| .. currentmodule:: bleio +//| +//| :class:`UUIDType` -- defines the type of a BLE UUID +//| ============================================================= +//| +//| .. class:: bleio.UUIDType +//| +//| Enum-like class to define the type of a BLE UUID. +//| +//| .. data:: TYPE_16BIT +//| +//| The UUID is 16-bit +//| +//| .. data:: TYPE_128BIT +//| +//| The UUID is 128-bit +//| +const mp_obj_type_t bleio_uuidtype_type; + +const bleio_uuidtype_obj_t bleio_uuidtype_16bit_obj = { + { &bleio_uuidtype_type }, +}; + +const bleio_uuidtype_obj_t bleio_uuidtype_128bit_obj = { + { &bleio_uuidtype_type }, +}; + +STATIC const mp_rom_map_elem_t bleio_uuidtype_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_TYPE_16BIT), MP_ROM_PTR(&bleio_uuidtype_16bit_obj) }, + { MP_ROM_QSTR(MP_QSTR_TYPE_128BIT), MP_ROM_PTR(&bleio_uuidtype_128bit_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(bleio_uuidtype_locals_dict, bleio_uuidtype_locals_dict_table); + +STATIC void bleio_uuidtype_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + qstr type = MP_QSTR_TYPE_128BIT; + if (MP_OBJ_TO_PTR(self_in) == MP_ROM_PTR(&bleio_uuidtype_16bit_obj)) { + type = MP_QSTR_TYPE_16BIT; + } + mp_printf(print, "%q.%q.%q", MP_QSTR_bleio, MP_QSTR_UUIDType, type); +} + +const mp_obj_type_t bleio_uuidtype_type = { + { &mp_type_type }, + .name = MP_QSTR_UUIDType, + .print = bleio_uuidtype_print, + .locals_dict = (mp_obj_t)&bleio_uuidtype_locals_dict, +}; diff --git a/shared-bindings/bleio/UUIDType.h b/shared-bindings/bleio/UUIDType.h new file mode 100644 index 000000000..87bbf9b53 --- /dev/null +++ b/shared-bindings/bleio/UUIDType.h @@ -0,0 +1,46 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Artur Pacholec + * + * 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_BLEIO_UUIDTYPE_H +#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_UUIDTYPE_H + +#include "py/obj.h" + +typedef enum { + UUID_TYPE_16BIT, + UUID_TYPE_128BIT +} bleio_uuid_type_t; + +extern const mp_obj_type_t bleio_uuidtype_type; + +typedef struct { + mp_obj_base_t base; +} bleio_uuidtype_obj_t; + +extern const bleio_uuidtype_obj_t bleio_uuidtype_16bit_obj; +extern const bleio_uuidtype_obj_t bleio_uuidtype_128bit_obj; + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_UUIDTYPE_H diff --git a/shared-bindings/bleio/__init__.c b/shared-bindings/bleio/__init__.c index 475fb395a..98099422c 100644 --- a/shared-bindings/bleio/__init__.c +++ b/shared-bindings/bleio/__init__.c @@ -25,8 +25,18 @@ * THE SOFTWARE. */ -#include "py/obj.h" #include "shared-bindings/bleio/__init__.h" +#include "shared-bindings/bleio/Address.h" +#include "shared-bindings/bleio/AddressType.h" +#include "shared-bindings/bleio/AdvertisementData.h" +#include "shared-bindings/bleio/Characteristic.h" +#include "shared-bindings/bleio/Descriptor.h" +#include "shared-bindings/bleio/Device.h" +#include "shared-bindings/bleio/ScanEntry.h" +#include "shared-bindings/bleio/Scanner.h" +#include "shared-bindings/bleio/Service.h" +#include "shared-bindings/bleio/UUID.h" +#include "shared-bindings/bleio/UUIDType.h" //| :mod:`bleio` --- Bluetooth Low Energy functionality //| ================================================================ @@ -42,7 +52,18 @@ //| .. toctree:: //| :maxdepth: 3 //| +//| Address +//| AddressType +//| AdvertisementData //| Adapter +//| Characteristic +//| Descriptor +//| Device +//| ScanEntry +//| Scanner +//| Service +//| UUID +//| UUIDType //| //| .. attribute:: adapter //| @@ -52,8 +73,23 @@ //| STATIC const mp_rom_map_elem_t bleio_module_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_bleio) }, - { MP_ROM_QSTR(MP_QSTR_adapter), MP_ROM_PTR(&common_hal_bleio_adapter_obj) }, + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_bleio) }, + { MP_ROM_QSTR(MP_QSTR_Address), MP_ROM_PTR(&bleio_address_type) }, + { MP_ROM_QSTR(MP_QSTR_AdvertisementData), MP_ROM_PTR(&bleio_advertisementdata_type) }, + { MP_ROM_QSTR(MP_QSTR_Characteristic), MP_ROM_PTR(&bleio_characteristic_type) }, + { MP_ROM_QSTR(MP_QSTR_Descriptor), MP_ROM_PTR(&bleio_descriptor_type) }, + { MP_ROM_QSTR(MP_QSTR_Device), MP_ROM_PTR(&bleio_device_type) }, + { MP_ROM_QSTR(MP_QSTR_ScanEntry), MP_ROM_PTR(&bleio_scanentry_type) }, + { MP_ROM_QSTR(MP_QSTR_Scanner), MP_ROM_PTR(&bleio_scanner_type) }, + { MP_ROM_QSTR(MP_QSTR_Service), MP_ROM_PTR(&bleio_service_type) }, + { MP_ROM_QSTR(MP_QSTR_UUID), MP_ROM_PTR(&bleio_uuid_type) }, + + // Properties + { MP_ROM_QSTR(MP_QSTR_adapter), MP_ROM_PTR(&common_hal_bleio_adapter_obj) }, + + // Enum-like Classes. + { MP_ROM_QSTR(MP_QSTR_AddressType), MP_ROM_PTR(&bleio_addresstype_type) }, + { MP_ROM_QSTR(MP_QSTR_UUIDType), MP_ROM_PTR(&bleio_uuidtype_type) }, }; STATIC MP_DEFINE_CONST_DICT(bleio_module_globals, bleio_module_globals_table); diff --git a/shared-bindings/busio/SPI.c b/shared-bindings/busio/SPI.c index 7983a3a56..d30bbbe06 100644 --- a/shared-bindings/busio/SPI.c +++ b/shared-bindings/busio/SPI.c @@ -136,19 +136,26 @@ static void check_lock(busio_spi_obj_t *self) { //| .. method:: SPI.configure(\*, baudrate=100000, polarity=0, phase=0, bits=8) //| -//| Configures the SPI bus. Only valid when locked. +//| Configures the SPI bus. The SPI object must be locked. //| //| :param int baudrate: the desired clock rate in Hertz. The actual clock rate may be higher or lower //| due to the granularity of available clock settings. //| Check the `frequency` attribute for the actual clock rate. -//| **Note:** on the SAMD21, it is possible to set the baud rate to 24 MHz, but that -//| speed is not guaranteed to work. 12 MHz is the next available lower speed, and is -//| within spec for the SAMD21. //| :param int polarity: the base state of the clock line (0 or 1) //| :param int phase: the edge of the clock that data is captured. First (0) //| or second (1). Rising or falling depends on clock polarity. //| :param int bits: the number of bits per word //| +//| .. note:: On the SAMD21, it is possible to set the baudrate to 24 MHz, but that +//| speed is not guaranteed to work. 12 MHz is the next available lower speed, and is +//| within spec for the SAMD21. +//| +//| .. note:: On the nRF52832, these baudrates are available: 125kHz, 250kHz, 1MHz, 2MHz, 4MHz, +//| and 8MHz. On the nRF52840, 16MHz and 32MHz are also available, but only on the first +//| `busio.SPI` object you create. Two more ``busio.SPI`` objects can be created, but they are restricted +//| to 8MHz maximum. This is a hardware restriction: there is only one high-speed SPI peripheral. +//| If you pick a a baudrate other than one of these, the nearest lower +//| baudrate will be chosen, with a minimum of 125kHz. STATIC mp_obj_t busio_spi_configure(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_baudrate, ARG_polarity, ARG_phase, ARG_bits }; static const mp_arg_t allowed_args[] = { diff --git a/shared-bindings/busio/SPI.h b/shared-bindings/busio/SPI.h index 555f32c92..2d12b8b76 100644 --- a/shared-bindings/busio/SPI.h +++ b/shared-bindings/busio/SPI.h @@ -61,4 +61,7 @@ extern bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, uint8_t *data_o // Return actual SPI bus frequency. uint32_t common_hal_busio_spi_get_frequency(busio_spi_obj_t* self); +// This is used by the supervisor to claim SPI devices indefinitely. +extern void common_hal_busio_spi_never_reset(busio_spi_obj_t *self); + #endif // MICROPY_INCLUDED_SHARED_BINDINGS_BUSIO_SPI_H diff --git a/shared-bindings/help.c b/shared-bindings/help.c index 78301a91a..e0770ff3c 100644 --- a/shared-bindings/help.c +++ b/shared-bindings/help.c @@ -24,8 +24,6 @@ * THE SOFTWARE. */ -#include "genhdr/mpversion.h" - //| :func:`help` - Built-in method to provide helpful information //| ============================================================== //| @@ -34,12 +32,3 @@ //| Prints a help method about the given object. When ``object`` is none, //| prints general port information. //| - -// TODO(tannewt): Figure out how to translate this. Its weird because its a global string. - -const char circuitpython_help_text[] = - "Welcome to Adafruit CircuitPython " MICROPY_GIT_TAG "!\r\n" - "\r\n" - "Please visit learn.adafruit.com/category/circuitpython for project guides.\r\n" - "\r\n" - "To list built-in modules please do `help(\"modules\")`.\r\n"; diff --git a/shared-bindings/network/__init__.c b/shared-bindings/network/__init__.c new file mode 100644 index 000000000..69f8bea60 --- /dev/null +++ b/shared-bindings/network/__init__.c @@ -0,0 +1,74 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2014 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include <stdio.h> +#include <stdint.h> +#include <string.h> + +#include "py/objlist.h" +#include "py/runtime.h" +#include "py/mphal.h" +#include "py/mperrno.h" +#include "lib/netutils/netutils.h" + +#include "shared-bindings/network/__init__.h" + +#if MICROPY_PY_NETWORK + +//| :mod:`network` --- Network Interface Management +//| =============================================== +//| +//| .. module:: network +//| :synopsis: Network Interface Management +//| :platform: SAMD +//| +//| This module provides a registry of configured NICs. +//| It is used by the 'socket' module to look up a suitable +//| NIC when a socket is created. +//| +//| .. function:: route +//| +//| Returns a list of all configured NICs. +//| + +STATIC mp_obj_t network_route(void) { + return MP_OBJ_FROM_PTR(&MP_STATE_PORT(mod_network_nic_list)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(network_route_obj, network_route); + +STATIC const mp_rom_map_elem_t mp_module_network_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_network) }, + { MP_ROM_QSTR(MP_QSTR_route), MP_ROM_PTR(&network_route_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(mp_module_network_globals, mp_module_network_globals_table); + +const mp_obj_module_t network_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&mp_module_network_globals, +}; + +#endif // MICROPY_PY_NETWORK diff --git a/shared-bindings/network/__init__.h b/shared-bindings/network/__init__.h new file mode 100644 index 000000000..4fe5e75a3 --- /dev/null +++ b/shared-bindings/network/__init__.h @@ -0,0 +1,31 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_NETWORK___INIT___H +#define MICROPY_INCLUDED_SHARED_BINDINGS_NETWORK___INIT___H + +// nothing + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_NETWORK___INIT___H diff --git a/shared-bindings/pulseio/PWMOut.c b/shared-bindings/pulseio/PWMOut.c index 9b7094b4e..362b8123d 100644 --- a/shared-bindings/pulseio/PWMOut.c +++ b/shared-bindings/pulseio/PWMOut.c @@ -192,7 +192,7 @@ STATIC mp_obj_t pulseio_pwmout_obj_set_frequency(mp_obj_t self_in, mp_obj_t freq raise_error_if_deinited(common_hal_pulseio_pwmout_deinited(self)); if (!common_hal_pulseio_pwmout_get_variable_frequency(self)) { mp_raise_AttributeError(translate( - "PWM frequency not writeable when variable_frequency is False on " + "PWM frequency not writable when variable_frequency is False on " "construction.")); } common_hal_pulseio_pwmout_set_frequency(self, mp_obj_get_int(frequency)); diff --git a/shared-bindings/pulseio/PulseOut.c b/shared-bindings/pulseio/PulseOut.c index 1c97c37c3..e9834c12a 100644 --- a/shared-bindings/pulseio/PulseOut.c +++ b/shared-bindings/pulseio/PulseOut.c @@ -47,7 +47,7 @@ //| //| .. class:: PulseOut(carrier) //| -//| Create a PulseOut object associated with the given PWM out experience. +//| Create a PulseOut object associated with the given PWMout object. //| //| :param ~pulseio.PWMOut carrier: PWMOut that is set to output on the desired pin. //| @@ -57,9 +57,10 @@ //| import pulseio //| import board //| -//| pwm = pulseio.PWMOut(board.D13, duty_cycle=2 ** 15) +//| # 50% duty cycle at 38kHz. +//| pwm = pulseio.PWMOut(board.D13, frequency=38000, duty_cycle=32768) //| pulse = pulseio.PulseOut(pwm) -//| # on off on off on +//| # on off on off on //| pulses = array.array('H', [65000, 1000, 65000, 65000, 1000]) //| pulse.send(pulses) //| diff --git a/shared-bindings/socket/__init__.c b/shared-bindings/socket/__init__.c new file mode 100644 index 000000000..d860c40c8 --- /dev/null +++ b/shared-bindings/socket/__init__.c @@ -0,0 +1,559 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2014 Damien P. George + * 2018 Nick Moore 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. + */ + +#include <stdio.h> +#include <string.h> + +#include "py/objtuple.h" +#include "py/objlist.h" +#include "py/runtime.h" +#include "py/stream.h" +#include "py/mperrno.h" +#include "lib/netutils/netutils.h" + +#include "shared-module/network/__init__.h" + +//| :mod:`socket` --- TCP, UDP and RAW socket support +//| ================================================= +//| +//| .. module:: socket +//| :synopsis: TCP, UDP and RAW sockets +//| :platform: SAMD21, SAMD51 +//| +//| Create TCP, UDP and RAW sockets for communicating over the Internet. +//| + +STATIC const mp_obj_type_t socket_type; + +//| .. currentmodule:: socket +//| +//| .. class:: socket(family, type, proto, ...) +//| +//| Create a new socket +//| +//| :param ~int family: AF_INET or AF_INET6 +//| :param ~int type: SOCK_STREAM, SOCK_DGRAM or SOCK_RAW +//| :param ~int proto: IPPROTO_TCP, IPPROTO_UDP or IPPROTO_RAW (ignored) +//| + +STATIC mp_obj_t socket_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, 4, false); + + // create socket object (not bound to any NIC yet) + mod_network_socket_obj_t *s = m_new_obj_with_finaliser(mod_network_socket_obj_t); + s->base.type = &socket_type; + s->nic = MP_OBJ_NULL; + s->nic_type = NULL; + s->u_param.domain = MOD_NETWORK_AF_INET; + s->u_param.type = MOD_NETWORK_SOCK_STREAM; + s->u_param.fileno = -1; + if (n_args >= 1) { + s->u_param.domain = mp_obj_get_int(args[0]); + if (n_args >= 2) { + s->u_param.type = mp_obj_get_int(args[1]); + if (n_args >= 4) { + s->u_param.fileno = mp_obj_get_int(args[3]); + } + } + } + + return MP_OBJ_FROM_PTR(s); +} + +STATIC void socket_select_nic(mod_network_socket_obj_t *self, const byte *ip) { + if (self->nic == MP_OBJ_NULL) { + // select NIC based on IP + self->nic = network_module_find_nic(ip); + self->nic_type = (mod_network_nic_type_t*)mp_obj_get_type(self->nic); + + // call the NIC to open the socket + int _errno; + if (self->nic_type->socket(self, &_errno) != 0) { + mp_raise_OSError(_errno); + } + } +} + +//| .. method:: bind(address) +//| +//| Bind a socket to an address +//| +//| :param ~tuple address: tuple of (remote_address, remote_port) +//| + +STATIC mp_obj_t socket_bind(mp_obj_t self_in, mp_obj_t addr_in) { + mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in); + + // get address + uint8_t ip[MOD_NETWORK_IPADDR_BUF_SIZE]; + mp_uint_t port = netutils_parse_inet_addr(addr_in, ip, NETUTILS_BIG); + + // check if we need to select a NIC + socket_select_nic(self, ip); + + // call the NIC to bind the socket + int _errno; + if (self->nic_type->bind(self, ip, port, &_errno) != 0) { + mp_raise_OSError(_errno); + } + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_bind_obj, socket_bind); + +//| .. method:: listen(backlog) +//| +//| Set socket to listen for incoming connections +//| +//| :param ~int backlog: length of backlog queue for waiting connetions +//| + +STATIC mp_obj_t socket_listen(mp_obj_t self_in, mp_obj_t backlog) { + mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in); + + if (self->nic == MP_OBJ_NULL) { + // not connected + // TODO I think we can listen even if not bound... + mp_raise_OSError(MP_ENOTCONN); + } + + int _errno; + if (self->nic_type->listen(self, mp_obj_get_int(backlog), &_errno) != 0) { + mp_raise_OSError(_errno); + } + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_listen_obj, socket_listen); + +//| .. method:: accept() +//| +//| Accept a connection on a listening socket of type SOCK_STREAM, +//| creating a new socket of type SOCK_STREAM. +//| Returns a tuple of (new_socket, remote_address) +//| + +STATIC mp_obj_t socket_accept(mp_obj_t self_in) { + mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in); + + // create new socket object + // starts with empty NIC so that finaliser doesn't run close() method if accept() fails + mod_network_socket_obj_t *socket2 = m_new_obj_with_finaliser(mod_network_socket_obj_t); + socket2->base.type = &socket_type; + socket2->nic = MP_OBJ_NULL; + socket2->nic_type = NULL; + + // accept incoming connection + uint8_t ip[MOD_NETWORK_IPADDR_BUF_SIZE]; + mp_uint_t port; + int _errno; + if (self->nic_type->accept(self, socket2, ip, &port, &_errno) != 0) { + mp_raise_OSError(_errno); + } + + // new socket has valid state, so set the NIC to the same as parent + socket2->nic = self->nic; + socket2->nic_type = self->nic_type; + + // make the return value + mp_obj_tuple_t *client = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL)); + client->items[0] = MP_OBJ_FROM_PTR(socket2); + client->items[1] = netutils_format_inet_addr(ip, port, NETUTILS_BIG); + + return MP_OBJ_FROM_PTR(client); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_accept_obj, socket_accept); + +//| .. method:: connect(address) +//| +//| Connect a socket to a remote address +//| +//| :param ~tuple address: tuple of (remote_address, remote_port) +//| + +STATIC mp_obj_t socket_connect(mp_obj_t self_in, mp_obj_t addr_in) { + mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in); + + // get address + uint8_t ip[MOD_NETWORK_IPADDR_BUF_SIZE]; + mp_uint_t port = netutils_parse_inet_addr(addr_in, ip, NETUTILS_BIG); + + // check if we need to select a NIC + socket_select_nic(self, ip); + + // call the NIC to connect the socket + int _errno; + if (self->nic_type->connect(self, ip, port, &_errno) != 0) { + mp_raise_OSError(_errno); + } + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_connect_obj, socket_connect); + +//| .. method:: send(bytes) +//| +//| Send some bytes to the connected remote address. +//| Suits sockets of type SOCK_STREAM +//| +//| :param ~bytes bytes: some bytes to send +//| + +STATIC mp_obj_t socket_send(mp_obj_t self_in, mp_obj_t buf_in) { + mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in); + if (self->nic == MP_OBJ_NULL) { + // not connected + mp_raise_OSError(MP_EPIPE); + } + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ); + int _errno; + mp_int_t ret = self->nic_type->send(self, bufinfo.buf, bufinfo.len, &_errno); + if (ret == -1) { + mp_raise_OSError(_errno); + } + return mp_obj_new_int_from_uint(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_send_obj, socket_send); + +//| .. method:: recv(bufsize) +//| +//| Reads some bytes from the connected remote address. +//| Suits sockets of type SOCK_STREAM +//| Returns a bytes() of length <= bufsize +//| +//| :param ~int bufsize: maximum number of bytes to receive + +STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) { + mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in); + if (self->nic == MP_OBJ_NULL) { + // not connected + mp_raise_OSError(MP_ENOTCONN); + } + mp_int_t len = mp_obj_get_int(len_in); + vstr_t vstr; + vstr_init_len(&vstr, len); + int _errno; + mp_int_t ret = self->nic_type->recv(self, (byte*)vstr.buf, len, &_errno); + if (ret == -1) { + mp_raise_OSError(_errno); + } + if (ret == 0) { + return mp_const_empty_bytes; + } + vstr.len = ret; + return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_recv_obj, socket_recv); + +//| .. method:: sendto(bytes, address) +//| +//| Send some bytes to a specific address. +//| Suits sockets of type SOCK_DGRAM +//| +//| :param ~bytes bytes: some bytes to send +//| :param ~tuple address: tuple of (remote_address, remote_port) +//| + +STATIC mp_obj_t socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t addr_in) { + mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in); + + // get the data + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(data_in, &bufinfo, MP_BUFFER_READ); + + // get address + uint8_t ip[MOD_NETWORK_IPADDR_BUF_SIZE]; + mp_uint_t port = netutils_parse_inet_addr(addr_in, ip, NETUTILS_BIG); + + // check if we need to select a NIC + socket_select_nic(self, ip); + + // call the NIC to sendto + int _errno; + mp_int_t ret = self->nic_type->sendto(self, bufinfo.buf, bufinfo.len, ip, port, &_errno); + if (ret == -1) { + mp_raise_OSError(_errno); + } + + return mp_obj_new_int(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(socket_sendto_obj, socket_sendto); + +//| .. method:: recvfrom(bufsize) +//| +//| Reads some bytes from the connected remote address. +//| Suits sockets of type SOCK_STREAM +//| +//| Returns a tuple containing +//| * a bytes() of length <= bufsize +//| * a remote_address, which is a tuple of ip address and port number +//| +//| :param ~int bufsize: maximum number of bytes to receive +//| + +STATIC mp_obj_t socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) { + mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in); + if (self->nic == MP_OBJ_NULL) { + // not connected + mp_raise_OSError(MP_ENOTCONN); + } + vstr_t vstr; + vstr_init_len(&vstr, mp_obj_get_int(len_in)); + byte ip[4]; + mp_uint_t port; + int _errno; + mp_int_t ret = self->nic_type->recvfrom(self, (byte*)vstr.buf, vstr.len, ip, &port, &_errno); + if (ret == -1) { + mp_raise_OSError(_errno); + } + mp_obj_t tuple[2]; + if (ret == 0) { + tuple[0] = mp_const_empty_bytes; + } else { + vstr.len = ret; + tuple[0] = mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); + } + tuple[1] = netutils_format_inet_addr(ip, port, NETUTILS_BIG); + return mp_obj_new_tuple(2, tuple); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_recvfrom_obj, socket_recvfrom); + +//| .. method:: setsockopt(level, optname, value) +//| +//| Sets socket options +//| + +STATIC mp_obj_t socket_setsockopt(size_t n_args, const mp_obj_t *args) { + mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(args[0]); + + mp_int_t level = mp_obj_get_int(args[1]); + mp_int_t opt = mp_obj_get_int(args[2]); + + const void *optval; + mp_uint_t optlen; + mp_int_t val; + if (mp_obj_is_integer(args[3])) { + val = mp_obj_get_int_truncated(args[3]); + optval = &val; + optlen = sizeof(val); + } else { + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ); + optval = bufinfo.buf; + optlen = bufinfo.len; + } + + int _errno; + if (self->nic_type->setsockopt(self, level, opt, optval, optlen, &_errno) != 0) { + mp_raise_OSError(_errno); + } + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_setsockopt_obj, 4, 4, socket_setsockopt); + +//| .. method:: settimeout(value) +//| +//| Set the timeout value for this socket. +//| +//| :param ~int value: timeout in seconds. 0 means non-blocking. None means block indefinitely. +//| + +STATIC mp_obj_t socket_settimeout(mp_obj_t self_in, mp_obj_t timeout_in) { + mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in); + if (self->nic == MP_OBJ_NULL) { + // not connected + mp_raise_OSError(MP_ENOTCONN); + } + mp_uint_t timeout; + if (timeout_in == mp_const_none) { + timeout = -1; + } else { + #if MICROPY_PY_BUILTINS_FLOAT + timeout = 1000 * mp_obj_get_float(timeout_in); + #else + timeout = 1000 * mp_obj_get_int(timeout_in); + #endif + } + int _errno; + if (self->nic_type->settimeout(self, timeout, &_errno) != 0) { + mp_raise_OSError(_errno); + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_settimeout_obj, socket_settimeout); + +//| .. method:: setblocking(flag) +//| +//| Set the blocking behaviour of this socket. +//| +//| :param ~bool flag: False means non-blocking, True means block indefinitely. +//| + +// method socket.setblocking(flag) +STATIC mp_obj_t socket_setblocking(mp_obj_t self_in, mp_obj_t blocking) { + if (mp_obj_is_true(blocking)) { + return socket_settimeout(self_in, mp_const_none); + } else { + return socket_settimeout(self_in, MP_OBJ_NEW_SMALL_INT(0)); + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_setblocking_obj, socket_setblocking); + +STATIC const mp_rom_map_elem_t socket_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) }, + { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) }, + { MP_ROM_QSTR(MP_QSTR_bind), MP_ROM_PTR(&socket_bind_obj) }, + { MP_ROM_QSTR(MP_QSTR_listen), MP_ROM_PTR(&socket_listen_obj) }, + { MP_ROM_QSTR(MP_QSTR_accept), MP_ROM_PTR(&socket_accept_obj) }, + { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&socket_connect_obj) }, + { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&socket_send_obj) }, + { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&socket_recv_obj) }, + { MP_ROM_QSTR(MP_QSTR_sendto), MP_ROM_PTR(&socket_sendto_obj) }, + { MP_ROM_QSTR(MP_QSTR_recvfrom), MP_ROM_PTR(&socket_recvfrom_obj) }, + { MP_ROM_QSTR(MP_QSTR_setsockopt), MP_ROM_PTR(&socket_setsockopt_obj) }, + { MP_ROM_QSTR(MP_QSTR_settimeout), MP_ROM_PTR(&socket_settimeout_obj) }, + { MP_ROM_QSTR(MP_QSTR_setblocking), MP_ROM_PTR(&socket_setblocking_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(socket_locals_dict, socket_locals_dict_table); + +mp_uint_t socket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { + mod_network_socket_obj_t *self = MP_OBJ_TO_PTR(self_in); + if (request == MP_STREAM_CLOSE) { + if (self->nic != MP_OBJ_NULL) { + self->nic_type->close(self); + self->nic = MP_OBJ_NULL; + } + return 0; + } + return self->nic_type->ioctl(self, request, arg, errcode); +} + +STATIC const mp_stream_p_t socket_stream_p = { + .ioctl = socket_ioctl, + .is_text = false, +}; + +STATIC const mp_obj_type_t socket_type = { + { &mp_type_type }, + .name = MP_QSTR_socket, + .make_new = socket_make_new, + .protocol = &socket_stream_p, + .locals_dict = (mp_obj_dict_t*)&socket_locals_dict, +}; + +//| .. function:: getaddrinfo(host, port) +//| +//| Gets the address information for a hostname and port +//| +//| Returns the appropriate family, socket type, socket protocol and +//| address information to call socket.socket() and socket.connect() with, +//| as a tuple. +//| + +STATIC mp_obj_t socket_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in) { + size_t hlen; + const char *host = mp_obj_str_get_data(host_in, &hlen); + mp_int_t port = mp_obj_get_int(port_in); + uint8_t out_ip[MOD_NETWORK_IPADDR_BUF_SIZE]; + bool have_ip = false; + + if (hlen > 0) { + // check if host is already in IP form + nlr_buf_t nlr; + if (nlr_push(&nlr) == 0) { + netutils_parse_ipv4_addr(host_in, out_ip, NETUTILS_BIG); + have_ip = true; + nlr_pop(); + } else { + // swallow exception: host was not in IP form so need to do DNS lookup + } + } + + if (!have_ip) { + // find a NIC that can do a name lookup + 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]; + mod_network_nic_type_t *nic_type = (mod_network_nic_type_t*)mp_obj_get_type(nic); + if (nic_type->gethostbyname != NULL) { + int ret = nic_type->gethostbyname(nic, host, hlen, out_ip); + if (ret != 0) { + mp_raise_OSError(ret); + } + have_ip = true; + break; + } + } + } + + if (!have_ip) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, translate("no available NIC"))); + } + + mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(mp_obj_new_tuple(5, NULL)); + tuple->items[0] = MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_AF_INET); + tuple->items[1] = MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_SOCK_STREAM); + tuple->items[2] = MP_OBJ_NEW_SMALL_INT(0); + tuple->items[3] = MP_OBJ_NEW_QSTR(MP_QSTR_); + tuple->items[4] = netutils_format_inet_addr(out_ip, port, NETUTILS_BIG); + return mp_obj_new_list(1, (mp_obj_t*)&tuple); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_getaddrinfo_obj, socket_getaddrinfo); + +STATIC const mp_rom_map_elem_t socket_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_usocket) }, + + { MP_ROM_QSTR(MP_QSTR_socket), MP_ROM_PTR(&socket_type) }, + { MP_ROM_QSTR(MP_QSTR_getaddrinfo), MP_ROM_PTR(&socket_getaddrinfo_obj) }, + + // class constants + { MP_ROM_QSTR(MP_QSTR_AF_INET), MP_ROM_INT(MOD_NETWORK_AF_INET) }, + { MP_ROM_QSTR(MP_QSTR_AF_INET6), MP_ROM_INT(MOD_NETWORK_AF_INET6) }, + + { MP_ROM_QSTR(MP_QSTR_SOCK_STREAM), MP_ROM_INT(MOD_NETWORK_SOCK_STREAM) }, + { MP_ROM_QSTR(MP_QSTR_SOCK_DGRAM), MP_ROM_INT(MOD_NETWORK_SOCK_DGRAM) }, + { MP_ROM_QSTR(MP_QSTR_SOCK_RAW), MP_ROM_INT(MOD_NETWORK_SOCK_RAW) }, + + /* + { MP_ROM_QSTR(MP_QSTR_IPPROTO_IP), MP_ROM_INT(MOD_NETWORK_IPPROTO_IP) }, + { MP_ROM_QSTR(MP_QSTR_IPPROTO_ICMP), MP_ROM_INT(MOD_NETWORK_IPPROTO_ICMP) }, + { MP_ROM_QSTR(MP_QSTR_IPPROTO_IPV4), MP_ROM_INT(MOD_NETWORK_IPPROTO_IPV4) }, + { MP_ROM_QSTR(MP_QSTR_IPPROTO_TCP), MP_ROM_INT(MOD_NETWORK_IPPROTO_TCP) }, + { MP_ROM_QSTR(MP_QSTR_IPPROTO_UDP), MP_ROM_INT(MOD_NETWORK_IPPROTO_UDP) }, + { MP_ROM_QSTR(MP_QSTR_IPPROTO_IPV6), MP_ROM_INT(MOD_NETWORK_IPPROTO_IPV6) }, + { MP_ROM_QSTR(MP_QSTR_IPPROTO_RAW), MP_ROM_INT(MOD_NETWORK_IPPROTO_RAW) }, + */ +}; + +STATIC MP_DEFINE_CONST_DICT(socket_globals, socket_globals_table); + +const mp_obj_module_t socket_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&socket_globals, +}; diff --git a/shared-bindings/supervisor/Runtime.c b/shared-bindings/supervisor/Runtime.c index b061595cf..5ba2198e1 100755 --- a/shared-bindings/supervisor/Runtime.c +++ b/shared-bindings/supervisor/Runtime.c @@ -80,8 +80,34 @@ const mp_obj_property_t supervisor_serial_connected_obj = { (mp_obj_t)&mp_const_none_obj}, }; + +//| .. attribute:: runtime.serial_bytes_available +//| +//| Returns the whether any bytes are available to read +//| on the USB serial input. Allows for polling to see whether +//| to call the built-in input() or wait. (read-only) +//| +STATIC mp_obj_t supervisor_get_serial_bytes_available(mp_obj_t self){ + if (!common_hal_get_serial_bytes_available()) { + return mp_const_false; + } + else { + return mp_const_true; + } +} +MP_DEFINE_CONST_FUN_OBJ_1(supervisor_get_serial_bytes_available_obj, supervisor_get_serial_bytes_available); + +const mp_obj_property_t supervisor_serial_bytes_available_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&supervisor_get_serial_bytes_available_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj}, +}; + + STATIC const mp_rom_map_elem_t supervisor_runtime_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_serial_connected), MP_ROM_PTR(&supervisor_serial_connected_obj) }, + { MP_ROM_QSTR(MP_QSTR_serial_bytes_available), MP_ROM_PTR(&supervisor_serial_bytes_available_obj) }, }; STATIC MP_DEFINE_CONST_DICT(supervisor_runtime_locals_dict, supervisor_runtime_locals_dict_table); diff --git a/shared-bindings/supervisor/Runtime.h b/shared-bindings/supervisor/Runtime.h index 4a67925ec..864b070cd 100755 --- a/shared-bindings/supervisor/Runtime.h +++ b/shared-bindings/supervisor/Runtime.h @@ -35,6 +35,8 @@ const mp_obj_type_t supervisor_runtime_type; bool common_hal_get_serial_connected(void); +bool common_hal_get_serial_bytes_available(void); + //TODO: placeholders for future functions //bool common_hal_get_repl_active(void); //bool common_hal_get_usb_enumerated(void); diff --git a/shared-bindings/time/__init__.c b/shared-bindings/time/__init__.c index 4d9554569..f97ad4a5d 100644 --- a/shared-bindings/time/__init__.c +++ b/shared-bindings/time/__init__.c @@ -206,6 +206,19 @@ STATIC mp_obj_t time_time(void) { } MP_DEFINE_CONST_FUN_OBJ_0(time_time_obj, time_time); +//| .. method:: monotonic_ns() +//| +//| Return the time of the specified clock clk_id in nanoseconds. +//| +//| :return: the current time +//| :rtype: int +//| +STATIC mp_obj_t time_monotonic_ns(void) { + uint64_t time64 = common_hal_time_monotonic() * 1000000llu; + return mp_obj_new_int_from_ll((long long) time64); +} +MP_DEFINE_CONST_FUN_OBJ_0(time_monotonic_ns_obj, time_monotonic_ns); + //| .. method:: localtime([secs]) //| //| Convert a time expressed in seconds since Jan 1, 1970 to a struct_time in @@ -280,6 +293,7 @@ STATIC const mp_rom_map_elem_t time_module_globals_table[] = { #endif // MICROPY_PY_COLLECTIONS #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE { MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&time_time_obj) }, + { MP_ROM_QSTR(MP_QSTR_monotonic_ns), MP_ROM_PTR(&time_monotonic_ns_obj) }, #endif }; diff --git a/shared-bindings/usb_hid/Device.h b/shared-bindings/usb_hid/Device.h index 2bc553c4a..cb9a64b5e 100644 --- a/shared-bindings/usb_hid/Device.h +++ b/shared-bindings/usb_hid/Device.h @@ -27,7 +27,7 @@ #ifndef MICROPY_INCLUDED_SHARED_BINDINGS_USB_HID_DEVICE_H #define MICROPY_INCLUDED_SHARED_BINDINGS_USB_HID_DEVICE_H -#include "common-hal/usb_hid/Device.h" +#include "shared-module/usb_hid/Device.h" const mp_obj_type_t usb_hid_device_type; diff --git a/ports/atmel-samd/common-hal/storage/__init__.c b/shared-bindings/wiznet/__init__.c index 501a19dd7..e230deecc 100644 --- a/ports/atmel-samd/common-hal/storage/__init__.c +++ b/shared-bindings/wiznet/__init__.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * Copyright (c) 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -24,35 +24,46 @@ * THE SOFTWARE. */ +#include <stdio.h> +#include <stdint.h> #include <string.h> -#include "flash_api.h" -#include "py/mperrno.h" +#include "py/objlist.h" +#include "py/objproperty.h" #include "py/runtime.h" -#include "shared-bindings/microcontroller/__init__.h" -#include "shared-bindings/storage/__init__.h" -#include "supervisor/filesystem.h" -#include "supervisor/shared/translate.h" -#include "usb.h" - -extern volatile bool mp_msc_enabled; - -void common_hal_storage_remount(const char* mount_path, bool readonly) { - if (strcmp(mount_path, "/") != 0) { - mp_raise_OSError(MP_EINVAL); - } - - // TODO(dhalbert): is this is a good enough check? It checks for - // CDC enabled. There is no "MSC enabled" check. - if (usb_connected()) { - mp_raise_RuntimeError(translate("Cannot remount '/' when USB is active.")); - } - - flash_set_usb_writable(readonly); -} - -void common_hal_storage_erase_filesystem(void) { - filesystem_init(false, true); // Force a re-format. - common_hal_mcu_reset(); - // We won't actually get here, since we're resetting. -} +#include "py/mphal.h" + +#include "shared-module/network/__init__.h" + +//| :mod:`wiznet` --- Support for WizNet hardware +//| ============================================= +//| +//| .. module:: wiznet +//| :synopsis: Support for WizNet hardware +//| :platform: SAMD +//| +//| Support for WizNet hardware, including the WizNet 5500 Ethernet adaptor. +//| +//| Libraries +//| +//| .. toctree:: +//| :maxdepth: 3 +//| +//| wiznet5k +//| + +extern const mod_network_nic_type_t mod_network_nic_type_wiznet5k; + +STATIC const mp_rom_map_elem_t mp_module_wiznet_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_wiznet) }, +#ifdef MICROPY_PY_WIZNET5K + { MP_ROM_QSTR(MP_QSTR_WIZNET5K), MP_ROM_PTR(&mod_network_nic_type_wiznet5k) }, +#endif // MICROPY_PY_WIZNET5K +}; +STATIC MP_DEFINE_CONST_DICT(mp_module_wiznet_globals, mp_module_wiznet_globals_table); + +const mp_obj_module_t wiznet_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&mp_module_wiznet_globals, +}; + diff --git a/shared-bindings/wiznet/wiznet5k.c b/shared-bindings/wiznet/wiznet5k.c new file mode 100644 index 000000000..4e5fff869 --- /dev/null +++ b/shared-bindings/wiznet/wiznet5k.c @@ -0,0 +1,183 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2014 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include <stdio.h> +#include <stdint.h> +#include <string.h> + +#include "py/objlist.h" +#include "py/objproperty.h" +#include "py/runtime.h" +#include "py/stream.h" +#include "py/mperrno.h" +#include "py/mphal.h" +#include "lib/netutils/netutils.h" + +#if MICROPY_PY_WIZNET5K + +#include "shared-bindings/digitalio/DigitalInOut.h" +#include "shared-bindings/digitalio/DriveMode.h" +#include "shared-bindings/busio/SPI.h" + +#include "shared-module/network/__init__.h" +#include "shared-module/wiznet/wiznet5k.h" + +//| .. currentmodule:: wiznet +//| +//| :class:`WIZNET5K` -- wrapper for Wiznet 5500 Ethernet interface +//| =============================================================== +//| +//| .. class:: WIZNET5K(spi, cs, rst) +//| +//| Create a new WIZNET5500 interface using the specified pins +//| +//| :param spi: spi bus to use +//| :param cs: pin to use for Chip Select +//| :param rst: pin to sue for Reset +//| + +STATIC mp_obj_t wiznet5k_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { + // check arguments + mp_arg_check_num(n_args, n_kw, 3, 3, false); + + return wiznet5k_create(args[0], args[1], args[2]); +} + +//| .. attribute:: connected +//| +//| is this device physically connected? +//| + +STATIC mp_obj_t wiznet5k_connected_get_value(mp_obj_t self_in) { + (void)self_in; + return mp_obj_new_bool(wizphy_getphylink() == PHY_LINK_ON); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(wiznet5k_connected_get_value_obj, wiznet5k_connected_get_value); + +const mp_obj_property_t wiznet5k_connected_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&wiznet5k_connected_get_value_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj}, +}; + +//| .. attribute:: dhcp +//| +//| is DHCP active on this device? (set to true to activate DHCP, false to turn it off) +//| + +STATIC mp_obj_t wiznet5k_dhcp_get_value(mp_obj_t self_in) { + (void)self_in; + return mp_obj_new_bool(wiznet5k_check_dhcp()); +} + +STATIC MP_DEFINE_CONST_FUN_OBJ_1(wiznet5k_dhcp_get_value_obj, wiznet5k_dhcp_get_value); + +STATIC mp_obj_t wiznet5k_dhcp_set_value(mp_obj_t self_in, mp_obj_t value) { + (void)self_in; + if (mp_obj_is_true(value)) { + wiznet5k_start_dhcp(); + } else { + wiznet5k_stop_dhcp(); + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(wiznet5k_dhcp_set_value_obj, wiznet5k_dhcp_set_value); + +const mp_obj_property_t wiznet5k_dhcp_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&wiznet5k_dhcp_get_value_obj, + (mp_obj_t)&wiznet5k_dhcp_set_value_obj, + (mp_obj_t)&mp_const_none_obj}, +}; + +//| .. method:: ifconfig(...) +//| +//| Called without parameters, returns a tuple of +//| (ip_address, subnet_mask, gateway_address, dns_server) +//| +//| Or can be called with the same tuple to set those parameters. +//| + +STATIC mp_obj_t wiznet5k_ifconfig(size_t n_args, const mp_obj_t *args) { + wiz_NetInfo netinfo; + ctlnetwork(CN_GET_NETINFO, &netinfo); + if (n_args == 1) { + // get + mp_obj_t tuple[4] = { + netutils_format_ipv4_addr(netinfo.ip, NETUTILS_BIG), + netutils_format_ipv4_addr(netinfo.sn, NETUTILS_BIG), + netutils_format_ipv4_addr(netinfo.gw, NETUTILS_BIG), + netutils_format_ipv4_addr(netinfo.dns, NETUTILS_BIG), + }; + return mp_obj_new_tuple(4, tuple); + } else { + // set + mp_obj_t *items; + mp_obj_get_array_fixed_n(args[1], 4, &items); + netutils_parse_ipv4_addr(items[0], netinfo.ip, NETUTILS_BIG); + netutils_parse_ipv4_addr(items[1], netinfo.sn, NETUTILS_BIG); + netutils_parse_ipv4_addr(items[2], netinfo.gw, NETUTILS_BIG); + netutils_parse_ipv4_addr(items[3], netinfo.dns, NETUTILS_BIG); + ctlnetwork(CN_SET_NETINFO, &netinfo); + return mp_const_none; + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wiznet5k_ifconfig_obj, 1, 2, wiznet5k_ifconfig); + +STATIC const mp_rom_map_elem_t wiznet5k_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&wiznet5k_ifconfig_obj) }, + { MP_ROM_QSTR(MP_QSTR_connected), MP_ROM_PTR(&wiznet5k_connected_obj) }, + { MP_ROM_QSTR(MP_QSTR_dhcp), MP_ROM_PTR(&wiznet5k_dhcp_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(wiznet5k_locals_dict, wiznet5k_locals_dict_table); + +const mod_network_nic_type_t mod_network_nic_type_wiznet5k = { + .base = { + { &mp_type_type }, + .name = MP_QSTR_WIZNET5K, + .make_new = wiznet5k_make_new, + .locals_dict = (mp_obj_dict_t*)&wiznet5k_locals_dict, + }, + .gethostbyname = wiznet5k_gethostbyname, + .socket = wiznet5k_socket_socket, + .close = wiznet5k_socket_close, + .bind = wiznet5k_socket_bind, + .listen = wiznet5k_socket_listen, + .accept = wiznet5k_socket_accept, + .connect = wiznet5k_socket_connect, + .send = wiznet5k_socket_send, + .recv = wiznet5k_socket_recv, + .sendto = wiznet5k_socket_sendto, + .recvfrom = wiznet5k_socket_recvfrom, + .setsockopt = wiznet5k_socket_setsockopt, + .settimeout = wiznet5k_socket_settimeout, + .ioctl = wiznet5k_socket_ioctl, + .timer_tick = wiznet5k_socket_timer_tick, +}; + +#endif // MICROPY_PY_WIZNET5K diff --git a/shared-module/audioio/Mixer.c b/shared-module/audioio/Mixer.c new file mode 100644 index 000000000..8020a621e --- /dev/null +++ b/shared-module/audioio/Mixer.c @@ -0,0 +1,341 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 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. + */ + +#include "shared-bindings/audioio/Mixer.h" + +#include <stdint.h> + +#include "py/runtime.h" +#include "shared-module/audioio/__init__.h" +#include "shared-module/audioio/RawSample.h" + +void common_hal_audioio_mixer_construct(audioio_mixer_obj_t* self, + uint8_t voice_count, + uint32_t buffer_size, + uint8_t bits_per_sample, + bool samples_signed, + uint8_t channel_count, + uint32_t sample_rate) { + self->len = buffer_size / 2 / sizeof(uint32_t) * sizeof(uint32_t); + + self->first_buffer = m_malloc(self->len, false); + if (self->first_buffer == NULL) { + common_hal_audioio_mixer_deinit(self); + mp_raise_msg(&mp_type_MemoryError, translate("Couldn't allocate first buffer")); + } + + self->second_buffer = m_malloc(self->len, false); + if (self->second_buffer == NULL) { + common_hal_audioio_mixer_deinit(self); + mp_raise_msg(&mp_type_MemoryError, translate("Couldn't allocate second buffer")); + } + + self->bits_per_sample = bits_per_sample; + self->samples_signed = samples_signed; + self->channel_count = channel_count; + self->sample_rate = sample_rate; + self->voice_count = voice_count; + + for (uint8_t i = 0; i < self->voice_count; i++) { + self->voice[i].sample = NULL; + } +} + +void common_hal_audioio_mixer_deinit(audioio_mixer_obj_t* self) { + self->first_buffer = NULL; + self->second_buffer = NULL; +} + +bool common_hal_audioio_mixer_deinited(audioio_mixer_obj_t* self) { + return self->first_buffer == NULL; +} + +uint32_t common_hal_audioio_mixer_get_sample_rate(audioio_mixer_obj_t* self) { + return self->sample_rate; +} + +void common_hal_audioio_mixer_play(audioio_mixer_obj_t* self, mp_obj_t sample, uint8_t v, bool loop) { + if (v >= self->voice_count) { + mp_raise_ValueError(translate("Voice index too high")); + } + if (audiosample_sample_rate(sample) != self->sample_rate) { + mp_raise_ValueError(translate("The sample's sample rate does not match the mixer's")); + } + if (audiosample_channel_count(sample) != self->channel_count) { + mp_raise_ValueError(translate("The sample's channel count does not match the mixer's")); + } + if (audiosample_bits_per_sample(sample) != self->bits_per_sample) { + mp_raise_ValueError(translate("The sample's bits_per_sample does not match the mixer's")); + } + bool single_buffer; + bool samples_signed; + uint32_t max_buffer_length; + uint8_t spacing; + audiosample_get_buffer_structure(sample, false, &single_buffer, &samples_signed, + &max_buffer_length, &spacing); + if (samples_signed != self->samples_signed) { + mp_raise_ValueError(translate("The sample's signedness does not match the mixer's")); + } + audioio_mixer_voice_t* voice = &self->voice[v]; + voice->sample = sample; + voice->loop = loop; + + audiosample_reset_buffer(sample, false, 0); + audioio_get_buffer_result_t result = audiosample_get_buffer(sample, false, 0, (uint8_t**) &voice->remaining_buffer, &voice->buffer_length); + // Track length in terms of words. + voice->buffer_length /= sizeof(uint32_t); + voice->more_data = result == GET_BUFFER_MORE_DATA; +} + +void common_hal_audioio_mixer_stop_voice(audioio_mixer_obj_t* self, uint8_t voice) { + self->voice[voice].sample = NULL; +} + +bool common_hal_audioio_mixer_get_playing(audioio_mixer_obj_t* self) { + for (int32_t v = 0; v < self->voice_count; v++) { + if (self->voice[v].sample != NULL) { + return true; + } + } + return false; +} + +void audioio_mixer_reset_buffer(audioio_mixer_obj_t* self, + bool single_channel, + uint8_t channel) { + for (int32_t i = 0; i < self->voice_count; i++) { + self->voice[i].sample = NULL; + } +} + +uint32_t add8signed(uint32_t a, uint32_t b) { + #if (defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1)) + return __QADD8(a, b); + #else + uint32_t result = 0; + for (int8_t i = 0; i < 4; i++) { + int8_t ai = a >> (sizeof(int8_t) * 8 * i); + int8_t bi = b >> (sizeof(int8_t) * 8 * i); + int32_t intermediate = (int32_t) ai + bi; + if (intermediate > CHAR_MAX) { + intermediate = CHAR_MAX; + } else if (intermediate < CHAR_MIN) { + //intermediate = CHAR_MIN; + } + result |= (((uint32_t) intermediate) & 0xff) << (sizeof(int8_t) * 8 * i); + } + return result; + #endif +} + +uint32_t add8unsigned(uint32_t a, uint32_t b) { + #if (defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1)) + // Subtract out the DC offset, add and then shift back. + a = __USUB8(a, 0x80808080); + b = __USUB8(b, 0x80808080); + uint32_t sum = __QADD8(a, b); + return __UADD8(sum, 0x80808080); + #else + uint32_t result = 0; + for (int8_t i = 0; i < 4; i++) { + int8_t ai = (a >> (sizeof(uint8_t) * 8 * i)) - 128; + int8_t bi = (b >> (sizeof(uint8_t) * 8 * i)) - 128; + int32_t intermediate = (int32_t) ai + bi; + if (intermediate > UCHAR_MAX) { + intermediate = UCHAR_MAX; + } + result |= ((uint8_t) intermediate + 128) << (sizeof(uint8_t) * 8 * i); + } + return result; + #endif +} + +uint32_t add16signed(uint32_t a, uint32_t b) { + #if (defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1)) + return __QADD16(a, b); + #else + uint32_t result = 0; + for (int8_t i = 0; i < 2; i++) { + int16_t ai = a >> (sizeof(int16_t) * 8 * i); + int16_t bi = b >> (sizeof(int16_t) * 8 * i); + int32_t intermediate = (int32_t) ai + bi; + if (intermediate > SHRT_MAX) { + intermediate = SHRT_MAX; + } else if (intermediate < SHRT_MIN) { + intermediate = SHRT_MIN; + } + result |= (((uint32_t) intermediate) & 0xffff) << (sizeof(int16_t) * 8 * i); + } + return result; + #endif +} + +uint32_t add16unsigned(uint32_t a, uint32_t b) { + #if (defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1)) + // Subtract out the DC offset, add and then shift back. + a = __USUB16(a, 0x80008000); + b = __USUB16(b, 0x80008000); + uint32_t sum = __QADD16(a, b); + return __UADD16(sum, 0x80008000); + #else + uint32_t result = 0; + for (int8_t i = 0; i < 2; i++) { + int16_t ai = (a >> (sizeof(uint16_t) * 8 * i)) - 0x8000; + int16_t bi = (b >> (sizeof(uint16_t) * 8 * i)) - 0x8000; + int32_t intermediate = (int32_t) ai + bi; + if (intermediate > USHRT_MAX) { + intermediate = USHRT_MAX; + } + result |= ((uint16_t) intermediate + 0x8000) << (sizeof(int16_t) * 8 * i); + } + return result; + #endif +} + +audioio_get_buffer_result_t audioio_mixer_get_buffer(audioio_mixer_obj_t* self, + bool single_channel, + uint8_t channel, + uint8_t** buffer, + uint32_t* buffer_length) { + if (!single_channel) { + channel = 0; + } + + uint32_t channel_read_count = self->left_read_count; + if (channel == 1) { + channel_read_count = self->right_read_count; + } + *buffer_length = self->len; + + bool need_more_data = self->read_count == channel_read_count; + if (need_more_data) { + uint32_t* word_buffer; + if (self->use_first_buffer) { + *buffer = (uint8_t*) self->first_buffer; + word_buffer = self->first_buffer; + } else { + *buffer = (uint8_t*) self->second_buffer; + word_buffer = self->second_buffer; + } + self->use_first_buffer = !self->use_first_buffer; + bool voices_active = false; + for (int32_t v = 0; v < self->voice_count; v++) { + audioio_mixer_voice_t* voice = &self->voice[v]; + + uint32_t j = 0; + bool voice_done = voice->sample == NULL; + for (uint32_t i = 0; i < self->len / sizeof(uint32_t); i++) { + if (!voice_done && j >= voice->buffer_length) { + if (!voice->more_data) { + if (voice->loop) { + audiosample_reset_buffer(voice->sample, false, 0); + } else { + voice->sample = NULL; + voice_done = true; + } + } + if (!voice_done) { + // Load another buffer + audioio_get_buffer_result_t result = audiosample_get_buffer(voice->sample, false, 0, (uint8_t**) &voice->remaining_buffer, &voice->buffer_length); + // Track length in terms of words. + voice->buffer_length /= sizeof(uint32_t); + voice->more_data = result == GET_BUFFER_MORE_DATA; + j = 0; + } + } + // First active voice gets copied over verbatim. + uint32_t sample_value; + if (voice_done) { + // Exit early if another voice already set all samples once. + if (voices_active) { + continue; + } + sample_value = 0; + if (!self->samples_signed) { + if (self->bits_per_sample == 8) { + sample_value = 0x7f7f7f7f; + } else { + sample_value = 0x7fff7fff; + } + } + } else { + sample_value = voice->remaining_buffer[j]; + } + + if (!voices_active) { + word_buffer[i] = sample_value; + } else { + if (self->bits_per_sample == 8) { + if (self->samples_signed) { + word_buffer[i] = add8signed(word_buffer[i], sample_value); + } else { + word_buffer[i] = add8unsigned(word_buffer[i], sample_value); + } + } else { + if (self->samples_signed) { + word_buffer[i] = add16signed(word_buffer[i], sample_value); + } else { + word_buffer[i] = add16unsigned(word_buffer[i], sample_value); + } + } + } + j++; + } + voice->buffer_length -= j; + voice->remaining_buffer += j; + + voices_active = true; + } + + self->read_count += 1; + } else if (!self->use_first_buffer) { + *buffer = (uint8_t*) self->first_buffer; + } else { + *buffer = (uint8_t*) self->second_buffer; + } + + + if (channel == 0) { + self->left_read_count += 1; + } else if (channel == 1) { + self->right_read_count += 1; + *buffer = *buffer + self->bits_per_sample / 8; + } + return GET_BUFFER_MORE_DATA; +} + +void audioio_mixer_get_buffer_structure(audioio_mixer_obj_t* self, bool single_channel, + bool* single_buffer, bool* samples_signed, + uint32_t* max_buffer_length, uint8_t* spacing) { + *single_buffer = false; + *samples_signed = self->samples_signed; + *max_buffer_length = self->len; + if (single_channel) { + *spacing = self->channel_count; + } else { + *spacing = 1; + } +} diff --git a/shared-module/audioio/Mixer.h b/shared-module/audioio/Mixer.h new file mode 100644 index 000000000..6a88fe0bd --- /dev/null +++ b/shared-module/audioio/Mixer.h @@ -0,0 +1,75 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Scott Shawcroft + * + * 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_MODULE_AUDIOIO_MIXER_H +#define MICROPY_INCLUDED_SHARED_MODULE_AUDIOIO_MIXER_H + +#include "py/obj.h" + +#include "shared-module/audioio/__init__.h" + +typedef struct { + mp_obj_t sample; + bool loop; + bool more_data; + uint32_t* remaining_buffer; + uint32_t buffer_length; +} audioio_mixer_voice_t; + +typedef struct { + mp_obj_base_t base; + uint32_t* first_buffer; + uint32_t* second_buffer; + uint32_t len; // in words + uint8_t bits_per_sample; + bool use_first_buffer; + bool samples_signed; + uint8_t channel_count; + uint32_t sample_rate; + + uint32_t read_count; + uint32_t left_read_count; + uint32_t right_read_count; + + uint8_t voice_count; + audioio_mixer_voice_t voice[]; +} audioio_mixer_obj_t; + + +// These are not available from Python because it may be called in an interrupt. +void audioio_mixer_reset_buffer(audioio_mixer_obj_t* self, + bool single_channel, + uint8_t channel); +audioio_get_buffer_result_t audioio_mixer_get_buffer(audioio_mixer_obj_t* self, + bool single_channel, + uint8_t channel, + uint8_t** buffer, + uint32_t* buffer_length); // length in bytes +void audioio_mixer_get_buffer_structure(audioio_mixer_obj_t* self, bool single_channel, + bool* single_buffer, bool* samples_signed, + uint32_t* max_buffer_length, uint8_t* spacing); + +#endif // MICROPY_INCLUDED_SHARED_MODULE_AUDIOIO_MIXER_H diff --git a/shared-module/audioio/WaveFile.c b/shared-module/audioio/WaveFile.c index 7efad05e0..d5dd9419c 100644 --- a/shared-module/audioio/WaveFile.c +++ b/shared-module/audioio/WaveFile.c @@ -141,6 +141,14 @@ void common_hal_audioio_wavefile_set_sample_rate(audioio_wavefile_obj_t* self, self->sample_rate = sample_rate; } +uint8_t common_hal_audioio_wavefile_get_bits_per_sample(audioio_wavefile_obj_t* self) { + return self->bits_per_sample; +} + +uint8_t common_hal_audioio_wavefile_get_channel_count(audioio_wavefile_obj_t* self) { + return self->channel_count; +} + bool audioio_wavefile_samples_signed(audioio_wavefile_obj_t* self) { return self->bits_per_sample > 8; } @@ -200,13 +208,29 @@ audioio_get_buffer_result_t audioio_wavefile_get_buffer(audioio_wavefile_obj_t* if (f_read(&self->file->fp, *buffer, num_bytes_to_load, &length_read) != FR_OK) { return GET_BUFFER_ERROR; } + self->bytes_remaining -= length_read; + // Pad the last buffer to word align it. + if (self->bytes_remaining == 0 && length_read % sizeof(uint32_t) != 0) { + uint32_t pad = length_read % sizeof(uint32_t); + length_read += pad; + if (self->bits_per_sample == 8) { + for (uint32_t i = 0; i < pad; i++) { + ((uint8_t*) (*buffer))[length_read / sizeof(uint8_t) - i - 1] = 0x80; + } + } else if (self->bits_per_sample == 16) { + // We know the buffer is aligned because we allocated it onto the heap ourselves. + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wcast-align" + ((int16_t*) (*buffer))[length_read / sizeof(int16_t) - 1] = 0; + #pragma GCC diagnostic pop + } + } *buffer_length = length_read; if (self->buffer_index % 2 == 1) { self->second_buffer_length = length_read; } else { self->buffer_length = length_read; } - self->bytes_remaining -= length_read; self->buffer_index += 1; self->read_count += 1; } diff --git a/shared-module/audioio/__init__.c b/shared-module/audioio/__init__.c new file mode 100644 index 000000000..b87b06a83 --- /dev/null +++ b/shared-module/audioio/__init__.c @@ -0,0 +1,125 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 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. + */ + +#include "shared-module/audioio/__init__.h" + +#include "py/obj.h" +#include "shared-bindings/audioio/Mixer.h" +#include "shared-bindings/audioio/RawSample.h" +#include "shared-bindings/audioio/WaveFile.h" +#include "shared-module/audioio/Mixer.h" +#include "shared-module/audioio/RawSample.h" +#include "shared-module/audioio/WaveFile.h" + +uint32_t audiosample_sample_rate(mp_obj_t sample_obj) { + if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) { + audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj); + return sample->sample_rate; + } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_wavefile_type)) { + audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj); + return file->sample_rate; + } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_mixer_type)) { + audioio_mixer_obj_t* mixer = MP_OBJ_TO_PTR(sample_obj); + return mixer->sample_rate; + } + return 16000; +} + +uint8_t audiosample_bits_per_sample(mp_obj_t sample_obj) { + if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) { + audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj); + return sample->bits_per_sample; + } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_wavefile_type)) { + audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj); + return file->bits_per_sample; + } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_mixer_type)) { + audioio_mixer_obj_t* mixer = MP_OBJ_TO_PTR(sample_obj); + return mixer->bits_per_sample; + } + return 8; +} + +uint8_t audiosample_channel_count(mp_obj_t sample_obj) { + if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) { + audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj); + return sample->channel_count; + } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_wavefile_type)) { + audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj); + return file->channel_count; + } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_mixer_type)) { + audioio_mixer_obj_t* mixer = MP_OBJ_TO_PTR(sample_obj); + return mixer->channel_count; + } + return 1; +} + +void audiosample_reset_buffer(mp_obj_t sample_obj, bool single_channel, uint8_t audio_channel) { + if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) { + audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj); + audioio_rawsample_reset_buffer(sample, single_channel, audio_channel); + } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_wavefile_type)) { + audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj); + audioio_wavefile_reset_buffer(file, single_channel, audio_channel); + } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_mixer_type)) { + audioio_mixer_obj_t* file = MP_OBJ_TO_PTR(sample_obj); + audioio_mixer_reset_buffer(file, single_channel, audio_channel); + } +} + +audioio_get_buffer_result_t audiosample_get_buffer(mp_obj_t sample_obj, + bool single_channel, + uint8_t channel, + uint8_t** buffer, uint32_t* buffer_length) { + if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) { + audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj); + return audioio_rawsample_get_buffer(sample, single_channel, channel, buffer, buffer_length); + } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_wavefile_type)) { + audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj); + return audioio_wavefile_get_buffer(file, single_channel, channel, buffer, buffer_length); + } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_mixer_type)) { + audioio_mixer_obj_t* file = MP_OBJ_TO_PTR(sample_obj); + return audioio_mixer_get_buffer(file, single_channel, channel, buffer, buffer_length); + } + return GET_BUFFER_DONE; +} + +void audiosample_get_buffer_structure(mp_obj_t sample_obj, bool single_channel, + bool* single_buffer, bool* samples_signed, + uint32_t* max_buffer_length, uint8_t* spacing) { + if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) { + audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj); + audioio_rawsample_get_buffer_structure(sample, single_channel, single_buffer, + samples_signed, max_buffer_length, spacing); + } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_wavefile_type)) { + audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj); + audioio_wavefile_get_buffer_structure(file, single_channel, single_buffer, samples_signed, + max_buffer_length, spacing); + } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_mixer_type)) { + audioio_mixer_obj_t* file = MP_OBJ_TO_PTR(sample_obj); + audioio_mixer_get_buffer_structure(file, single_channel, single_buffer, samples_signed, + max_buffer_length, spacing); + } +} diff --git a/shared-module/audioio/__init__.h b/shared-module/audioio/__init__.h index 2491beb12..c805f3116 100644 --- a/shared-module/audioio/__init__.h +++ b/shared-module/audioio/__init__.h @@ -27,10 +27,27 @@ #ifndef MICROPY_INCLUDED_SHARED_MODULE_AUDIOIO__INIT__H #define MICROPY_INCLUDED_SHARED_MODULE_AUDIOIO__INIT__H +#include <stdbool.h> +#include <stdint.h> + +#include "py/obj.h" + typedef enum { GET_BUFFER_DONE, // No more data to read GET_BUFFER_MORE_DATA, // More data to read. GET_BUFFER_ERROR, // Error while reading data. } audioio_get_buffer_result_t; +uint32_t audiosample_sample_rate(mp_obj_t sample_obj); +uint8_t audiosample_bits_per_sample(mp_obj_t sample_obj); +uint8_t audiosample_channel_count(mp_obj_t sample_obj); +void audiosample_reset_buffer(mp_obj_t sample_obj, bool single_channel, uint8_t audio_channel); +audioio_get_buffer_result_t audiosample_get_buffer(mp_obj_t sample_obj, + bool single_channel, + uint8_t channel, + uint8_t** buffer, uint32_t* buffer_length); +void audiosample_get_buffer_structure(mp_obj_t sample_obj, bool single_channel, + bool* single_buffer, bool* samples_signed, + uint32_t* max_buffer_length, uint8_t* spacing); + #endif // MICROPY_INCLUDED_SHARED_MODULE_AUDIOIO__INIT__H diff --git a/shared-module/bitbangio/SPI.c b/shared-module/bitbangio/SPI.c index 9e4508355..6d3a28523 100644 --- a/shared-module/bitbangio/SPI.c +++ b/shared-module/bitbangio/SPI.c @@ -24,8 +24,7 @@ * THE SOFTWARE. */ -#include "mpconfigport.h" - +#include "py/mpconfig.h" #include "py/obj.h" #include "py/runtime.h" diff --git a/shared-module/bleio/Address.h b/shared-module/bleio/Address.h new file mode 100644 index 000000000..f0998c163 --- /dev/null +++ b/shared-module/bleio/Address.h @@ -0,0 +1,40 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Artur Pacholec + * + * 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_MODULE_BLEIO_ADDRESS_H +#define MICROPY_INCLUDED_SHARED_MODULE_BLEIO_ADDRESS_H + +#include "shared-bindings/bleio/AddressType.h" + +#define BLEIO_ADDRESS_BYTES 6 + +typedef struct { + mp_obj_base_t base; + bleio_address_type_t type; + uint8_t value[BLEIO_ADDRESS_BYTES]; +} bleio_address_obj_t; + +#endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_ADDRESS_H diff --git a/shared-module/bleio/AdvertisementData.h b/shared-module/bleio/AdvertisementData.h new file mode 100644 index 000000000..738d53b23 --- /dev/null +++ b/shared-module/bleio/AdvertisementData.h @@ -0,0 +1,85 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Artur Pacholec + * + * 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_MODULE_BLEIO_ADVERTISEMENTDATA_H +#define MICROPY_INCLUDED_SHARED_MODULE_BLEIO_ADVERTISEMENTDATA_H + +#include "py/obj.h" + +// Taken from https://www.bluetooth.com/specifications/assigned-numbers/generic-access-profile +enum { + AdFlags = 0x01, + AdIncompleteListOf16BitServiceClassUUIDs = 0x02, + AdCompleteListOf16BitServiceClassUUIDs = 0x03, + AdIncompleteListOf32BitServiceClassUUIDs = 0x04, + AdCompleteListOf32BitServiceClassUUIDs = 0x05, + AdIncompleteListOf128BitServiceClassUUIDs = 0x06, + AdCompleteListOf128BitServiceClassUUIDs = 0x07, + AdShortenedLocalName = 0x08, + AdCompleteLocalName = 0x09, + AdTxPowerLevel = 0x0A, + AdClassOfDevice = 0x0D, + AdSimplePairingHashC = 0x0E, + AdSimplePairingRandomizerR = 0x0F, + AdSecurityManagerTKValue = 0x10, + AdSecurityManagerOOBFlags = 0x11, + AdSlaveConnectionIntervalRange = 0x12, + AdListOf16BitServiceSolicitationUUIDs = 0x14, + AdListOf128BitServiceSolicitationUUIDs = 0x15, + AdServiceData = 0x16, + AdPublicTargetAddress = 0x17, + AdRandomTargetAddress = 0x18, + AdAppearance = 0x19, + AdAdvertisingInterval = 0x1A, + AdLEBluetoothDeviceAddress = 0x1B, + AdLERole = 0x1C, + AdSimplePairingHashC256 = 0x1D, + AdSimplePairingRandomizerR256 = 0x1E, + AdListOf32BitServiceSolicitationUUIDs = 0x1F, + AdServiceData32BitUUID = 0x20, + AdServiceData128BitUUID = 0x21, + AdLESecureConnectionsConfirmationValue = 0x22, + AdLESecureConnectionsRandomValue = 0x23, + AdURI = 0x24, + AdIndoorPositioning = 0x25, + AdTransportDiscoveryData = 0x26, + AdLESupportedFeatures = 0x27, + AdChannelMapUpdateIndication = 0x28, + AdPBADV = 0x29, + AdMeshMessage = 0x2A, + AdMeshBeacon = 0x2B, + Ad3DInformationData = 0x3D, + AdManufacturerSpecificData = 0xFF, +}; + +typedef struct { + mp_obj_t device_name; + mp_obj_t services; + mp_obj_t data; + bool connectable; +} bleio_advertisement_data_t; + +#endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_ADVERTISEMENTDATA_H diff --git a/shared-module/bleio/Characteristic.h b/shared-module/bleio/Characteristic.h new file mode 100644 index 000000000..94c43f81e --- /dev/null +++ b/shared-module/bleio/Characteristic.h @@ -0,0 +1,52 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Artur Pacholec + * + * 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_MODULE_BLEIO_CHARACTERISTIC_H +#define MICROPY_INCLUDED_SHARED_MODULE_BLEIO_CHARACTERISTIC_H + +#include "shared-module/bleio/Service.h" +#include "common-hal/bleio/UUID.h" + +typedef struct { + mp_obj_base_t base; + bleio_service_obj_t *service; + bleio_uuid_obj_t *uuid; + mp_obj_t value_data; + uint16_t handle; + struct { + bool broadcast : 1; + bool read : 1; + bool write_wo_resp : 1; + bool write : 1; + bool notify : 1; + bool indicate : 1; + } props; + uint16_t user_desc_handle; + uint16_t cccd_handle; + uint16_t sccd_handle; +} bleio_characteristic_obj_t; + +#endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_CHARACTERISTIC_H diff --git a/shared-module/bleio/Device.h b/shared-module/bleio/Device.h new file mode 100644 index 000000000..8d9ece5ef --- /dev/null +++ b/shared-module/bleio/Device.h @@ -0,0 +1,45 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Artur Pacholec + * + * 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_MODULE_BLEIO_DEVICE_H +#define MICROPY_INCLUDED_SHARED_MODULE_BLEIO_DEVICE_H + +#include <stdbool.h> + +#include "shared-module/bleio/Address.h" + +typedef struct { + mp_obj_base_t base; + bool is_peripheral; + mp_obj_t name; + bleio_address_obj_t address; + volatile uint16_t conn_handle; + mp_obj_t service_list; + mp_obj_t notif_handler; + mp_obj_t conn_handler; +} bleio_device_obj_t; + +#endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_DEVICE_H diff --git a/shared-module/bleio/ScanEntry.h b/shared-module/bleio/ScanEntry.h new file mode 100644 index 000000000..2f01669e2 --- /dev/null +++ b/shared-module/bleio/ScanEntry.h @@ -0,0 +1,40 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Artur Pacholec + * + * 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_MODULE_BLEIO_SCANENTRY_H +#define MICROPY_INCLUDED_SHARED_MODULE_BLEIO_SCANENTRY_H + +#include "shared-module/bleio/Address.h" + +typedef struct { + mp_obj_base_t base; + bleio_address_obj_t address; + bool connectable; + int8_t rssi; + mp_obj_t data; +} bleio_scanentry_obj_t; + +#endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_SCANENTRY_H diff --git a/shared-module/bleio/Scanner.h b/shared-module/bleio/Scanner.h new file mode 100644 index 000000000..76f5e5866 --- /dev/null +++ b/shared-module/bleio/Scanner.h @@ -0,0 +1,39 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Artur Pacholec + * + * 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_MODULE_BLEIO_SCANNER_H +#define MICROPY_INCLUDED_SHARED_MODULE_BLEIO_SCANNER_H + +#include "py/obj.h" + +typedef struct { + mp_obj_base_t base; + mp_obj_t adv_reports; + uint16_t interval; + uint16_t window; +} bleio_scanner_obj_t; + +#endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_SCANNER_H diff --git a/shared-module/bleio/Service.h b/shared-module/bleio/Service.h new file mode 100644 index 000000000..ff506d3f3 --- /dev/null +++ b/shared-module/bleio/Service.h @@ -0,0 +1,44 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Artur Pacholec + * + * 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_MODULE_BLEIO_SERVICE_H +#define MICROPY_INCLUDED_SHARED_MODULE_BLEIO_SERVICE_H + +#include "common-hal/bleio/UUID.h" +#include "shared-module/bleio/Device.h" + +typedef struct { + mp_obj_base_t base; + uint16_t handle; + bool is_secondary; + bleio_uuid_obj_t *uuid; + bleio_device_obj_t *device; + mp_obj_t char_list; + uint16_t start_handle; + uint16_t end_handle; +} bleio_service_obj_t; + +#endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_SERVICE_H diff --git a/shared-module/displayio/Sprite.c b/shared-module/displayio/Sprite.c index 4fe8d1ff6..87600f721 100644 --- a/shared-module/displayio/Sprite.c +++ b/shared-module/displayio/Sprite.c @@ -68,7 +68,7 @@ bool displayio_sprite_get_pixel(displayio_sprite_t *self, int16_t x, int16_t y, if (y < 0 || y >= self->height || x >= self->width || x < 0) { return false; } - uint32_t value; + uint32_t value = 0; if (MP_OBJ_IS_TYPE(self->bitmap, &displayio_bitmap_type)) { value = common_hal_displayio_bitmap_get_pixel(self->bitmap, x, y); } else if (MP_OBJ_IS_TYPE(self->bitmap, &displayio_ondiskbitmap_type)) { diff --git a/shared-module/network/__init__.c b/shared-module/network/__init__.c new file mode 100644 index 000000000..a674e8478 --- /dev/null +++ b/shared-module/network/__init__.c @@ -0,0 +1,95 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Nick Moore + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include <stdio.h> + +#include "py/objlist.h" +#include "py/runtime.h" +#include "py/mphal.h" +#include "py/mperrno.h" + +#include "shared-bindings/random/__init__.h" + +#include "shared-module/network/__init__.h" + +// mod_network_nic_list needs to be declared in mpconfigport.h + + +void network_module_init(void) { + mp_obj_list_init(&MP_STATE_PORT(mod_network_nic_list), 0); +} + +void network_module_deinit(void) { +} + +void network_module_background(void) { + static uint32_t next_tick = 0; + uint32_t this_tick = ticks_ms; + if (this_tick < next_tick) return; + next_tick = this_tick + 1000; + + 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]; + mod_network_nic_type_t *nic_type = (mod_network_nic_type_t*)mp_obj_get_type(nic); + if (nic_type->timer_tick != NULL) nic_type->timer_tick(nic); + } +} + +void network_module_register_nic(mp_obj_t nic) { + for (mp_uint_t i = 0; i < MP_STATE_PORT(mod_network_nic_list).len; i++) { + if (MP_STATE_PORT(mod_network_nic_list).items[i] == nic) { + // nic already registered + return; + } + } + // nic not registered so add to list + mp_obj_list_append(MP_OBJ_FROM_PTR(&MP_STATE_PORT(mod_network_nic_list)), nic); +} + +mp_obj_t network_module_find_nic(const uint8_t *ip) { + // find a NIC that is suited to given IP address + 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]; + // TODO check IP suitability here + //mod_network_nic_type_t *nic_type = (mod_network_nic_type_t*)mp_obj_get_type(nic); + return nic; + } + + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, translate("no available NIC"))); +} + +void network_module_create_random_mac_address(uint8_t *mac) { + uint32_t rb1 = shared_modules_random_getrandbits(24); + uint32_t rb2 = shared_modules_random_getrandbits(24); + // first octet has multicast bit (0) cleared and local bit (1) set + // everything else is just set randomly + mac[0] = ((uint8_t)(rb1 >> 16) & 0xfe) | 0x02; + mac[1] = (uint8_t)(rb1 >> 8); + mac[2] = (uint8_t)(rb1); + mac[3] = (uint8_t)(rb2 >> 16); + mac[4] = (uint8_t)(rb2 >> 8); + mac[5] = (uint8_t)(rb2); +} diff --git a/shared-module/network/__init__.h b/shared-module/network/__init__.h new file mode 100644 index 000000000..00a3c3957 --- /dev/null +++ b/shared-module/network/__init__.h @@ -0,0 +1,90 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2018 Nick Moore + * + * 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. + */ + +void network_module_create_random_mac_address(uint8_t *mac); + +#ifndef MICROPY_INCLUDED_SHARED_MODULE_NETWORK___INIT___H +#define MICROPY_INCLUDED_SHARED_MODULE_NETWORK___INIT___H + +#define MOD_NETWORK_IPADDR_BUF_SIZE (4) + +#define MOD_NETWORK_AF_INET (2) +#define MOD_NETWORK_AF_INET6 (10) + +#define MOD_NETWORK_SOCK_STREAM (1) +#define MOD_NETWORK_SOCK_DGRAM (2) +#define MOD_NETWORK_SOCK_RAW (3) + +struct _mod_network_socket_obj_t; + +typedef struct _mod_network_nic_type_t { + mp_obj_type_t base; + + // API for non-socket operations + int (*gethostbyname)(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *ip_out); + + // API for socket operations; return -1 on error + int (*socket)(struct _mod_network_socket_obj_t *socket, int *_errno); + void (*close)(struct _mod_network_socket_obj_t *socket); + int (*bind)(struct _mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno); + int (*listen)(struct _mod_network_socket_obj_t *socket, mp_int_t backlog, int *_errno); + int (*accept)(struct _mod_network_socket_obj_t *socket, struct _mod_network_socket_obj_t *socket2, byte *ip, mp_uint_t *port, int *_errno); + int (*connect)(struct _mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno); + mp_uint_t (*send)(struct _mod_network_socket_obj_t *socket, const byte *buf, mp_uint_t len, int *_errno); + mp_uint_t (*recv)(struct _mod_network_socket_obj_t *socket, byte *buf, mp_uint_t len, int *_errno); + mp_uint_t (*sendto)(struct _mod_network_socket_obj_t *socket, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno); + mp_uint_t (*recvfrom)(struct _mod_network_socket_obj_t *socket, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno); + int (*setsockopt)(struct _mod_network_socket_obj_t *socket, mp_uint_t level, mp_uint_t opt, const void *optval, mp_uint_t optlen, int *_errno); + int (*settimeout)(struct _mod_network_socket_obj_t *socket, mp_uint_t timeout_ms, int *_errno); + int (*ioctl)(struct _mod_network_socket_obj_t *socket, mp_uint_t request, mp_uint_t arg, int *_errno); + void (*timer_tick)(struct _mod_network_socket_obj_t *socket); +} mod_network_nic_type_t; + +typedef struct _mod_network_socket_obj_t { + mp_obj_base_t base; + mp_obj_t nic; + mod_network_nic_type_t *nic_type; + union { + struct { + uint8_t domain; + uint8_t type; + int8_t fileno; + } u_param; + mp_uint_t u_state; + }; +} mod_network_socket_obj_t; + +extern const mod_network_nic_type_t mod_network_nic_type_wiznet5k; +extern const mod_network_nic_type_t mod_network_nic_type_cc3k; + +void network_module_init(void); +void network_module_deinit(void); +void network_module_background(void); +void network_module_register_nic(mp_obj_t nic); +mp_obj_t network_module_find_nic(const uint8_t *ip); + +#endif // MICROPY_INCLUDED_SHARED_MODULE_NETWORK___INIT___H diff --git a/shared-module/os/__init__.c b/shared-module/os/__init__.c index a38f3781f..313893d97 100644 --- a/shared-module/os/__init__.c +++ b/shared-module/os/__init__.c @@ -50,6 +50,20 @@ STATIC mp_vfs_mount_t *lookup_path(const char* path, mp_obj_t *path_out) { return vfs; } +// Strip off trailing slashes to please underlying libraries +STATIC mp_vfs_mount_t *lookup_dir_path(const char* path, mp_obj_t *path_out) { + const char *p_out; + mp_vfs_mount_t *vfs = mp_vfs_lookup_path(path, &p_out); + if (vfs != MP_VFS_NONE && vfs != MP_VFS_ROOT) { + size_t len = strlen(p_out); + while (len > 1 && p_out[len - 1] == '/') { + len--; + } + *path_out = mp_obj_new_str_of_type(&mp_type_str, (const byte*)p_out, len); + } + return vfs; +} + STATIC mp_obj_t mp_vfs_proxy_call(mp_vfs_mount_t *vfs, qstr meth_name, size_t n_args, const mp_obj_t *args) { if (vfs == MP_VFS_NONE) { // mount point not found @@ -69,7 +83,7 @@ STATIC mp_obj_t mp_vfs_proxy_call(mp_vfs_mount_t *vfs, qstr meth_name, size_t n_ void common_hal_os_chdir(const char* path) { mp_obj_t path_out; - mp_vfs_mount_t *vfs = lookup_path(path, &path_out); + mp_vfs_mount_t *vfs = lookup_dir_path(path, &path_out); MP_STATE_VM(vfs_cur) = vfs; if (vfs == MP_VFS_ROOT) { // If we change to the root dir and a VFS is mounted at the root then @@ -93,7 +107,7 @@ mp_obj_t common_hal_os_getcwd(void) { mp_obj_t common_hal_os_listdir(const char* path) { mp_obj_t path_out; - mp_vfs_mount_t *vfs = lookup_path(path, &path_out); + mp_vfs_mount_t *vfs = lookup_dir_path(path, &path_out); mp_vfs_ilistdir_it_t iter; mp_obj_t iter_obj = MP_OBJ_FROM_PTR(&iter); @@ -120,7 +134,7 @@ mp_obj_t common_hal_os_listdir(const char* path) { void common_hal_os_mkdir(const char* path) { mp_obj_t path_out; - mp_vfs_mount_t *vfs = lookup_path(path, &path_out); + mp_vfs_mount_t *vfs = lookup_dir_path(path, &path_out); if (vfs == MP_VFS_ROOT || (vfs != MP_VFS_NONE && !strcmp(mp_obj_str_get_str(path_out), "/"))) { mp_raise_OSError(MP_EEXIST); } @@ -146,7 +160,7 @@ void common_hal_os_rename(const char* old_path, const char* new_path) { void common_hal_os_rmdir(const char* path) { mp_obj_t path_out; - mp_vfs_mount_t *vfs = lookup_path(path, &path_out); + mp_vfs_mount_t *vfs = lookup_dir_path(path, &path_out); mp_vfs_proxy_call(vfs, MP_QSTR_rmdir, 1, &path_out); } diff --git a/shared-module/socket/__init__.c b/shared-module/socket/__init__.c new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/shared-module/socket/__init__.c diff --git a/shared-module/storage/__init__.c b/shared-module/storage/__init__.c index edce286b1..f09edd785 100644 --- a/shared-module/storage/__init__.c +++ b/shared-module/storage/__init__.c @@ -32,8 +32,12 @@ #include "py/mperrno.h" #include "py/obj.h" #include "py/runtime.h" +#include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/os/__init__.h" #include "shared-bindings/storage/__init__.h" +#include "supervisor/filesystem.h" +#include "supervisor/flash.h" +#include "supervisor/usb.h" STATIC mp_obj_t mp_vfs_proxy_call(mp_vfs_mount_t *vfs, qstr meth_name, size_t n_args, const mp_obj_t *args) { if (vfs == MP_VFS_NONE) { @@ -138,3 +142,25 @@ void common_hal_storage_umount_path(const char* mount_path) { mp_obj_t common_hal_storage_getmount(const char *mount_path) { return storage_object_from_path(mount_path); } + +void common_hal_storage_remount(const char *mount_path, bool readonly) { + if (strcmp(mount_path, "/") != 0) { + mp_raise_OSError(MP_EINVAL); + } + + #ifdef USB_AVAILABLE + // TODO(dhalbert): is this is a good enough check? It checks for + // CDC enabled. There is no "MSC enabled" check. + if (usb_enabled()) { + mp_raise_RuntimeError(translate("Cannot remount '/' when USB is active.")); + } + #endif + + supervisor_flash_set_usb_writable(readonly); +} + +void common_hal_storage_erase_filesystem(void) { + filesystem_init(false, true); // Force a re-format. + common_hal_mcu_reset(); + // We won't actually get here, since we're resetting. +} diff --git a/ports/nrf/common-hal/usb_hid/Device.c b/shared-module/usb_hid/Device.c index 6acb2717f..820e14ad0 100644 --- a/ports/nrf/common-hal/usb_hid/Device.c +++ b/shared-module/usb_hid/Device.c @@ -26,9 +26,9 @@ #include <string.h> #include "tick.h" -#include "common-hal/usb_hid/Device.h" #include "py/runtime.h" #include "shared-bindings/usb_hid/Device.h" +#include "shared-module/usb_hid/Device.h" #include "supervisor/shared/translate.h" #include "tusb.h" diff --git a/ports/atmel-samd/common-hal/usb_hid/Device.h b/shared-module/usb_hid/Device.h index b81c0e709..10f2ee897 100644 --- a/ports/atmel-samd/common-hal/usb_hid/Device.h +++ b/shared-module/usb_hid/Device.h @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * Copyright (c) 2018 hathach 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 @@ -24,30 +24,32 @@ * THE SOFTWARE. */ -#ifndef COMMON_HAL_USB_HID_DEVICE_H -#define COMMON_HAL_USB_HID_DEVICE_H +#ifndef SHARED_MODULE_USB_HID_DEVICE_H +#define SHARED_MODULE_USB_HID_DEVICE_H #include <stdint.h> #include <stdbool.h> #include "py/obj.h" -#include "genhdr/autogen_usb_descriptor.h" +#ifdef __cplusplus + extern "C" { +#endif -typedef struct { +typedef struct { mp_obj_base_t base; uint8_t* report_buffer; - uint8_t endpoint; - uint8_t report_id; // If non-zero, prefix report with given id. - uint8_t report_length; // Length not including Report ID. + uint8_t report_id; + uint8_t report_length; uint8_t usage_page; uint8_t usage; - } usb_hid_device_obj_t; -extern usb_hid_device_obj_t usb_hid_devices[USB_HID_NUM_DEVICES]; -void usb_hid_init(void); -void usb_hid_reset(void); +extern usb_hid_device_obj_t usb_hid_devices[]; + +#ifdef __cplusplus + } +#endif -#endif // COMMON_HAL_USB_HID_DEVICE_H +#endif /* SHARED_MODULE_USB_HID_DEVICE_H */ diff --git a/ports/nrf/common-hal/usb_hid/__init__.c b/shared-module/usb_hid/__init__.c index 00fc8bd00..f14fdd41e 100644 --- a/ports/nrf/common-hal/usb_hid/__init__.c +++ b/shared-module/usb_hid/__init__.c @@ -28,43 +28,37 @@ #include "py/mphal.h" #include "py/runtime.h" -#include "common-hal/usb_hid/Device.h" +#include "genhdr/autogen_usb_descriptor.h" +#include "shared-module/usb_hid/Device.h" #include "shared-bindings/usb_hid/Device.h" #include "tusb.h" -#define USB_HID_REPORT_LENGTH_KEYBOARD 8 -#define USB_HID_REPORT_LENGTH_MOUSE 4 -#define USB_HID_REPORT_LENGTH_CONSUMER 2 -#define USB_HID_REPORT_LENGTH_SYS_CONTROL 1 -#define USB_HID_REPORT_LENGTH_GAMEPAD 6 -#define USB_HID_REPORT_LENGTH_DIGITIZER 5 - -#if USB_HID_DEVICE_KEYBOARD +#ifdef USB_HID_REPORT_ID_KEYBOARD static uint8_t keyboard_report_buffer[USB_HID_REPORT_LENGTH_KEYBOARD]; #endif -#if USB_HID_DEVICE_MOUSE +#ifdef USB_HID_REPORT_ID_MOUSE static uint8_t mouse_report_buffer[USB_HID_REPORT_LENGTH_MOUSE]; #endif -#if USB_HID_DEVICE_CONSUMER +#ifdef USB_HID_REPORT_ID_CONSUMER static uint8_t consumer_report_buffer[USB_HID_REPORT_LENGTH_CONSUMER]; #endif -#if USB_HID_DEVICE_SYS_CONTROL +#ifdef USB_HID_REPORT_ID_SYS_CONTROL static uint8_t sys_control_report_buffer[USB_HID_REPORT_LENGTH_SYS_CONTROL]; #endif -#if USB_HID_DEVICE_GAMEPAD +#ifdef USB_HID_REPORT_ID_GAMEPAD static uint8_t gamepad_report_buffer[USB_HID_REPORT_LENGTH_GAMEPAD]; #endif -#if USB_HID_DEVICE_DIGITIZER +#ifdef USB_HID_REPORT_ID_DIGITIZER static uint8_t digitizer_report_buffer[USB_HID_REPORT_LENGTH_DIGITIZER]; #endif usb_hid_device_obj_t usb_hid_devices[] = { -#if USB_HID_DEVICE_KEYBOARD +#ifdef USB_HID_REPORT_ID_KEYBOARD { .base = { .type = &usb_hid_device_type } , .report_buffer = keyboard_report_buffer , @@ -75,7 +69,7 @@ usb_hid_device_obj_t usb_hid_devices[] = { }, #endif -#if USB_HID_DEVICE_MOUSE +#ifdef USB_HID_REPORT_ID_MOUSE { .base = { .type = &usb_hid_device_type } , .report_buffer = mouse_report_buffer , @@ -86,7 +80,7 @@ usb_hid_device_obj_t usb_hid_devices[] = { }, #endif -#if USB_HID_DEVICE_CONSUMER +#ifdef USB_HID_REPORT_ID_CONSUMER { .base = { .type = &usb_hid_device_type } , .report_buffer = consumer_report_buffer , @@ -97,7 +91,7 @@ usb_hid_device_obj_t usb_hid_devices[] = { }, #endif -#if USB_HID_DEVICE_SYS_CONTROL +#ifdef USB_HID_REPORT_ID_SYS_CONTROL { .base = { .type = &usb_hid_device_type } , .report_buffer = sys_control_report_buffer , @@ -108,7 +102,7 @@ usb_hid_device_obj_t usb_hid_devices[] = { }, #endif -#if USB_HID_DEVICE_GAMEPAD +#ifdef USB_HID_REPORT_ID_GAMEPAD { .base = { .type = &usb_hid_device_type } , .report_buffer = gamepad_report_buffer , @@ -119,7 +113,7 @@ usb_hid_device_obj_t usb_hid_devices[] = { }, #endif -#if USB_HID_DEVICE_DIGITIZER +#ifdef USB_HID_REPORT_ID_DIGITIZER { .base = { .type = &usb_hid_device_type } , .report_buffer = digitizer_report_buffer , diff --git a/shared-module/wiznet/__init__.c b/shared-module/wiznet/__init__.c new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/shared-module/wiznet/__init__.c diff --git a/shared-module/wiznet/wiznet5k.c b/shared-module/wiznet/wiznet5k.c new file mode 100644 index 000000000..ee732859a --- /dev/null +++ b/shared-module/wiznet/wiznet5k.c @@ -0,0 +1,406 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2014 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include <stdio.h> +#include <stdint.h> +#include <string.h> + +#include "py/objlist.h" +#include "py/objproperty.h" +#include "py/runtime.h" +#include "py/stream.h" +#include "py/mperrno.h" +#include "py/mphal.h" +#include "lib/netutils/netutils.h" + +#if MICROPY_PY_WIZNET5K + +#include "shared-module/network/__init__.h" +#include "shared-bindings/digitalio/DigitalInOut.h" +#include "shared-bindings/digitalio/DriveMode.h" +#include "shared-bindings/busio/SPI.h" + +#include "shared-module/network/__init__.h" + +#include "ethernet/wizchip_conf.h" +#include "ethernet/socket.h" +#include "internet/dns/dns.h" +#include "internet/dhcp/dhcp.h" + +#include "shared-module/wiznet/wiznet5k.h" + +STATIC wiznet5k_obj_t wiznet5k_obj; + +STATIC void wiz_cris_enter(void) { + wiznet5k_obj.cris_state = MICROPY_BEGIN_ATOMIC_SECTION(); +} + +STATIC void wiz_cris_exit(void) { + MICROPY_END_ATOMIC_SECTION(wiznet5k_obj.cris_state); +} + +STATIC void wiz_cs_select(void) { + common_hal_digitalio_digitalinout_set_value(&wiznet5k_obj.cs, 0); +} + +STATIC void wiz_cs_deselect(void) { + common_hal_digitalio_digitalinout_set_value(&wiznet5k_obj.cs, 1); +} + +STATIC void wiz_spi_read(uint8_t *buf, uint32_t len) { + (void)common_hal_busio_spi_read(wiznet5k_obj.spi, buf, len, 0); +} + +STATIC void wiz_spi_write(const uint8_t *buf, uint32_t len) { + (void)common_hal_busio_spi_write(wiznet5k_obj.spi, buf, len); +} + +int wiznet5k_gethostbyname(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *out_ip) { + uint8_t dns_ip[MOD_NETWORK_IPADDR_BUF_SIZE] = {8, 8, 8, 8}; + uint8_t *buf = m_new(uint8_t, MAX_DNS_BUF_SIZE); + DNS_init(0, buf); + mp_int_t ret = DNS_run(dns_ip, (uint8_t*)name, out_ip); + m_del(uint8_t, buf, MAX_DNS_BUF_SIZE); + if (ret == 1) { + // success + return 0; + } else { + // failure + return -2; + } +} + +int wiznet5k_socket_socket(mod_network_socket_obj_t *socket, int *_errno) { + if (socket->u_param.domain != MOD_NETWORK_AF_INET) { + *_errno = MP_EAFNOSUPPORT; + return -1; + } + + switch (socket->u_param.type) { + case MOD_NETWORK_SOCK_STREAM: socket->u_param.type = Sn_MR_TCP; break; + case MOD_NETWORK_SOCK_DGRAM: socket->u_param.type = Sn_MR_UDP; break; + default: *_errno = MP_EINVAL; return -1; + } + + if (socket->u_param.fileno == -1) { + // get first unused socket number + for (mp_uint_t sn = 0; sn < _WIZCHIP_SOCK_NUM_; sn++) { + if ((wiznet5k_obj.socket_used & (1 << sn)) == 0) { + wiznet5k_obj.socket_used |= (1 << sn); + socket->u_param.fileno = sn; + break; + } + } + if (socket->u_param.fileno == -1) { + // too many open sockets + *_errno = MP_EMFILE; + return -1; + } + } + + // WIZNET does not have a concept of pure "open socket". You need to know + // if it's a server or client at the time of creation of the socket. + // So, we defer the open until we know what kind of socket we want. + + // use "domain" to indicate that this socket has not yet been opened + socket->u_param.domain = 0; + + return 0; +} + +void wiznet5k_socket_close(mod_network_socket_obj_t *socket) { + uint8_t sn = (uint8_t)socket->u_param.fileno; + if (sn < _WIZCHIP_SOCK_NUM_) { + wiznet5k_obj.socket_used &= ~(1 << sn); + WIZCHIP_EXPORT(close)(sn); + } +} + +int wiznet5k_socket_bind(mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno) { + // open the socket in server mode (if port != 0) + mp_int_t ret = WIZCHIP_EXPORT(socket)(socket->u_param.fileno, socket->u_param.type, port, 0); + if (ret < 0) { + wiznet5k_socket_close(socket); + *_errno = -ret; + return -1; + } + + // indicate that this socket has been opened + socket->u_param.domain = 1; + + // success + return 0; +} + +int wiznet5k_socket_listen(mod_network_socket_obj_t *socket, mp_int_t backlog, int *_errno) { + mp_int_t ret = WIZCHIP_EXPORT(listen)(socket->u_param.fileno); + if (ret < 0) { + wiznet5k_socket_close(socket); + *_errno = -ret; + return -1; + } + return 0; +} + +int wiznet5k_socket_accept(mod_network_socket_obj_t *socket, mod_network_socket_obj_t *socket2, byte *ip, mp_uint_t *port, int *_errno) { + for (;;) { + int sr = getSn_SR((uint8_t)socket->u_param.fileno); + if (sr == SOCK_ESTABLISHED) { + socket2->u_param = socket->u_param; + getSn_DIPR((uint8_t)socket2->u_param.fileno, ip); + *port = getSn_PORT(socket2->u_param.fileno); + + // WIZnet turns the listening socket into the client socket, so we + // need to re-bind and re-listen on another socket for the server. + // TODO handle errors, especially no-more-sockets error + socket->u_param.domain = MOD_NETWORK_AF_INET; + socket->u_param.fileno = -1; + int _errno2; + if (wiznet5k_socket_socket(socket, &_errno2) != 0) { + //printf("(bad resocket %d)\n", _errno2); + } else if (wiznet5k_socket_bind(socket, NULL, *port, &_errno2) != 0) { + //printf("(bad rebind %d)\n", _errno2); + } else if (wiznet5k_socket_listen(socket, 0, &_errno2) != 0) { + //printf("(bad relisten %d)\n", _errno2); + } + + return 0; + } + if (sr == SOCK_CLOSED || sr == SOCK_CLOSE_WAIT) { + wiznet5k_socket_close(socket); + *_errno = MP_ENOTCONN; // ?? + return -1; + } + mp_hal_delay_ms(1); + } +} + +int wiznet5k_socket_connect(mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno) { + // use "bind" function to open the socket in client mode + if (wiznet5k_socket_bind(socket, ip, 0, _errno) != 0) { + return -1; + } + + // now connect + MP_THREAD_GIL_EXIT(); + mp_int_t ret = WIZCHIP_EXPORT(connect)(socket->u_param.fileno, ip, port); + MP_THREAD_GIL_ENTER(); + + if (ret < 0) { + wiznet5k_socket_close(socket); + *_errno = -ret; + return -1; + } + + // success + return 0; +} + +mp_uint_t wiznet5k_socket_send(mod_network_socket_obj_t *socket, const byte *buf, mp_uint_t len, int *_errno) { + MP_THREAD_GIL_EXIT(); + mp_int_t ret = WIZCHIP_EXPORT(send)(socket->u_param.fileno, (byte*)buf, len); + MP_THREAD_GIL_ENTER(); + + // TODO convert Wiz errno's to POSIX ones + if (ret < 0) { + wiznet5k_socket_close(socket); + *_errno = -ret; + return -1; + } + return ret; +} + +mp_uint_t wiznet5k_socket_recv(mod_network_socket_obj_t *socket, byte *buf, mp_uint_t len, int *_errno) { + MP_THREAD_GIL_EXIT(); + mp_int_t ret = WIZCHIP_EXPORT(recv)(socket->u_param.fileno, buf, len); + MP_THREAD_GIL_ENTER(); + + // TODO convert Wiz errno's to POSIX ones + if (ret < 0) { + wiznet5k_socket_close(socket); + *_errno = -ret; + return -1; + } + return ret; +} + +mp_uint_t wiznet5k_socket_sendto(mod_network_socket_obj_t *socket, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno) { + if (socket->u_param.domain == 0) { + // socket not opened; use "bind" function to open the socket in client mode + if (wiznet5k_socket_bind(socket, ip, 0, _errno) != 0) { + return -1; + } + } + + MP_THREAD_GIL_EXIT(); + mp_int_t ret = WIZCHIP_EXPORT(sendto)(socket->u_param.fileno, (byte*)buf, len, ip, port); + MP_THREAD_GIL_ENTER(); + + if (ret < 0) { + wiznet5k_socket_close(socket); + *_errno = -ret; + return -1; + } + return ret; +} + +mp_uint_t wiznet5k_socket_recvfrom(mod_network_socket_obj_t *socket, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno) { + uint16_t port2; + MP_THREAD_GIL_EXIT(); + mp_int_t ret = WIZCHIP_EXPORT(recvfrom)(socket->u_param.fileno, buf, len, ip, &port2); + MP_THREAD_GIL_ENTER(); + *port = port2; + if (ret < 0) { + wiznet5k_socket_close(socket); + *_errno = -ret; + return -1; + } + return ret; +} + +int wiznet5k_socket_setsockopt(mod_network_socket_obj_t *socket, mp_uint_t level, mp_uint_t opt, const void *optval, mp_uint_t optlen, int *_errno) { + // TODO + *_errno = MP_EINVAL; + return -1; +} + +int wiznet5k_socket_settimeout(mod_network_socket_obj_t *socket, mp_uint_t timeout_ms, int *_errno) { + // TODO + *_errno = MP_EINVAL; + return -1; + + /* + if (timeout_ms == 0) { + // set non-blocking mode + uint8_t arg = SOCK_IO_NONBLOCK; + WIZCHIP_EXPORT(ctlsocket)(socket->u_param.fileno, CS_SET_IOMODE, &arg); + } + */ +} + +int wiznet5k_socket_ioctl(mod_network_socket_obj_t *socket, mp_uint_t request, mp_uint_t arg, int *_errno) { + if (request == MP_STREAM_POLL) { + int ret = 0; + if (arg & MP_STREAM_POLL_RD && getSn_RX_RSR(socket->u_param.fileno) != 0) { + ret |= MP_STREAM_POLL_RD; + } + if (arg & MP_STREAM_POLL_WR && getSn_TX_FSR(socket->u_param.fileno) != 0) { + ret |= MP_STREAM_POLL_WR; + } + return ret; + } else { + *_errno = MP_EINVAL; + return MP_STREAM_ERROR; + } +} + +void wiznet5k_socket_timer_tick(mod_network_socket_obj_t *socket) { + if (wiznet5k_obj.dhcp_active) { + DHCP_time_handler(); + DHCP_run(); + } +} + +void wiznet5k_start_dhcp(void) { + static DHCP_INIT_BUFFER_TYPE dhcp_buf[DHCP_INIT_BUFFER_SIZE]; + + if (!wiznet5k_obj.dhcp_active) { + // Set up the socket to listen on UDP 68 before calling DHCP_init + WIZCHIP_EXPORT(socket)(0, MOD_NETWORK_SOCK_DGRAM, DHCP_CLIENT_PORT, 0); + DHCP_init(0, dhcp_buf); + wiznet5k_obj.dhcp_active = 1; + } +} + +void wiznet5k_stop_dhcp(void) { + if (wiznet5k_obj.dhcp_active) { + wiznet5k_obj.dhcp_active = 0; + DHCP_stop(); + WIZCHIP_EXPORT(close)(0); + } +} + +bool wiznet5k_check_dhcp(void) { + return wiznet5k_obj.dhcp_active; +} + +/// Create and return a WIZNET5K object. +mp_obj_t wiznet5k_create(mp_obj_t spi_in, mp_obj_t cs_in, mp_obj_t rst_in) { + + // init the wiznet5k object + wiznet5k_obj.base.type = (mp_obj_type_t*)&mod_network_nic_type_wiznet5k; + wiznet5k_obj.cris_state = 0; + wiznet5k_obj.spi = MP_OBJ_TO_PTR(spi_in); + common_hal_digitalio_digitalinout_construct(&wiznet5k_obj.cs, cs_in); + common_hal_digitalio_digitalinout_construct(&wiznet5k_obj.rst, rst_in); + wiznet5k_obj.socket_used = 0; + + /*!< SPI configuration */ + // XXX probably should check if the provided SPI is already configured, and + // if so skip configuration? + + common_hal_busio_spi_configure(wiznet5k_obj.spi, + 10000000, // BAUDRATE 10MHz + 1, // HIGH POLARITY + 1, // SECOND PHASE TRANSITION + 8 // 8 BITS + ); + + common_hal_digitalio_digitalinout_switch_to_output(&wiznet5k_obj.cs, 1, DRIVE_MODE_PUSH_PULL); + common_hal_digitalio_digitalinout_switch_to_output(&wiznet5k_obj.rst, 1, DRIVE_MODE_PUSH_PULL); + + common_hal_digitalio_digitalinout_set_value(&wiznet5k_obj.rst, 0); + mp_hal_delay_us(10); // datasheet says 2us + common_hal_digitalio_digitalinout_set_value(&wiznet5k_obj.rst, 1); + mp_hal_delay_ms(160); // datasheet says 150ms + + reg_wizchip_cris_cbfunc(wiz_cris_enter, wiz_cris_exit); + reg_wizchip_cs_cbfunc(wiz_cs_select, wiz_cs_deselect); + reg_wizchip_spi_cbfunc(wiz_spi_read, wiz_spi_write); + + // 2k buffer for each socket + uint8_t sn_size[16] = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; + ctlwizchip(CW_INIT_WIZCHIP, sn_size); + + wiz_NetInfo netinfo = { + .dhcp = NETINFO_DHCP, + }; + network_module_create_random_mac_address(netinfo.mac); + ctlnetwork(CN_SET_NETINFO, (void*)&netinfo); + + // seems we need a small delay after init + mp_hal_delay_ms(250); + + wiznet5k_start_dhcp(); + + // register with network module + network_module_register_nic(&wiznet5k_obj); + + // return wiznet5k object + return &wiznet5k_obj; +} + +#endif // MICROPY_PY_WIZNET5K diff --git a/shared-module/wiznet/wiznet5k.h b/shared-module/wiznet/wiznet5k.h new file mode 100644 index 000000000..1284a44fd --- /dev/null +++ b/shared-module/wiznet/wiznet5k.h @@ -0,0 +1,69 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2014 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_SHARED_MODULE_WIZNET_WIZNET5K_H +#define MICROPY_INCLUDED_SHARED_MODULE_WIZNET_WIZNET5K_H + +#include "ethernet/wizchip_conf.h" +#include "ethernet/socket.h" +#include "internet/dns/dns.h" +#include "internet/dhcp/dhcp.h" + +typedef struct _wiznet5k_obj_t { + mp_obj_base_t base; + mp_uint_t cris_state; + busio_spi_obj_t *spi; + digitalio_digitalinout_obj_t cs; + digitalio_digitalinout_obj_t rst; + uint8_t socket_used; + bool dhcp_active; +} wiznet5k_obj_t; + +int wiznet5k_gethostbyname(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *out_ip); +int wiznet5k_socket_socket(mod_network_socket_obj_t *socket, int *_errno); +void wiznet5k_socket_close(mod_network_socket_obj_t *socket); +int wiznet5k_socket_bind(mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno); +int wiznet5k_socket_listen(mod_network_socket_obj_t *socket, mp_int_t backlog, int *_errno); +int wiznet5k_socket_accept(mod_network_socket_obj_t *socket, mod_network_socket_obj_t *socket2, byte *ip, mp_uint_t *port, int *_errno); +int wiznet5k_socket_connect(mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno); +mp_uint_t wiznet5k_socket_send(mod_network_socket_obj_t *socket, const byte *buf, mp_uint_t len, int *_errno); +mp_uint_t wiznet5k_socket_recv(mod_network_socket_obj_t *socket, byte *buf, mp_uint_t len, int *_errno); +mp_uint_t wiznet5k_socket_sendto(mod_network_socket_obj_t *socket, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno); +mp_uint_t wiznet5k_socket_recvfrom(mod_network_socket_obj_t *socket, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno); +int wiznet5k_socket_setsockopt(mod_network_socket_obj_t *socket, mp_uint_t level, mp_uint_t opt, const void *optval, mp_uint_t optlen, int *_errno); +int wiznet5k_socket_settimeout(mod_network_socket_obj_t *socket, mp_uint_t timeout_ms, int *_errno); +int wiznet5k_socket_ioctl(mod_network_socket_obj_t *socket, mp_uint_t request, mp_uint_t arg, int *_errno); +void wiznet5k_socket_timer_tick(mod_network_socket_obj_t *socket); +mp_obj_t wiznet5k_socket_disconnect(mp_obj_t self_in); +mp_obj_t wiznet5k_create(mp_obj_t spi_in, mp_obj_t cs_in, mp_obj_t rst_in); + +void wiznet5k_start_dhcp(void); +void wiznet5k_stop_dhcp(void); +bool wiznet5k_check_dhcp(void); + +extern const mod_network_nic_type_t mod_network_nic_type_wiznet5k; + +#endif // MICROPY_INCLUDED_SHARED_MODULE_WIZNET_WIZNET5K_H diff --git a/ports/atmel-samd/usb_mass_storage.h b/supervisor/flash.h index 767a6779c..ae6a44fd0 100644 --- a/ports/atmel-samd/usb_mass_storage.h +++ b/supervisor/flash.h @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2016 Scott Shawcroft for Adafruit Industries + * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,26 +23,32 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +#ifndef MICROPY_INCLUDED_SUPERVISOR_FLASH_H +#define MICROPY_INCLUDED_SUPERVISOR_FLASH_H -// This adapts the ASF4 USB mass storage API to MicroPython's VFS API so we can -// expose all VFS block devices as Lun's over USB mass storage control. +#include <stdint.h> +#include <stdbool.h> -#ifndef MICROPY_INCLUDED_ATMEL_SAMD_USB_MASS_STORAGE_H -#define MICROPY_INCLUDED_ATMEL_SAMD_USB_MASS_STORAGE_H +#include "py/mpconfig.h" -#include <stdint.h> +#ifdef EXTERNAL_FLASH_DEVICE_COUNT +#include "supervisor/shared/external_flash/external_flash.h" +#else +#include "supervisor/internal_flash.h" +#endif + +void supervisor_flash_set_usb_writable(bool usb_writable); +void supervisor_flash_init(void); +uint32_t supervisor_flash_get_block_size(void); +uint32_t supervisor_flash_get_block_count(void); +void supervisor_flash_flush(void); -// "background" task that actually manages loading to and from the file systems. -void usb_msc_background(void); +// these return 0 on success, non-zero on error +mp_uint_t supervisor_flash_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks); +mp_uint_t supervisor_flash_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks); -// Callbacks that hook into ASF4's USB stack. -int32_t usb_msc_disk_eject(uint8_t lun); -int32_t usb_msc_disk_is_writable(uint8_t lun); -int32_t usb_msc_disk_is_ready(uint8_t lun); -int32_t usb_msc_new_read(uint8_t lun, uint32_t addr, uint32_t nblocks); -int32_t usb_msc_new_write(uint8_t lun, uint32_t addr, uint32_t nblocks); -int32_t usb_msc_xfer_done(uint8_t lun); -uint8_t *usb_msc_inquiry_info(uint8_t lun); -uint8_t *usb_msc_get_capacity(uint8_t lun); +struct _fs_user_mount_t; +void supervisor_flash_init_vfs(struct _fs_user_mount_t *vfs); +void supervisor_flash_flush(void); -#endif // MICROPY_INCLUDED_ATMEL_SAMD_USB_MASS_STORAGE_H +#endif // MICROPY_INCLUDED_SUPERVISOR_FLASH_H diff --git a/supervisor/flash_root_pointers.h b/supervisor/flash_root_pointers.h new file mode 100644 index 000000000..634ae58d3 --- /dev/null +++ b/supervisor/flash_root_pointers.h @@ -0,0 +1,35 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries LLC + * + * 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_SUPERVISOR_FLASH_ROOT_POINTERS_H +#define MICROPY_INCLUDED_SUPERVISOR_FLASH_ROOT_POINTERS_H + +#ifdef EXTERNAL_FLASH_DEVICE_COUNT +#include "supervisor/shared/external_flash/external_flash_root_pointers.h" +#else +#include "supervisor/internal_flash_root_pointers.h" +#endif + +#endif // MICROPY_INCLUDED_SUPERVISOR_FLASH_ROOT_POINTERS_H diff --git a/supervisor/port.h b/supervisor/port.h index f30d87b47..dd4a82209 100644 --- a/supervisor/port.h +++ b/supervisor/port.h @@ -57,6 +57,9 @@ void reset_port(void); // Reset the rest of the board. void reset_board(void); +// Reset to the bootloader +void reset_to_bootloader(void); + #ifdef NRF52_SERIES void HardFault_Handler(void); #endif diff --git a/supervisor/serial.h b/supervisor/serial.h index 9446ee71c..84b3062a3 100644 --- a/supervisor/serial.h +++ b/supervisor/serial.h @@ -30,8 +30,18 @@ #include <stdbool.h> #include <stdint.h> +#include "py/mpconfig.h" + +#ifdef CIRCUITPY_BOOT_OUTPUT_FILE +#include "lib/oofatfs/ff.h" + +FIL* boot_output_file; +#endif + void serial_init(void); void serial_write(const char* text); +// Only writes up to given length. Does not check for null termination at all. +void serial_write_substring(const char* text, uint32_t length); char serial_read(void); bool serial_bytes_available(void); bool serial_connected(void); diff --git a/ports/atmel-samd/external_flash/common_commands.h b/supervisor/shared/external_flash/common_commands.h index d82d2c046..cc0da2175 100644 --- a/ports/atmel-samd/external_flash/common_commands.h +++ b/supervisor/shared/external_flash/common_commands.h @@ -28,6 +28,7 @@ #define CMD_READ_JEDEC_ID 0x9f #define CMD_READ_DATA 0x03 +#define CMD_FAST_READ_DATA 0x0B #define CMD_SECTOR_ERASE 0x20 // #define CMD_SECTOR_ERASE CMD_READ_JEDEC_ID #define CMD_DISABLE_WRITE 0x04 diff --git a/ports/atmel-samd/external_flash/devices.h b/supervisor/shared/external_flash/devices.h index ea1b24a32..86e0868d0 100644 --- a/ports/atmel-samd/external_flash/devices.h +++ b/supervisor/shared/external_flash/devices.h @@ -40,6 +40,11 @@ typedef struct { // Max clock speed for all operations and the fastest read mode. uint8_t max_clock_speed_mhz; + + // Bitmask for Quad Enable bit if present. 0x00 otherwise. This is for the highest byte in the + // status register. + uint8_t quad_enable_bit_mask; + bool has_sector_protection : 1; // Supports the 0x0b fast read command with 8 dummy cycles. @@ -48,9 +53,6 @@ typedef struct { // Supports the fast read, quad output command 0x6b with 8 dummy cycles. bool supports_qspi : 1; - // Requires quad enable set in status bit 9. - bool has_quad_enable : 1; - // Supports the quad input page program command 0x32. This is known as 1-1-4 because it only // uses all four lines for data. bool supports_qspi_writes: 1; @@ -58,6 +60,10 @@ typedef struct { // Requires a separate command 0x31 to write to the second byte of the status register. // Otherwise two byte are written via 0x01. bool write_status_register_split: 1; + + // True when the status register is a single byte. This implies the Quad Enable bit is in the + // first byte and the Read Status Register 2 command (0x35) is unsupported. + bool single_status_byte: 1; } external_flash_device; // Settings for the Adesto Tech AT25DF081A 1MiB SPI flash. Its on the SAMD21 @@ -70,16 +76,17 @@ typedef struct { .memory_type = 0x45, \ .capacity = 0x01, \ .max_clock_speed_mhz = 85, \ + .quad_enable_bit_mask = 0x00, \ .has_sector_protection = true, \ .supports_fast_read = true, \ .supports_qspi = false, \ - .has_quad_enable = false, \ .supports_qspi_writes = false, \ .write_status_register_split = false, \ + .single_status_byte = false, \ } // Settings for the Gigadevice GD25Q16C 2MiB SPI flash. -// Datasheet: http://www.gigadevice.com/wp-content/uploads/2017/12/DS-00086-GD25Q16C-Rev2.6.pdf +// Datasheet: http://www.gigadevice.com/datasheet/gd25q16c/ #define GD25Q16C {\ .total_size = (1 << 21), /* 2 MiB */ \ .start_up_time_us = 5000, \ @@ -87,12 +94,13 @@ typedef struct { .memory_type = 0x40, \ .capacity = 0x15, \ .max_clock_speed_mhz = 104, /* if we need 120 then we can turn on high performance mode */ \ + .quad_enable_bit_mask = 0x02, \ .has_sector_protection = false, \ .supports_fast_read = true, \ .supports_qspi = true, \ - .has_quad_enable = true, \ .supports_qspi_writes = true, \ .write_status_register_split = false, \ + .single_status_byte = false, \ } // Settings for the Gigadevice GD25Q64C 8MiB SPI flash. @@ -104,12 +112,13 @@ typedef struct { .memory_type = 0x40, \ .capacity = 0x17, \ .max_clock_speed_mhz = 104, /* if we need 120 then we can turn on high performance mode */ \ + .quad_enable_bit_mask = 0x02, \ .has_sector_protection = false, \ .supports_fast_read = true, \ .supports_qspi = true, \ - .has_quad_enable = true, \ .supports_qspi_writes = true, \ .write_status_register_split = true, \ + .single_status_byte = false, \ } // Settings for the Cypress (was Spansion) S25FL064L 8MiB SPI flash. @@ -121,12 +130,13 @@ typedef struct { .memory_type = 0x60, \ .capacity = 0x17, \ .max_clock_speed_mhz = 108, \ + .quad_enable_bit_mask = 0x02, \ .has_sector_protection = false, \ .supports_fast_read = true, \ .supports_qspi = true, \ - .has_quad_enable = true, \ .supports_qspi_writes = true, \ .write_status_register_split = false, \ + .single_status_byte = false, \ } // Settings for the Cypress (was Spansion) S25FL116K 2MiB SPI flash. @@ -138,12 +148,13 @@ typedef struct { .memory_type = 0x40, \ .capacity = 0x15, \ .max_clock_speed_mhz = 108, \ + .quad_enable_bit_mask = 0x02, \ .has_sector_protection = false, \ .supports_fast_read = true, \ .supports_qspi = true, \ - .has_quad_enable = true, \ .supports_qspi_writes = false, \ .write_status_register_split = false, \ + .single_status_byte = false, \ } // Settings for the Cypress (was Spansion) S25FL216K 2MiB SPI flash. @@ -155,12 +166,13 @@ typedef struct { .memory_type = 0x40, \ .capacity = 0x15, \ .max_clock_speed_mhz = 65, \ + .quad_enable_bit_mask = 0x02, \ .has_sector_protection = false, \ .supports_fast_read = true, \ .supports_qspi = false, \ - .has_quad_enable = false, \ .supports_qspi_writes = false, \ .write_status_register_split = false, \ + .single_status_byte = false, \ } // Settings for the Winbond W25Q16FW 2MiB SPI flash. @@ -172,23 +184,42 @@ typedef struct { .memory_type = 0x60, \ .capacity = 0x15, \ .max_clock_speed_mhz = 133, \ + .quad_enable_bit_mask = 0x02, \ .has_sector_protection = false, \ .supports_fast_read = true, \ .supports_qspi = true, \ - .has_quad_enable = true, \ .supports_qspi_writes = true, \ .write_status_register_split = false, \ + .single_status_byte = false, \ } -// Settings for the Winbond W25Q16JV 2MiB SPI flash. +// Settings for the Winbond W25Q16JV-IQ 2MiB SPI flash. Note that JV-IM has a different .memory_type (0x70) // Datasheet: https://www.winbond.com/resource-files/w25q16jv%20spi%20revf%2005092017.pdf -#define W25Q16JV {\ +#define W25Q16JV_IQ {\ .total_size = (1 << 21), /* 2 MiB */ \ .start_up_time_us = 5000, \ .manufacturer_id = 0xef, \ .memory_type = 0x40, \ .capacity = 0x15, \ .max_clock_speed_mhz = 133, \ + .quad_enable_bit_mask = 0x02, \ + .has_sector_protection = false, \ + .supports_fast_read = true, \ + .supports_qspi = true, \ + .supports_qspi_writes = true, \ + .write_status_register_split = false, \ + .single_status_byte = false, \ +} + +// Settings for the Winbond W25Q16JV-IM 2MiB SPI flash. Note that JV-IQ has a different .memory_type (0x40) +// Datasheet: https://www.winbond.com/resource-files/w25q16jv%20spi%20revf%2005092017.pdf +#define W25Q16JV_IM {\ + .total_size = (1 << 21), /* 2 MiB */ \ + .start_up_time_us = 5000, \ + .manufacturer_id = 0xef, \ + .memory_type = 0x70, \ + .capacity = 0x15, \ + .max_clock_speed_mhz = 133, \ .has_sector_protection = false, \ .supports_fast_read = true, \ .supports_qspi = true, \ @@ -206,12 +237,29 @@ typedef struct { .memory_type = 0x60, \ .capacity = 0x16, \ .max_clock_speed_mhz = 104, \ + .quad_enable_bit_mask = 0x02, \ .has_sector_protection = false, \ .supports_fast_read = true, \ .supports_qspi = true, \ - .has_quad_enable = true, \ .supports_qspi_writes = false, \ .write_status_register_split = false, \ + .single_status_byte = false, \ +} +// Settings for the Winbond W25Q32JV-IM 4MiB SPI flash. +// Datasheet: https://www.winbond.com/resource-files/w25q32jv%20revg%2003272018%20plus.pdf +#define W25Q32JV_IM {\ + .total_size = (1 << 22), /* 4 MiB */ \ + .start_up_time_us = 5000, \ + .manufacturer_id = 0xef, \ + .memory_type = 0x70, \ + .capacity = 0x16, \ + .max_clock_speed_mhz = 133, \ + .has_sector_protection = false, \ + .supports_fast_read = true, \ + .supports_qspi = true, \ + .has_quad_enable = true, \ + .supports_qspi_writes = true, \ + .write_status_register_split = false, \ } // Settings for the Winbond W25Q64JV-IM 8MiB SPI flash. Note that JV-IQ has a different .memory_type (0x40) @@ -223,12 +271,14 @@ typedef struct { .memory_type = 0x70, \ .capacity = 0x17, \ .max_clock_speed_mhz = 133, \ + .quad_enable_bit_mask = 0x02, \ .has_sector_protection = false, \ .supports_fast_read = true, \ .supports_qspi = true, \ .has_quad_enable = true, \ .supports_qspi_writes = true, \ .write_status_register_split = false, \ + .single_status_byte = false, \ } // Settings for the Winbond W25Q64JV-IQ 8MiB SPI flash. Note that JV-IM has a different .memory_type (0x70) @@ -240,12 +290,13 @@ typedef struct { .memory_type = 0x40, \ .capacity = 0x17, \ .max_clock_speed_mhz = 133, \ + .quad_enable_bit_mask = 0x02, \ .has_sector_protection = false, \ .supports_fast_read = true, \ .supports_qspi = true, \ - .has_quad_enable = true, \ .supports_qspi_writes = true, \ .write_status_register_split = false, \ + .single_status_byte = false, \ } // Settings for the Winbond W25Q80DL 1MiB SPI flash. @@ -257,14 +308,68 @@ typedef struct { .memory_type = 0x60, \ .capacity = 0x14, \ .max_clock_speed_mhz = 104, \ + .quad_enable_bit_mask = 0x02, \ .has_sector_protection = false, \ .supports_fast_read = true, \ .supports_qspi = true, \ - .has_quad_enable = true, \ .supports_qspi_writes = false, \ .write_status_register_split = false, \ + .single_status_byte = false, \ } +// Settings for the Winbond W25Q128JV-SQ 16MiB SPI flash. Note that JV-IM has a different .memory_type (0x70) +// Datasheet: https://www.winbond.com/resource-files/w25q128jv%20revf%2003272018%20plus.pdf +#define W25Q128JV_SQ {\ + .total_size = (1 << 24), /* 16 MiB */ \ + .start_up_time_us = 5000, \ + .manufacturer_id = 0xef, \ + .memory_type = 0x40, \ + .capacity = 0x18, \ + .max_clock_speed_mhz = 133, \ + .quad_enable_bit_mask = 0x02, \ + .has_sector_protection = false, \ + .supports_fast_read = true, \ + .supports_qspi = true, \ + .supports_qspi_writes = true, \ + .write_status_register_split = false, \ + .single_status_byte = false, \ +} + +// Settings for the Macronix MX25R6435F 8MiB SPI flash. +// Datasheet: http://www.macronix.com/Lists/Datasheet/Attachments/7428/MX25R6435F,%20Wide%20Range,%2064Mb,%20v1.4.pdf +// By default its in lower power mode which can only do 8mhz. In high power mode it can do 80mhz. +#define MX25R6435F {\ + .total_size = (1 << 23), /* 8 MiB */ \ + .start_up_time_us = 5000, \ + .manufacturer_id = 0xc2, \ + .memory_type = 0x28, \ + .capacity = 0x17, \ + .max_clock_speed_mhz = 8, \ + .quad_enable_bit_mask = 0x40, \ + .has_sector_protection = false, \ + .supports_fast_read = true, \ + .supports_qspi = true, \ + .supports_qspi_writes = true, \ + .write_status_register_split = false, \ + .single_status_byte = true, \ +} + +// Settings for the Winbond W25Q128JV-PM 16MiB SPI flash. Note that JV-IM has a different .memory_type (0x70) +// Datasheet: https://www.winbond.com/resource-files/w25q128jv%20revf%2003272018%20plus.pdf +#define W25Q128JV_PM {\ + .total_size = (1 << 24), /* 16 MiB */ \ + .start_up_time_us = 5000, \ + .manufacturer_id = 0xef, \ + .memory_type = 0x70, \ + .capacity = 0x18, \ + .max_clock_speed_mhz = 133, \ + .has_sector_protection = false, \ + .supports_fast_read = true, \ + .supports_qspi = true, \ + .has_quad_enable = true, \ + .supports_qspi_writes = true, \ + .write_status_register_split = false, \ +} #endif // MICROPY_INCLUDED_ATMEL_SAMD_EXTERNAL_FLASH_DEVICES_H diff --git a/ports/atmel-samd/external_flash/external_flash.c b/supervisor/shared/external_flash/external_flash.c index b4a637be4..73b7f7f91 100644 --- a/ports/atmel-samd/external_flash/external_flash.c +++ b/supervisor/shared/external_flash/external_flash.c @@ -28,8 +28,8 @@ #include <stdint.h> #include <string.h> -#include "external_flash/spi_flash_api.h" -#include "external_flash/common_commands.h" +#include "supervisor/spi_flash_api.h" +#include "supervisor/shared/external_flash/common_commands.h" #include "extmod/vfs.h" #include "extmod/vfs_fat.h" #include "py/misc.h" @@ -40,15 +40,8 @@ #include "supervisor/memory.h" #include "supervisor/shared/rgb_led_status.h" -#include "hal_gpio.h" -#include "hal_spi_m_sync.h" - -#define SPI_FLASH_PART1_START_BLOCK (0x1) - #define NO_SECTOR_LOADED 0xFFFFFFFF -struct spi_m_sync_descriptor spi_flash_desc; - // The currently cached sector in the cache, ram or flash based. static uint32_t current_sector; @@ -181,7 +174,7 @@ static bool copy_block(uint32_t src_address, uint32_t dest_address) { return true; } -void external_flash_init(void) { +void supervisor_flash_init(void) { if (flash_device != NULL) { return; } @@ -265,15 +258,15 @@ void external_flash_init(void) { } // The size of each individual block. -uint32_t external_flash_get_block_size(void) { +uint32_t supervisor_flash_get_block_size(void) { return FILESYSTEM_BLOCK_SIZE; } // The total number of available blocks. -uint32_t external_flash_get_block_count(void) { +uint32_t supervisor_flash_get_block_count(void) { // We subtract one erase sector size because we may use it as a staging area // for writes. - return SPI_FLASH_PART1_START_BLOCK + (flash_device->total_size - SPI_FLASH_ERASE_SIZE) / FILESYSTEM_BLOCK_SIZE; + return (flash_device->total_size - SPI_FLASH_ERASE_SIZE) / FILESYSTEM_BLOCK_SIZE; } // Flush the cache that was written to the scratch portion of flash. Only used @@ -445,56 +438,13 @@ static void spi_flash_flush_keep_cache(bool keep_cache) { // External flash function used. If called externally we assume we won't need // the cache after. -void external_flash_flush(void) { +void supervisor_flash_flush(void) { spi_flash_flush_keep_cache(false); } -void flash_flush(void) { - external_flash_flush(); -} - -// Builds a partition entry for the MBR. -static void build_partition(uint8_t *buf, int boot, int type, - uint32_t start_block, uint32_t num_blocks) { - buf[0] = boot; - - if (num_blocks == 0) { - buf[1] = 0; - buf[2] = 0; - buf[3] = 0; - } else { - buf[1] = 0xff; - buf[2] = 0xff; - buf[3] = 0xff; - } - - buf[4] = type; - - if (num_blocks == 0) { - buf[5] = 0; - buf[6] = 0; - buf[7] = 0; - } else { - buf[5] = 0xff; - buf[6] = 0xff; - buf[7] = 0xff; - } - - buf[8] = start_block; - buf[9] = start_block >> 8; - buf[10] = start_block >> 16; - buf[11] = start_block >> 24; - - buf[12] = num_blocks; - buf[13] = num_blocks >> 8; - buf[14] = num_blocks >> 16; - buf[15] = num_blocks >> 24; -} - static int32_t convert_block_to_flash_addr(uint32_t block) { - if (SPI_FLASH_PART1_START_BLOCK <= block && block < external_flash_get_block_count()) { + if (0 <= block && block < supervisor_flash_get_block_count()) { // a block in partition 1 - block -= SPI_FLASH_PART1_START_BLOCK; return block * FILESYSTEM_BLOCK_SIZE; } // bad block @@ -502,110 +452,82 @@ static int32_t convert_block_to_flash_addr(uint32_t block) { } bool external_flash_read_block(uint8_t *dest, uint32_t block) { - if (block == 0) { - // Fake the MBR so we can decide on our own partition table - for (int i = 0; i < 446; i++) { - dest[i] = 0; - } - - build_partition(dest + 446, 0, 0x01 /* FAT12 */, - SPI_FLASH_PART1_START_BLOCK, - external_flash_get_block_count() - SPI_FLASH_PART1_START_BLOCK); - build_partition(dest + 462, 0, 0, 0, 0); - build_partition(dest + 478, 0, 0, 0, 0); - build_partition(dest + 494, 0, 0, 0, 0); - - dest[510] = 0x55; - dest[511] = 0xaa; - - return true; - } else if (block < SPI_FLASH_PART1_START_BLOCK) { - memset(dest, 0, FILESYSTEM_BLOCK_SIZE); - return true; - } else { - // Non-MBR block, get data from flash memory. - int32_t address = convert_block_to_flash_addr(block); - if (address == -1) { - // bad block number - return false; - } - - // Mask out the lower bits that designate the address within the sector. - uint32_t this_sector = address & (~(SPI_FLASH_ERASE_SIZE - 1)); - uint8_t block_index = (address / FILESYSTEM_BLOCK_SIZE) % (SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE); - uint8_t mask = 1 << (block_index); - // We're reading from the currently cached sector. - if (current_sector == this_sector && (mask & dirty_mask) > 0) { - if (MP_STATE_VM(flash_ram_cache) != NULL) { - uint8_t pages_per_block = FILESYSTEM_BLOCK_SIZE / SPI_FLASH_PAGE_SIZE; - for (int i = 0; i < pages_per_block; i++) { - memcpy(dest + i * SPI_FLASH_PAGE_SIZE, - MP_STATE_VM(flash_ram_cache)[block_index * pages_per_block + i], - SPI_FLASH_PAGE_SIZE); - } - return true; - } else { - uint32_t scratch_address = flash_device->total_size - SPI_FLASH_ERASE_SIZE + block_index * FILESYSTEM_BLOCK_SIZE; - return read_flash(scratch_address, dest, FILESYSTEM_BLOCK_SIZE); - } - } - return read_flash(address, dest, FILESYSTEM_BLOCK_SIZE); + int32_t address = convert_block_to_flash_addr(block); + if (address == -1) { + // bad block number + return false; } -} -bool external_flash_write_block(const uint8_t *data, uint32_t block) { - if (block < SPI_FLASH_PART1_START_BLOCK) { - // Fake writing below the flash partition. - return true; - } else { - // Non-MBR block, copy to cache - int32_t address = convert_block_to_flash_addr(block); - if (address == -1) { - // bad block number - return false; - } - // Wait for any previous writes to finish. - wait_for_flash_ready(); - // Mask out the lower bits that designate the address within the sector. - uint32_t this_sector = address & (~(SPI_FLASH_ERASE_SIZE - 1)); - uint8_t block_index = (address / FILESYSTEM_BLOCK_SIZE) % (SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE); - uint8_t mask = 1 << (block_index); - // Flush the cache if we're moving onto a sector or we're writing the - // same block again. - if (current_sector != this_sector || (mask & dirty_mask) > 0) { - // Check to see if we'd write to an erased page. In that case we - // can write directly. - if (page_erased(address)) { - return write_flash(address, data, FILESYSTEM_BLOCK_SIZE); - } - if (current_sector != NO_SECTOR_LOADED) { - spi_flash_flush_keep_cache(true); - } - if (MP_STATE_VM(flash_ram_cache) == NULL && !allocate_ram_cache()) { - erase_sector(flash_device->total_size - SPI_FLASH_ERASE_SIZE); - wait_for_flash_ready(); - } - current_sector = this_sector; - dirty_mask = 0; - } - dirty_mask |= mask; - // Copy the block to the appropriate cache. + // Mask out the lower bits that designate the address within the sector. + uint32_t this_sector = address & (~(SPI_FLASH_ERASE_SIZE - 1)); + uint8_t block_index = (address / FILESYSTEM_BLOCK_SIZE) % (SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE); + uint8_t mask = 1 << (block_index); + // We're reading from the currently cached sector. + if (current_sector == this_sector && (mask & dirty_mask) > 0) { if (MP_STATE_VM(flash_ram_cache) != NULL) { uint8_t pages_per_block = FILESYSTEM_BLOCK_SIZE / SPI_FLASH_PAGE_SIZE; for (int i = 0; i < pages_per_block; i++) { - memcpy(MP_STATE_VM(flash_ram_cache)[block_index * pages_per_block + i], - data + i * SPI_FLASH_PAGE_SIZE, + memcpy(dest + i * SPI_FLASH_PAGE_SIZE, + MP_STATE_VM(flash_ram_cache)[block_index * pages_per_block + i], SPI_FLASH_PAGE_SIZE); } return true; } else { uint32_t scratch_address = flash_device->total_size - SPI_FLASH_ERASE_SIZE + block_index * FILESYSTEM_BLOCK_SIZE; - return write_flash(scratch_address, data, FILESYSTEM_BLOCK_SIZE); + return read_flash(scratch_address, dest, FILESYSTEM_BLOCK_SIZE); + } + } + return read_flash(address, dest, FILESYSTEM_BLOCK_SIZE); +} + +bool external_flash_write_block(const uint8_t *data, uint32_t block) { + // Non-MBR block, copy to cache + int32_t address = convert_block_to_flash_addr(block); + if (address == -1) { + // bad block number + return false; + } + // Wait for any previous writes to finish. + wait_for_flash_ready(); + // Mask out the lower bits that designate the address within the sector. + uint32_t this_sector = address & (~(SPI_FLASH_ERASE_SIZE - 1)); + uint8_t block_index = (address / FILESYSTEM_BLOCK_SIZE) % (SPI_FLASH_ERASE_SIZE / FILESYSTEM_BLOCK_SIZE); + uint8_t mask = 1 << (block_index); + // Flush the cache if we're moving onto a sector or we're writing the + // same block again. + if (current_sector != this_sector || (mask & dirty_mask) > 0) { + // Check to see if we'd write to an erased page. In that case we + // can write directly. + if (page_erased(address)) { + return write_flash(address, data, FILESYSTEM_BLOCK_SIZE); + } + if (current_sector != NO_SECTOR_LOADED) { + spi_flash_flush_keep_cache(true); } + if (MP_STATE_VM(flash_ram_cache) == NULL && !allocate_ram_cache()) { + erase_sector(flash_device->total_size - SPI_FLASH_ERASE_SIZE); + wait_for_flash_ready(); + } + current_sector = this_sector; + dirty_mask = 0; + } + dirty_mask |= mask; + // Copy the block to the appropriate cache. + if (MP_STATE_VM(flash_ram_cache) != NULL) { + uint8_t pages_per_block = FILESYSTEM_BLOCK_SIZE / SPI_FLASH_PAGE_SIZE; + for (int i = 0; i < pages_per_block; i++) { + memcpy(MP_STATE_VM(flash_ram_cache)[block_index * pages_per_block + i], + data + i * SPI_FLASH_PAGE_SIZE, + SPI_FLASH_PAGE_SIZE); + } + return true; + } else { + uint32_t scratch_address = flash_device->total_size - SPI_FLASH_ERASE_SIZE + block_index * FILESYSTEM_BLOCK_SIZE; + return write_flash(scratch_address, data, FILESYSTEM_BLOCK_SIZE); } } -mp_uint_t external_flash_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks) { +mp_uint_t supervisor_flash_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks) { for (size_t i = 0; i < num_blocks; i++) { if (!external_flash_read_block(dest + i * FILESYSTEM_BLOCK_SIZE, block_num + i)) { return 1; // error @@ -614,7 +536,7 @@ mp_uint_t external_flash_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t return 0; // success } -mp_uint_t external_flash_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks) { +mp_uint_t supervisor_flash_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks) { for (size_t i = 0; i < num_blocks; i++) { if (!external_flash_write_block(src + i * FILESYSTEM_BLOCK_SIZE, block_num + i)) { return 1; // error @@ -622,78 +544,3 @@ mp_uint_t external_flash_write_blocks(const uint8_t *src, uint32_t block_num, ui } return 0; // success } - -/******************************************************************************/ -// MicroPython bindings -// -// Expose the flash as an object with the block protocol. - -// there is a singleton Flash object -STATIC const mp_obj_base_t external_flash_obj = {&external_flash_type}; - -STATIC mp_obj_t external_flash_obj_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - // check arguments - mp_arg_check_num(n_args, n_kw, 0, 0, false); - - // return singleton object - return (mp_obj_t)&external_flash_obj; -} - -STATIC mp_obj_t external_flash_obj_readblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) { - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_WRITE); - mp_uint_t ret = external_flash_read_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / FILESYSTEM_BLOCK_SIZE); - return MP_OBJ_NEW_SMALL_INT(ret); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_3(external_flash_obj_readblocks_obj, external_flash_obj_readblocks); - -STATIC mp_obj_t external_flash_obj_writeblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) { - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ); - mp_uint_t ret = external_flash_write_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / FILESYSTEM_BLOCK_SIZE); - return MP_OBJ_NEW_SMALL_INT(ret); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_3(external_flash_obj_writeblocks_obj, external_flash_obj_writeblocks); - -STATIC mp_obj_t external_flash_obj_ioctl(mp_obj_t self, mp_obj_t cmd_in, mp_obj_t arg_in) { - mp_int_t cmd = mp_obj_get_int(cmd_in); - switch (cmd) { - case BP_IOCTL_INIT: external_flash_init(); return MP_OBJ_NEW_SMALL_INT(0); - case BP_IOCTL_DEINIT: external_flash_flush(); return MP_OBJ_NEW_SMALL_INT(0); // TODO properly - case BP_IOCTL_SYNC: external_flash_flush(); return MP_OBJ_NEW_SMALL_INT(0); - case BP_IOCTL_SEC_COUNT: return MP_OBJ_NEW_SMALL_INT(external_flash_get_block_count()); - case BP_IOCTL_SEC_SIZE: return MP_OBJ_NEW_SMALL_INT(external_flash_get_block_size()); - default: return mp_const_none; - } -} -STATIC MP_DEFINE_CONST_FUN_OBJ_3(external_flash_obj_ioctl_obj, external_flash_obj_ioctl); - -STATIC const mp_rom_map_elem_t external_flash_obj_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&external_flash_obj_readblocks_obj) }, - { MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&external_flash_obj_writeblocks_obj) }, - { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&external_flash_obj_ioctl_obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(external_flash_obj_locals_dict, external_flash_obj_locals_dict_table); - -const mp_obj_type_t external_flash_type = { - { &mp_type_type }, - .name = MP_QSTR_SPIFlash, - .make_new = external_flash_obj_make_new, - .locals_dict = (mp_obj_t)&external_flash_obj_locals_dict, -}; - -void flash_init_vfs(fs_user_mount_t *vfs) { - vfs->base.type = &mp_fat_vfs_type; - vfs->flags |= FSUSER_NATIVE | FSUSER_HAVE_IOCTL; - vfs->fatfs.drv = vfs; - vfs->fatfs.part = 1; // flash filesystem lives on first partition - vfs->readblocks[0] = (mp_obj_t)&external_flash_obj_readblocks_obj; - vfs->readblocks[1] = (mp_obj_t)&external_flash_obj; - vfs->readblocks[2] = (mp_obj_t)external_flash_read_blocks; // native version - vfs->writeblocks[0] = (mp_obj_t)&external_flash_obj_writeblocks_obj; - vfs->writeblocks[1] = (mp_obj_t)&external_flash_obj; - vfs->writeblocks[2] = (mp_obj_t)external_flash_write_blocks; // native version - vfs->u.ioctl[0] = (mp_obj_t)&external_flash_obj_ioctl_obj; - vfs->u.ioctl[1] = (mp_obj_t)&external_flash_obj; -} diff --git a/supervisor/shared/external_flash/external_flash.h b/supervisor/shared/external_flash/external_flash.h new file mode 100644 index 000000000..72b619a2a --- /dev/null +++ b/supervisor/shared/external_flash/external_flash.h @@ -0,0 +1,48 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries LLC + * + * 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_SUPERVISOR_SHARED_EXTERNAL_FLASH_EXTERNAL_FLASH_H +#define MICROPY_INCLUDED_SUPERVISOR_SHARED_EXTERNAL_FLASH_EXTERNAL_FLASH_H + +#include <stdbool.h> +#include <stdint.h> + +#include "py/mpconfig.h" + +// Erase sector size. +#define SPI_FLASH_SECTOR_SIZE (0x1000 - 100) + +// These are common across all NOR Flash. +#define SPI_FLASH_ERASE_SIZE (1 << 12) +#define SPI_FLASH_PAGE_SIZE (256) + +#define SPI_FLASH_SYSTICK_MASK (0x1ff) // 512ms +#define SPI_FLASH_IDLE_TICK(tick) (((tick) & SPI_FLASH_SYSTICK_MASK) == 2) + +#ifndef SPI_FLASH_MAX_BAUDRATE +#define SPI_FLASH_MAX_BAUDRATE 8000000 +#endif + +#endif // MICROPY_INCLUDED_SUPERVISOR_SHARED_EXTERNAL_FLASH_EXTERNAL_FLASH_H diff --git a/supervisor/shared/external_flash/external_flash_root_pointers.h b/supervisor/shared/external_flash/external_flash_root_pointers.h new file mode 100644 index 000000000..cb1b86d19 --- /dev/null +++ b/supervisor/shared/external_flash/external_flash_root_pointers.h @@ -0,0 +1,35 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries LLC + * + * 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_SUPERVISOR_SHARED_EXTERNAL_FLASH_EXTERNAL_FLASH_ROOT_POINTERS_H +#define MICROPY_INCLUDED_SUPERVISOR_SHARED_EXTERNAL_FLASH_EXTERNAL_FLASH_ROOT_POINTERS_H + +#include <stdint.h> + +// We use this when we can allocate the whole cache in RAM. +#define FLASH_ROOT_POINTERS \ + uint8_t** flash_ram_cache; \ + +#endif // MICROPY_INCLUDED_SUPERVISOR_SHARED_EXTERNAL_FLASH_EXTERNAL_FLASH_ROOT_POINTERS_H diff --git a/supervisor/shared/external_flash/qspi_flash.c b/supervisor/shared/external_flash/qspi_flash.c new file mode 100644 index 000000000..48266540c --- /dev/null +++ b/supervisor/shared/external_flash/qspi_flash.c @@ -0,0 +1,56 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016, 2017, 2018 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. + */ + +#include "supervisor/spi_flash_api.h" + +#include "supervisor/shared/external_flash/common_commands.h" + +void check_quad_enable(const external_flash_device* device) { + if (device->quad_enable_bit_mask == 0x00) { + return; + } + + // Verify that QSPI mode is enabled. + uint8_t status; + if (device->single_status_byte) { + spi_flash_read_command(CMD_READ_STATUS, &status, 1); + } else { + spi_flash_read_command(CMD_READ_STATUS2, &status, 1); + } + + // Check the quad enable bit. + if ((status & device->quad_enable_bit_mask) == 0) { + uint8_t full_status[2] = {0x00, device->quad_enable_bit_mask}; + spi_flash_command(CMD_ENABLE_WRITE); + if (device->write_status_register_split) { + spi_flash_write_command(CMD_WRITE_STATUS_BYTE2, full_status + 1, 1); + } else if (device->single_status_byte) { + spi_flash_write_command(CMD_WRITE_STATUS_BYTE1, full_status + 1, 1); + } else { + spi_flash_write_command(CMD_WRITE_STATUS_BYTE1, full_status, 2); + } + } +} diff --git a/supervisor/shared/external_flash/qspi_flash.h b/supervisor/shared/external_flash/qspi_flash.h new file mode 100644 index 000000000..b72e37b26 --- /dev/null +++ b/supervisor/shared/external_flash/qspi_flash.h @@ -0,0 +1,31 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries LLC + * + * 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_SUPERVISOR_SHARED_EXTERNAL_FLASH_QSPI_FLASH_H +#define MICROPY_INCLUDED_SUPERVISOR_SHARED_EXTERNAL_FLASH_QSPI_FLASH_H + +void check_quad_enable(const external_flash_device* device); + +#endif // MICROPY_INCLUDED_SUPERVISOR_SHARED_EXTERNAL_FLASH_QSPI_FLASH_H diff --git a/ports/atmel-samd/external_flash/spi_flash.c b/supervisor/shared/external_flash/spi_flash.c index 273915df7..ec7101bc9 100644 --- a/ports/atmel-samd/external_flash/spi_flash.c +++ b/supervisor/shared/external_flash/spi_flash.c @@ -23,40 +23,50 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include "spi_flash_api.h" +#include "supervisor/spi_flash_api.h" #include <stdint.h> #include <string.h> -#include "external_flash/common_commands.h" -#include "samd/sercom.h" +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/digitalio/DigitalInOut.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "supervisor/shared/external_flash/common_commands.h" +#include "supervisor/shared/external_flash/external_flash.h" #include "py/mpconfig.h" -#include "hal_gpio.h" -#include "hal_spi_m_sync.h" +digitalio_digitalinout_obj_t cs_pin; +busio_spi_obj_t spi; -struct spi_m_sync_descriptor spi_flash_desc; +const external_flash_device* flash_device; +uint32_t spi_flash_baudrate; // Enable the flash over SPI. static void flash_enable(void) { - gpio_set_pin_level(SPI_FLASH_CS_PIN, false); + while (!common_hal_busio_spi_try_lock(&spi)) {} + common_hal_digitalio_digitalinout_set_value(&cs_pin, false); } // Disable the flash over SPI. static void flash_disable(void) { - gpio_set_pin_level(SPI_FLASH_CS_PIN, true); + common_hal_digitalio_digitalinout_set_value(&cs_pin, true); + common_hal_busio_spi_unlock(&spi); } static bool transfer(uint8_t* command, uint32_t command_length, uint8_t* data_in, uint8_t* data_out, uint32_t data_length) { - struct spi_xfer xfer = { command, NULL, command_length }; flash_enable(); - int32_t status = spi_m_sync_transfer(&spi_flash_desc, &xfer); - if (status >= 0 && !(data_in == NULL && data_out == NULL)) { - struct spi_xfer data_xfer = {data_in, data_out, data_length}; - status = spi_m_sync_transfer(&spi_flash_desc, &data_xfer); + bool status = common_hal_busio_spi_write(&spi, command, command_length); + if (status) { + if (data_in != NULL && data_out != NULL) { + status = common_hal_busio_spi_transfer(&spi, data_out, data_in, data_length); + } else if (data_out != NULL) { + status = common_hal_busio_spi_read(&spi, data_out, data_length, 0xff); + } else if (data_in != NULL) { + status = common_hal_busio_spi_write(&spi, data_in, data_length); + } } flash_disable(); - return status >= 0; + return status; } static bool transfer_command(uint8_t command, uint8_t* data_in, uint8_t* data_out, uint32_t data_length) { @@ -92,67 +102,49 @@ bool spi_flash_write_data(uint32_t address, uint8_t* data, uint32_t data_length) uint8_t request[4] = {CMD_PAGE_PROGRAM, 0x00, 0x00, 0x00}; // Write the SPI flash write address into the bytes following the command byte. address_to_bytes(address, request + 1); - struct spi_xfer xfer = { request, NULL, 4 }; flash_enable(); - int32_t status = spi_m_sync_transfer(&spi_flash_desc, &xfer); - if (status >= 0) { - status = sercom_dma_write(spi_flash_desc.dev.prvt, data, data_length); + common_hal_busio_spi_configure(&spi, spi_flash_baudrate, 0, 0, 8); + bool status = common_hal_busio_spi_write(&spi, request, 4); + if (status) { + status = common_hal_busio_spi_write(&spi, data, data_length); } flash_disable(); - return status >= 0; + return status; } bool spi_flash_read_data(uint32_t address, uint8_t* data, uint32_t data_length) { - uint8_t request[4] = {CMD_READ_DATA, 0x00, 0x00, 0x00}; + uint8_t request[5] = {CMD_READ_DATA, 0x00, 0x00, 0x00}; + uint8_t command_length = 4; + if (flash_device->supports_fast_read) { + request[0] = CMD_FAST_READ_DATA; + command_length = 5; + } // Write the SPI flash write address into the bytes following the command byte. address_to_bytes(address, request + 1); - struct spi_xfer xfer = { request, NULL, 4 }; flash_enable(); - int32_t status = spi_m_sync_transfer(&spi_flash_desc, &xfer); - if (status >= 0) { - status = sercom_dma_read(spi_flash_desc.dev.prvt, data, data_length, 0xff); + common_hal_busio_spi_configure(&spi, spi_flash_baudrate, 0, 0, 8); + bool status = common_hal_busio_spi_write(&spi, request, command_length); + if (status) { + status = common_hal_busio_spi_read(&spi, data, data_length, 0xff); } flash_disable(); - return status >= 0; + return status; } void spi_flash_init(void) { - samd_peripherals_sercom_clock_init(SPI_FLASH_SERCOM, SPI_FLASH_SERCOM_INDEX); - - // Set up with defaults, then change. - spi_m_sync_init(&spi_flash_desc, SPI_FLASH_SERCOM); - - hri_sercomspi_write_CTRLA_DOPO_bf(SPI_FLASH_SERCOM, SPI_FLASH_DOPO); - hri_sercomspi_write_CTRLA_DIPO_bf(SPI_FLASH_SERCOM, SPI_FLASH_DIPO); - - gpio_set_pin_direction(SPI_FLASH_SCK_PIN, GPIO_DIRECTION_OUT); - gpio_set_pin_pull_mode(SPI_FLASH_SCK_PIN, GPIO_PULL_OFF); - gpio_set_pin_function(SPI_FLASH_SCK_PIN, SPI_FLASH_SCK_PIN_FUNCTION); - - gpio_set_pin_direction(SPI_FLASH_MOSI_PIN, GPIO_DIRECTION_OUT); - gpio_set_pin_pull_mode(SPI_FLASH_MOSI_PIN, GPIO_PULL_OFF); - gpio_set_pin_function(SPI_FLASH_MOSI_PIN, SPI_FLASH_MOSI_PIN_FUNCTION); - - gpio_set_pin_direction(SPI_FLASH_MISO_PIN, GPIO_DIRECTION_IN); - gpio_set_pin_pull_mode(SPI_FLASH_MISO_PIN, GPIO_PULL_OFF); - gpio_set_pin_function(SPI_FLASH_MISO_PIN, SPI_FLASH_MISO_PIN_FUNCTION); - - hri_sercomspi_write_CTRLA_DOPO_bf(SPI_FLASH_SERCOM, SPI_FLASH_DOPO); - hri_sercomspi_write_CTRLA_DIPO_bf(SPI_FLASH_SERCOM, SPI_FLASH_DIPO); - - spi_m_sync_set_baudrate(&spi_flash_desc, samd_peripherals_spi_baudrate_to_baud_reg_value(SPI_FLASH_BAUDRATE)); - - gpio_set_pin_direction(SPI_FLASH_CS_PIN, GPIO_DIRECTION_OUT); - // There's already a pull-up on the board. - gpio_set_pin_pull_mode(SPI_FLASH_CS_PIN, GPIO_PULL_OFF); - gpio_set_pin_function(SPI_FLASH_CS_PIN, GPIO_PIN_FUNCTION_OFF); + common_hal_digitalio_digitalinout_construct(&cs_pin, SPI_FLASH_CS_PIN); // Set CS high (disabled). - flash_disable(); + common_hal_digitalio_digitalinout_switch_to_output(&cs_pin, true, DRIVE_MODE_PUSH_PULL); - spi_m_sync_enable(&spi_flash_desc); + common_hal_busio_spi_construct(&spi, SPI_FLASH_SCK_PIN, SPI_FLASH_MOSI_PIN, SPI_FLASH_MISO_PIN); + common_hal_busio_spi_never_reset(&spi); } void spi_flash_init_device(const external_flash_device* device) { - + flash_device = device; + spi_flash_baudrate = device->max_clock_speed_mhz * 1000000; + if (spi_flash_baudrate > SPI_FLASH_MAX_BAUDRATE) { + spi_flash_baudrate = SPI_FLASH_MAX_BAUDRATE; + } } diff --git a/ports/atmel-samd/supervisor/filesystem.c b/supervisor/shared/filesystem.c index 8a6010951..d968f4798 100644 --- a/ports/atmel-samd/supervisor/filesystem.c +++ b/supervisor/shared/filesystem.c @@ -30,10 +30,10 @@ #include "py/mpstate.h" -#include "flash_api.h" +#include "supervisor/flash.h" -fs_user_mount_t fs_user_mount_flash; -mp_vfs_mount_t mp_vfs_mount_flash; +static mp_vfs_mount_t _mp_vfs; +static fs_user_mount_t _internal_vfs; static void make_empty_file(FATFS *fatfs, const char *path) { FIL fp; @@ -45,9 +45,9 @@ static void make_empty_file(FATFS *fatfs, const char *path) { // want it to be executed without using stack within main() function void filesystem_init(bool create_allowed, bool force_create) { // init the vfs object - fs_user_mount_t *vfs_fat = &fs_user_mount_flash; + fs_user_mount_t *vfs_fat = &_internal_vfs; vfs_fat->flags = 0; - flash_init_vfs(vfs_fat); + supervisor_flash_init_vfs(vfs_fat); // try to mount the flash FRESULT res = f_mount(&vfs_fat->fatfs); @@ -57,7 +57,7 @@ void filesystem_init(bool create_allowed, bool force_create) { uint8_t working_buf[_MAX_SS]; res = f_mkfs(&vfs_fat->fatfs, FM_FAT, 0, working_buf, sizeof(working_buf)); // Flush the new file system to make sure it's repaired immediately. - flash_flush(); + supervisor_flash_flush(); if (res != FR_OK) { return; } @@ -72,11 +72,11 @@ void filesystem_init(bool create_allowed, bool force_create) { make_empty_file(&vfs_fat->fatfs, "/.fseventsd/no_log"); // and ensure everything is flushed - flash_flush(); + supervisor_flash_flush(); } else if (res != FR_OK) { return; } - mp_vfs_mount_t *vfs = &mp_vfs_mount_flash; + mp_vfs_mount_t *vfs = &_mp_vfs; vfs->str = "/"; vfs->len = 1; vfs->obj = MP_OBJ_FROM_PTR(vfs_fat); @@ -89,11 +89,17 @@ void filesystem_init(bool create_allowed, bool force_create) { } void filesystem_flush(void) { - flash_flush(); + supervisor_flash_flush(); } void filesystem_writable_by_python(bool writable) { - flash_set_usb_writable(!writable); + fs_user_mount_t *vfs = &_internal_vfs; + + if (writable) { + vfs->flags |= FSUSER_USB_WRITABLE; + } else { + vfs->flags &= ~FSUSER_USB_WRITABLE; + } } bool filesystem_present(void) { diff --git a/supervisor/shared/flash.c b/supervisor/shared/flash.c new file mode 100644 index 000000000..c8921aa85 --- /dev/null +++ b/supervisor/shared/flash.c @@ -0,0 +1,202 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Scott Shawcroft + * + * 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 "supervisor/flash.h" + +#include "extmod/vfs_fat.h" +#include "py/runtime.h" +#include "lib/oofatfs/ff.h" + +#define VFS_INDEX 0 + +#define PART1_START_BLOCK (0x1) + +void supervisor_flash_set_usb_writable(bool usb_writable) { + mp_vfs_mount_t* current_mount = MP_STATE_VM(vfs_mount_table); + for (uint8_t i = 0; current_mount != NULL; i++) { + if (i == VFS_INDEX) { + break; + } + current_mount = current_mount->next; + } + if (current_mount == NULL) { + return; + } + fs_user_mount_t *vfs = (fs_user_mount_t *) current_mount->obj; + + if (usb_writable) { + vfs->flags |= FSUSER_USB_WRITABLE; + } else { + vfs->flags &= ~FSUSER_USB_WRITABLE; + } +} + +// there is a singleton Flash object +const mp_obj_type_t supervisor_flash_type; +STATIC const mp_obj_base_t supervisor_flash_obj = {&supervisor_flash_type}; + +STATIC mp_obj_t supervisor_flash_obj_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { + // check arguments + mp_arg_check_num(n_args, n_kw, 0, 0, false); + + // return singleton object + return (mp_obj_t)&supervisor_flash_obj; +} + +uint32_t flash_get_block_count(void) { + return PART1_START_BLOCK + supervisor_flash_get_block_count(); +} + +static void build_partition(uint8_t *buf, int boot, int type, uint32_t start_block, uint32_t num_blocks) { + buf[0] = boot; + + if (num_blocks == 0) { + buf[1] = 0; + buf[2] = 0; + buf[3] = 0; + } else { + buf[1] = 0xff; + buf[2] = 0xff; + buf[3] = 0xff; + } + + buf[4] = type; + + if (num_blocks == 0) { + buf[5] = 0; + buf[6] = 0; + buf[7] = 0; + } else { + buf[5] = 0xff; + buf[6] = 0xff; + buf[7] = 0xff; + } + + buf[8] = start_block; + buf[9] = start_block >> 8; + buf[10] = start_block >> 16; + buf[11] = start_block >> 24; + + buf[12] = num_blocks; + buf[13] = num_blocks >> 8; + buf[14] = num_blocks >> 16; + buf[15] = num_blocks >> 24; +} + +mp_uint_t flash_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks) { + if (block_num == 0) { + if (block_num > 1) { + return 1; // error + } + // fake the MBR so we can decide on our own partition table + + for (int i = 0; i < 446; i++) { + dest[i] = 0; + } + + build_partition(dest + 446, 0, 0x01 /* FAT12 */, PART1_START_BLOCK, supervisor_flash_get_block_count()); + build_partition(dest + 462, 0, 0, 0, 0); + build_partition(dest + 478, 0, 0, 0, 0); + build_partition(dest + 494, 0, 0, 0, 0); + + dest[510] = 0x55; + dest[511] = 0xaa; + + return 0; // ok + + } + return supervisor_flash_read_blocks(dest, block_num - PART1_START_BLOCK, num_blocks); +} + +mp_uint_t flash_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks) { + if (block_num == 0) { + if (num_blocks > 1) { + return 1; // error + } + // can't write MBR, but pretend we did + return 0; + } else { + return supervisor_flash_write_blocks(src, block_num - PART1_START_BLOCK, num_blocks); + } +} + +STATIC mp_obj_t supervisor_flash_obj_readblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) { + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_WRITE); + mp_uint_t ret = flash_read_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / FILESYSTEM_BLOCK_SIZE); + return MP_OBJ_NEW_SMALL_INT(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(supervisor_flash_obj_readblocks_obj, supervisor_flash_obj_readblocks); + +STATIC mp_obj_t supervisor_flash_obj_writeblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) { + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ); + mp_uint_t ret = flash_write_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / FILESYSTEM_BLOCK_SIZE); + return MP_OBJ_NEW_SMALL_INT(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(supervisor_flash_obj_writeblocks_obj, supervisor_flash_obj_writeblocks); + +STATIC mp_obj_t supervisor_flash_obj_ioctl(mp_obj_t self, mp_obj_t cmd_in, mp_obj_t arg_in) { + mp_int_t cmd = mp_obj_get_int(cmd_in); + switch (cmd) { + case BP_IOCTL_INIT: supervisor_flash_init(); return MP_OBJ_NEW_SMALL_INT(0); + case BP_IOCTL_DEINIT: supervisor_flash_flush(); return MP_OBJ_NEW_SMALL_INT(0); // TODO properly + case BP_IOCTL_SYNC: supervisor_flash_flush(); return MP_OBJ_NEW_SMALL_INT(0); + case BP_IOCTL_SEC_COUNT: return MP_OBJ_NEW_SMALL_INT(flash_get_block_count()); + case BP_IOCTL_SEC_SIZE: return MP_OBJ_NEW_SMALL_INT(supervisor_flash_get_block_size()); + default: return mp_const_none; + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(supervisor_flash_obj_ioctl_obj, supervisor_flash_obj_ioctl); + +STATIC const mp_rom_map_elem_t supervisor_flash_obj_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&supervisor_flash_obj_readblocks_obj) }, + { MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&supervisor_flash_obj_writeblocks_obj) }, + { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&supervisor_flash_obj_ioctl_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(supervisor_flash_obj_locals_dict, supervisor_flash_obj_locals_dict_table); + +const mp_obj_type_t supervisor_flash_type = { + { &mp_type_type }, + .name = MP_QSTR_Flash, + .make_new = supervisor_flash_obj_make_new, + .locals_dict = (mp_obj_t)&supervisor_flash_obj_locals_dict, +}; + +void supervisor_flash_init_vfs(fs_user_mount_t *vfs) { + vfs->base.type = &mp_fat_vfs_type; + vfs->flags |= FSUSER_NATIVE | FSUSER_HAVE_IOCTL; + vfs->fatfs.drv = vfs; + vfs->fatfs.part = 1; // flash filesystem lives on first partition + vfs->readblocks[0] = (mp_obj_t)&supervisor_flash_obj_readblocks_obj; + vfs->readblocks[1] = (mp_obj_t)&supervisor_flash_obj; + vfs->readblocks[2] = (mp_obj_t)flash_read_blocks; // native version + vfs->writeblocks[0] = (mp_obj_t)&supervisor_flash_obj_writeblocks_obj; + vfs->writeblocks[1] = (mp_obj_t)&supervisor_flash_obj; + vfs->writeblocks[2] = (mp_obj_t)flash_write_blocks; // native version + vfs->u.ioctl[0] = (mp_obj_t)&supervisor_flash_obj_ioctl_obj; + vfs->u.ioctl[1] = (mp_obj_t)&supervisor_flash_obj; +} diff --git a/supervisor/shared/micropython.c b/supervisor/shared/micropython.c new file mode 100644 index 000000000..245db11d4 --- /dev/null +++ b/supervisor/shared/micropython.c @@ -0,0 +1,58 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 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. + */ + +#include <string.h> + +#include "supervisor/serial.h" +#include "lib/oofatfs/ff.h" +#include "py/mpconfig.h" + +#include "supervisor/shared/status_leds.h" + +int mp_hal_stdin_rx_chr(void) { + for (;;) { + #ifdef MICROPY_VM_HOOK_LOOP + MICROPY_VM_HOOK_LOOP + #endif + if (serial_bytes_available()) { + toggle_rx_led(); + return serial_read(); + } + } +} + +void mp_hal_stdout_tx_strn(const char *str, size_t len) { + toggle_tx_led(); + + #ifdef CIRCUITPY_BOOT_OUTPUT_FILE + if (boot_output_file != NULL) { + UINT bytes_written = 0; + f_write(boot_output_file, str, len, &bytes_written); + } + #endif + + serial_write_substring(str, len); +} diff --git a/supervisor/shared/rgb_led_status.h b/supervisor/shared/rgb_led_status.h index 24e071aac..9542b3197 100644 --- a/supervisor/shared/rgb_led_status.h +++ b/supervisor/shared/rgb_led_status.h @@ -33,7 +33,7 @@ #include "lib/utils/pyexec.h" #include "supervisor/port.h" -#include "mpconfigport.h" +#include "py/mpconfig.h" #include "rgb_led_colors.h" // Overall, the time module must be implemented. diff --git a/ports/atmel-samd/flash_api.c b/supervisor/shared/serial.c index b8a212718..c57688ddc 100644 --- a/ports/atmel-samd/flash_api.c +++ b/supervisor/shared/serial.c @@ -24,28 +24,40 @@ * THE SOFTWARE. */ -#include "flash_api.h" +#include <string.h> -#include "py/mpstate.h" +#include "supervisor/serial.h" +#include "supervisor/usb.h" -#define VFS_INDEX 0 +#include "tusb.h" -void flash_set_usb_writable(bool usb_writable) { - mp_vfs_mount_t* current_mount = MP_STATE_VM(vfs_mount_table); - for (uint8_t i = 0; current_mount != NULL; i++) { - if (i == VFS_INDEX) { - break; - } - current_mount = current_mount->next; - } - if (current_mount == NULL) { +void serial_init(void) { + usb_init(); +} + +bool serial_connected(void) { + return tud_cdc_connected(); +} + +char serial_read(void) { + return (char) tud_cdc_read_char(); +} + +bool serial_bytes_available(void) { + return tud_cdc_available() > 0; +} + +void serial_write_substring(const char* text, uint32_t length) { + if (!tud_cdc_connected()) { return; } - fs_user_mount_t *vfs = (fs_user_mount_t *) current_mount->obj; - - if (usb_writable) { - vfs->flags |= FSUSER_USB_WRITABLE; - } else { - vfs->flags &= ~FSUSER_USB_WRITABLE; + uint32_t count = 0; + while (count < length) { + count += tud_cdc_write(text + count, length - count); + usb_background(); } } + +void serial_write(const char* text) { + serial_write_substring(text, strlen(text)); +} diff --git a/supervisor/shared/status_leds.c b/supervisor/shared/status_leds.c new file mode 100644 index 000000000..d99853ceb --- /dev/null +++ b/supervisor/shared/status_leds.c @@ -0,0 +1,62 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 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. + */ + +#include "supervisor/shared/status_leds.h" + +#include "common-hal/digitalio/DigitalInOut.h" +#include "shared-bindings/digitalio/DigitalInOut.h" + +#ifdef MICROPY_HW_LED_RX +digitalio_digitalinout_obj_t rx_led; +#endif + +#ifdef MICROPY_HW_LED_TX +digitalio_digitalinout_obj_t tx_led; +#endif + +void init_status_leds(void) { + #ifdef MICROPY_HW_LED_RX + common_hal_digitalio_digitalinout_construct(&rx_led, MICROPY_HW_LED_RX); + common_hal_digitalio_digitalinout_switch_to_output(&rx_led, true, DRIVE_MODE_PUSH_PULL); + #endif + #ifdef MICROPY_HW_LED_TX + common_hal_digitalio_digitalinout_construct(&tx_led, MICROPY_HW_LED_TX); + common_hal_digitalio_digitalinout_switch_to_output(&tx_led, true, DRIVE_MODE_PUSH_PULL); + #endif +} + +void toggle_rx_led(void) { + #ifdef MICROPY_HW_LED_RX + common_hal_digitalio_digitalinout_set_value(&rx_led, !common_hal_digitalio_digitalinout_get_value(&rx_led)); + #endif +} + + +void toggle_tx_led(void) { + #ifdef MICROPY_HW_LED_TX + common_hal_digitalio_digitalinout_set_value(&tx_led, !common_hal_digitalio_digitalinout_get_value(&tx_led)); + #endif +} diff --git a/supervisor/shared/status_leds.h b/supervisor/shared/status_leds.h new file mode 100644 index 000000000..30132753f --- /dev/null +++ b/supervisor/shared/status_leds.h @@ -0,0 +1,36 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 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_SUPERVISOR_STATUS_LEDS_H +#define MICROPY_INCLUDED_SUPERVISOR_STATUS_LEDS_H + +void init_status_leds(void); + +void toggle_rx_led(void); + +void toggle_tx_led(void); + +#endif // MICROPY_INCLUDED_SUPERVISOR_STATUS_LEDS_H diff --git a/ports/nrf/usb/tusb_config.h b/supervisor/shared/usb/tusb_config.h index 626b99eeb..649c390ac 100644 --- a/ports/nrf/usb/tusb_config.h +++ b/supervisor/shared/usb/tusb_config.h @@ -38,6 +38,8 @@ #ifndef _TUSB_CONFIG_H_ #define _TUSB_CONFIG_H_ +#include "genhdr/autogen_usb_descriptor.h" + #ifdef __cplusplus extern "C" { #endif @@ -45,7 +47,6 @@ //--------------------------------------------------------------------+ // COMMON CONFIGURATION //--------------------------------------------------------------------+ -#define CFG_TUSB_MCU OPT_MCU_NRF5X #define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE #define CFG_TUSB_DEBUG 0 @@ -74,16 +75,12 @@ #define CFG_TUD_CDC 1 #define CFG_TUD_MSC 1 #define CFG_TUD_HID 1 +#define CFG_TUD_CUSTOM_CLASS 0 /*------------------------------------------------------------------*/ /* CLASS DRIVER *------------------------------------------------------------------*/ -/*------------- CDC -------------*/ -// FIFO size of CDC TX and RX -#define CFG_TUD_CDC_RX_BUFSIZE 1024 -#define CFG_TUD_CDC_TX_BUFSIZE 1024 - /* TX is sent automatically on every Start of Frame event ~ 1ms. * If not enabled, application must call tud_cdc_flush() periodically * Note: Enabled this could overflow device task, if it does, define @@ -99,17 +96,7 @@ // Number of Blocks #define CFG_TUD_MSC_BLOCK_NUM (256*1024)/512 -// Block size -#define CFG_TUD_MSC_BLOCK_SZ 512 - -// Buffer size for each read/write transfer, the more the better -#define CFG_TUD_MSC_BUFSIZE (4*1024) - -// Vendor name included in Inquiry response, max 8 bytes -#define CFG_TUD_MSC_VENDOR "Adafruit" -// Product name included in Inquiry response, max 16 bytes -#define CFG_TUD_MSC_PRODUCT "CircuitPY nRF52" // Product revision string included in Inquiry response, max 4 bytes #define CFG_TUD_MSC_PRODUCT_REV "1.0" diff --git a/ports/nrf/usb/usb.c b/supervisor/shared/usb/usb.c index 248d31e21..1aa34e9e6 100644 --- a/ports/nrf/usb/usb.c +++ b/supervisor/shared/usb/usb.c @@ -24,79 +24,47 @@ * THE SOFTWARE. */ -#include "nrfx.h" -#include "nrfx_power.h" #include "tick.h" -#include "usb.h" +#include "shared-bindings/microcontroller/Processor.h" +#include "supervisor/port.h" +#include "supervisor/usb.h" #include "lib/utils/interrupt_char.h" #include "lib/mp-readline/readline.h" -#ifdef SOFTDEVICE_PRESENT -#include "nrf_sdm.h" -#include "nrf_soc.h" -#endif - -/* tinyusb function that handles power event (detected, ready, removed) - * We must call it within SD's SOC event handler, or set it as power event handler if SD is not enabled. - */ -extern void tusb_hal_nrf_power_event(uint32_t event); - -void usb_init(void) { - - // USB power may already be ready at this time -> no event generated - // We need to invoke the handler based on the status initially - uint32_t usb_reg; - -#ifdef SOFTDEVICE_PRESENT - uint8_t sd_en = false; - (void) sd_softdevice_is_enabled(&sd_en); - - if ( sd_en ) { - sd_power_usbdetected_enable(true); - sd_power_usbpwrrdy_enable(true); - sd_power_usbremoved_enable(true); - - sd_power_usbregstatus_get(&usb_reg); - }else -#endif - { - // Power module init - const nrfx_power_config_t pwr_cfg = { 0 }; - nrfx_power_init(&pwr_cfg); - - // Register tusb function as USB power handler - const nrfx_power_usbevt_config_t config = { .handler = (nrfx_power_usb_event_handler_t) tusb_hal_nrf_power_event }; - nrfx_power_usbevt_init(&config); - - nrfx_power_usbevt_enable(); - - usb_reg = NRF_POWER->USBREGSTATUS; - } +#include "tusb.h" - if ( usb_reg & POWER_USBREGSTATUS_VBUSDETECT_Msk ) { - tusb_hal_nrf_power_event(NRFX_POWER_USB_EVT_DETECTED); - } - - if ( usb_reg & POWER_USBREGSTATUS_OUTPUTRDY_Msk ) { - tusb_hal_nrf_power_event(NRFX_POWER_USB_EVT_READY); - } +// Serial number as hex characters. This writes directly to the USB +// descriptor. +extern uint16_t usb_serial_number[1 + COMMON_HAL_MCU_PROCESSOR_UID_LENGTH * 2]; +void load_serial_number(void) { // create serial number based on device unique id - extern uint16_t usb_desc_str_serial[1 + 16]; + uint8_t raw_id[COMMON_HAL_MCU_PROCESSOR_UID_LENGTH]; + common_hal_mcu_processor_get_uid(raw_id); + + const char nibble_to_hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'A', 'B', 'C', 'D', 'E', 'F'}; + for (int i = 0; i < COMMON_HAL_MCU_PROCESSOR_UID_LENGTH; i++) { + for (int j = 0; j < 2; j++) { + uint8_t nibble = (raw_id[i] >> (j * 4)) & 0xf; + // Strings are UTF-16-LE encoded. + usb_serial_number[1 + i * 2 + j] = nibble_to_hex[nibble]; + } + } +} - char nibble_to_hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; +bool _usb_enabled = false; - for (int i = 0; i < 2; i++) { - for (int j = 0; j < 8; j++) { - uint8_t nibble = (NRF_FICR->DEVICEID[i] >> j * 4) & 0xf; +bool usb_enabled(void) { + return _usb_enabled; +} - // Invert order since it is LE, +1 for skipping descriptor header - uint8_t const idx = (15 - (i * 8 + j)) + 1; - usb_desc_str_serial[idx] = nibble_to_hex[nibble]; - } - } +void usb_init(void) { + init_usb_hardware(); + load_serial_number(); tusb_init(); + _usb_enabled = true; #if MICROPY_KBD_EXCEPTION // Set Ctrl+C as wanted char, tud_cdc_rx_wanted_cb() callback will be invoked when Ctrl+C is received @@ -105,6 +73,13 @@ void usb_init(void) { #endif } +void usb_background(void) { + if (usb_enabled()) { + tusb_task(); + tud_cdc_write_flush(); + } +} + //--------------------------------------------------------------------+ // tinyusb callbacks //--------------------------------------------------------------------+ @@ -138,10 +113,7 @@ void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) { if ( coding.bit_rate == 1200 ) { - enum { DFU_MAGIC_SERIAL = 0x4e }; - - NRF_POWER->GPREGRET = DFU_MAGIC_SERIAL; - NVIC_SystemReset(); + reset_to_bootloader(); } } } @@ -166,4 +138,3 @@ void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char) } #endif - diff --git a/supervisor/shared/usb/usb_desc.c b/supervisor/shared/usb/usb_desc.c new file mode 100644 index 000000000..5a0de1ffc --- /dev/null +++ b/supervisor/shared/usb/usb_desc.c @@ -0,0 +1,46 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 hathach 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. + */ + +#include "supervisor/shared/usb/usb_desc.h" +#include "shared-module/usb_hid/Device.h" + +#include "genhdr/autogen_usb_descriptor.h" + +// tud_desc_set is required by tinyusb stack +tud_desc_set_t tud_desc_set = +{ + .device = &usb_desc_dev, + .config = &usb_desc_cfg, + .string_arr = (uint8_t const **) string_desc_arr, + .string_count = sizeof(string_desc_arr)/sizeof(string_desc_arr[0]), + + .hid_report = + { + .generic = hid_report_descriptor, + .boot_keyboard = NULL, + .boot_mouse = NULL + } +}; diff --git a/supervisor/shared/usb/usb_desc.h b/supervisor/shared/usb/usb_desc.h new file mode 100644 index 000000000..250147aa6 --- /dev/null +++ b/supervisor/shared/usb/usb_desc.h @@ -0,0 +1,43 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 hathach 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 USB_DESC_H_ +#define USB_DESC_H_ + +#include "lib/tinyusb/src/tusb.h" + +#ifdef __cplusplus + extern "C" { +#endif + +// Descriptors set used by tinyusb stack +extern tud_desc_set_t tud_desc_set; + +#ifdef __cplusplus + } +#endif + +#endif /* USB_DESC_H_ */ diff --git a/ports/nrf/usb/usb_msc_flash.c b/supervisor/shared/usb/usb_msc_flash.c index f78c24145..658aab0d8 100644 --- a/ports/nrf/usb/usb_msc_flash.c +++ b/supervisor/shared/usb/usb_msc_flash.c @@ -25,37 +25,60 @@ */ #include "tusb.h" -#include "internal_flash.h" +// // #include "supervisor/flash.h" // For updating fatfs's cache #include "extmod/vfs.h" #include "extmod/vfs_fat.h" +#include "lib/oofatfs/diskio.h" #include "lib/oofatfs/ff.h" #include "py/mpstate.h" #include "supervisor/shared/autoreload.h" -/*------------------------------------------------------------------*/ -/* MACRO TYPEDEF CONSTANT ENUM - *------------------------------------------------------------------*/ -#define MSC_FLASH_ADDR_END 0xED000 -#define MSC_FLASH_SIZE (256*1024) -#define MSC_FLASH_ADDR_START (MSC_FLASH_ADDR_END-MSC_FLASH_SIZE) #define MSC_FLASH_BLOCK_SIZE 512 -#define FL_PAGE_SZ 4096 +static bool ejected[1]; + +// The root FS is always at the end of the list. +static fs_user_mount_t* get_vfs(int lun) { + // TODO(tannewt): Return the mount which matches the lun where 0 is the end + // and is counted in reverse. + if (lun > 0) { + return NULL; + } + mp_vfs_mount_t* current_mount = MP_STATE_VM(vfs_mount_table); + if (current_mount == NULL) { + return NULL; + } + while (current_mount->next != NULL) { + current_mount = current_mount->next; + } + return current_mount->obj; +} // Callback invoked when received an SCSI command not in built-in list below // - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, MODE_SENSE6, REQUEST_SENSE -// - READ10 and WRITE10 has their own callbacks +// - READ10 and WRITE10 have their own callbacks int32_t tud_msc_scsi_cb (uint8_t lun, const uint8_t scsi_cmd[16], void* buffer, uint16_t bufsize) { const void* response = NULL; - uint16_t resplen = 0; + int32_t resplen = 0; switch ( scsi_cmd[0] ) { case SCSI_CMD_TEST_UNIT_READY: // Command that host uses to check our readiness before sending other commands resplen = 0; + if (lun > 1) { + resplen = -1; + } else { + fs_user_mount_t* current_mount = get_vfs(lun); + if (current_mount == NULL) { + resplen = -1; + } + if (ejected[lun]) { + resplen = -1; + } + } break; case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL: @@ -64,14 +87,28 @@ int32_t tud_msc_scsi_cb (uint8_t lun, const uint8_t scsi_cmd[16], void* buffer, break; case SCSI_CMD_START_STOP_UNIT: + { // Host try to eject/safe remove/poweroff us. We could safely disconnect with disk storage, or go into lower power - /* scsi_start_stop_unit_t const * start_stop = (scsi_start_stop_unit_t const *) scsi_cmd; + const scsi_start_stop_unit_t* start_stop = (const scsi_start_stop_unit_t*) scsi_cmd; // Start bit = 0 : low power mode, if load_eject = 1 : unmount disk storage as well // Start bit = 1 : Ready mode, if load_eject = 1 : mount disk storage - start_stop->start; - start_stop->load_eject; - */ resplen = 0; + if (start_stop->load_eject == 1) { + if (lun > 1) { + resplen = -1; + } else { + fs_user_mount_t* current_mount = get_vfs(lun); + if (current_mount == NULL) { + resplen = -1; + } + if (disk_ioctl(current_mount, CTRL_SYNC, NULL) != RES_OK) { + resplen = -1; + } else { + ejected[lun] = true; + } + } + } + } break; default: @@ -96,6 +133,28 @@ int32_t tud_msc_scsi_cb (uint8_t lun, const uint8_t scsi_cmd[16], void* buffer, return resplen; } +void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size) { + fs_user_mount_t * vfs = get_vfs(lun); + disk_ioctl(vfs, GET_SECTOR_COUNT, block_count); + disk_ioctl(vfs, GET_SECTOR_SIZE, block_size); +} + +bool tud_msc_is_writable_cb(uint8_t lun) { + if (lun > 1) { + return false; + } + + fs_user_mount_t* vfs = get_vfs(lun); + if (vfs == NULL) { + return false; + } + if (vfs->writeblocks[0] == MP_OBJ_NULL || + (vfs->flags & FSUSER_USB_WRITABLE) == 0) { + return false; + } + return true; +} + // Callback invoked when received READ10 command. // Copy disk's data to buffer (up to bufsize) and return number of copied bytes. int32_t tud_msc_read10_cb (uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize) { @@ -104,27 +163,36 @@ int32_t tud_msc_read10_cb (uint8_t lun, uint32_t lba, uint32_t offset, void* buf const uint32_t block_count = bufsize / MSC_FLASH_BLOCK_SIZE; - internal_flash_read_blocks(buffer, lba, block_count); + fs_user_mount_t * vfs = get_vfs(lun); + disk_read(vfs, buffer, lba, block_count); return block_count * MSC_FLASH_BLOCK_SIZE; } // Callback invoked when received WRITE10 command. // Process data in buffer to disk's storage and return number of written bytes -int32_t tud_msc_write10_cb (uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize) { +int32_t tud_msc_write10_cb (uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize) { (void) lun; (void) offset; const uint32_t block_count = bufsize / MSC_FLASH_BLOCK_SIZE; - // bufsize <= CFG_TUD_MSC_BUFSIZE (4096) - internal_flash_write_blocks(buffer, lba, block_count); - - // update fatfs's cache if address matches - fs_user_mount_t* vfs = MP_STATE_VM(vfs_mount_table)->obj; - - if ( (lba <= vfs->fatfs.winsect) && (vfs->fatfs.winsect <= (lba + bufsize / MSC_FLASH_BLOCK_SIZE)) ) { - memcpy(vfs->fatfs.win, buffer + MSC_FLASH_BLOCK_SIZE * (vfs->fatfs.winsect - lba), MSC_FLASH_BLOCK_SIZE); + fs_user_mount_t * vfs = get_vfs(lun); + disk_write(vfs, buffer, lba, block_count); + // Since by getting here we assume the mount is read-only to + // MicroPython let's update the cached FatFs sector if it's the one + // we just wrote. + #if _MAX_SS != _MIN_SS + if (vfs->ssize == MSC_FLASH_BLOCK_SIZE) { + #else + // The compiler can optimize this away. + if (_MAX_SS == FILESYSTEM_BLOCK_SIZE) { + #endif + if (lba == vfs->fatfs.winsect && lba > 0) { + memcpy(vfs->fatfs.win, + buffer + MSC_FLASH_BLOCK_SIZE * (vfs->fatfs.winsect - lba), + MSC_FLASH_BLOCK_SIZE); + } } return block_count * MSC_FLASH_BLOCK_SIZE; @@ -135,9 +203,6 @@ int32_t tud_msc_write10_cb (uint8_t lun, uint32_t lba, uint32_t offset, void* bu void tud_msc_write10_complete_cb (uint8_t lun) { (void) lun; - // flush pending cache when write10 is complete - internal_flash_flush(); - // This write is complete, start the autoreload clock. autoreload_start(); } diff --git a/ports/atmel-samd/external_flash/spi_flash_api.h b/supervisor/spi_flash_api.h index a6df0c459..28cccb1b1 100644 --- a/ports/atmel-samd/external_flash/spi_flash_api.h +++ b/supervisor/spi_flash_api.h @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries LLC * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,13 +23,13 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_ATMEL_SAMD_SPI_FLASH_H -#define MICROPY_INCLUDED_ATMEL_SAMD_SPI_FLASH_H +#ifndef MICROPY_INCLUDED_SUPERVISOR_SPI_FLASH_H +#define MICROPY_INCLUDED_SUPERVISOR_SPI_FLASH_H #include <stdbool.h> #include <stdint.h> -#include "external_flash/devices.h" +#include "supervisor/shared/external_flash/devices.h" // This API is implemented for both normal SPI peripherals and QSPI peripherals. @@ -42,4 +42,4 @@ bool spi_flash_read_data(uint32_t address, uint8_t* data, uint32_t data_length); void spi_flash_init(void); void spi_flash_init_device(const external_flash_device* device); -#endif // MICROPY_INCLUDED_ATMEL_SAMD_SPI_FLASH_H +#endif // MICROPY_INCLUDED_SUPERVISOR_SPI_FLASH_H diff --git a/supervisor/supervisor.mk b/supervisor/supervisor.mk index e516dcb2d..73c76ebb7 100644 --- a/supervisor/supervisor.mk +++ b/supervisor/supervisor.mk @@ -2,22 +2,82 @@ SRC_SUPERVISOR = \ main.c \ supervisor/port.c \ supervisor/shared/autoreload.c \ + supervisor/shared/filesystem.c \ + supervisor/shared/flash.c \ + supervisor/shared/micropython.c \ supervisor/shared/rgb_led_status.c \ supervisor/shared/stack.c \ + supervisor/shared/status_leds.c \ supervisor/shared/translate.c -ifeq ($(wildcard atmel-samd/supervisor/filesystem.c),) - SRC_SUPERVISOR += supervisor/filesystem.c +ifndef $(NO_USB) +NO_USB = $(wildcard supervisor/usb.c) +endif + + +# Choose which flash filesystem impl to use. +# (Right now INTERNAL_FLASH_FILESYSTEM and SPI_FLASH_FILESYSTEM are mutually exclusive. +# But that might not be true in the future.) +ifdef EXTERNAL_FLASH_DEVICES + CFLAGS += -DEXTERNAL_FLASH_DEVICES=$(EXTERNAL_FLASH_DEVICES) \ + -DEXTERNAL_FLASH_DEVICE_COUNT=$(EXTERNAL_FLASH_DEVICE_COUNT) + + SRC_SUPERVISOR += supervisor/shared/external_flash/external_flash.c + ifeq ($(SPI_FLASH_FILESYSTEM),1) + CFLAGS += -DSPI_FLASH_FILESYSTEM + SRC_SUPERVISOR += supervisor/shared/external_flash/spi_flash.c + endif + ifeq ($(QSPI_FLASH_FILESYSTEM),1) + CFLAGS += -DQSPI_FLASH_FILESYSTEM + SRC_SUPERVISOR += supervisor/qspi_flash.c supervisor/shared/external_flash/qspi_flash.c + endif else - SRC_SUPERVISOR += supervisor/stub/filesystem.c + SRC_SUPERVISOR += supervisor/internal_flash.c endif -ifeq ($(wildcard atmel-samd/supervisor/serial.c),) - SRC_SUPERVISOR += supervisor/serial.c +ifeq ($(USB),FALSE) + ifeq ($(wildcard supervisor/serial.c),) + SRC_SUPERVISOR += supervisor/stub/serial.c + else + SRC_SUPERVISOR += supervisor/serial.c + endif else - SRC_SUPERVISOR += supervisor/stub/serial.c + SRC_SUPERVISOR += lib/tinyusb/src/common/tusb_fifo.c \ + lib/tinyusb/src/device/usbd.c \ + lib/tinyusb/src/device/usbd_control.c \ + lib/tinyusb/src/class/msc/msc_device.c \ + lib/tinyusb/src/class/cdc/cdc_device.c \ + lib/tinyusb/src/class/hid/hid_device.c \ + lib/tinyusb/src/tusb.c \ + supervisor/shared/serial.c \ + supervisor/usb.c \ + supervisor/shared/usb/usb_desc.c \ + supervisor/shared/usb/usb.c \ + supervisor/shared/usb/usb_msc_flash.c \ + shared-bindings/usb_hid/__init__.c \ + shared-bindings/usb_hid/Device.c \ + shared-module/usb_hid/__init__.c \ + shared-module/usb_hid/Device.c \ + $(BUILD)/autogen_usb_descriptor.c + CFLAGS += -DUSB_AVAILABLE endif SUPERVISOR_O = $(addprefix $(BUILD)/, $(SRC_SUPERVISOR:.c=.o)) $(BUILD)/supervisor/shared/translate.o: $(HEADER_BUILD)/qstrdefs.generated.h + +$(BUILD)/autogen_usb_descriptor.c $(BUILD)/genhdr/autogen_usb_descriptor.h: autogen_usb_descriptor.intermediate + +.INTERMEDIATE: autogen_usb_descriptor.intermediate + +autogen_usb_descriptor.intermediate: ../../tools/gen_usb_descriptor.py Makefile | $(HEADER_BUILD) + $(STEPECHO) "GEN $@" + $(Q)install -d $(BUILD)/genhdr + $(Q)$(PYTHON3) ../../tools/gen_usb_descriptor.py \ + --manufacturer $(USB_MANUFACTURER)\ + --product $(USB_PRODUCT)\ + --vid $(USB_VID)\ + --pid $(USB_PID)\ + --serial_number_length $(USB_SERIAL_NUMBER_LENGTH)\ + --output_c_file $(BUILD)/autogen_usb_descriptor.c\ + --output_h_file $(BUILD)/genhdr/autogen_usb_descriptor.h diff --git a/supervisor/usb.h b/supervisor/usb.h new file mode 100644 index 000000000..c87540d40 --- /dev/null +++ b/supervisor/usb.h @@ -0,0 +1,44 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 hathach 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_SUPERVISOR_USB_H +#define MICROPY_INCLUDED_SUPERVISOR_USB_H + +#include <stdbool.h> + +// Ports must call this as frequently as they can in order to keep the USB connection +// alive and responsive. +void usb_background(void); + +// Only inits the USB peripheral clocks and pins. The peripheral will be initialized by +// TinyUSB. +void init_usb_hardware(void); + +// Shared implementation. +bool usb_enabled(void); +void usb_init(void); + +#endif // MICROPY_INCLUDED_SUPERVISOR_USB_H diff --git a/tools/build_adafruit_bins.sh b/tools/build_adafruit_bins.sh index 595d5ba5d..4c672c6de 100755 --- a/tools/build_adafruit_bins.sh +++ b/tools/build_adafruit_bins.sh @@ -6,7 +6,9 @@ rm -rf ports/nrf/build* # Alphabetical. HW_BOARDS="\ +arduino_mkr1300 \ arduino_zero \ +catwan_usbstick \ circuitplayground_express \ circuitplayground_express_crickit \ feather_huzzah \ @@ -25,8 +27,10 @@ grandcentral_m4_express \ hallowing_m0_express \ itsybitsy_m0_express \ itsybitsy_m4_express \ +makerdiary_nrf52840_mdk \ metro_m0_express \ metro_m4_express \ +meowmeow \ pca10056 \ pca10059 \ pirkey_m0 \ @@ -66,8 +70,9 @@ for board in $boards; do for language_file in $(ls locale/*.po); do language=$(basename -s .po $language_file) echo "Building $board for $language" + # There is a bug in the Huzzah Makefile that causes it to fail occasionally with -j > 1. if [[ $board == "feather_huzzah" ]]; then - make $PARALLEL -C ports/esp8266 TRANSLATION=$language BOARD=$board + make -C ports/esp8266 TRANSLATION=$language BOARD=$board (( exit_status = exit_status || $? )) temp_filename=ports/esp8266/build/firmware-combined.bin extension=bin @@ -81,6 +86,11 @@ for board in $boards; do (( exit_status = exit_status || $? )) temp_filename=ports/nrf/build-$board-s140/firmware.uf2 extension=uf2 + elif [[ $board == "makerdiary_nrf52840_mdk" ]]; then + make $PARALLEL -C ports/nrf TRANSLATION=$language BOARD=$board SD=s140 + (( exit_status = exit_status || $? )) + temp_filename=ports/nrf/build-$board-s140/firmware.hex + extension=hex else time make $PARALLEL -C ports/atmel-samd TRANSLATION=$language BOARD=$board (( exit_status = exit_status || $? )) diff --git a/ports/atmel-samd/tools/gen_usb_descriptor.py b/tools/gen_usb_descriptor.py index efa8124bf..2cb06ec2f 100644 --- a/ports/atmel-samd/tools/gen_usb_descriptor.py +++ b/tools/gen_usb_descriptor.py @@ -3,10 +3,9 @@ import argparse import os import sys -# path hacking sys.path.append("../../tools/usb_descriptor") -from adafruit_usb_descriptor import cdc, hid, msc, standard, util +from adafruit_usb_descriptor import audio, audio10, cdc, hid, midi, msc, standard, util import hid_report_descriptors parser = argparse.ArgumentParser(description='Generate USB descriptors.') @@ -28,16 +27,21 @@ args = parser.parse_args() class StringIndex: """Assign a monotonically increasing index to each unique string. Start with 0.""" string_to_index = {} + index_to_variable = {} strings = [] @classmethod - def index(cls, string): + def index(cls, string, *, variable_name = None): if string in cls.string_to_index: - return cls.string_to_index[string] + idx = cls.string_to_index[string] + if not cls.index_to_variable[idx]: + cls.index_to_variable[idx] = variable_name + return idx else: idx = len(cls.strings) cls.string_to_index[string] = idx cls.strings.append(string) + cls.index_to_variable[idx] = variable_name return idx @classmethod @@ -47,9 +51,9 @@ class StringIndex: # langid must be the 0th string descriptor -LANGID_INDEX = StringIndex.index("\u0409") +LANGID_INDEX = StringIndex.index("\u0409", variable_name="language_id") assert LANGID_INDEX == 0 -SERIAL_NUMBER_INDEX = StringIndex.index("S" * args.serial_number_length) +SERIAL_NUMBER_INDEX = StringIndex.index("S" * args.serial_number_length, variable_name="usb_serial_number") device = standard.DeviceDescriptor( description="top", @@ -155,12 +159,6 @@ hid_endpoint_in_descriptor = standard.EndpointDescriptor( bmAttributes=standard.EndpointDescriptor.TYPE_INTERRUPT, bInterval=10) -hid_endpoint_out_descriptor = standard.EndpointDescriptor( - description="HID out", - bEndpointAddress=0x0 | standard.EndpointDescriptor.DIRECTION_OUT, - bmAttributes=standard.EndpointDescriptor.TYPE_INTERRUPT, - bInterval=10) - hid_interfaces = [ standard.InterfaceDescriptor( description="HID Multiple Devices", @@ -173,11 +171,71 @@ hid_interfaces = [ description="HID", wDescriptorLength=len(bytes(combined_hid_report_descriptor))), hid_endpoint_in_descriptor, - hid_endpoint_out_descriptor, ] ), ] +# Audio! +midi_in_jack = midi.InJackDescriptor( + description="MIDI PC <- CircuitPython internals", + bJackType=midi.JACK_TYPE_EMBEDDED, + iJack=0) +midi_out_jack = midi.OutJackDescriptor( + description="MIDI PC -> CircuitPython internals", + bJackType=midi.JACK_TYPE_EMBEDDED, + iJack=0) +audio_midi_interface = standard.InterfaceDescriptor( + description="All the audio", + bInterfaceClass=audio.AUDIO_CLASS_DEVICE, + bInterfaceSubClass=audio.AUDIO_SUBCLASS_MIDI_STREAMING, + bInterfaceProtocol=audio.AUDIO_PROTOCOL_V1, + iInterface=StringIndex.index("CircuitPython MIDI"), + subdescriptors=[ + midi.Header( + jacks_and_elements=[ + midi_in_jack, + midi.InJackDescriptor( + description="MIDI data in from user code.", + bJackType=midi.JACK_TYPE_EXTERNAL, iJack=0), + midi_out_jack, + midi.OutJackDescriptor( + description="MIDI data out to user code.", + bJackType=midi.JACK_TYPE_EXTERNAL, iJack=0), + ] + ), + standard.EndpointDescriptor( + description="MIDI data out", + bEndpointAddress=0x0 | standard.EndpointDescriptor.DIRECTION_OUT, + bmAttributes=standard.EndpointDescriptor.TYPE_BULK), + midi.DataEndpointDescriptor(baAssocJack=[midi_out_jack]), + standard.EndpointDescriptor( + description="MIDI data in", + bEndpointAddress=0x0 | standard.EndpointDescriptor.DIRECTION_IN, + bmAttributes=standard.EndpointDescriptor.TYPE_BULK), + midi.DataEndpointDescriptor(baAssocJack=[midi_in_jack]), + ]) + +cs_ac_interface = audio10.AudioControlInterface( + description="Empty audio control", + audio_streaming_interfaces = [], + midi_streaming_interfaces = [ + audio_midi_interface + ] + ) + +audio_control_interface = standard.InterfaceDescriptor( + description="All the audio", + bInterfaceClass=audio.AUDIO_CLASS_DEVICE, + bInterfaceSubClass=audio.AUDIO_SUBCLASS_CONTROL, + bInterfaceProtocol=audio.AUDIO_PROTOCOL_V1, + iInterface=StringIndex.index("CircuitPython Audio"), + subdescriptors=[ + cs_ac_interface, + ]) + +# Audio streaming interfaces must occur before MIDI ones. +# audio_interfaces = [audio_control_interface] + cs_ac_interface.audio_streaming_interfaces + cs_ac_interface.midi_streaming_interfaces + # This will renumber the endpoints to make them unique across descriptors, # and renumber the interfaces in order. But we still need to fix up certain # interface cross-references. @@ -194,23 +252,25 @@ cdc_iad = standard.InterfaceAssociationDescriptor( description="CDC IAD", bFirstInterface=cdc_comm_interface.bInterfaceNumber, bInterfaceCount=len(cdc_interfaces), - bFunctionClass=0x2, # Communications Device Class - bFunctionSubClass=0x2, # Abstract control model - bFunctionProtocol=0x1) + bFunctionClass=cdc.CDC_CLASS_COMM, # Communications Device Class + bFunctionSubClass=cdc.CDC_SUBCLASS_ACM, # Abstract control model + bFunctionProtocol=cdc.CDC_PROTOCOL_NONE) + +# audio_iad = standard.InterfaceAssociationDescriptor( +# description="Audio IAD", +# bFirstInterface=audio_control_interface.bInterfaceNumber, +# bInterfaceCount=len(audio_interfaces), +# bFunctionClass=audio.AUDIO_CLASS_DEVICE, +# bFunctionSubClass=audio.AUDIO_SUBCLASS_UNKNOWN, +# bFunctionProtocol=audio.AUDIO_PROTOCOL_V1) -configuration = standard.ConfigurationDescriptor( - description="Composite configuration", - wTotalLength=(standard.ConfigurationDescriptor.bLength + - cdc_iad.bLength + - sum([len(bytes(x)) for x in interfaces])), - bNumInterfaces=len(interfaces)) descriptor_list = [] -descriptor_list.append(device) -descriptor_list.append(configuration) descriptor_list.append(cdc_iad) +# descriptor_list.append(audio_iad) descriptor_list.extend(cdc_interfaces) descriptor_list.extend(msc_interfaces) +# descriptor_list.append(audio_control_interface) # Put the CDC IAD just before the CDC interfaces. # There appears to be a bug in the Windows composite USB driver that requests the # HID report descriptor with the wrong interface number if the HID interface is not given @@ -219,9 +279,15 @@ descriptor_list.extend(msc_interfaces) # there for backwards compatibility. descriptor_list.extend(hid_interfaces) +configuration = standard.ConfigurationDescriptor( + description="Composite configuration", + wTotalLength=(standard.ConfigurationDescriptor.bLength + + sum([len(bytes(x)) for x in descriptor_list])), + bNumInterfaces=len(interfaces)) +descriptor_list.insert(0, configuration) + string_descriptors = [standard.StringDescriptor(string) for string in StringIndex.strings_in_order()] serial_number_descriptor = string_descriptors[SERIAL_NUMBER_INDEX] -descriptor_list.extend(string_descriptors) c_file = args.output_c_file h_file = args.output_h_file @@ -232,17 +298,29 @@ c_file.write("""\ #include "{H_FILE_NAME}" -#include "usb/device/usbdc.h" - """.format(H_FILE_NAME=h_file.name)) c_file.write("""\ -uint8_t usb_descriptors[] = { +// {DESCRIPTION} : {CLASS} +""".format(DESCRIPTION=device.description, + CLASS=device.__class__)) + +c_file.write("""\ +const uint8_t usb_desc_dev[] = { +""") +for b in bytes(device): + c_file.write("0x{:02x}, ".format(b)) + +c_file.write("""\ +}; +""") + +c_file.write("""\ +const uint8_t usb_desc_cfg[] = { """) # Write out all the regular descriptors as one long array (that's how ASF4 does it). descriptor_length = 0 -serial_number_offset = None for descriptor in descriptor_list: c_file.write("""\ // {DESCRIPTION} : {CLASS} @@ -250,91 +328,140 @@ for descriptor in descriptor_list: CLASS=descriptor.__class__)) b = bytes(descriptor) + notes = descriptor.notes() i = 0 - if descriptor == serial_number_descriptor: - # Add two for bLength and bDescriptorType. - serial_number_offset = descriptor_length + 2 - # This prints each subdescriptor on a separate line. + n = 0 while i < len(b): length = b[i] for j in range(length): c_file.write("0x{:02x}, ".format(b[i + j])) + c_file.write("// " + notes[n]) + n += 1 c_file.write("\n") i += length - descriptor_length += length + descriptor_length += len(b) +c_file.write("""\ +}; +""") + +pointers_to_strings = [] + +for idx, descriptor in enumerate(string_descriptors): + c_file.write("""\ +// {DESCRIPTION} : {CLASS} +""".format(DESCRIPTION=descriptor.description, + CLASS=descriptor.__class__)) + + b = bytes(descriptor) + notes = descriptor.notes() + i = 0 + + # This prints each subdescriptor on a separate line. + variable_name = StringIndex.index_to_variable[idx] + if not variable_name: + variable_name = "string_descriptor{}".format(idx) + + const = "const " + if variable_name == "usb_serial_number": + const = "" + c_file.write("""\ +{const}uint16_t {NAME}[] = {{ +""".format(const=const, NAME=variable_name)) + pointers_to_strings.append("{name}".format(name=variable_name)) + n = 0 + while i < len(b): + length = b[i] + for j in range(length // 2): + c_file.write("0x{:04x}, ".format(b[i + 2*j + 1] << 8 | b[i + 2*j])) + n += 1 + c_file.write("\n") + i += length + c_file.write("""\ +}; +""") c_file.write("""\ +// array of pointer to string descriptors +uint16_t const * const string_desc_arr [] = +{ +""") +c_file.write(""",\ + +""".join(pointers_to_strings)) + +c_file.write(""" }; """) +c_file.write("\n"); + +hid_descriptor_length = len(bytes(combined_hid_report_descriptor)) + # Now we values we need for the .h file. h_file.write("""\ #ifndef MICROPY_INCLUDED_AUTOGEN_USB_DESCRIPTOR_H #define MICROPY_INCLUDED_AUTOGEN_USB_DESCRIPTOR_H -#define SERIAL_NUMBER_OFFSET {SERIAL_NUMBER_OFFSET} -#define SERIAL_NUMBER_LENGTH {SERIAL_NUMBER_LENGTH} -uint8_t* serial_number; +#include <stdint.h> + +const uint8_t usb_desc_dev[{device_length}]; +// Make sure the control buffer is big enough to fit the descriptor. +#define CFG_TUD_ENUM_BUFFER_SIZE {max_configuration_length} +const uint8_t usb_desc_cfg[{configuration_length}]; +uint16_t usb_serial_number[{serial_number_length}]; +uint16_t const * const string_desc_arr [{string_descriptor_length}]; + +const uint8_t hid_report_descriptor[{HID_REPORT_DESCRIPTOR_LENGTH}]; + +// Vendor name included in Inquiry response, max 8 bytes +#define CFG_TUD_MSC_VENDOR "{msc_vendor}" -uint8_t hid_report_descriptor[{HID_REPORT_DESCRIPTOR_LENGTH}]; -#define USB_HID_ENDPOINT_IN {HID_ENDPOINT_IN_ADDRESS} -#define USB_HID_ENDPOINT_OUT {HID_ENDPOINT_OUT_ADDRESS} +// Product name included in Inquiry response, max 16 bytes +#define CFG_TUD_MSC_PRODUCT "{msc_product}" """ -.format(SERIAL_NUMBER_OFFSET=serial_number_offset, - SERIAL_NUMBER_LENGTH=args.serial_number_length, +.format(serial_number_length=len(bytes(serial_number_descriptor)) // 2, + device_length=len(bytes(device)), + configuration_length=descriptor_length, + max_configuration_length=max(hid_descriptor_length, descriptor_length), + string_descriptor_length=len(pointers_to_strings), HID_REPORT_DESCRIPTOR_LENGTH=len(bytes(combined_hid_report_descriptor)), - HID_ENDPOINT_IN_ADDRESS=hex(hid_endpoint_in_descriptor.bEndpointAddress), - HID_ENDPOINT_OUT_ADDRESS=hex(hid_endpoint_out_descriptor.bEndpointAddress))) - -# Write out #define's that declare which endpoints are in use. -# These provide information for declaring cache sizes and perhaps other things at compile time -for interface in interfaces: - for subdescriptor in interface.subdescriptors: - if isinstance(subdescriptor, standard.EndpointDescriptor): - endpoint_num = subdescriptor.bEndpointAddress & standard.EndpointDescriptor.NUMBER_MASK - endpoint_in = ((subdescriptor.bEndpointAddress & standard.EndpointDescriptor.DIRECTION_MASK) == - standard.EndpointDescriptor.DIRECTION_IN) - h_file.write("""\ -#define USB_ENDPOINT_{NUMBER}_{DIRECTION}_USED 1 -""".format(NUMBER=endpoint_num, - DIRECTION="IN" if endpoint_in else "OUT")) - -h_file.write("\n") + msc_vendor=args.manufacturer[:8], + msc_product=args.product[:16])) # #define the report ID's used in the combined HID descriptor for name, id in hid_report_ids_dict.items(): h_file.write("""\ -#define USB_HID_REPORT_ID_{NAME} {ID} -""".format(NAME=name, - ID = id)) +#define USB_HID_REPORT_ID_{name} {id} +""".format(name=name, + id=id)) h_file.write("\n") # #define the report sizes used in the combined HID descriptor for name, length in hid_report_lengths_dict.items(): h_file.write("""\ -#define USB_HID_REPORT_LENGTH_{NAME} {LENGTH} -""".format(NAME=name, - LENGTH=length)) +#define USB_HID_REPORT_LENGTH_{name} {length} +""".format(name=name, + length=length)) h_file.write("\n") h_file.write("""\ -#define USB_HID_NUM_DEVICES {NUM_DEVICES} -#define USB_HID_MAX_REPORT_LENGTH {MAX_LENGTH} -""".format(NUM_DEVICES=len(hid_report_lengths_dict), - MAX_LENGTH=hid_max_report_length)) +#define USB_HID_NUM_DEVICES {num_devices} +#define USB_HID_MAX_REPORT_LENGTH {max_length} +""".format(num_devices=len(hid_report_lengths_dict), + max_length=hid_max_report_length)) # Write out the report descriptor and info c_file.write("""\ -uint8_t hid_report_descriptor[{HID_DESCRIPTOR_LENGTH}] = {{ -""".format(HID_DESCRIPTOR_LENGTH=len(bytes(combined_hid_report_descriptor)))) +const uint8_t hid_report_descriptor[{HID_DESCRIPTOR_LENGTH}] = {{ +""".format(HID_DESCRIPTOR_LENGTH=hid_descriptor_length)) for b in bytes(combined_hid_report_descriptor): c_file.write("0x{:02x}, ".format(b)) @@ -342,12 +469,6 @@ c_file.write(""" }; """) -c_file.write("""\ - -struct usbd_descriptors descriptor_bounds = {{usb_descriptors, usb_descriptors + sizeof(usb_descriptors)}}; -uint8_t* serial_number = usb_descriptors + {SERIAL_NUMBER_OFFSET}; -""".format(SERIAL_NUMBER_OFFSET=serial_number_offset)) - h_file.write("""\ #endif // MICROPY_INCLUDED_AUTOGEN_USB_DESCRIPTOR_H """) diff --git a/ports/atmel-samd/tools/hid_report_descriptors.py b/tools/hid_report_descriptors.py index f3b28ebcf..f3b28ebcf 100644 --- a/ports/atmel-samd/tools/hid_report_descriptors.py +++ b/tools/hid_report_descriptors.py diff --git a/tools/mpy-tool.py b/tools/mpy-tool.py index 7deb76a8d..5ce24061b 100755 --- a/tools/mpy-tool.py +++ b/tools/mpy-tool.py @@ -78,6 +78,18 @@ MP_BC_LOAD_GLOBAL = 0x1d MP_BC_LOAD_ATTR = 0x1e MP_BC_STORE_ATTR = 0x26 +# load opcode names +opcode_names = {} +with open("../../py/bc0.h") as f: + for line in f.readlines(): + if line.startswith("#define"): + s = line.split(maxsplit=3) + if len(s) < 3: + continue + _, name, value = s[:3] + opcode = int(value.strip("()"), 0) + opcode_names[opcode] = name + def make_opcode_format(): def OC4(a, b, c, d): return a | (b << 2) | (c << 4) | (d << 6) @@ -252,35 +264,50 @@ class RawCode: i += 1 RawCode.escaped_names.add(self.escaped_name) + sizes = {"bytecode": 0, "strings": 0, "raw_code_overhead": 0, "const_table_overhead": 0, "string_overhead": 0, "number_overhead": 0} # emit children first for rc in self.raw_codes: - rc.freeze(self.escaped_name + '_') + subsize = rc.freeze(self.escaped_name + '_') + for k in sizes: + sizes[k] += subsize[k] + # generate bytecode data print() print('// frozen bytecode for file %s, scope %s%s' % (self.source_file.str, parent_name, self.simple_name.str)) + print("// bytecode size", len(self.bytecode)) print('STATIC ', end='') if not config.MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE: print('const ', end='') print('byte bytecode_data_%s[%u] = {' % (self.escaped_name, len(self.bytecode))) + sizes["bytecode"] += len(self.bytecode) print(' ', end='') for i in range(self.ip2): print(' 0x%02x,' % self.bytecode[i], end='') print() + print(" // simple name") print(' ', self.simple_name.qstr_id, '& 0xff,', self.simple_name.qstr_id, '>> 8,') + print(" // source file") print(' ', self.source_file.qstr_id, '& 0xff,', self.source_file.qstr_id, '>> 8,') + print(" // code info") print(' ', end='') for i in range(self.ip2 + 4, self.ip): print(' 0x%02x,' % self.bytecode[i], end='') print() + print(" // bytecode") ip = self.ip while ip < len(self.bytecode): f, sz = mp_opcode_format(self.bytecode, ip) + opcode = self.bytecode[ip] + if opcode in opcode_names: + opcode = opcode_names[opcode] + else: + opcode = '0x%02x' % opcode if f == 1: qst = self._unpack_qstr(ip + 1).qstr_id - print(' ', '0x%02x,' % self.bytecode[ip], qst, '& 0xff,', qst, '>> 8,') + print(' {}, {} & 0xff, {} >> 8,'.format(opcode, qst, qst)) else: - print(' ', ''.join('0x%02x, ' % self.bytecode[ip + i] for i in range(sz))) + print(' {},{}'.format(opcode, ''.join(' 0x%02x,' % self.bytecode[ip + i] for i in range(1, sz)))) ip += sz print('};') @@ -295,9 +322,12 @@ class RawCode: obj_type = 'mp_type_str' else: obj_type = 'mp_type_bytes' - print('STATIC const mp_obj_str_t %s = {{&%s}, %u, %u, (const byte*)"%s"};' + print('STATIC const mp_obj_str_t %s = {{&%s}, %u, %u, (const byte*)"%s"}; // %s' % (obj_name, obj_type, qstrutil.compute_hash(obj, config.MICROPY_QSTR_BYTES_IN_HASH), - len(obj), ''.join(('\\x%02x' % b) for b in obj))) + len(obj), ''.join(('\\x%02x' % b) for b in obj), obj)) + sizes["strings"] += len(obj) + sizes["string_overhead"] += 16 + elif is_int_type(obj): if config.MICROPY_LONGINT_IMPL == config.MICROPY_LONGINT_IMPL_NONE: # TODO check if we can actually fit this long-int into a small-int @@ -321,14 +351,17 @@ class RawCode: print('STATIC const mp_obj_int_t %s = {{&mp_type_int}, ' '{.neg=%u, .fixed_dig=1, .alloc=%u, .len=%u, .dig=(uint%u_t[]){%s}}};' % (obj_name, neg, ndigs, ndigs, bits_per_dig, digs)) + sizes["number_overhead"] += 16 elif type(obj) is float: print('#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_A || MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_B') print('STATIC const mp_obj_float_t %s = {{&mp_type_float}, %.16g};' % (obj_name, obj)) print('#endif') + sizes["number_overhead"] += 8 elif type(obj) is complex: print('STATIC const mp_obj_complex_t %s = {{&mp_type_complex}, %.16g, %.16g};' % (obj_name, obj.real, obj.imag)) + sizes["number_overhead"] += 12 else: raise FreezeError(self, 'freezing of object %r is not implemented' % (obj,)) @@ -338,8 +371,10 @@ class RawCode: print('STATIC const mp_rom_obj_t const_table_data_%s[%u] = {' % (self.escaped_name, const_table_len)) for qst in self.qstrs: + sizes["const_table_overhead"] += 4 print(' MP_ROM_QSTR(%s),' % global_qstrs[qst].qstr_id) for i in range(len(self.objs)): + sizes["const_table_overhead"] += 4 if type(self.objs[i]) is float: print('#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_A || MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_B') print(' MP_ROM_PTR(&const_obj_%s_%u),' % (self.escaped_name, i)) @@ -353,6 +388,7 @@ class RawCode: else: print(' MP_ROM_PTR(&const_obj_%s_%u),' % (self.escaped_name, i)) for rc in self.raw_codes: + sizes["const_table_overhead"] += 4 print(' MP_ROM_PTR(&raw_code_%s),' % rc.escaped_name) print('};') @@ -376,6 +412,9 @@ class RawCode: print(' #endif') print(' },') print('};') + sizes["raw_code_overhead"] += 16 + + return sizes def read_uint(f): i = 0 @@ -467,6 +506,7 @@ def freeze_mpy(base_qstrs, raw_codes): new[q.qstr_esc] = (len(new), q.qstr_esc, q.str) new = sorted(new.values(), key=lambda x: x[0]) + print('#include "py/bc0.h"') print('#include "py/mpconfig.h"') print('#include "py/objint.h"') print('#include "py/objstr.h"') @@ -523,27 +563,45 @@ def freeze_mpy(base_qstrs, raw_codes): print(' %u, // allocated entries' % len(new)) print(' %u, // used entries' % len(new)) print(' {') + qstr_size = {"metadata": 0, "data": 0} for _, _, qstr in new: + qstr_size["metadata"] += config.MICROPY_QSTR_BYTES_IN_LEN + config.MICROPY_QSTR_BYTES_IN_HASH + qstr_size["data"] += len(qstr) print(' %s,' % qstrutil.make_bytes(config.MICROPY_QSTR_BYTES_IN_LEN, config.MICROPY_QSTR_BYTES_IN_HASH, qstr)) print(' },') print('};') + sizes = {} for rc in raw_codes: - rc.freeze(rc.source_file.str.replace('/', '_')[:-3] + '_') + sizes[rc.source_file.str] = rc.freeze(rc.source_file.str.replace('/', '_')[:-3] + '_') print() print('const char mp_frozen_mpy_names[] = {') + qstr_size["filenames"] = 1 for rc in raw_codes: module_name = rc.source_file.str print('"%s\\0"' % module_name) + qstr_size["filenames"] += len(module_name) + 1 print('"\\0"};') print('const mp_raw_code_t *const mp_frozen_mpy_content[] = {') for rc in raw_codes: print(' &raw_code_%s,' % rc.escaped_name) + size = sizes[rc.source_file.str] + print(' // Total size:', sum(size.values())) + for k in size: + print(" // {} {}".format(k, size[k])) print('};') + print() + print('// Total size:', sum([sum(x.values()) for x in sizes.values()]) + sum(qstr_size.values())) + for k in size: + total = sum([x[k] for x in sizes.values()]) + print("// {} {}".format(k, total)) + for k in qstr_size: + print("// qstr {} {}".format(k, qstr_size[k])) + def main(): import argparse cmd_parser = argparse.ArgumentParser(description='A tool to work with MicroPython .mpy files.') diff --git a/tools/preprocess_frozen_modules.py b/tools/preprocess_frozen_modules.py index d157deeee..bb6959f0d 100755 --- a/tools/preprocess_frozen_modules.py +++ b/tools/preprocess_frozen_modules.py @@ -33,7 +33,7 @@ def copy_and_process(in_dir, out_dir): for root, subdirs, files in os.walk(in_dir): # Skip library examples directories. - if Path(root).name in ['examples', 'docs']: + if Path(root).name in ['examples', 'docs', 'tests']: continue for file in files: diff --git a/tools/usb_descriptor b/tools/usb_descriptor -Subproject 2507847031a0395465956539253cbfa27f87511 +Subproject 57bf602dac9cba8c4226f764c286cbc60103d67 |
