diff --git a/.github/workflows/macOS.yml b/.github/workflows/macOS.yml index ca3308ed..cd66c608 100644 --- a/.github/workflows/macOS.yml +++ b/.github/workflows/macOS.yml @@ -1,10 +1,48 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + name: macOS build on: push: pull_request: jobs: - build: + + build_macos: + if: ${{ github.event_name != 'pull_request' || github.repository != github.event.pull_request.head.repo.full_name }} + runs-on: macos-latest + + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - name: Install Dependencies + run: | + brew install --force ninja + brew install --force sdl2 + brew install --force libffi + git submodule update --init -- lib/pycparser + git submodule update --init --jobs 4 -- lib/micropython + git submodule update --init --jobs 4 -- lib/lvgl + + # - name: Build STM32 port + # run: python3 make.py stm32 submodules clean mpy_cross BOARD=STM32H7B3I_DK DISPLAY=rgb_display INDEV=gt911 + + # - name: Build Raspberry Pi PICO port + # run: python3 make.py rp2 submodules clean mpy_cross BOARD=RPI_PICO DISPLAY=rgb_display INDEV=gt911 + + - name: Build macOS port + run: python3 make.py macOS DISPLAY=sdl_display INDEV=sdl_pointer + + - uses: actions/upload-artifact@v4 + with: + name: lvgl_micropy_macos + path: build/lvgl_micropy_macos + if-no-files-found: ignore + + build_esp32: if: ${{ github.event_name != 'pull_request' || github.repository != github.event.pull_request.head.repo.full_name }} runs-on: macos-latest @@ -20,8 +58,6 @@ jobs: - name: Install Dependencies run: | - brew install --force ninja - brew install --force sdl2 git submodule update --init -- lib/pycparser git submodule update --init --jobs 4 -- lib/micropython git submodule update --init --jobs 4 -- lib/lvgl @@ -51,15 +87,6 @@ jobs: # - name: Build Raspberry Pi PICO port # run: python3 make.py rp2 submodules clean mpy_cross BOARD=RPI_PICO DISPLAY=rgb_display INDEV=gt911 - - name: Get build datetime - id: datetime - uses: Kaven-Universe/github-action-current-date-time@v1 - with: - format: "YYYY_MM_DD HH_mm_ss_SSS" - - - name: Build macOS port - run: python3 make.py macOS DISPLAY=sdl_display INDEV=sdl_pointer - - name: Setup ESP-IDF run: | export "IDF_PATH=${GITHUB_WORKSPACE}/lib/esp-idf" @@ -67,10 +94,3 @@ jobs: - name: Build ESP32 port run: python3 make.py esp32 BOARD=ESP32_GENERIC_S3 BOARD_VARIANT=SPIRAM_OCT DISPLAY=rgb_display INDEV=gt911 - - - - uses: actions/upload-artifact@v4 - with: - name: lvgl_micropy_macos-${{ steps.datetime.outputs.month }}.${{ steps.datetime.outputs.day }}.${{ steps.datetime.outputs.year }}-${{ steps.datetime.outputs.hours }}_${{ steps.datetime.outputs.minutes }}_${{ steps.datetime.outputs.seconds }} - path: build/lvgl_micropy_macos - if-no-files-found: ignore diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6601d4f4..30f710a8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + name: Release on: diff --git a/.github/workflows/unix.yml b/.github/workflows/unix.yml index ae514034..4738874d 100644 --- a/.github/workflows/unix.yml +++ b/.github/workflows/unix.yml @@ -1,37 +1,28 @@ -name: Unix build - +# Copyright (c) 2024 - 2025 Kevin G. Schlosser +name: Unix build on: push: pull_request: jobs: - build: + build_esp32: if: ${{ github.event_name != 'pull_request' || github.repository != github.event.pull_request.head.repo.full_name }} - runs-on: ubuntu-latest - + runs-on: self-hosted steps: - uses: actions/checkout@v4 - - uses: carlosperate/arm-none-eabi-gcc-action@v1.8.1 - with: - release: 'latest' # 9-2020-q2 The arm-none-eabi-gcc release to use. - - uses: actions/setup-python@v5 with: - python-version: '3.10' + python-version: '3.11' - name: Install Deps + # sudo apt-get update && sudo apt-get install --assume-yes --allow-downgrades --allow-remove-essential --allow-change-held-packages build-essential pkg-config cmake ninja-build ccache run: | - sudo apt-get update && sudo apt-get install --assume-yes --allow-downgrades --allow-remove-essential --allow-change-held-packages build-essential pkg-config cmake ninja-build libffi-dev gnome-desktop-testing libasound2-dev libpulse-dev libaudio-dev libjack-dev libsndio-dev libx11-dev libxext-dev libxrandr-dev libxcursor-dev libxfixes-dev libxi-dev libxss-dev libxkbcommon-dev libdrm-dev libgbm-dev libgl1-mesa-dev libgles2-mesa-dev libegl1-mesa-dev libdbus-1-dev libibus-1.0-dev libudev-dev fcitx-libs-dev libpipewire-0.3-dev libwayland-dev libdecor-0-dev ccache - git submodule update --init -- lib/pycparser - git submodule update --init --jobs 4 -- lib/micropython - git submodule update --init --jobs 4 -- lib/lvgl - git submodule update --init --jobs 4 -- lib/SDL - cd lib/SDL - git checkout release-2.30.2 - cd ../.. + git submodule update --init --depth 1 -- lib/pycparser + git submodule update --init --depth 1 --jobs 4 -- lib/micropython + git submodule update --init --depth 1 --jobs 4 -- lib/lvgl - name: Cached Deps id: cache-deps @@ -45,9 +36,9 @@ jobs: - name: Get Build Deps if: steps.cache-deps.outputs.cache-hit != 'true' run: | - git submodule update --init --jobs 4 -- lib/esp-idf + git submodule update --init --depth 1 --jobs 4 -- lib/esp-idf cd lib/esp-idf - git submodule update --init --jobs 4 -- components/bt/host/nimble/nimble components/esp_wifi components/esptool_py/esptool components/lwip/lwip components/mbedtls/mbedtls components/bt/controller/lib_esp32 components/bt/controller/lib_esp32c3_family + git submodule update --init --depth 1 --jobs 4 -- components/bt/host/nimble/nimble components/esp_wifi components/esptool_py/esptool components/lwip/lwip components/mbedtls/mbedtls components/bt/controller/lib_esp32 components/bt/controller/lib_esp32c3_family cd ../.. export "IDF_PATH=${GITHUB_WORKSPACE}/lib/esp-idf" ./lib/esp-idf/install.sh all @@ -57,26 +48,89 @@ jobs: export "IDF_PATH=${GITHUB_WORKSPACE}/lib/esp-idf" . ./lib/esp-idf/export.sh - - name: Build ESP32 port - run: python3 make.py esp32 BOARD=ESP32_GENERIC_S3 BOARD_VARIANT=SPIRAM_OCT DISPLAY=rgb_display INDEV=gt911 --ccache + - name: Build ESP32_GENERIC_S3 4 + run: python3 make.py esp32 BOARD=ESP32_GENERIC_S3 DISPLAY=all INDEV=all EXPANDER=all --ccache --no-scrub + + - name: Build ESP32_GENERIC_S3 SPIRAM_OCT 4 + run: python3 make.py esp32 BOARD=ESP32_GENERIC_S3 BOARD_VARIANT=SPIRAM_OCT DISPLAY=all INDEV=all EXPANDER=all --ccache --no-scrub + + - name: Build ESP32_GENERIC_S3 OCT RAM 8 + run: python3 make.py esp32 BOARD=ESP32_GENERIC_S3 BOARD_VARIANT=SPIRAM_OCT --flash-size=8 DISPLAY=all INDEV=all EXPANDER=all --ccache --no-scrub + + - name: Build ESP32_GENERIC_S3 OCT RAM/FLASH 8 + run: python3 make.py esp32 BOARD=ESP32_GENERIC_S3 BOARD_VARIANT=SPIRAM_OCT --flash-size=8 --octal-flash DISPLAY=all INDEV=all EXPANDER=all --ccache --no-scrub + + - name: Build ESP32_GENERIC_S3 OCT RAM/FLASH 16 + run: python3 make.py esp32 BOARD=ESP32_GENERIC_S3 BOARD_VARIANT=SPIRAM_OCT --flash-size=16 --octal-flash DISPLAY=all INDEV=all EXPANDER=all --ccache --no-scrub + + - name: Build ESP32_GENERIC_S2 4 + run: python3 make.py esp32 BOARD=ESP32_GENERIC_S2 DISPLAY=all INDEV=all EXPANDER=all --ccache --no-scrub - # - name: Build STM32 port - # run: python3 make.py stm32 submodules clean mpy_cross BOARD=STM32H7B3I_DK DISPLAY=rgb_display INDEV=gt911 + - uses: actions/upload-artifact@v4 + with: + name: lvgl_micropy_ESP32 + path: build/*.bin + if-no-files-found: ignore - # - name: Build Raspberry Pi PICO port - # run: python3 make.py rp2 submodules clean mpy_cross BOARD=RPI_PICO DISPLAY=rgb_display INDEV=gt911 + build_unix: + if: ${{ github.event_name != 'pull_request' || github.repository != github.event.pull_request.head.repo.full_name }} + runs-on: self-hosted - - name: Get build datetime - id: datetime - uses: Kaven-Universe/github-action-current-date-time@v1 + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: - format: "YYYY_MM_DD HH_mm_ss_SSS" + python-version: '3.11' + + - name: Install Deps + # sudo apt-get update && sudo apt-get install --assume-yes --allow-downgrades --allow-remove-essential --allow-change-held-packages build-essential pkg-config cmake ninja-build libffi-dev gnome-desktop-testing libasound2-dev libpulse-dev libaudio-dev libjack-dev libsndio-dev libx11-dev libxext-dev libxrandr-dev libxcursor-dev libxfixes-dev libxi-dev libxss-dev libxkbcommon-dev libdrm-dev libgbm-dev libgl1-mesa-dev libgles2-mesa-dev libegl1-mesa-dev libdbus-1-dev libibus-1.0-dev libudev-dev fcitx-libs-dev libpipewire-0.3-dev libwayland-dev libdecor-0-dev + run: | + git submodule update --init -- lib/pycparser + git submodule update --init --jobs 4 -- lib/micropython + git submodule update --init --jobs 4 -- lib/lvgl + git submodule update --init --jobs 4 -- lib/SDL + cd lib/SDL + git checkout release-2.30.2 + cd ../.. - name: Build Unix port run: python3 make.py unix DISPLAY=sdl_display INDEV=sdl_pointer - uses: actions/upload-artifact@v4 with: - name: lvgl_micropy_unix-${{ steps.datetime.outputs.month }}.${{ steps.datetime.outputs.day }}.${{ steps.datetime.outputs.year }}-${{ steps.datetime.outputs.hours }}_${{ steps.datetime.outputs.minutes }}_${{ steps.datetime.outputs.seconds }} + name: lvgl_micropy_unix path: build/lvgl_micropy_unix if-no-files-found: ignore + + # - name: Build Raspberry Pi PICO port + # run: python3 make.py rp2 submodules clean mpy_cross BOARD=RPI_PICO DISPLAY=rgb_display INDEV=gt911 + + # build_stm32: + # if: ${{ github.event_name != 'pull_request' || github.repository != github.event.pull_request.head.repo.full_name }} + # runs-on: ubuntu-latest + # steps: + # - uses: actions/checkout@v4 + # + # - uses: carlosperate/arm-none-eabi-gcc-action@v1.8.1 + # with: + # release: 'latest' # 9-2020-q2 The arm-none-eabi-gcc release to use. + # + # - uses: actions/setup-python@v5 + # with: + # python-version: '3.11' + # + # - name: Install Deps + # run: | + # sudo apt-get update && sudo apt-get install --assume-yes --allow-downgrades --allow-remove-essential --allow-change-held-packages build-essential pkg-config cmake ninja-build + # git submodule update --init -- lib/pycparser + # git submodule update --init --jobs 4 -- lib/micropython + # git submodule update --init --jobs 4 -- lib/lvgl + # + # - name: Build STM32 port + # run: python3 make.py stm32 submodules clean mpy_cross BOARD=STM32H7B3I_DK DISPLAY=rgb_display INDEV=gt911 + # + # - uses: actions/upload-artifact@v4 + # with: + # name: lvgl_micropy_ESP32_GENERIC_S3-8 + # path: build/lvgl_micropy_ESP32_GENERIC_S3-8.bin + # if-no-files-found: ignore diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 760cf35b..6230a6d0 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + name: Windows build on: diff --git a/LICENSE b/LICENSE index 9d3c9d06..37bbb1b7 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,39 @@ + + +lvgl_micropython +################################################################################ + MIT License -Copyright (c) 2019-2021 LVGL +Copyright (c) 2024 - 2025 Kevin G. Schlosser + +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. + +END! lvgl_micropython + + +MicroPython +################################################################################ + +The MIT License (MIT) + +Copyright (c) 2013-2024 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 @@ -9,9 +42,392 @@ 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. + +-------------------------------------------------------------------------------- + +Unless specified otherwise (see below), the above license and copyright applies +to all files in this repository. + +Individual files may include additional copyright holders. + +The various ports of MicroPython may include third-party software that is +licensed under different terms. These licenses are summarised in the tree +below, please refer to these files and directories for further license and +copyright information. Note that (L)GPL-licensed code listed below is only +used during the build process and is not part of the compiled source code. + +/ (MIT) + /drivers + /cc3100 (BSD-3-clause) + /lib + /asf4 (Apache-2.0) + /axtls (BSD-3-clause) + /config + /scripts + /config (GPL-2.0-or-later) + /Rules.mak (GPL-2.0) + /berkeley-db-1xx (BSD-4-clause) + /btstack (See btstack/LICENSE) + /cmsis (BSD-3-clause) + /crypto-algorithms (NONE) + /libhydrogen (ISC) + /libmetal (BSD-3-clause) + /littlefs (BSD-3-clause) + /lwip (BSD-3-clause) + /mynewt-nimble (Apache-2.0) + /nrfx (BSD-3-clause) + /nxp_driver (BSD-3-Clause) + /oofatfs (BSD-1-clause) + /open-amp (BSD-3-clause) + /pico-sdk (BSD-3-clause) + /re15 (BSD-3-clause) + /stm32lib (BSD-3-clause) + /tinyusb (MIT) + /uzlib (Zlib) + /wiznet5k (MIT) + /logo (uses OFL-1.1) + /ports + /cc3200 + /hal (BSD-3-clause) + /simplelink (BSD-3-clause) + /FreeRTOS (GPL-2.0 with FreeRTOS exception) + /esp32 + /ppp_set_auth.* (Apache-2.0) + /rp2 + /mutex_extra.c (BSD-3-clause) + /clocks_extra.c (BSD-3-clause) + /stm32 + /usbd*.c (MCD-ST Liberty SW License Agreement V2) + /stm32_it.* (MIT + BSD-3-clause) + /system_stm32*.c (MIT + BSD-3-clause) + /boards + /startup_stm32*.s (BSD-3-clause) + /*/stm32*.h (BSD-3-clause) + /usbdev (MCD-ST Liberty SW License Agreement V2) + /usbhost (MCD-ST Liberty SW License Agreement V2) + /zephyr + /src (Apache-2.0) + /tools + /dfu.py (LGPL-3.0-only) + +END! MicroPython + + +SDL +################################################################################ + +Copyright (C) 1997-2024 Sam Lantinga + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + +END! SDL + + +pycparser +################################################################################ + +pycparser -- A C parser in Python + +Copyright (c) 2008-2022, Eli Bendersky +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 copyright holder 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 HOLDER 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. + +END! pycparser + + +LVGL +################################################################################ + +MIT licence +=========== +Copyright (c) 2021 LVGL Kft + +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. + +END! LVGL + + +LZ4 +################################################################################ + +LZ4 Library +Copyright (c) 2011-2020, Yann Collet +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. + +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 HOLDER 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. + +END! LZ4 + + +LodePNG +################################################################################ + +LodePNG version 20230410 + +Copyright (c) 2005-2023 Lode Vandevenne + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + +END! LodePNG + + +code128.h & code128.c (LVGL) +################################################################################ + +Copyright (c) 2013-15, LKC Technologies, Inc. +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. 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 HOLDER 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. + +END! code128.h & code128.c (LVGL) + + +FreeType (LVGL) +################################################################################ + +FREETYPE LICENSES +----------------- + +The FreeType 2 font engine is copyrighted work and cannot be used +legally without a software license. In order to make this project +usable to a vast majority of developers, we distribute it under two +mutually exclusive open-source licenses. + +This means that *you* must choose *one* of the two licenses described +below, then obey all its terms and conditions when using FreeType 2 in +any of your projects or products. + + - The FreeType License, found in the file `docs/FTL.TXT`, which is + similar to the original BSD license *with* an advertising clause + that forces you to explicitly cite the FreeType project in your + product's documentation. All details are in the license file. + This license is suited to products which don't use the GNU General + Public License. + + Note that this license is compatible to the GNU General Public + License version 3, but not version 2. + + - The GNU General Public License version 2, found in + `docs/GPLv2.TXT` (any later version can be used also), for + programs which already use the GPL. Note that the FTL is + incompatible with GPLv2 due to its advertisement clause. + +The contributed BDF and PCF drivers come with a license similar to +that of the X Window System. It is compatible to the above two +licenses (see files `src/bdf/README` and `src/pcf/README`). The same +holds for the source code files `src/base/fthash.c` and +`include/freetype/internal/fthash.h`; they were part of the BDF driver +in earlier FreeType versions. + +The gzip module uses the zlib license (see `src/gzip/zlib.h`) which +too is compatible to the above two licenses. + +The files `src/autofit/ft-hb.c` and `src/autofit/ft-hb.h` contain code +taken almost verbatim from the HarfBuzz file `hb-ft.cc`, which uses +the 'Old MIT' license, compatible to the above two licenses. + +The MD5 checksum support (only used for debugging in development +builds) is in the public domain. + +END! FreeType (LVGL) + + +GIFDec +################################################################################ + +All of the source code and documentation for gifdec is released into the +public domain and provided without warranty of any kind. + +END! GIFDec + + +QR Code generator library +################################################################################ + +QR Code generator library (C) + +Copyright (c) Project Nayuki. (MIT License) +https://www.nayuki.io/page/qr-code-generator-library + +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. + +END! QR Code generator library + + +ThorVG +################################################################################ + +Copyright (c) 2020 - 2025 notice for the ThorVG Project (see CONTRIBUTORS) + +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. + +END! ThorVG + + +Sean Barrett - stb_rect_pack +################################################################################ + +v1.01 - public domain - rectangle packing +Sean Barrett 2014 + +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +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 @@ -19,3 +435,4211 @@ 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. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +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 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. +------------------------------------------------------------------------------ + +END! Sean Barrett + + +TJpgDec +################################################################################ +---------------------------------------------------------------------------- +TJpgDec - Tiny JPEG Decompressor R0.03 include file (C)ChaN, 2021 +---------------------------------------------------------------------------- +The TJpgDec is a generic JPEG decompressor module for tiny embedded systems. +This is a free software that opened for education, research and commercial +developments under license policy of following terms. + + Copyright (C) 2021, ChaN, all right reserved. + +* The TJpgDec module is a free software and there is NO WARRANTY. +* No restriction on use. You can use, modify and redistribute it for + personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY. +* Redistributions of source code must retain the above copyright notice. + +!END TJpgDec + + +rlottie +################################################################################ +Copyright 2020 + +Subhransu Mohanty +Hermet Park +Youngbok Shin +Jaeun Choi +Bryce Harrington +Junsu Choi +Yuangu +Mihai Serban +Shinwoo Kim +Vincent Torri +Nicholas Guriev +John Preston +Anatoly Korniltsev +Александр Першин +Anton Sergeev +HyunGu Lee +ChaeLin Shin +Seungjae Yoon + + +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. + +END! rlottie + + +(rlottie) src/vector/freetype +################################################################################ + + + The FreeType Project LICENSE + ---------------------------- + + 2006-Jan-27 + + Copyright 1996-2002, 2006 by + David Turner, Robert Wilhelm, and Werner Lemberg + + + +Introduction +============ + + The FreeType Project is distributed in several archive packages; + some of them may contain, in addition to the FreeType font engine, + various tools and contributions which rely on, or relate to, the + FreeType Project. + + This license applies to all files found in such packages, and + which do not fall under their own explicit license. The license + affects thus the FreeType font engine, the test programs, + documentation and makefiles, at the very least. + + This license was inspired by the BSD, Artistic, and IJG + (Independent JPEG Group) licenses, which all encourage inclusion + and use of free software in commercial and freeware products + alike. As a consequence, its main points are that: + + o We don't promise that this software works. However, we will be + interested in any kind of bug reports. (`as is' distribution) + + o You can use this software for whatever you want, in parts or + full form, without having to pay us. (`royalty-free' usage) + + o You may not pretend that you wrote this software. If you use + it, or only parts of it, in a program, you must acknowledge + somewhere in your documentation that you have used the + FreeType code. (`credits') + + We specifically permit and encourage the inclusion of this + software, with or without modifications, in commercial products. + We disclaim all warranties covering The FreeType Project and + assume no liability related to The FreeType Project. + + + Finally, many people asked us for a preferred form for a + credit/disclaimer to use in compliance with this license. We thus + encourage you to use the following text: + + """ + Portions of this software are copyright � The FreeType + Project (www.freetype.org). All rights reserved. + """ + + Please replace with the value from the FreeType version you + actually use. + + +Legal Terms +=========== + +0. Definitions +-------------- + + Throughout this license, the terms `package', `FreeType Project', + and `FreeType archive' refer to the set of files originally + distributed by the authors (David Turner, Robert Wilhelm, and + Werner Lemberg) as the `FreeType Project', be they named as alpha, + beta or final release. + + `You' refers to the licensee, or person using the project, where + `using' is a generic term including compiling the project's source + code as well as linking it to form a `program' or `executable'. + This program is referred to as `a program using the FreeType + engine'. + + This license applies to all files distributed in the original + FreeType Project, including all source code, binaries and + documentation, unless otherwise stated in the file in its + original, unmodified form as distributed in the original archive. + If you are unsure whether or not a particular file is covered by + this license, you must contact us to verify this. + + The FreeType Project is copyright (C) 1996-2000 by David Turner, + Robert Wilhelm, and Werner Lemberg. All rights reserved except as + specified below. + +1. No Warranty +-------------- + + THE FREETYPE PROJECT IS PROVIDED `AS IS' WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE. IN NO EVENT WILL ANY OF THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY DAMAGES CAUSED BY THE USE OR THE INABILITY TO + USE, OF THE FREETYPE PROJECT. + +2. Redistribution +----------------- + + This license grants a worldwide, royalty-free, perpetual and + irrevocable right and license to use, execute, perform, compile, + display, copy, create derivative works of, distribute and + sublicense the FreeType Project (in both source and object code + forms) and derivative works thereof for any purpose; and to + authorize others to exercise some or all of the rights granted + herein, subject to the following conditions: + + o Redistribution of source code must retain this license file + (`FTL.TXT') unaltered; any additions, deletions or changes to + the original files must be clearly indicated in accompanying + documentation. The copyright notices of the unaltered, + original files must be preserved in all copies of source + files. + + o Redistribution in binary form must provide a disclaimer that + states that the software is based in part of the work of the + FreeType Team, in the distribution documentation. We also + encourage you to put an URL to the FreeType web page in your + documentation, though this isn't mandatory. + + These conditions apply to any software derived from or based on + the FreeType Project, not just the unmodified files. If you use + our work, you must acknowledge us. However, no fee need be paid + to us. + +3. Advertising +-------------- + + Neither the FreeType authors and contributors nor you shall use + the name of the other for commercial, advertising, or promotional + purposes without specific prior written permission. + + We suggest, but do not require, that you use one or more of the + following phrases to refer to this software in your documentation + or advertising materials: `FreeType Project', `FreeType Engine', + `FreeType library', or `FreeType Distribution'. + + As you have not signed this license, you are not required to + accept it. However, as the FreeType Project is copyrighted + material, only this license, or another one contracted with the + authors, grants you the right to use, distribute, and modify it. + Therefore, by using, distributing, or modifying the FreeType + Project, you indicate that you understand and accept all the terms + of this license. + +4. Contacts +----------- + + There are two mailing lists related to FreeType: + + o freetype@nongnu.org + + Discusses general use and applications of FreeType, as well as + future and wanted additions to the library and distribution. + If you are looking for support, start in this list if you + haven't found anything to help you in the documentation. + + o freetype-devel@nongnu.org + + Discusses bugs, as well as engine internals, design issues, + specific licenses, porting, etc. + + Our home page can be found at + + http://www.freetype.org + +END! (rlottie) src/vector/freetype + + +(rlottie) src/vector/pixman +################################################################################ + +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. + + + +The following is the MIT license, agreed upon by most contributors. +Copyright holders of new code should use this license statement where +possible. They may also add themselves to the list below. + + +Copyright 1987, 1988, 1989, 1998 The Open Group +Copyright 1987, 1988, 1989 Digital Equipment Corporation +Copyright 1999, 2004, 2008 Keith Packard +Copyright 2000 SuSE, Inc. +Copyright 2000 Keith Packard, member of The XFree86 Project, Inc. +Copyright 2004, 2005, 2007, 2008, 2009, 2010 Red Hat, Inc. +Copyright 2004 Nicholas Miell +Copyright 2005 Lars Knoll & Zack Rusin, Trolltech +Copyright 2005 Trolltech AS +Copyright 2007 Luca Barbato +Copyright 2008 Aaron Plattner, NVIDIA Corporation +Copyright 2008 Rodrigo Kumpera +Copyright 2008 André Tupinambá +Copyright 2008 Mozilla Corporation +Copyright 2008 Frederic Plourde +Copyright 2009, Oracle and/or its affiliates. All rights reserved. +Copyright 2009, 2010 Nokia Corporation + +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 (including the next +paragraph) 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. + +END! (rlottie) src/vector/pixman + + +(rlottie) src/lottie/rapidjson +################################################################################ + +Tencent is pleased to support the open source community by +making RapidJSON available. + +Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. +All rights reserved. + +If you have downloaded a copy of the RapidJSON binary from Tencent, please note +that the RapidJSON binary is licensed under the MIT License. + +If you have downloaded a copy of the RapidJSON source code from Tencent, please +note that RapidJSON source code is licensed under the MIT License, except for +the third-party components listed below which are subject to different license +terms. Your integration of RapidJSON into your own projects may require +compliance with the MIT License, as well as the other licenses applicable to +the third-party components included within RapidJSON. To avoid the problematic +JSON license in your own projects, it's sufficient to exclude the +bin/jsonchecker/ directory, as it's the only code under the JSON license. + +A copy of the MIT License is included in this file. + +Other dependencies and licenses: + +Open Source Software Licensed Under the BSD License: +-------------------------------------------------------------------- + +The msinttypes r29 +Copyright (c) 2006-2013 Alexander Chemeris +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 copyright holder 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 REGENTS 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 REGENTS AND 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. + +Open Source Software Licensed Under the JSON License: +-------------------------------------------------------------------- + +json.org +Copyright (c) 2002 JSON.org +All Rights Reserved. + +JSON_checker +Copyright (c) 2002 JSON.org +All Rights Reserved. + + +Terms of the JSON License: +--------------------------------------------------- + +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 shall be used for Good, not Evil. + +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. + + +Terms of the MIT License: +-------------------------------------------------------------------- + +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. + +!END (rlottie) src/lottie/rapidjson + + +(rlottie) src/vector/ +################################################################################ + +rlottie +Copyright 2020 + +Subhransu Mohanty +Hermet Park +Youngbok Shin +Jaeun Choi +Bryce Harrington +Junsu Choi +Yuangu +Mihai Serban +Shinwoo Kim +Vincent Torri +Nicholas Guriev +John Preston +Anatoly Korniltsev +Александр Першин +Anton Sergeev +HyunGu Lee +ChaeLin Shin +Seungjae Yoon + + +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. + +-------------------------------------------------------------------------------- + +Copyright (c) 2011 Google Inc. 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 copyright holder 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. + +END! (rlottie) src/vector/ + + +(rlottie) src/vector/stb +################################################################################ + + MIT License +Copyright (c) 2017 Sean Barrett +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. + +END! (rlottie) src/vector/stb + + +ESP-IDF +================================================================================ + +Copyright (C) 2015-2023 Espressif Systems + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +END! ESP-IDF + + +sphinx_idf_theme +################################################################################ + +The MIT License (MIT) + +Copyright (c) 2013-2020 Dave Snider, Read the Docs, Inc. & contributors, +and Espressif Systems (Shanghai) CO., LTD + +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. + + +END! sphinx_idf_theme + + +FreeRTOS +################################################################################ + +MIT License + +Copyright (C) 2017 Amazon.com, Inc. or its affiliates + +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. + +END! FreeRTOS + + +LWIP +################################################################################ + +Copyright (c) 2001, 2002 Swedish Institute of Computer Science. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. +2. 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. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + +Author: Adam Dunkels + +END! LWIP + + +wpa_supplicant and hostapd +################################################################################ + +Copyright (c) 2002-2019, Jouni Malinen and contributors +All Rights Reserved. + +These programs are licensed under the BSD license (the one with +advertisement clause removed). + +License +------- + +This software may be distributed, used, and modified under the terms of +BSD license: + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. 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. + +3. Neither the name(s) of the above-listed copyright holder(s) 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. + +END! wpa_supplicant and hostapd + + +Faster PBKDF2 +################################################################################ + +Written in 2015 by Joseph Birr-Pixton + +Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work. + +END! Faster PBKDF2 + + +FreeBSD net80211 +################################################################################ + +Copyright (c) 2001 Atsushi Onoe +Copyright (c) 2002-2008 Sam Leffler, Errno Consulting +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. 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. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + +END! FreeBSD net80211 + + +argtable3 +################################################################################ + +Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + +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 STEWART HEITMANN 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 STEWART HEITMANN 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. + + +FreeBSD getopt library +====================== + +Copyright (c) 2000 The NetBSD Foundation, Inc. +All rights reserved. + +This code is derived from software contributed to The NetBSD Foundation +by Dieter Baron and Thomas Klausner. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. 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. + +THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. + + +Tcl library +=========== + +This software is copyrighted by the Regents of the University of +California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState +Corporation and other parties. The following terms apply to all files +associated with the software unless explicitly disclaimed in +individual files. + +The authors hereby grant permission to use, copy, modify, distribute, +and license this software and its documentation for any purpose, provided +that existing copyright notices are retained in all copies and that this +notice is included verbatim in any distributions. No written agreement, +license, or royalty fee is required for any of the authorized uses. +Modifications to this software may be copyrighted by their authors +and need not follow the licensing terms described here, provided that +the new terms are clearly indicated on the first page of each file where +they apply. + +IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY +FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES +ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY +DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE +IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE +NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR +MODIFICATIONS. + +GOVERNMENT USE: If you are acquiring this software on behalf of the +U.S. government, the Government shall have only "Restricted Rights" +in the software and related documentation as defined in the Federal +Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you +are acquiring the software on behalf of the Department of Defense, the +software shall be classified as "Commercial Computer Software" and the +Government shall have only "Restricted Rights" as defined in Clause +252.227-7014 (b) (3) of DFARs. Notwithstanding the foregoing, the +authors grant the U.S. Government and others acting in its behalf +permission to use and distribute the software in accordance with the +terms specified in this license. + + +C Hash Table library +==================== + +Copyright (c) 2002, Christopher Clark +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 original author; nor the names of any 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. + + +The Better String library +========================= + +Copyright (c) 2014, Paul Hsieh +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 bstrlib 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 HOLDER 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. + +END! argtable3 + + +linenoise +################################################################################ + +Copyright (c) 2010-2014, Salvatore Sanfilippo +Copyright (c) 2010-2013, Pieter Noordhuis + +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. + +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. + +END! linenoise + + +FatFS +################################################################################ + +FatFs License + +FatFs has being developped as a personal project of the author, ChaN. +It is free from the code anyone else wrote at current release. +Following code block shows a copy of the FatFs license document that heading +the source files. + +---------------------------------------------------------------------------- +FatFs - Generic FAT Filesystem Module Rx.xx +---------------------------------------------------------------------------- + +Copyright (C) 20xx, ChaN, all right reserved. + +FatFs module is an open source software. Redistribution and use of FatFs in +source and binary forms, with or without modification, are permitted provided +that the following condition is met: + +1. Redistributions of source code must retain the above copyright notice, + this condition and the following disclaimer. + +This software is provided by the copyright holder and contributors "AS IS" +and any warranties related to this software are DISCLAIMED. +The copyright owner or contributors be NOT LIABLE for any damages caused +by use of this software. +---------------------------------------------------------------------------- + +Therefore FatFs license is one of the BSD-style licenses, but there is a +significant feature. FatFs is mainly intended for embedded systems. +In order to extend the usability for commercial products, the redistributions +of FatFs in binary form, such as embedded code, binary library and any forms +without source code, do not need to include about FatFs in the documentations. +This is equivalent to the 1-clause BSD license. Of course FatFs is compatible +with the most of open source software licenses include GNU GPL. When you +redistribute the FatFs source code with changes or create a fork, the license +can also be changed to GNU GPL, BSD-style license or any open source software +license that not conflict with FatFs license. + +END! FatFS + + +cJSON +################################################################################ + +Copyright (c) 2009-2017 Dave Gamble and cJSON contributors + +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. + +END! cJSON + + +micro-ecc +################################################################################ + +Copyright (c) 2014, Kenneth MacKay +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. + +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 HOLDER 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. + +END! micro-ecc + + +Mbed TLS +################################################################################ + +Mbed TLS files are provided under a dual [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) +OR [GPL-2.0-or-later](https://spdx.org/licenses/GPL-2.0-or-later.html) license. +This means that users may choose which of these licenses they take the code +under. + +The full text of each of these licenses is given below. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +=============================================================================== + + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. + +END! Mbed TLS + + +SPIFFS +################################################################################ + +The MIT License (MIT) + +Copyright (c) 2013-2017 Peter Andersson (pelleplutt1976gmail.com) + +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. + +END! SPIFFS + + +SD/MMC driver derived from OpenBSD SD/MMC driver +################################################################################ + +Zero-Clause BSD +=============== + +Copyright (c) 2006 Uwe Stuehler + +Permission to use, copy, modify, and distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +END! SD/MMC driver + + +ESP-MQTT +################################################################################ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2016 Tuan PM + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +END! ESP-MQTT + + +BLE Mesh is adapted from Zephyr Project +################################################################################ + + Copyright (c) 2019 Tobias Svehagen + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +END! BLE Mesh + + +Apache Mynewt NimBLE +################################################################################ + + Copyright 2015-2024 The Apache Software Foundation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). + +Portions of this software were developed at +Runtime Inc, copyright 2015. + + + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + +This product bundles queue.h 8.5, which is available under the "3-clause BSD" +license. For details, see porting/nimble/include/os/queue.h + +This product partly derives from FreeBSD, which is available under the +"3-clause BSD" license. For details, see: + * porting/nimble/src/os_mbuf.c + +This product bundles Gary S. Brown's CRC32 implementation, which is available +under the following license: + COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or + code or tables extracted from it, as desired without restriction. + +This product bundles tinycrypt, which is available under the "3-clause BSD" +license. For details, and bundled files see: + * ext/tinycrypt/LICENSE + +This product bundles and partly derives from parts of the Nordic nRF52 SDK, +which are available under a BSD style license. Relevant files are: + * babblesim/hw/mcu/nordic/nrf52_bsim/src/system_nrf52.c + +This product bundles additional files from CMSIS-CORE, but these files are +missing licensing information. The BSD license was subsequently added to +these files in later releases. These files are: + * babblesim/hw/mcu/nordic/nrf52_bsim/include/mcu/cmsis_nvic.h + +This product bundles part of linker scripts from Nordic Semiconductor, +which is available under the "modified Tcl/Tk" license. Bundled files are: + * targets/auracast_usb/nrf5340-mcu.ld + +END! Apache Mynewt NimBLE + + +TLSF (Two Level Segregated Fit) memory allocator +################################################################################ + +Copyright (c) 2006-2016 Matthew Conte +All Rights Reserved. + +These programs are licensed under the BSD license (the one with +advertisement clause removed). + +License +------- + +This software may be distributed, used, and modified under the terms of +BSD license: + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. 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. + +3. Neither the name(s) of the above-listed copyright holder(s) 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. + +END! TLSF + + +openthread +################################################################################ + +Copyright (c) 2016, The OpenThread Authors. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. 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. +3. Neither the name of the copyright holder 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 HOLDER 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. + +END! openthread + + +UBSAN runtime +################################################################################ + +Copyright (c) 2016, Linaro Limited +Modified for HelenOS use by Jiří Zárevúcky. +Adaptations for ESP-IDF Copyright (c) 2020 Espressif Systems (Shanghai) Co. Ltd. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +2. 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. + +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 HOLDER 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. + +END! UBSAN runtime + + +* HTTP Parser - Based on ngx_http_parse.c from NGINX +################################################################################ + +Copyright (C) 2002-2021 Igor Sysoev +Copyright (C) 2011-2024 Nginx, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. 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. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + +END! HTTP Parser + + +SEGGER SystemView +################################################################################ +Copyright (c) 1995-2021 +SEGGER Microcontroller GmbH +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted +provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions + and the following disclaimer. + +THIS SOFTWARE IS PROVIDED BY SEGGER Microcontroller GmbH “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 SEGGER Microcontroller GmbH 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. + +END! SEGGER SystemView + + +Xtensa libhal +################################################################################ + +MIT License +=========== + +Copyright (c) 2003, 2006, 2010 Tensilica Inc. + +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. + +END! Xtensa libhal + + +TinyBasic Plus +################################################################################ + +MIT License + +Copyright (c) 2012-2013 + +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. + +END! TinyBasic Plus + + +TJpgDec +################################################################################ + +TJpgDec - Tiny JPEG Decompressor R0.01 (C) ChaN, 2011 +The TJpgDec is a generic JPEG decompressor module for tiny embedded systems. +This is a free software that opened for education, research and commercial +developments under license policy of following terms. + +Copyright (C) 2011, ChaN, all right reserved. + +* The TJpgDec module is a free software and there is NO WARRANTY. +* No restriction on use. You can use, modify and redistribute it for personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY. +* Redistributions of source code must retain the above copyright notice. + +END! TJpgDec + + +Newlib +################################################################################ + +BSD License + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. +2. 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. +3. Neither the name of the copyright holder 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 HOLDER 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. + +END! Newlib + + +Red Hat Incorporated (Newlib) +################################################################################ + +Copyright (c) 1994-2009 Red Hat, Inc. All rights reserved. + +This copyrighted material is made available to anyone wishing to use, +modify, copy, or redistribute it subject to the terms and conditions +of the BSD License. This program is distributed in the hope that +it will be useful, but WITHOUT ANY WARRANTY expressed or implied, +including the implied warranties of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. A copy of this license is available at +http://www.opensource.org/licenses. Any Red Hat trademarks that are +incorporated in the source code or documentation are not subject to +the BSD License and may only be used or replicated with the express +permission of Red Hat, Inc. + +END! Red Hat Incorporated + + +University of California, Berkeley (Newlib) +################################################################################ + +Copyright (c) 1981-2000 The Regents of the University of California. +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 University 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. + +END! University of California, Berkeley + + +David M. Gay (AT&T 1991, Lucent 1998) (Newlib) +################################################################################ + +The author of this software is David M. Gay. + +Copyright (c) 1991 by AT&T. + +Permission to use, copy, modify, and distribute this software for any +purpose without fee is hereby granted, provided that this entire notice +is included in all copies of any software which is or includes a copy +or modification of this software and in all copies of the supporting +documentation for such software. + +THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED +WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR AT&T MAKES ANY +REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY +OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + +------------------------------------------------------------------- + +The author of this software is David M. Gay. + +Copyright (C) 1998-2001 by Lucent Technologies +All Rights Reserved + +Permission to use, copy, modify, and distribute this software and +its documentation for any purpose and without fee is hereby +granted, provided that the above copyright notice appear in all +copies and that both that the copyright notice and this +permission notice and warranty disclaimer appear in supporting +documentation, and that the name of Lucent or any of its entities +not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. + +END! David M. Gay + + +Advanced Micro Devices (Newlib) +################################################################################ + +Copyright 1989, 1990 Advanced Micro Devices, Inc. + +This software is the property of Advanced Micro Devices, Inc (AMD) which +specifically grants the user the right to modify, use and distribute this +software provided this notice is not removed or altered. All other rights +are reserved by AMD. + +AMD MAKES NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, WITH REGARD TO THIS +SOFTWARE. IN NO EVENT SHALL AMD BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL +DAMAGES IN CONNECTION WITH OR ARISING FROM THE FURNISHING, PERFORMANCE, OR +USE OF THIS SOFTWARE. + +So that all may benefit from your experience, please report any problems +or suggestions about this software to the 29K Technical Support Center at +800-29-29-AMD (800-292-9263) in the USA, or 0800-89-1131 in the UK, or +0031-11-1129 in Japan, toll free. The direct dial number is 512-462-4118. + +Advanced Micro Devices, Inc. +29K Support Products +Mail Stop 573 +5900 E. Ben White Blvd. +Austin, TX 78741 +800-292-9263 + +END! Advanced Micro Devices + + +Sun Microsystems (Newlib) +################################################################################ + +Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + +Developed at SunPro, a Sun Microsystems, Inc. business. +Permission to use, copy, modify, and distribute this +software is freely granted, provided that this notice is preserved. + +END! Sun Microsystems + + +Hewlett Packard (Newlib) +################################################################################ + +(c) Copyright 1986 HEWLETT-PACKARD COMPANY + +To anyone who acknowledges that this file is provided "AS IS" +without any express or implied warranty: + permission to use, copy, modify, and distribute this file +for any purpose is hereby granted without fee, provided that +the above copyright notice and this notice appears in all +copies, and that the name of Hewlett-Packard Company not be +used in advertising or publicity pertaining to distribution +of the software without specific, written prior permission. +Hewlett-Packard Company makes no representations about the +suitability of this software for any purpose. + +END! Hewlett Packard + + +Hans-Peter Nilsson (Newlib) +################################################################################ + +Copyright (C) 2001 Hans-Peter Nilsson + +Permission to use, copy, modify, and distribute this software is +freely granted, provided that the above copyright notice, this notice +and the following disclaimer are preserved with no changes. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. + +END! Hans-Peter Nilsson + + +Stephane Carrez (m68hc11-elf/m68hc12-elf targets only) (Newlib) +################################################################################ + +Copyright (C) 1999, 2000, 2001, 2002 Stephane Carrez (stcarrez@nerim.fr) + +The authors hereby grant permission to use, copy, modify, distribute, +and license this software and its documentation for any purpose, provided +that existing copyright notices are retained in all copies and that this +notice is included verbatim in any distributions. No written agreement, +license, or royalty fee is required for any of the authorized uses. +Modifications to this software may be copyrighted by their authors +and need not follow the licensing terms described here, provided that +the new terms are clearly indicated on the first page of each file where +they apply. + +END! Stephane Carrez + + +Christopher G. Demetriou (Newlib) +################################################################################ + +Copyright (c) 2001 Christopher G. Demetriou +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. 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. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + +END! Christopher G. Demetriou + + +SuperH, Inc. (Newlib) +################################################################################ + +Copyright 2002 SuperH, Inc. All rights reserved + +This software is the property of SuperH, Inc (SuperH) which specifically +grants the user the right to modify, use and distribute this software +provided this notice is not removed or altered. All other rights are +reserved by SuperH. + +SUPERH MAKES NO WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, WITH REGARD TO +THIS SOFTWARE. IN NO EVENT SHALL SUPERH BE LIABLE FOR INDIRECT, SPECIAL, +INCIDENTAL OR CONSEQUENTIAL DAMAGES IN CONNECTION WITH OR ARISING FROM +THE FURNISHING, PERFORMANCE, OR USE OF THIS SOFTWARE. + +So that all may benefit from your experience, please report any problems +or suggestions about this software to the SuperH Support Center via +e-mail at softwaresupport@superh.com . + +SuperH, Inc. +405 River Oaks Parkway +San Jose +CA 95134 +USA + +END! SuperH, Inc. + + +Royal Institute of Technology (Newlib) +################################################################################ + +Copyright (c) 1999 Kungliga Tekniska Högskolan +(Royal Institute of Technology, Stockholm, Sweden). +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. 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. + +3. Neither the name of KTH 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 KTH AND ITS 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 KTH OR ITS 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. + +END! Royal Institute of Technology + + +Alexey Zelkin (Newlib) +################################################################################ + +Copyright (c) 2000, 2001 Alexey Zelkin +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. 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. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + +END! Alexey Zelkin + + +Andrey A. Chernov (Newlib) +################################################################################ + +Copyright (C) 1997 by Andrey A. Chernov, Moscow, Russia. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. 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. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 REGENTS 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. + +END! Andrey A. Chernov + + +FreeBSD (Newlib) +################################################################################ + +Copyright (c) 1997-2002 FreeBSD Project. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. 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. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + +END! FreeBSD + + +S. L. Moshier (Newlib) +################################################################################ + +Author: S. L. Moshier. + +Copyright (c) 1984,2000 S.L. Moshier + +Permission to use, copy, modify, and distribute this software for any +purpose without fee is hereby granted, provided that this entire notice +is included in all copies of any software which is or includes a copy +or modification of this software and in all copies of the supporting +documentation for such software. + +THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED +WARRANTY. IN PARTICULAR, THE AUTHOR MAKES NO REPRESENTATION +OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY OF THIS +SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. + +END! S. L. Moshier + + +Citrus Project (Newlib) +################################################################################ + +Copyright (c)1999 Citrus Project, +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. 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. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + +END! Citrus Project + + +Todd C. Miller (Newlib) +################################################################################ + +Copyright (c) 1998 Todd C. Miller +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. 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. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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. + +END! Todd C. Miller + + +DJ Delorie (i386) (Newlib) +################################################################################ + +Copyright (C) 1991 DJ Delorie +All rights reserved. + +Redistribution, modification, and use in source and binary forms is permitted +provided that the above copyright notice and following paragraph are +duplicated in all such forms. + +This file is distributed WITHOUT ANY WARRANTY; without even the implied +warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +END! DJ Delorie + + +Free Software Foundation (*-linux* targets only) (Newlib) +################################################################################ + +LGPL License +============ + + Copyright (C) 1990-1999, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Mark Kettenis , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA. + +END! Free Software Foundation + + +Xavier Leroy (i[3456]86-*-linux* targets only) (Newlib) +################################################################################ + +LGPL License +============ + +Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Library General Public License for more details. + +END! Xavier Leroy + + +Intel (i960) (Newlib) +################################################################################ + +Copyright (c) 1993 Intel Corporation + +Intel hereby grants you permission to copy, modify, and distribute this +software and its documentation. Intel grants this permission provided +that the above copyright notice appears in all copies and that both the +copyright notice and this permission notice appear in supporting +documentation. In addition, Intel grants this permission provided that +you prominently mark as "not part of the original" any modifications +made to this software or documentation, and that the name of Intel +Corporation not be used in advertising or publicity pertaining to +distribution of the software or the documentation without specific, +written prior permission. + +Intel Corporation provides this AS IS, WITHOUT ANY WARRANTY, EXPRESS OR +IMPLIED, INCLUDING, WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY +OR FITNESS FOR A PARTICULAR PURPOSE. Intel makes no guarantee or +representations regarding the use of, or the results of the use of, +the software and documentation in terms of correctness, accuracy, +reliability, currentness, or otherwise; and you rely on the software, +documentation and results solely at your own risk. + +IN NO EVENT SHALL INTEL BE LIABLE FOR ANY LOSS OF USE, LOSS OF BUSINESS, +LOSS OF PROFITS, INDIRECT, INCIDENTAL, SPECIAL OR CONSEQUENTIAL DAMAGES +OF ANY KIND. IN NO EVENT SHALL INTEL'S TOTAL LIABILITY EXCEED THE SUM +PAID TO INTEL FOR THE PRODUCT LICENSED HEREUNDER. + +END! Intel + + +Hewlett-Packard (hppa targets only) (Newlib) +################################################################################ + +(c) Copyright 1986 HEWLETT-PACKARD COMPANY + +To anyone who acknowledges that this file is provided "AS IS" +without any express or implied warranty: + permission to use, copy, modify, and distribute this file +for any purpose is hereby granted without fee, provided that +the above copyright notice and this notice appears in all +copies, and that the name of Hewlett-Packard Company not be +used in advertising or publicity pertaining to distribution +of the software without specific, written prior permission. +Hewlett-Packard Company makes no representations about the +suitability of this software for any purpose. + +END! Hewlett-Packard + + +Henry Spencer (only *-linux targets) (Newlib) +################################################################################ + +Copyright 1992, 1993, 1994 Henry Spencer. All rights reserved. +This software is not subject to any license of the American Telephone +and Telegraph Company or of the Regents of the University of California. + +Permission is granted to anyone to use this software for any purpose on +any computer system, and to alter it and redistribute it, subject +to the following restrictions: + +1. The author is not responsible for the consequences of use of this + software, no matter how awful, even if they arise from flaws in it. + +2. The origin of this software must not be misrepresented, either by + explicit claim or by omission. Since few users ever read sources, + credits must appear in the documentation. + +3. Altered versions must be plainly marked as such, and must not be + misrepresented as being the original software. Since few users + ever read sources, credits must appear in the documentation. + +4. This notice may not be removed or altered. + +END! Henry Spencer + + +Mike Barcroft (Newlib) +################################################################################ + +Copyright (c) 2001 Mike Barcroft +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. 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. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + +END! Mike Barcroft + + +iconv (Charset Conversion Library) v2.0 (Newlib) +################################################################################ + +Konstantin Chuguev (--enable-newlib-iconv) +-------------------------------------------------------------------------------- + +Copyright (c) 1999, 2000 + Konstantin Chuguev. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. 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. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + +-------------------------------------------------------------------------------- + + +Artem Bityuckiy (--enable-newlib-iconv) +-------------------------------------------------------------------------------- + +Copyright (c) 2003, Artem B. Bityuckiy, SoftMine Corporation. +Rights transferred to Franklin Electronic Publishers. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. 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. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + +END! iconv + + +IBM, Sony, Toshiba (only spu-* targets) (Newlib) +################################################################################ + + (C) Copyright 2001,2006, + International Business Machines Corporation, + Sony Computer Entertainment, Incorporated, + Toshiba Corporation, + + 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 names of the copyright holders nor the names of their + 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. + +END! IBM, Sony, Toshiba + + +Alex Tatmanjants (targets using libc/posix) (Newlib) +################################################################################ + + Copyright (c) 1995 Alex Tatmanjants + at Electronni Visti IA, Kiev, Ukraine. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. 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. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + +END! Alex Tatmanjants + + +M. Warner Losh (targets using libc/posix) (Newlib) +################################################################################ + + Copyright (c) 1998, M. Warner Losh + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. 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. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + +END! M. Warner Losh + + +Andrey A. Chernov (targets using libc/posix) (Newlib) +################################################################################ + + Copyright (C) 1996 by Andrey A. Chernov, Moscow, Russia. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. 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. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 REGENTS 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. + +END! Andrey A. Chernov + + +Daniel Eischen (targets using libc/posix) (Newlib) +################################################################################ + + Copyright (c) 2001 Daniel Eischen . + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. 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. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 REGENTS 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. + +END! Daniel Eischen + + +Jon Beniston (only lm32-* targets) (Newlib) +################################################################################ + + Contributed by Jon Beniston + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. 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. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + +END! Jon Beniston + + +ARM Ltd (arm and thumb variant targets only) (Newlib) +################################################################################ + + Copyright (c) 2009 ARM 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: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. 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. + 3. The name of the company may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY ARM LTD ``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 ARM LTD 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. + +END! ARM Ltd + + +Xilinx, Inc. (microblaze-* and powerpc-* targets) (Newlib) +################################################################################ + +Copyright (c) 2004, 2009 Xilinx, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. 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. + +3. Neither the name of Xilinx 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 HOLDER 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 +HOLDER 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. + +END! Xilinx, Inc. + + +Texas Instruments Incorporated (tic6x-*, *-tirtos targets) (Newlib) +################################################################################ + +Copyright (c) 1996-2010,2014 Texas Instruments Incorporated +http://www.ti.com/ + + 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 Texas Instruments Incorporated 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. + +END! Texas Instruments Incorporated + + +National Semiconductor (cr16-* and crx-* targets) (Newlib) +################################################################################ + +Copyright (c) 2004 National Semiconductor Corporation + +The authors hereby grant permission to use, copy, modify, distribute, +and license this software and its documentation for any purpose, provided +that existing copyright notices are retained in all copies and that this +notice is included verbatim in any distributions. No written agreement, +license, or royalty fee is required for any of the authorized uses. +Modifications to this software may be copyrighted by their authors +and need not follow the licensing terms described here, provided that +the new terms are clearly indicated on the first page of each file where +they apply. + +END! National Semiconductor + + +Adapteva, Inc. (epiphany-* targets) (Newlib) +################################################################################ + +Copyright (c) 2011, Adapteva, Inc. +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 Adapteva 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 HOLDER 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. + +END! Adapteva, Inc. + + +Altera Corportion (nios2-* targets) (Newlib) +################################################################################ + +Copyright (c) 2003 Altera Corporation +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + o Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + o 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. + o Neither the name of Altera Corporation 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 ALTERA CORPORATION, THE COPYRIGHT HOLDER, +AND ITS 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 HOLDER 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. + +END! Altera Corportion + + +Ed Schouten - Free BSD (Newlib) +################################################################################ + +Copyright (c) 2008 Ed Schouten +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. 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. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + +END! Ed Schouten - Free BSD + + +Newlib: https://sourceware.org/newlib/ +FreeRTOS: https://freertos.org/ +esptool.py: https://github.com/espressif/esptool +LWIP: https://savannah.nongnu.org/projects/lwip/ +TinyBasic: https://github.com/BleuLlama/TinyBasicPlus +miniz: https://code.google.com/archive/p/miniz/ +wpa_supplicant: https://w1.fi/wpa_supplicant/ +FreeBSD net80211: https://github.com/freebsd/freebsd-src/tree/master/sys/net80211 +TJpgDec: http://elm-chan.org/fsw/tjpgd/00index.html +argtable3: https://github.com/argtable/argtable3 +linenoise: https://github.com/antirez/linenoise +fatfs: http://elm-chan.org/fsw/ff/00index_e.html +cJSON: https://github.com/DaveGamble/cJSON +micro-ecc: https://github.com/kmackay/micro-ecc +OpenBSD SD/MMC driver: https://github.com/openbsd/src/blob/f303646/sys/dev/sdmmc/sdmmc.c +Mbed TLS: https://github.com/Mbed-TLS/mbedtls +spiffs: https://github.com/pellepl/spiffs +asio: https://github.com/chriskohlhoff/asio +mqtt: https://github.com/espressif/esp-mqtt +zephyr: https://github.com/zephyrproject-rtos/zephyr +mynewt-nimble: https://github.com/apache/mynewt-nimble +ESP-IDF Programming Guide: https://docs.espressif.com/projects/esp-idf/en/latest/ +sphinx_idf_theme: https://github.com/espressif/sphinx_idf_theme +sphinx_rtd_theme: https://github.com/readthedocs/sphinx_rtd_theme +SEGGER SystemView: https://www.segger.com/downloads/systemview/ +DesignWare USB device driver: https://github.com/zephyrproject-rtos/zephyr/blob/v1.12-branch/drivers/usb/device/usb_dc_dw.c +Generic USB device driver: https://github.com/zephyrproject-rtos/zephyr/blob/v1.12-branch/subsys/usb/usb_device.c +USB descriptors functionality: https://github.com/zephyrproject-rtos/zephyr/blob/v1.12-branch/subsys/usb/usb_descriptor.c +USB DFU class driver: https://github.com/zephyrproject-rtos/zephyr/blob/v1.12-branch/subsys/usb/class/usb_dfu.c +USB CDC ACM class driver: https://github.com/zephyrproject-rtos/zephyr/blob/v1.12-branch/subsys/usb/class/cdc_acm.c + + +END! ESP-IDF \ No newline at end of file diff --git a/Makefile b/Makefile index ecbb4e1f..280d8099 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + # Makefile for LVGL_Micropython Binding PYTHON_CMD=python3 diff --git a/README.md b/README.md index 569a551a..c3009baa 100644 --- a/README.md +++ b/README.md @@ -32,13 +32,13 @@ related bits of a microcontroller. ***What is LVGL?*** -[LVGL](https://lvgl.io) is a graphics framework writtemn for C99. It is also written to run on resource constrained devices. +[LVGL](https://lvgl.io) is a graphics framework written for C99. It is also written to run on resource constrained devices. It is a feature rich framework that provides a plethora of different controls (widgets) as well as the ability to make your owmn custom controls. ***What is a binding?*** -A Binding is a code that encapsulates code written in one programming language so it is accessable from another +A Binding is code that encapsulates code written in one programming language so it is accessable from another programming language. It is best to think of it as a translator, in the case of this project it translates Python to C99 and vice versa. It allows us access to the LVGL code by using the Python programming language. @@ -87,6 +87,8 @@ used to be. - [*Model/Variant*](#model/variant) - [*Model/Variant specific options*](#model/variant-specific-options) - [*ESP32 options*](#esp32-options) + - [*Custom Boards*](https://github.com/lvgl-micropython/lvgl_micropython/tree/main/custom_board_and_toml_examples/README.md#custom-boards) + - [*TOML Example*](https://github.com/lvgl-micropython/lvgl_micropython/tree/main/custom_board_and_toml_examples/README.md#toml-example) - [*Global Options (optional)*](#global-options-(optional)) - [*Input/Output*](#input/output) - [*Other global options*](#other-global-options) @@ -276,7 +278,7 @@ To compile you will need Python >= 3.10 for for all build types. #### Compiling for Windows: - * not supported yet + * Not yet supported
@@ -329,7 +331,7 @@ Target options is broken down into 2 sections ##### *Model/Variant* -The model is the processor model being used or the build type. the build type is what is +The model is the processor model being used or the build type. The build type is what is specified when compiling to run on macOS or Unix. When compiling for macOS or Unix you are able to specify the build type. That is done by using @@ -547,9 +549,9 @@ ______________________________________ Common options that are available across all esp32 targets: -* `BAUD={bits per second}`: how fast to flash the firmware, `deploy` must also be set to use this -* `PORT={serial port}`: port the ESP is connected to, `deploy` must also be set to use this -* `deploy`: after building flash the firmware, `PORT` and `BAUD` are optional. The speed will default +* `BAUD={bits per second}`: How fast to flash the firmware, `deploy` must also be set to use this +* `PORT={serial port}`: Port the ESP is connected to, `deploy` must also be set to use this +* `deploy`: After building flash the firmware, `PORT` and `BAUD` are optional. The speed will default to whatever the ESP-IDF is set to and there will be an attempt at detecting the port automatically * `--skip-partition-resize`: If you do not want the build system to resize the application partition automatically. * `--partition-size={app partition size}`: Manually set the application partition size. This is something you want @@ -564,8 +566,8 @@ Common options that are available across all esp32 targets: * `--flash-size={4, 8, 16, 32, 64 or 128}`: Sets the flash size that you have available on your ESP32 * `--ota`: Add this flag if you wanbt to do OTA updates. This creates 2 application partitions that are the same size. * `--dual-core-threads`: (Experimental) MicroPython is written so that the user is only able to run code on a single core of the ESP32. - That is very limiting. This option allows code to run on both CPU cores. Be warned mthis option also disables the GIL - So care must be given to accessing global variables. You need to put nlocks in place to keep the memory from getting + That is very limiting. This option allows code to run on both CPU cores. Be warned this option also disables the GIL + so care must be given to accessing global variables. You need to put nlocks in place to keep the memory from getting corrupted. You do not get to decide what core to use. That is automatically done based on the load that is on the cores. * `--task-stack-size={stack size in bytes}`: Sets the default stack size for threads * `CONFIG_*={value}`: You can alter the config settings of the esp-idf by using these settings. Refer to the ESP-IDF documentation @@ -586,49 +588,9 @@ Options specific to the ESP32-S2, ESP32-S3, ESP32-C3 and ESP32-C6 processors: * `--enable-cdc-repl={y/n}`: Enable/disable REPL output over CDC on the USB pins * `--enable-jtag-repl={y/n}`: Enable/disable REPL output over JTAG on the USB pins +* `--custom-board-path={path to custom board}`: [Custom Board](https://github.com/lvgl-micropython/lvgl_micropython/tree/main/custom_board_and_toml_examples/README.md#custom-boards) +* `--toml={path to .toml file}`: [TOML Example](https://github.com/lvgl-micropython/lvgl_micropython/tree/main/custom_board_and_toml_examples/README.md#toml-example) -This next option is abailable for all ESP32 series MCU's I placed it here instead of above -because it is going to need some in depth explaining. This is for advanced users. - -* `--custom-board-path` - -I added the ability to provide a path to a custom board. There are a few requirememnts for -this to work properly. The path needs to point to the folder that holds the board specification -files. Here is a list of required files. - -* `board.json`: This file outlines what the board is. At a minimum the file needs to contain the following. - ``` - { - "mcu": "{MCU}" - } - ``` - where `{MCU}` is one of the follwing: - - * esp32 - * esp32s2 - * exp32s3 - * exp32c3 - * exp32c6 - -* `sdkconfig.board`: This file contains all of the ESP-IDF specific config settings. If you don't know - what needs to be set in here then please ask me for assistance. -* `mpconfigboard.h`: MicroPython config settings. If you don't know what needs to be set in here then - please ask me for assistance. -* `mpconfigboard.cmake`: Build script. At a minimum the following should be in the build script. - `{MCU}` is replaced with one of the options from the list of MCU's above. - `{BOARD_CONATINING_FOLDER}` if the name of the folder these files are located in. -``` -set(IDF_TARGET {MCU}) - -set(SDKCONFIG_DEFAULTS - boards/sdkconfig.base - ${SDKCONFIG_IDF_VERSION_SPECIFIC} - boards/{BOARD_CONATINING_FOLDER}/sdkconfig.board -) -``` - -* `partition.csv`: This file dictates what the partitions are supposed to be on the ESP32. As for assistance - If you do not know how to create one of these.
@@ -644,10 +606,10 @@ The global options are broken down into 2 secions ##### *Input/Output* - * `DISPLAY={ic model or path}`: model number of the display driver that is located in `api_drivers/common_api_drivers/display` + * `DISPLAY={ic model or path}`: Model number of the display driver that is located in `api_drivers/common_api_drivers/display` or it can be the absolute path to a custom driver you have written. This must be the path to the folder that contains the driver files. - * `INDEV={ic model or path}`: model number of indev driver that is located in `api_drivers/common_api_drivers/indev` + * `INDEV={ic model or path}`: Model number of indev driver that is located in `api_drivers/common_api_drivers/indev` or it can be the absolute path to your own custom driver (with the .py extension) The above options are able to be repeated if you want to include multiple drivers. diff --git a/_indev_base.pyi b/_indev_base.pyi index 4c5dd3cf..eb4d8631 100644 --- a/_indev_base.pyi +++ b/_indev_base.pyi @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + from typing import Optional, ClassVar, TYPE_CHECKING, Union diff --git a/api_drivers/common_api_drivers/display/axs15231b/_axs15231b_init.py b/api_drivers/common_api_drivers/display/axs15231b/_axs15231b_init.py new file mode 100644 index 00000000..4f10c09c --- /dev/null +++ b/api_drivers/common_api_drivers/display/axs15231b/_axs15231b_init.py @@ -0,0 +1,94 @@ +# Based on the work by straga (https://github.com/straga) +# https://github.com/straga/micropython_lcd/blob/master/device/JC3248W535/driver/axs15231b/_axs15231b_init_type1.py +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + +import time +from micropython import const # NOQA +import lvgl as lv # NOQA + + +_AXS_LCD_NOP = const(0x02000000) # No operation (C) +_AXS_LCD_SWRESET = const(0x02000100) # Software reset (C) +_AXS_LCD_RDDID = const(0x02000400) # Read display (R) +_AXS_LCD_RDNUMED = const(0x02000500) # Read Number of the Errors on DSI (R) +_AXS_LCD_RDDST = const(0x02000900) # Read display status (R) +_AXS_LCD_RDDPM = const(0x02000A00) # Read display power (R) +_AXS_LCD_RDDMADC = const(0x02000B00) # Read memory data access control (R) +_AXS_LCD_RDDIPF = const(0x02000C00) # Read Interface Pixel Format (R) +_AXS_LCD_RDDIM = const(0x02000D00) # Read display image (R) +_AXS_LCD_RDDSM = const(0x02000E00) # Read display signal (R) +_AXS_LCD_RDDSDR = const(0x02000F00) # Read display self-diagnostic result (R) +_AXS_LCD_SLPIN = const(0x02001000) # Sleep in (C) +_AXS_LCD_SLPOUT = const(0x02001100) # Sleep out (C) +_AXS_LCD_PTLON = const(0x02001200) # Partial mode on (C) +_AXS_LCD_NORON = const(0x02001300) # Partial mode off(Normal) (C) +_AXS_LCD_INVOFF = const(0x02002000) # Display inversion off (C) +_AXS_LCD_INVON = const(0x02002100) # Display inversion on (C) +_AXS_LCD_ALLPOFF = const(0x02002200) # All pixel off (C) +_AXS_LCD_ALLPON = const(0x02002300) # All pixel on (C) +_AXS_LCD_ALLPFILL = const(0x02002400) # All pixel fill given color (W) +_AXS_LCD_GAMSET = const(0x02002600) # Gamma curve set (W) +_AXS_LCD_DISPOFF = const(0x02002800) # Display off (C) +_AXS_LCD_DISPON = const(0x02002900) # Display on (C) +_AXS_LCD_CASET = const(0x02002A00) # Column address set (W) +_AXS_LCD_RASET = const(0x02002B00) # Row address set (W) +_AXS_LCD_RAMWR = const(0x02002C00) # Memory write any length MIPI/SPI/QSPI/DBI (W) +_AXS_LCD_RAMRD = const(0x02002E00) # Memory read any length SPI/QSPI/DBI (R) +_AXS_LCD_RAWFILL = const(0x02002F00) # Memory fill given color at window (W) +_AXS_LCD_PTLAR = const(0x02003000) # Partial start/end address set (W) +_AXS_LCD_PTLARC = const(0x02003100) # set_partial_columns (W) +_AXS_LCD_VSCRDEF = const(0x02003300) # Vertical scrolling definition (W) +_AXS_LCD_TEOFF = const(0x02003400) # Tearing effect line off (C) +_AXS_LCD_TEON = const(0x02003500) # Tearing effect line on (W) +_AXS_LCD_MADCTL = const(0x02003600) # Memory data access control (W) +_AXS_LCD_VSCRSADD = const(0x02003700) # Vertical scrolling start address (W) +_AXS_LCD_IDMOFF = const(0x02003800) # Idle mode off (C) +_AXS_LCD_IDMON = const(0x02003900) # Idle mode on (C) +_AXS_LCD_IPF = const(0x02003A00) # Interface pixel format (W) +_AXS_LCD_RAMWRC = const(0x02003C00) # Memory write continue any length MIPI/SPI/QSPI/DBI (W) +_AXS_LCD_RAMRDC = const(0x02003E00) # Memory read continue any length SPI/QSPI/DBI (R) +_AXS_LCD_TESCAN = const(0x02004400) # Set tear scanline (W) +_AXS_LCD_RDTESCAN = const(0x02004500) # Get tear scanline (R) +_AXS_LCD_WRDISBV = const(0x02005100) # Write display brightness value (W) +_AXS_LCD_RDDISBV = const(0x02005200) # Read display brightness value (R) +_AXS_LCD_WRCTRLD = const(0x02005300) # Write CTRL display (W) +_AXS_LCD_RDCTRLD = const(0x02005400) # Read CTRL dsiplay (R) +_AXS_LCD_RDFCHKSU = const(0x0200AA00) # Read First Checksum (R) +_AXS_LCD_RDCCHKSU = const(0x0200AA00) # Read Continue Checksum (R) +_AXS_LCD_RDID1 = const(0x0200DA00) # Read ID1 (R) +_AXS_LCD_RDID2 = const(0x0200DB00) # Read ID2 (R) +_AXS_LCD_RDID3 = const(0x0200DC00) # Read ID3 (R) +_AXS_LCD_DSTB = const(0x02009000) # Enter Deep-Standby (W) + + +def init(self): + param_buf = self._param_buf + param_mv = self._param_mv + + # Pixel size + color_size = lv.color_format_get_size(self._color_space) + if color_size == 2: + pixel_format = 0x55 + else: + pixel_format = 0x66 + + param_buf[0] = pixel_format + self.set_params(_AXS_LCD_IPF, param_mv[:1]) + + self.set_params(_AXS_LCD_TEOFF) + + # 0xD0 BRIGHTNESS + param_buf[0] = 0xD0 + self.set_params(_AXS_LCD_WRDISBV, param_mv[:1]) + + # # Disable Partial Display Mode (return to Normal Display Mode) + self.set_params(_AXS_LCD_NORON) + time.sleep_ms(10) # NOQA + + # AXS_LCD_SLPOUT + self.set_params(_AXS_LCD_SLPOUT) + time.sleep_ms(150) # NOQA + + # AXS_LCD_DISPON + self.set_params(_AXS_LCD_DISPON) + time.sleep_ms(150) # NOQA diff --git a/api_drivers/common_api_drivers/display/axs15231b/axs15231b.py b/api_drivers/common_api_drivers/display/axs15231b/axs15231b.py new file mode 100644 index 00000000..6e53af00 --- /dev/null +++ b/api_drivers/common_api_drivers/display/axs15231b/axs15231b.py @@ -0,0 +1,217 @@ +# Based on the work by straga (https://github.com/straga) +# https://github.com/straga/micropython_lcd/blob/master/device/JC3248W535/driver/axs15231b/axs15231b.py +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + + +import display_driver_framework +from micropython import const # NOQA + +import lcd_bus +import gc + +import lvgl as lv # NOQA + + +STATE_HIGH = display_driver_framework.STATE_HIGH +STATE_LOW = display_driver_framework.STATE_LOW +STATE_PWM = display_driver_framework.STATE_PWM + +BYTE_ORDER_RGB = display_driver_framework.BYTE_ORDER_RGB +BYTE_ORDER_BGR = display_driver_framework.BYTE_ORDER_BGR + +_RASET = const(0x02002B00) +_CASET = const(0x02002A00) +_MADCTL = const(0x02003600) + +_RAMWR = const(0x32002C00) +_RAMWRC = const(0x32003C00) + +_WRDISBV = const(0x02005100) + + +class AXS15231B(display_driver_framework.DisplayDriver): + + def __init__( + self, + data_bus, + display_width, + display_height, + frame_buffer1=None, + frame_buffer2=None, + reset_pin=None, + reset_state=STATE_HIGH, + power_pin=None, + power_on_state=STATE_HIGH, + backlight_pin=None, + backlight_on_state=STATE_HIGH, + offset_x=0, + offset_y=0, + color_byte_order=BYTE_ORDER_RGB, + color_space=lv.COLOR_FORMAT.RGB888, # NOQA + rgb565_byte_swap=False + ): + self.__tx_color_count = 0 + self._brightness = 0xD0 + color_size = lv.color_format_get_size(color_space) + buf_size = display_width * display_height * color_size + if isinstance(data_bus, lcd_bus.RGBBus): + buf_size = int(buf_size // 10) + + if frame_buffer1 is None: + gc.collect() + + if isinstance(data_bus, lcd_bus.RGBBus): + memory_flags = (lcd_bus.MEMORY_INTERNAL, lcd_bus.MEMORY_SPIRAM) + else: + memory_flags = ( + lcd_bus.MEMORY_INTERNAL | lcd_bus.MEMORY_DMA, + lcd_bus.MEMORY_SPIRAM | lcd_bus.MEMORY_DMA, + lcd_bus.MEMORY_INTERNAL, + lcd_bus.MEMORY_SPIRAM + ) + + for flags in memory_flags: + try: + frame_buffer1 = ( + data_bus.allocate_framebuffer(buf_size, flags) + ) + + if (flags | lcd_bus.MEMORY_DMA) == flags: + frame_buffer2 = ( + data_bus.allocate_framebuffer(buf_size, flags) + ) + + break + + except MemoryError: + frame_buffer1 = data_bus.free_framebuffer(frame_buffer1) + + if frame_buffer1 is None: + raise MemoryError( + f'Unable to allocate memory for frame buffer ({buf_size})' + # NOQA + ) + + if not isinstance(data_bus, lcd_bus.RGBBus): + if len(frame_buffer1) != buf_size: + raise MemoryError(f'The frame buffer is too small ({buf_size})') + + super().__init__( + data_bus, + display_width, + display_height, + frame_buffer1, + frame_buffer2, + reset_pin, + reset_state, + power_pin, + power_on_state, + backlight_pin, + backlight_on_state, + offset_x, + offset_y, + color_byte_order, + color_space, # NOQA + rgb565_byte_swap, + _cmd_bits=32 + ) + + def _init_bus(self): + buffer_size = len(self._frame_buffer1) + + self._data_bus.init( + self.display_width, + self.display_height, + lv.color_format_get_size(self._color_space) * 8, + buffer_size, + self._rgb565_byte_swap, + self._cmd_bits, + self._param_bits + ) + + self._disp_drv.set_flush_cb(self._flush_cb) + + if isinstance(self._data_bus, lcd_bus.RGBBus): + setattr( + self, + '_set_memory_location', + self._dummy_set_memory_location + ) + render_mode = lv.DISPLAY_RENDER_MODE.PARTIAL # NOQA + else: + render_mode = lv.DISPLAY_RENDER_MODE.DIRECT # NOQA + + self._disp_drv.set_buffers( + self._frame_buffer1, + self._frame_buffer2, + len(self._frame_buffer1), + render_mode + ) + + self._data_bus.register_callback(self._flush_ready_cb) + self.set_default() + self._disp_drv.add_event_cb( + self._on_size_change, + lv.EVENT.RESOLUTION_CHANGED, # NOQA + None + ) + + self._displays.append(self) + + def set_rotation(self, value): + if not isinstance(self._data_bus, lcd_bus.RGBBus): + raise NotImplementedError + + super().set_rotation(value) + + def set_brightness(self, value): + value = int(value / 100.0 * 255) + value = max(0x00, min(value, 0xFF)) + + self._brightness = value + + self._param_buf[0] = value + self.set_params(_WRDISBV, self._param_mv[:1]) + + def get_brightness(self): + return round(self._brightness / 255.0 * 100.0, 1) + + def _flush_ready_cb(self, *_): + self.__tx_color_count += 1 + if self.__tx_color_count == 2: + self._disp_drv.flush_ready() + self.__tx_color_count = 0 + + def _set_memory_location(self, x1: int, y1: int, x2: int, y2: int): + param_buf = self._param_buf # NOQA + + param_buf[0] = (x1 >> 8) & 0xFF + param_buf[1] = x1 & 0xFF + param_buf[2] = (x2 >> 8) & 0xFF + param_buf[3] = x2 & 0xFF + self.set_params(_CASET, self._param_mv) + + return _RAMWR + + def _flush_cb(self, _, area, color_p): + x1 = area.x1 + self._offset_x + x2 = area.x2 + self._offset_x + + y1 = area.y1 + self._offset_y + y2 = area.y2 + self._offset_y + + cmd = self._set_memory_location(x1, y1, x2, y2) + + width = x2 - x1 + 1 + height = y2 - y1 + 1 + + color_size = lv.color_format_get_size(self._color_space) + size = width * height * color_size + chunk_size = int(width * height // 2) * color_size + + data_view = color_p.__dereference__(size) + + self._data_bus.tx_color(cmd, data_view[:chunk_size], x1, y1, x2, y2, + self._rotation, self._disp_drv.flush_is_last()) + self._data_bus.tx_color(_RAMWRC, data_view[chunk_size:], x1, y1, x2, y2, + self._rotation, self._disp_drv.flush_is_last()) diff --git a/api_drivers/common_api_drivers/display/driver_use_exmple.py b/api_drivers/common_api_drivers/display/driver_use_exmple.py index acbedb57..84282cdb 100644 --- a/api_drivers/common_api_drivers/display/driver_use_exmple.py +++ b/api_drivers/common_api_drivers/display/driver_use_exmple.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + from micropython import const _WIDTH = const(480) diff --git a/api_drivers/common_api_drivers/display/gc9107/_gc9107_init.py b/api_drivers/common_api_drivers/display/gc9107/_gc9107_init.py new file mode 100644 index 00000000..f7a31e74 --- /dev/null +++ b/api_drivers/common_api_drivers/display/gc9107/_gc9107_init.py @@ -0,0 +1,181 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + +import time +from micropython import const # NOQA +import lvgl as lv + +_SLPOUT = const(0x11) +_INVON = const(0x21) +_DISPON = const(0x29) +_TEON = const(0x35) +_MADCTL = const(0x36) +_COLMOD = const(0x3A) +_DFC = const(0xB6) +_VREG1ACTL = 0xC3 +_VREG1BCTL = 0xC4 +_VREG2ACTL = 0xC9 +_DOCA = const(0xE8) +_REG_ENA2 = const(0xEF) +_SET_GAMMA1 = const(0xF0) +_SET_GAMMA2 = const(0xF1) +_SET_GAMMA3 = const(0xF2) +_SET_GAMMA4 = const(0xF3) +_REG_ENA1 = const(0xFE) + + +def init(self): + param_buf = bytearray(12) + param_mv = memoryview(param_buf) + + self.set_params(_REG_ENA2) + + param_buf[0] = 0x14 + self.set_params(0xEB, param_mv[:1]) + + self.set_params(_REG_ENA1) + self.set_params(_REG_ENA2) + + param_buf[0] = 0x14 + self.set_params(0xEB, param_mv[:1]) + + param_buf[0] = 0x40 + self.set_params(0x84, param_mv[:1]) + + param_buf[0] = 0xFF + self.set_params(0x85, param_mv[:1]) + self.set_params(0x86, param_mv[:1]) + self.set_params(0x87, param_mv[:1]) + + param_buf[0] = 0x0A + self.set_params(0x88, param_mv[:1]) + + param_buf[0] = 0x21 + self.set_params(0x89, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x8A, param_mv[:1]) + + param_buf[0] = 0x80 + self.set_params(0x8B, param_mv[:1]) + + param_buf[0] = 0x01 + self.set_params(0x8C, param_mv[:1]) + self.set_params(0x8D, param_mv[:1]) + + param_buf[0] = 0xFF + self.set_params(0x8E, param_mv[:1]) + self.set_params(0x8F, param_mv[:1]) + + param_buf[:2] = bytearray([0x00, 0x20]) + self.set_params(_DFC, param_mv[:2]) + + color_size = lv.color_format_get_size(self._color_space) + if color_size == 2: # NOQA + pixel_format = 0x55 + elif color_size == 3: + pixel_format = 0x77 + else: + raise RuntimeError( + f'{self.__class__.__name__} IC only supports ' + 'lv.COLOR_FORMAT.RGB565 or lv.COLOR_FORMAT.RGB888' + ) + + param_buf[0] = pixel_format + self.set_params(_COLMOD, param_mv[:1]) + + param_buf[0] = ( + self._madctl( + self._color_byte_order, + self._ORIENTATION_TABLE # NOQA + ) + ) + self.set_params(_MADCTL, param_mv[:1]) + + param_buf[:5] = bytearray([0x08, 0x08, 0x08, 0x08, 0x08]) + self.set_params(0x90, param_mv[:5]) + + param_buf[0] = 0x06 + self.set_params(0xBD, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0xBC, param_mv[:1]) + + param_buf[:3] = bytearray([0x60, 0x01, 0x04]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[0] = 0x13 + self.set_params(_VREG1ACTL, param_mv[:1]) + self.set_params(_VREG1BCTL, param_mv[:1]) + + param_buf[0] = 0x22 + self.set_params(_VREG2ACTL, param_mv[:1]) + + param_buf[0] = 0x11 + self.set_params(0xBE, param_mv[:1]) + + param_buf[:2] = bytearray([0x10, 0x0E]) + self.set_params(0xE1, param_mv[:2]) + + param_buf[:3] = bytearray([0x21, 0x0c, 0x02]) + self.set_params(0xDF, param_mv[:3]) + + param_buf[:6] = bytearray([0x45, 0x09, 0x08, 0x08, 0x26, 0x2A]) + self.set_params(_SET_GAMMA1, param_mv[:6]) + + param_buf[:6] = bytearray([0x43, 0x70, 0x72, 0x36, 0x37, 0x6F]) + self.set_params(_SET_GAMMA2, param_mv[:6]) + + param_buf[:6] = bytearray([0x45, 0x09, 0x08, 0x08, 0x26, 0x2A]) + self.set_params(_SET_GAMMA3, param_mv[:6]) + + param_buf[:6] = bytearray([0x43, 0x70, 0x72, 0x36, 0x37, 0x6F]) + self.set_params(_SET_GAMMA4, param_mv[:6]) + + param_buf[:2] = bytearray([0x1B, 0x0B]) + self.set_params(0xED, param_mv[:2]) + + param_buf[0] = 0x77 + self.set_params(0xAE, param_mv[:1]) + + param_buf[0] = 0x63 + self.set_params(0xCD, param_mv[:1]) + + param_buf[:9] = bytearray([ + 0x07, 0x07, 0x04, 0x0E, 0x0F, 0x09, 0x07, 0x08, 0x03]) + self.set_params(0x70, param_mv[:9]) + + param_buf[0] = 0x34 + self.set_params(_DOCA, param_mv[:1]) + + param_buf[:12] = bytearray([ + 0x18, 0x0D, 0x71, 0xED, 0x70, 0x70, 0x18, 0x0F, 0x71, 0xEF, 0x70, 0x70]) + self.set_params(0x62, param_mv[:12]) + + param_buf[:12] = bytearray([ + 0x18, 0x11, 0x71, 0xF1, 0x70, 0x70, 0x18, 0x13, 0x71, 0xF3, 0x70, 0x70]) + self.set_params(0x63, param_mv[:12]) + + param_buf[:7] = bytearray([0x28, 0x29, 0xF1, 0x01, 0xF1, 0x00, 0x07]) + self.set_params(0x64, param_mv[:7]) + + param_buf[:10] = bytearray([ + 0x3C, 0x00, 0xCD, 0x67, 0x45, 0x45, 0x10, 0x00, 0x00, 0x00]) + self.set_params(0x66, param_mv[:10]) + + param_buf[:10] = bytearray([ + 0x00, 0x3C, 0x00, 0x00, 0x00, 0x01, 0x54, 0x10, 0x32, 0x98]) + self.set_params(0x67, param_mv[:10]) + + param_buf[:7] = bytearray([0x10, 0x85, 0x80, 0x00, 0x00, 0x4E, 0x00]) + self.set_params(0x74, param_mv[:7]) + + param_buf[:2] = bytearray([0x3e, 0x07]) + self.set_params(0x98, param_mv[:2]) + + self.set_params(_TEON) + self.set_params(_INVON) + + self.set_params(_SLPOUT) + time.sleep_ms(120) # NOQA + self.set_params(_DISPON) + time.sleep_ms(20) # NOQA diff --git a/api_drivers/common_api_drivers/display/gc9107/gc9107.py b/api_drivers/common_api_drivers/display/gc9107/gc9107.py new file mode 100644 index 00000000..62299c31 --- /dev/null +++ b/api_drivers/common_api_drivers/display/gc9107/gc9107.py @@ -0,0 +1,47 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + +from micropython import const # NOQA + +import lvgl as lv # NOQA +import lcd_bus # NOQA +import display_driver_framework + + +STATE_HIGH = display_driver_framework.STATE_HIGH +STATE_LOW = display_driver_framework.STATE_LOW +STATE_PWM = display_driver_framework.STATE_PWM + +BYTE_ORDER_RGB = display_driver_framework.BYTE_ORDER_RGB +BYTE_ORDER_BGR = display_driver_framework.BYTE_ORDER_BGR + + +_MADCTL_MH = const(0x04) # Refresh 0=Left to Right, 1=Right to Left +_MADCTL_BGR = const(0x08) # BGR color order +_MADCTL_ML = const(0x10) # Refresh 0=Top to Bottom, 1=Bottom to Top +_MADCTL_MV = const(0x20) # 0=Normal, 1=Row/column exchange +_MADCTL_MX = const(0x40) # 0=Left to Right, 1=Right to Left +_MADCTL_MY = const(0x80) # 0=Top to Bottom, 1=Bottom to Top + + +class GC9107(display_driver_framework.DisplayDriver): + + _ORIENTATION_TABLE = ( + 0, + _MADCTL_MX | _MADCTL_MV, + _MADCTL_MY | _MADCTL_MX, + _MADCTL_MY | _MADCTL_MV + ) + + def _set_memory_location(self, x1, y1, x2, y2): + if self._rotation in (0, 2): + x1 += 2 + x2 += 2 + y1 += 1 + y2 += 1 + else: + x1 += 1 + x2 += 1 + y1 += 2 + y2 += 2 + + return display_driver_framework.DisplayDriver(self, x1, y1, x2, y2) diff --git a/api_drivers/common_api_drivers/display/gc9a01/_gc9a01_init.py b/api_drivers/common_api_drivers/display/gc9a01/_gc9a01_init.py index 1dc436cc..f7a31e74 100644 --- a/api_drivers/common_api_drivers/display/gc9a01/_gc9a01_init.py +++ b/api_drivers/common_api_drivers/display/gc9a01/_gc9a01_init.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import time from micropython import const # NOQA import lvgl as lv diff --git a/api_drivers/common_api_drivers/display/gc9a01/gc9a01.py b/api_drivers/common_api_drivers/display/gc9a01/gc9a01.py index fab8cd0c..df8b4b86 100644 --- a/api_drivers/common_api_drivers/display/gc9a01/gc9a01.py +++ b/api_drivers/common_api_drivers/display/gc9a01/gc9a01.py @@ -1,4 +1,5 @@ -import time +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + from micropython import const # NOQA import lvgl as lv # NOQA diff --git a/api_drivers/common_api_drivers/display/hx8357.wip/_hx8357c_init.py b/api_drivers/common_api_drivers/display/hx8357.wip/_hx8357c_init.py new file mode 100644 index 00000000..7a76c694 --- /dev/null +++ b/api_drivers/common_api_drivers/display/hx8357.wip/_hx8357c_init.py @@ -0,0 +1 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser diff --git a/api_drivers/common_api_drivers/display/hx8357c/hx8357c.py b/api_drivers/common_api_drivers/display/hx8357.wip/hx8357c.py similarity index 99% rename from api_drivers/common_api_drivers/display/hx8357c/hx8357c.py rename to api_drivers/common_api_drivers/display/hx8357.wip/hx8357c.py index 9600fd44..c92064fd 100644 --- a/api_drivers/common_api_drivers/display/hx8357c/hx8357c.py +++ b/api_drivers/common_api_drivers/display/hx8357.wip/hx8357c.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + ''' // Configure HX8357C display diff --git a/api_drivers/common_api_drivers/display/hx8357b/_hx8357b_init.py b/api_drivers/common_api_drivers/display/hx8357b/_hx8357b_init.py index efd5f40f..b910108d 100644 --- a/api_drivers/common_api_drivers/display/hx8357b/_hx8357b_init.py +++ b/api_drivers/common_api_drivers/display/hx8357b/_hx8357b_init.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import time from micropython import const # NOQA diff --git a/api_drivers/common_api_drivers/display/hx8357b/hx8357b.py b/api_drivers/common_api_drivers/display/hx8357b/hx8357b.py index 59ee2484..955d5ce5 100644 --- a/api_drivers/common_api_drivers/display/hx8357b/hx8357b.py +++ b/api_drivers/common_api_drivers/display/hx8357b/hx8357b.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import display_driver_framework diff --git a/api_drivers/common_api_drivers/display/hx8357c/_hx8357c_init.py b/api_drivers/common_api_drivers/display/hx8357c/_hx8357c_init.py deleted file mode 100644 index e69de29b..00000000 diff --git a/api_drivers/common_api_drivers/display/hx8357d/_hx8357d_init.py b/api_drivers/common_api_drivers/display/hx8357d/_hx8357d_init.py index 05f4726a..8ade855c 100644 --- a/api_drivers/common_api_drivers/display/hx8357d/_hx8357d_init.py +++ b/api_drivers/common_api_drivers/display/hx8357d/_hx8357d_init.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import time from micropython import const # NOQA diff --git a/api_drivers/common_api_drivers/display/hx8357d/hx8357d.py b/api_drivers/common_api_drivers/display/hx8357d/hx8357d.py index 3c30ee15..90b91306 100644 --- a/api_drivers/common_api_drivers/display/hx8357d/hx8357d.py +++ b/api_drivers/common_api_drivers/display/hx8357d/hx8357d.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import display_driver_framework @@ -11,5 +13,3 @@ class HX8357D(display_driver_framework.DisplayDriver): pass - - diff --git a/api_drivers/common_api_drivers/display/hx8369/_hx8369_init_type1.py b/api_drivers/common_api_drivers/display/hx8369/_hx8369_init_type1.py index e91a3c45..285113a3 100644 --- a/api_drivers/common_api_drivers/display/hx8369/_hx8369_init_type1.py +++ b/api_drivers/common_api_drivers/display/hx8369/_hx8369_init_type1.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import time import lvgl as lv from micropython import const # NOQA diff --git a/api_drivers/common_api_drivers/display/hx8369/hx8369.py b/api_drivers/common_api_drivers/display/hx8369/hx8369.py index a5eb1a46..fa48f9b7 100644 --- a/api_drivers/common_api_drivers/display/hx8369/hx8369.py +++ b/api_drivers/common_api_drivers/display/hx8369/hx8369.py @@ -1,7 +1,8 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import display_driver_framework from micropython import const # NOQA -import lvgl as lv import time TYPE_A = 1 diff --git a/api_drivers/common_api_drivers/display/ili9163/_ili9163_init.py b/api_drivers/common_api_drivers/display/ili9163/_ili9163_init.py index 683ffa42..942147e0 100644 --- a/api_drivers/common_api_drivers/display/ili9163/_ili9163_init.py +++ b/api_drivers/common_api_drivers/display/ili9163/_ili9163_init.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import time from micropython import const # NOQA diff --git a/api_drivers/common_api_drivers/display/ili9163/ili9163.py b/api_drivers/common_api_drivers/display/ili9163/ili9163.py index 40f2fb01..6ced484a 100644 --- a/api_drivers/common_api_drivers/display/ili9163/ili9163.py +++ b/api_drivers/common_api_drivers/display/ili9163/ili9163.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import display_driver_framework diff --git a/api_drivers/common_api_drivers/display/ili9225/_ili9225_init.py b/api_drivers/common_api_drivers/display/ili9225/_ili9225_init.py index 48159869..d6d2c1ea 100644 --- a/api_drivers/common_api_drivers/display/ili9225/_ili9225_init.py +++ b/api_drivers/common_api_drivers/display/ili9225/_ili9225_init.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import time from micropython import const # NOQA diff --git a/api_drivers/common_api_drivers/display/ili9225/ili9225.py b/api_drivers/common_api_drivers/display/ili9225/ili9225.py index 6ff6cfe7..8c297bb8 100644 --- a/api_drivers/common_api_drivers/display/ili9225/ili9225.py +++ b/api_drivers/common_api_drivers/display/ili9225/ili9225.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import display_driver_framework from micropython import const # NOQA @@ -70,7 +72,7 @@ def _on_size_change(self, _): if self._initilized: if rotation <= 1: - value = int(not rotation) + rotation = int(not rotation) self._param_buf[0] = rotation self._param_buf[1] = 0x1C diff --git a/api_drivers/common_api_drivers/display/ili9341/_ili9341_init_type1.py b/api_drivers/common_api_drivers/display/ili9341/_ili9341_init_type1.py index 95e6f118..7b973dbe 100644 --- a/api_drivers/common_api_drivers/display/ili9341/_ili9341_init_type1.py +++ b/api_drivers/common_api_drivers/display/ili9341/_ili9341_init_type1.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import time from micropython import const # NOQA import lvgl as lv # NOQA @@ -84,7 +86,7 @@ def init(self): param_buf[0] = pixel_format self.set_params(_COLMOD, param_mv[:1]) - param_buf[:2] = bytearray([0x00, 0x13]) # 0x18 ?? + param_buf[:2] = bytearray([0x00, 0x13]) # 0x18 ?? self.set_params(_FRMCTR1, param_mv[:2]) param_buf[:3] = bytearray([0x08, 0x82, 0x27]) diff --git a/api_drivers/common_api_drivers/display/ili9341/_ili9341_init_type2.py b/api_drivers/common_api_drivers/display/ili9341/_ili9341_init_type2.py index 76bf71ba..769aea31 100644 --- a/api_drivers/common_api_drivers/display/ili9341/_ili9341_init_type2.py +++ b/api_drivers/common_api_drivers/display/ili9341/_ili9341_init_type2.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import time from micropython import const # NOQA import lvgl as lv # NOQA diff --git a/api_drivers/common_api_drivers/display/ili9341/ili9341.py b/api_drivers/common_api_drivers/display/ili9341/ili9341.py index d895b372..e4ac2c32 100644 --- a/api_drivers/common_api_drivers/display/ili9341/ili9341.py +++ b/api_drivers/common_api_drivers/display/ili9341/ili9341.py @@ -1,4 +1,5 @@ -import sys +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import display_driver_framework @@ -12,6 +13,3 @@ class ILI9341(display_driver_framework.DisplayDriver): pass - - - diff --git a/api_drivers/common_api_drivers/display/ili9481/_ili9481_init_type1.py b/api_drivers/common_api_drivers/display/ili9481/_ili9481_init_type1.py index 2ce19782..dcf17cbf 100644 --- a/api_drivers/common_api_drivers/display/ili9481/_ili9481_init_type1.py +++ b/api_drivers/common_api_drivers/display/ili9481/_ili9481_init_type1.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import time from micropython import const # NOQA @@ -110,5 +112,3 @@ def init(self): time.sleep_ms(120) # NOQA self.set_params(_DISPON) time.sleep_ms(25) # NOQA - - display_driver_framework.DisplayDriver.init(self) \ No newline at end of file diff --git a/api_drivers/common_api_drivers/display/ili9481/_ili9481_init_type2.py b/api_drivers/common_api_drivers/display/ili9481/_ili9481_init_type2.py index c328574f..7b040f45 100644 --- a/api_drivers/common_api_drivers/display/ili9481/_ili9481_init_type2.py +++ b/api_drivers/common_api_drivers/display/ili9481/_ili9481_init_type2.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import time from micropython import const # NOQA diff --git a/api_drivers/common_api_drivers/display/ili9481/_ili9481_init_type3.py b/api_drivers/common_api_drivers/display/ili9481/_ili9481_init_type3.py index 77579dc0..149cbe4c 100644 --- a/api_drivers/common_api_drivers/display/ili9481/_ili9481_init_type3.py +++ b/api_drivers/common_api_drivers/display/ili9481/_ili9481_init_type3.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import time from micropython import const # NOQA @@ -26,7 +28,7 @@ _SWRESET = const(0x01) -def init(self1): +def init(self): param_buf = bytearray(12) param_mv = memoryview(param_buf) @@ -58,7 +60,6 @@ def init(self1): param_buf[0] = 0x03 self.set_params(_VCOMCTL1, param_mv[:1]) - param_buf[0] = 0x00 param_buf[1] = 0x14 param_buf[2] = 0x33 @@ -73,7 +74,6 @@ def init(self1): param_buf[11] = 0x00 self.set_params(_GAMMASET, param_mv[:12]) - param_buf[0] = 0x00 self.set_params(_IFMODE, param_mv[:1]) diff --git a/api_drivers/common_api_drivers/display/ili9481/_ili9481_init_type4.py b/api_drivers/common_api_drivers/display/ili9481/_ili9481_init_type4.py index 65309b5c..acbce08d 100644 --- a/api_drivers/common_api_drivers/display/ili9481/_ili9481_init_type4.py +++ b/api_drivers/common_api_drivers/display/ili9481/_ili9481_init_type4.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import time from micropython import const # NOQA @@ -72,14 +74,12 @@ def init(self): param_buf[11] = 0x0C self.set_params(_GAMMASET, param_mv[:12]) - param_buf[0] = 0x00 self.set_params(_IFMODE, param_mv[:1]) param_buf[0] = 0xA0 self.set_params(0xE4, param_mv[:1]) - param_buf[0] = 0x01 self.set_params(0xF0, param_mv[:1]) diff --git a/api_drivers/common_api_drivers/display/ili9481/_ili9481_init_type5.py b/api_drivers/common_api_drivers/display/ili9481/_ili9481_init_type5.py index 15e003cb..69ee7a91 100644 --- a/api_drivers/common_api_drivers/display/ili9481/_ili9481_init_type5.py +++ b/api_drivers/common_api_drivers/display/ili9481/_ili9481_init_type5.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import time from micropython import const # NOQA diff --git a/api_drivers/common_api_drivers/display/ili9481/_ili9481_init_type6.py b/api_drivers/common_api_drivers/display/ili9481/_ili9481_init_type6.py index 9f6adf66..5c3c6fd2 100644 --- a/api_drivers/common_api_drivers/display/ili9481/_ili9481_init_type6.py +++ b/api_drivers/common_api_drivers/display/ili9481/_ili9481_init_type6.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import time from micropython import const # NOQA @@ -76,7 +78,6 @@ def init(self): param_buf[11] = 0x00 self.set_params(_GAMMASET, param_mv[:12]) - param_buf[0] = 0x00 self.set_params(_IFMODE, param_mv[:1]) @@ -144,5 +145,3 @@ def init(self): time.sleep_ms(120) # NOQA self.set_params(_DISPON) time.sleep_ms(25) # NOQA - - display_driver_framework.DisplayDriver.init(self) \ No newline at end of file diff --git a/api_drivers/common_api_drivers/display/ili9481/_ili9481_init_type7.py b/api_drivers/common_api_drivers/display/ili9481/_ili9481_init_type7.py index 0c16d7d1..e24fe564 100644 --- a/api_drivers/common_api_drivers/display/ili9481/_ili9481_init_type7.py +++ b/api_drivers/common_api_drivers/display/ili9481/_ili9481_init_type7.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import time from micropython import const # NOQA @@ -111,5 +113,3 @@ def init(self): time.sleep_ms(120) # NOQA self.set_params(_DISPON) time.sleep_ms(25) # NOQA - - display_driver_framework.DisplayDriver.init(self) \ No newline at end of file diff --git a/api_drivers/common_api_drivers/display/ili9481/_ili9481_init_type8.py b/api_drivers/common_api_drivers/display/ili9481/_ili9481_init_type8.py index 9eeef068..d2864cc3 100644 --- a/api_drivers/common_api_drivers/display/ili9481/_ili9481_init_type8.py +++ b/api_drivers/common_api_drivers/display/ili9481/_ili9481_init_type8.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import time from micropython import const # NOQA @@ -48,7 +50,6 @@ def init(self): param_buf[1] = 0x11 self.set_params(_RDNVSTAT, param_mv[:2]) - param_buf[0] = 0x00 param_buf[1] = 0x3B param_buf[2] = 0x00 diff --git a/api_drivers/common_api_drivers/display/ili9481/ili9481.py b/api_drivers/common_api_drivers/display/ili9481/ili9481.py index 9de12871..98dcd71f 100644 --- a/api_drivers/common_api_drivers/display/ili9481/ili9481.py +++ b/api_drivers/common_api_drivers/display/ili9481/ili9481.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import display_driver_framework diff --git a/api_drivers/common_api_drivers/display/ili9486/_ili9486_init.py b/api_drivers/common_api_drivers/display/ili9486/_ili9486_init.py index 8432c8d9..002a170c 100644 --- a/api_drivers/common_api_drivers/display/ili9486/_ili9486_init.py +++ b/api_drivers/common_api_drivers/display/ili9486/_ili9486_init.py @@ -1,3 +1,4 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser import time from micropython import const # NOQA diff --git a/api_drivers/common_api_drivers/display/ili9486/ili9486.py b/api_drivers/common_api_drivers/display/ili9486/ili9486.py index 8e09516c..b3fd8f1c 100644 --- a/api_drivers/common_api_drivers/display/ili9486/ili9486.py +++ b/api_drivers/common_api_drivers/display/ili9486/ili9486.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import display_driver_framework diff --git a/api_drivers/common_api_drivers/display/ili9488/_ili9488_init.py b/api_drivers/common_api_drivers/display/ili9488/_ili9488_init.py index cab27eac..ff664c53 100644 --- a/api_drivers/common_api_drivers/display/ili9488/_ili9488_init.py +++ b/api_drivers/common_api_drivers/display/ili9488/_ili9488_init.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + from micropython import const # NOQA import time import lvgl as lv # NOQA diff --git a/api_drivers/common_api_drivers/display/ili9488/ili9488.py b/api_drivers/common_api_drivers/display/ili9488/ili9488.py index ba1f251d..9e5b1073 100644 --- a/api_drivers/common_api_drivers/display/ili9488/ili9488.py +++ b/api_drivers/common_api_drivers/display/ili9488/ili9488.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import display_driver_framework from micropython import const # NOQA diff --git a/api_drivers/common_api_drivers/display/lcd_commands.py b/api_drivers/common_api_drivers/display/lcd_commands.py index 2c24d015..6ed93b8c 100644 --- a/api_drivers/common_api_drivers/display/lcd_commands.py +++ b/api_drivers/common_api_drivers/display/lcd_commands.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + # These are here as a reference of the most common commands that displays use. # this module is not meant to be loaded or imported. It is a complete waste # of memory if that is done. Most of the init commands are a fire once and done diff --git a/api_drivers/common_api_drivers/display/lt7381/_lt7381_init_type1.py b/api_drivers/common_api_drivers/display/lt7381/_lt7381_init_type1.py new file mode 100644 index 00000000..f3878485 --- /dev/null +++ b/api_drivers/common_api_drivers/display/lt7381/_lt7381_init_type1.py @@ -0,0 +1,1304 @@ +from micropython import const # NOQA +import time +import lvgl as lv +import lcd_bus + + +_H_BACK_PORCH = const(140) +_H_FRONT_PORCH = const(160) +_H_PULSE_WIDTH = const(20) + +_V_BACK_PORCH = const(20) +_V_FRONT_PORCH = const(12) +_V_PULSE_WIDTH = const(3) + +# Software Reset Register +# bits 7: Reconfigure PLL frequency +# 1: to activate reconfigure +# bits 6: Reset +# 1: to perform reset +_SRR = const(0x00) # default 0x00 + +_SSR_PLL = const(0x80) +_SSR_RST = const(0x40) + +# Chip Configuration Register +# bits 7: Check PLL Ready +# bits 6: Mask WAIT# on CS# De-assert +# 0: No Mask, WAIT# keep assert if internal state keep busy and +# cannot accept next R/W cycle, no matter CS# assert/de- +# assert. If Host cycle cannot be extended while WAIT# keep +# low, Host program should poll WAIT# and wait it goes high +# then start next access. +# 1: Mask, WAIT# de-assert when CS# de-assert. Use in Host cycle +# can be extended by WAIT# automatically. +# bits 6: Keypad-scan Enable/Disable +# bits 4 - 3: TFT Panel I/F Setting +# 11: no output +# 10: 16 bit +# 01: 18 bit +# 00: 24 bit +# bits 2: I2C Master Interface Enable/Disable +# bits 1: Serial Flash or SPI Interface Enable/Disable +# bite 0: Host Data Bus Width Selection +# 0: 8 lanes +# 1: 16 lanes +_CCR = const(0x01) # default 0x48 + +_CCR_LANE8 = const(0x00) +_CCR_LANE16 = const(0x01) +_CCR_WAIT_MASK_ON = const(0x40) +_CCR_COLOR_MASK = const(0x18) +_CCR_16BIT_COLOR = const(0x10) +_CCR_18BIT_COLOR = const(0x08) # default +_CCR_24BIT_COLOR = const(0x00) +_CCR_SFLASH = const(0x02) # default is off +_CCR_KEY_SCAN = const(0x40) # default is on + +# Memory Access Control Register +# bits 7 - 6: Host Read/Write Image Data Format +# 0xb: Direct Write, for below I/F format: +# 1. 8bits MCU I/F. +# 2. 16bits MCU I/F with 8bpp data mode 1 & 2. +# 3. 16bits MCU I/F with 16/24bpp data mode 1. +# 4. Serial SPI/I2C I/F. +# 10b: Mask high byte of each data +# (ex. 16 bit MPU I/F with 8-bpp data mode 1) +# 11b: Mask high byte of even data +# (ex. 16 bit MPU I/F with 24-bpp data mode 2) +# bits 5 - 4: Host Read Memory Direction (Only for Graphic Mode) +# 00b: Left Right then Top Bottom. +# 01b: Right Left then Top Bottom. +# 10b: Top Bottom then Left Right. +# 11b: Bottom Top then Left Right. +# bits 3: always 0x00 +# bits 2 - 1: Host Write Memory Direction (Only for Graphic Mode) +# 00b: Left Right then Top Bottom (Original) 0° +# 01b: Right Left then Top Bottom (Hor Flip) +# 10b: Top Bottom then Left Right (Rotate right 90° & Hor flip) +# 11b: Bottom Top then Left Right (Rotate left 90°) +_MACR = const(0x02) # default 0x00 + + +# rotate 180° +# VDIR (REG[12h] bit3) = 1 +# MACR_W_RLTB + + +# rotate 270° +# VDIR (REG[12h] bit3) = 1 +# MACR_W_TBLR + +_MACR_W_MASK = const(0x06) +_MACR_W_LRTB = const(0x00) +_MACR_W_RLTB = const(0x02) +_MACR_W_TBLR = const(0x04) +_MACR_W_BTLR = const(0x06) + +# Input Control Register +# bits 7: Interrupt Pin Active Level +# bits 6: External Interrupt Signal - PSM[0] Pin De-bounce +# bits 5 - 4: External Interrupt Signal - PSM[0] Pin Trigger Type +# 00b: low level trigger +# 01b: falling edge trigger +# 10b: high level trigger +# 11b: rising edge trigger +# bits 2: Text Mode Enable +# 0: Graphic mode +# 1: Text mode +# bits 1 - 0: Memory Port Read/Write Destination Selection +# 00b: Image buffer (Display RAM) for image data, pattern, user- +# characters. Support Read-modify-Write. +# 01b: Gamma table for Color Red/Green/Blue. Each color‟s +# gamma table has 256 bytes. User need specify desired +# gamma table and continuous write 256 bytes. +# 10b: Graphic Cursor RAM (only accept low 8-bits MPU data, +# similar normal register data r/w.), not support Graphic +# Cursor RAM read. It contains 4 graphic cursor sets. Each +# set has 128x16 bits. User need specify target graphic +# cursor set and continue write 256 bytes. +# 11b: Color palette RAM. It is 64x12 bits SRAM, so even address‟ +# data only low 4 bits are valid. Not support Color palette +# RAM read. User need continue write 128 bytes. +_ICR = const(0x03) # default 0x00 + +# Memory Data Read/Write Port +# bits 7 - 0: Write Function: Memory Write Data +# Data to write in memory corresponding to the setting of +# REG[03h][1:0]. Continuous data write cycle can be accepted in bulk +# data write case. +# Note: +# A. Image data in Display RAM: according MPU I/F bit width +# setting (8/16-bits), Host R/W image data format, canvas +# color depth and set canvas in block mode. +# B. Pattern data for BTE operation in Display RAM: according +# MPU I/F bit width setting (8/16-bits), Host R/W image data +# format, canvas color depth and set canvas in block mode. +# Active window‟s width and height should set as 8x8 or +# 16x16 depend on user required. +# C. User-characters in Display RAM: according MPU I/F bit +# width setting (8/16-bits), Host R/W image data format and +# set canvas in linear mode. +# D. Character code: only accept low 8-bits MPU data, similar +# to normal register R/W. For two bytes character code, +# input high byte first. To user defined Character, +# code < 8000h is half size, code >= 8000h is full size. +# E. Gamma table data: only accept low 8-bits MPU data. User +# must set “Select Gamma table sets([3Ch] Bit6-5)” to clear +# internal Gamma table‟s address counter then start to write +# data. User should program 256 bytes data to memory data +# port. +# F. Graphic Cursor RAM data: only accept low 8-bits MPU data. +# User must set “Select Graphic Cursor sets” bits to clear +# internal Graphic Cursor RAM address counter then start t +# write data. +# G. Color palette RAM data: only accept low 8-bits MPU data. +# User must program full Color palette RAM in a continuous +# 128 byte data write to memory data port and cannot change +# register address. +# Read Function: Memory Read Data +# Data to read from memory corresponding to the +# setting of REG[03h][1:0]. Continuous data read +# cycle can be accepted in bulk data read case. +# Note1: if you set this port address from different port address, +# must issue a dummy read, the first data read cycle is dummy +# read and data should be ignored. Graphic Cursor RAM & Color +# palette RAM data are not support data read function. +# Note2: read memory data is 4 bytes alignment no matter color depth +# setting. +# Note3: If user write data to Display RAM user must make sure write +# FIFO is empty before he change register number or core task +# busy status bit becomes idle +_MRWDP = const(0x04) + +# PCLK PLL Control Register 1 +# bits 7 - 6: PCLK Output Divider Ratio, OD[1:0] +# 00b: Divided by 1. +# 01b: Divided by 2. +# 10b: Divided by 3. +# 11b: Divided by 4 +# bits 5 - 1: PCLK Input Divider Ratio, R[4:0] +# The value should be 2~31. +# bits 0: PCLK Feedback Divider Ratio of Loop, N[8] +# Total 9 bits, the value should be 2~511.. +_PPLLC1 = const(0x05) # default 0x14 + +_PLLC_DIV1 = const(0x00) +_PLLC_DIV2 = const(0x40) +_PLLC_DIV3 = const(0x80) +_PLLC_DIV4 = const(0x60) + +# PCLK PLL Control Register 2 +# bits 7 - 0: PCLK PLLDIVN[7:0] +# Total 9 bits, the value should be 2~511.. +_PPLLC2 = const(0x06) # default 0x3C + +# MCLK PLL Control Register 1 +# bits 7 - 6: MCLK output divider Ratio, OD[1:0] +# 00b: Divided by 1. +# 01b: Divided by 2. +# 10b: Divided by 3. +# 11b: Divided by 4 +# bits 5 - 1: MCLK Input Divider Ratio, R[4:0] +# The value should be 2~31. +# bits 0: MCLK Feedback Divider Ratio of Loop, N[8] +# Total 9 bits, the value should be 2~511.. +_MPLLC1 = const(0x07) # default 0x14 + + +# MCLK PLL Control Register 2 +# bits 7 - 0: MCLK PLLDIVN[7:0] +# Total 9 bits, the value should be 2~511.. +_MPLLC2 = const(0x08) # default 0x85 + +# CCLK PLL Control Register 1 +# bits 7 - 6: CCLK output divider Ratio, OD[1:0] +# 00b: Divided by 1. +# 01b: Divided by 2. +# 10b: Divided by 3. +# 11b: Divided by 4 +# bits 5 - 1: CCLK Input Divider Ratio, R[4:0] +# The value should be 2~31. +# bits 0: CCLK Feedback Divider Ratio of Loop, N[8] +# Total 9 bits, the value should be 2~511.. +_CPLLC1 = const(0x09) # default 0x14 + +# CCLK PLL Control Register 2 +# bits 7 - 0: CCLK PLLDIVN[7:0] +# Total 9 bits, the value should be 2~511.. +_CPLLC2 = const(0x0A) # default 0x85 + +# Interrupt Enable Register +# bits 7: Wakeup/Resume Interrupt Enable +# bits 6: External Interrupt Input - PSM[0] Enable) +# bits 5: I2C Master Interrupt Enable +# bits 4: VSYNC Time Base Interrupt Enable +# bits 3: Keypad-scan Interrupt Enable +# bits 2: Serial Flash DMA Complete / Draw Task Finished / BTE Process +# Complete etc. Interrupt Enable +# bits 1: PWM Timer-1 Interrupt Enable +# bits 0: PWM Timer-0 Interrupt Enable +_INTEN = const(0x0B) # default 0x00 + +_INTEN_WAKE_RES_EN = const(0x80) +_INTEN_KEYPAD_EN = const(0x10) + +# Interrupt Event Flag Register +# bits 7: Wakeup/Resume Interrupt Flag +# bits 6: External Interrupt Input - PSM[0] Flag +# bits 5: I2C Master Interrupt Flag +# bits 4: VSYNC Time Base Interrupt Flag +# bits 3: Keypad-scan Interrupt Flag +# bits 2: Serial Flash DMA Complete | Draw Task Finished | BTE Process +# bits 1: PWM1 Timer Interrupt Flag +# bits 0: PPWM0 Timer Interrupt Flag +# +# all of the above flags are handled in this manner. +# Write: Clear Interrupt Flag +# 0: No Operation +# 1: Clears Interrupt Flag +# Read: Read Interrupt Flag +# 0: No Interrupt has happened +# 1: Interrupt has Happened +_INTF = const(0x0C) # default 0x00 + +# Mask Interrupt Flag Register +# bits 7: Wakeup/Resume Interrupt Flag +# bits 6: External Interrupt Input - PSM[0] Flag +# bits 5: I2C Master Interrupt Flag +# bits 4: VSYNC Time Base Interrupt Flag +# bits 3: Keypad-scan Interrupt Flag +# bits 2: Serial Flash DMA Complete | Draw Task Finished | BTE Process +# bits 1: PWM1 Timer Interrupt Flag +# bits 0: PPWM0 Timer Interrupt Flag +# +# all of the above flags are handled in this manner. +# 0: Unmask +# 1: Mask +_MINTFR = const(0x0D) # default 0x00 + +# Pull-High Control Register +# bits 5: GPIO-F[7:0] Pull-High Enable +# bits 4: GPIO-E[7:0] Pull-High Enable +# bits 3: GPIO-D[7:0] Pull-High Enable +# bits 2: GPIO-C[4:0] Pull-High Enable +# bits 1: DB[15:8] Pull- High Enable +# bits 0: DB[7:0] Pull- High Enable +# +# all of the above flags are handled in this manner. +# 0: disable pullup +# 1: enable pullup +_PUENR = const(0x0E) # default 0x00 + +# PD for GPIO/Key Function Select Register +# bits 7: PD[18] – Function Select +# 0: GPIO-D7 +# 1: KO[4] +# bits 6: PD[17] – Function Select +# 0: GPIO-D5 +# 1: KO[2] +# bits 5: PD[16] – Function Select +# 0: GPIO-D4 +# 1: KO[1] +# bits 4: PD[9] – Function Select +# 0: GPIO-D3 +# 1: KO[3] +# bits 3: PD[8] – Function Select +# 0: GPIO-D2 +# 1: KI[3] +# bits 2: PD[2] – Function Select +# 0: GPIO-D6 +# 1: KI[4] +# bits 1: PD[1] – Function Select +# 0: GPIO-D1 +# 1: KI[2] +# bits 0: PD[0] – Function Select +# 0: GPIO-D0 +# 1: KI[1] +_PSFSR = const(0x0F) # default 0x00 + +# Main/PIP Window Control Register +# bits 7: PIP-1 Window Enable/Disable +# 0: PIP-1 Window Disable +# 1: PIP-1 Window Enable +# PIP-1window always on top of PIP-2 window. +# bits 6: PIP-2 Window Enable/Disable +# 0: PIP-2 Window Disable +# 1: PIP-2 Window Enable +# PIP-1 window always on top of PIP-2 window +# bits 5: N/A +# bits 4: Select Configure PIP 1 or 2 Window’s parameters +# PIP window‟s parameter including Color Depth, Starting Address, +# Image Width, Display Coordinates, Window Coordinates, Window +# Width and Window Height. +# 0: To configure PIP 1‟s parameters. +# 1: To configure PIP 2‟s parameters. +# bits 3 - 2: Main Image Color Depth Setting +# 00b: 8bpp Generic TFT (256 color) +# 01b: 16bpp Generic TFT (65K color) +# 1xb: 24bpp Generic TFT (1.67M color) +# bits 1: N/A +# bits 0: To Control Panel’s Synchronous Signals +# 0: Sync Mode +# Enable VSYNC, HSYNC, DE +# 1: DE Mode +# Only DE enable, VSYNC & HSYNC in idle state. +_MPWCTR = const(0x10) # default 0x04 + +_MPWCTR_MAIN_COLOR_MASK = const(0x0C) +_MPWCTR_MAIN_COLOR_8BPP = const(0x00) +_MPWCTR_MAIN_COLOR_16BPP = const(0x04) +_MPWCTR_MAIN_COLOR_24BPP = const(0x08) + +# PIP Window Color Depth Setting +# bits 7 - 4: N/A +# bits 3 - 2: PIP-1 Window Color Depth Setting +# 00b: 8bpp Generic TFT (256 color) +# 01b: 16bpp Generic TFT (65K color) +# 1xb: 24bpp Generic TFT (1.67M color) +# bits 1 - 0: PIP-2 Window Color Depth Setting +# 00b: 8bpp Generic TFT (256 color) +# 01b: 16bpp Generic TFT (65K color) +# 1xb: 24bpp Generic TFT (1.67M color) +_PIPCDEP = const(0x11) # default 0x05 + +# Display Configuration Register +# bits 7: PCLK Inversion +# 0: TFT Panel fetches PD at PCLK rising edge. +# 1: TFT Panel fetches PD at PCLK falling edge. +# bits 6: Display ON/OFF +# 0b: Display Off +# 1b: Display On +# bits 5: Display Test Color Bar +# 0b: Disable +# 1b: Enable +# bits 4: MUST BE 0 +# bits 3: VDIR: Vertical Scan Direction +# 0: From Top to Bottom +# 1: From bottom to Top +# bits 2 - 0: Parallel PD[23:0] Output Sequence +# 000b: RGB +# 001b: RBG +# 010b: GRB +# 011b: GBR +# 100b: BRG +# 101b: BGR +# 110b: Gray +# 111b: Send out Idle State. All data are 0 (Black) or 1(White). +# This option has to setup with REG[13h]. +_DPCR = const(0x12) # default 0x00 + +_DPCR_PCLK_INV = const(0x80) +_DPCR_DISP_PWR = const(0x40) + +_DPCR_VDIR_MASK = const(0x20) +_DPCR_VDIR_TOP_BOT = const(0x00) +_DPCR_VDIR_BOT_TOP = const(0x20) + +_DPCR_COLOR_MASK = const(0x07) +_DPCR_COLOR_RGB = const(0x00) +_DPCR_COLOR_RBG = const(0x01) +_DPCR_COLOR_GRB = const(0x02) +_DPCR_COLOR_GBR = const(0x03) +_DPCR_COLOR_BRG = const(0x04) +_DPCR_COLOR_BGR = const(0x05) +_DPCR_COLOR_GRAY = const(0x06) + +# Panel Scan Clock and Data Setting Register +# bits 7: HSYNC Polarity +# 0: Low Active +# 1: High Active +# bits 6: VSYNC Polarity +# 0: Low Active +# 1: High Active +# bits 5: PDE Polarity +# 0: High Active +# 1: Low Active +# bits 4: PDE Idle State +# This is used to setup the PDE output status in +# Power Saving mode or Display Off. +# 0: Pin “PDE” output Low +# 1: Pin “PDE” output High +# bits 3: PCLK Idle State +# This is used to setup the PCLK output status in +# Power Saving mode or Display Off. +# 0: Pin “PCLK” output Low +# 1: Pin “PCLK” output High +# bits 2: PD Idle State +# This is used to setup the PD output status in Vertical/Horizontal +# Non-Display Period, Power Saving mode or Display Off. +# 0: Pins “PD[23:0]” output Low +# 1: Pins “PD[23:0]” output High +# bits 1: HSYNC Idle State +# This is used to setup the HSYNC output status in Power Saving mode +# or Display Off. +# 0: Pin “HSYNC” output Low +# 1: Pin “HSYNC” output High +# bits 0: VSYNC Idle State +# This is used to setup the VSYNC output status in Power Saving mode +# or Display Off. +# 0: Pin “VSYNC” output Low +# 1: Pin “VSYNC” output High +_PCSR = const(0x13) # default 0x03 + +_PCSR_HSYNC_HIGH = const(0x80) +_PCSR_HSYNC_IDLE_HIGH = const(0x02) +_PCSR_VSYNC_HIGH = const(0x40) +_PCSR_VSYNC_IDLE_HIGH = const(0x01) +_PCSR_PCLK_IDLE_HIGH = const(0x08) +_PCSR_DE_LOW = const(0x10) +_PCSR_DE_IDLE_HIGH = const(0x08) + +# Horizontal Display Width Register +# bits 7 - 0: Horizontal Display Width Setting +# This register is set to a horizontal display width. Its specified +# LCD screen resolution is 8 pixels in one unit resolution. +# +# Horizontal Display Width (pixels) = (HDWR + 1) x 8 + HDWFTR +# +# HDWFTR (REG[15h]) is the fine-tuning value for Horizontal Display +# Width. Each fine-tuning resolution is 1 pixels, and the maximum +# horizontal width is 2,048 pixels. +_HDWR = const(0x14) # default 0x4F + +# Horizontal Display Width Fine Tune Register +# bits 7 - 4: N/A +# bits 3 - 0: Horizontal Display Width Fine Tuning +# This Register is the fine-tuning value for Horizontal Display +# Width, and each fine-tuning resolution is 1 pixels. +_HDWFTR = const(0x15) # default 0x00 + +# Horizontal Non-Display Period Register +# bits 7 - 5: N/A +# bits 4 - 0: Horizontal Non-Display Period +# This register assign the Period of Horizontal Non-Display. +# It‟s also called “Back Porch”. +# +# Horizontal Non-Display Period (Pixels) = (HNDR + 1) x 8 + HNDFTR +# +# HNDFTR (REG[17h]) is the fine-tuning value for Horizontal Non- +# display Period. Each fine-tuning resolution is 1 pixels, and the +# maximum horizontal width is 2,048 pixels. +_HNDR = const(0x16) # default 0x03 + +# Horizontal Non-Display Period Fine Tune Register +# bits 7 - 4: N/A +# bits 3 - 0: Horizontal Non-Display Period Fine Tuning +# This Register is the fine-tuning value for Horizontal Non-display +# Period, and each fine-tuning resolution is 1 pixels. it is used to +# support the SYNC mode panel. +_HNDFTR = const(0x17) # default 0x06 + +# HSYNC Start Position Register +# bits 7 - 5: N/A +# bits 4 - 0: HSYNC Start Position +# This register specifies the starting address of the HSYNC. The +# starting point for the calculation is the point at which the end +# of the display area is to start producing HSYNC. The basic unit +# of each adjustment is 8pixel. It‟s also called “Front Porch”. +# +# HSYNC Start Position = (HSTR + 1) x 8 +# +_HSTR = const(0x18) # default 0x1F + +# HSYNC Pulse Width Register +# bits 7 - 5: N/A +# bits 4 - 0: HSYNC Pulse Width +# HSYNC Pulse Width (Pixels) = (HPW + 1) x 8 +_HPWR = const(0x19) # default 0x00 + +# Vertical Display Height Register +# bits 10 - 0: Vertical Display Height +# REG[1Ah] mapping to VDHR [7:0] +# REG[1Bh] bit[2:0] mapping to VDHR [10:8], bit[7:3] are not used. +# The height of the vertical display is in line, and the formula +# is as follows: +# +# Vertical Display Height (Line) = VDHR + 1 +# +_VDHR_L = const(0x1A) # default 0xDF +_VDHR_H = const(0x1B) + +# Vertical Non-Display Period Register +# bits 9 - 0: Vertical Non-Display Period +# REG[1Ch] mapping to VNDR [7:0] +# REG[1Dh] bit[1:0] mapping to VNDR [9:8], REG[1Dh] bit[7:2] are +# not used. +# The formula is as follows: +# +# Vertical Non-Display Period (Line)= (VNDR + 1) +_VNDR_L = const(0x1C) # default 0x15 +_VNDR_H = const(0x1D) + +# VSYNC Start Position Register +# bits 7 - 0: The starting position from the end of display area to +# the beginning of VSYNC. +_VSTR = const(0x1E) # default 0x0B + +# VSYNC Pulse Width Register +# bits 7 - 6: N/A +# bits 5 - 0: VSYNC Pulse Width +# VSYNC Pulse Width (Line)= (VPWR + 1) +_VPWR = const(0x1F) # default 0x00 + +# Main Image Start Address +# bits 31 - 0: Main Image Start Address +# REG[20h] mapping to MISA[7:0], **bit[1:0] must be 0. +# REG[21h] mapping to MISA[15:8] +# REG[22h] mapping to MISA[23:16] +# REG[23h] mapping to MISA[31:24] +_MISA_1 = const(0x20) # default 0x00 +_MISA_2 = const(0x21) +_MISA_3 = const(0x22) +_MISA_4 = const(0x23) + +# Main Image Width +# bits 12 - 0: Main Image Width +# The unit is pixel, which is the pixel that represents the +# horizontal width of the actual LCD. The maximum setting is +# 8,192 pixels. +# REG[24h] mapping to MIW[7:0], bit[1:0] must be 0. +# REG[25h] bit[4:0] mapping to MIW[12:8], bit[7:5] are not used.. +_MIW_L = const(0x24) # default 0x00 +_MIW_H = const(0x25) + +# Main Window Upper-Left Corner X-Coordinates +# bits 12 - 0: Main Window Upper-Left Corner X-Coordinates +# The Unit is pixel. The sum of X-Coordinates plus Horizontal +# Display Width cannot be greater than 8,191. +# REG[26h] mapping to MWULX[7:0], bit[1:0] must be 0. +# REG[27h] bit[4:0] mapping to MWULX [12:8], bit[7:5] are not used. +_MWULX_L = const(0x26) # default 0x00 +_MWULX_H = const(0x27) + +# Main Window Upper-Left Corner Y-Coordinates +# bits 12 - 0: Main Window Upper-Left Corner Y-Coordinates +# Unit: Pixel. Range is between 0 and 8,191. +# REG[28h] mapping to MWULY[7:0] +# REG[29h] bit[4:0] mapping to MWULY [12:8], bit[7:5] are not used. +_MWULY_L = const(0x28) # default 0x00 +_MWULY_H = const(0x29) + +# PIP Window 1 or 2 Display Upper-Left Corner X-Coordinates +# bits 12 - 0: PIP Window Display Upper-Left Corner X-Coordinates +# Unit: Pixel. Y-axis coordinates should less than vertical display +# height. According to bit of Select Configure PIP 1 or 2 Window‟s +# parameters(REG[10h]), value will be configured for relative +# PIP window. +# REG[2Ah] mapping to PWDULX[7:0], bit[1:0] must be 0. +# REG[2Bh] bit[4:0] mapping to PWDULX[12:8], bit[7:5] are not used. +_PWDULX_L = const(0x2A) # default 0x00 +_PWDULX_H = const(0x2B) + +# PIP Window 1 or 2 Display Upper-Left corner Y-Coordinates +# bits 12 - 0: PIP Window Display Upper-Left Corner Y-Coordinates +# Unit: Pixel. Y-axis coordinates should less than vertical display +# height. According to bit of Select Configure PIP 1 or 2 Window‟s +# parameters(REG[10h]), value will be configured for relative +# PIP window. +# REG[2Ah] mapping to PWDULX[7:0], bit[1:0] must be 0. +# REG[2Bh] bit[4:0] mapping to PWDULX[12:8], bit[7:5] are not used. +_PWDULY_L = const(0x2C) # default 0x00 +_PWDULY_H = const(0x2D) + +# PIP Image 1 or 2 Start Address +# bits 31 - 0: PIP Image Start Address +# According to bit of Select Configure PIP 1 or 2 Window‟s +# parameters. +# Function bit will be configured for relative PIP window. +# REG[2Eh] mapping to PISA[7:0], bit[1:0] must be 0. +# REG[2Fh] mapping to PISA [15:8] +# REG[30h] mapping to PISA [23:16] +# REG[31h] mapping to PISA [31:24] +_PISA_1 = const(0x2E) # default 0x00 +_PISA_2 = const(0x2F) +_PISA_3 = const(0x30) +_PISA_4 = const(0x31) + +# PIP Image 1 or 2 Width +# bits 13 - 0: PIP Image Width +# Unit: Pixel. The value is physical width, and maximum value is +# 8192 pixels. +# This width should less than horizontal display width. According +# to bit of Select Configure PIP 1 or 2 Window‟s parameters, value +# will be configured for relative PIP window. +# +# REG[32h] mapping to PIW[7:0], bit[1:0] must be 0. +# REG[33h] bit[5:0] mapping to PIW[13:8], bit[7:6] are not used. +_PIW_L = const(0x32) # default 0x00 +_PIW_H = const(0x33) + +# PIP Window Image 1 or 2 Upper-Left Corner X-Coordinates +# bits 12 - 0: PIP Window Image 1 or 2 Upper-Left Corner X-Coordinates +# Unit: Pixel. The sum of X-axis coordinates plus PIP image width +# must less or equal to 8,191. +# REG[34h] mapping to PWIULX[7:0], bit[1:0] must be 0. +# REG[35h] bit[4:0] mapping to PWIULX[12:8], bit[7:5] are not used. +_PWIULX_L = const(0x34) # default 0x00 +_PWIULX_H = const(0x35) + +# PIP Window Image 1 or 2 Upper-Left Corner Y-Coordinates +# bits 12 - 0: PIP Window Image 1 or 2 Upper-Left Corner Y-Coordinates +# Unit: Pixel. The sum of Y-axis coordinates plus PIP image height +# must less or equal to 8,191. +# REG[36h] mapping to PWIULY[7:0], bit[1:0] must be 0. +# REG[37h] bit[4:0] mapping to PWIULY[12:8], bit[7:5] are not used. +_PWIULY_L = const(0x36) # default 0x00 +_PWIULY_H = const(0x37) + +# PIP Window 1 or 2 Width +# bits 13 - 0: PIP Window 1 or 2 Width +# Unit: Pixel. Maximum value is 8,192 pixels +# REG[38h] mapping to PWW[7:0], bit[1:0] must be 0. +# REG[39h] bit[5:0] mapping to PWW[13:8], bit[7:6] are not used. +_PWW_L = const(0x38) # default 0x00 +_PWW_H = const(0x39) + +# PIP Window 1 or 2 Height +# bits 13 - 0: PIP Window 1 or 2 Height +# Unit: Pixel. Maximum value is 8,192 pixels +# REG[3Ah] mapping to PWH[7:0], bit[1:0] must be 0. +# REG[3Bh] bit[5:0] mapping to PWH[13:8], bit[7:6] are not used. + +# Note 1: Pip Window Size and Starting Position in the horizontal direction is +# 8 pixels, the vertical resolution is 1 line. +# Note 2: The above registers REG[20h] ~ REG[3Bh] need to be written in turn by +# LSB to MSB. Suppose we need to set the Main Image Start Address, this +# relative register are REG[20h] to REG[23h]. Then Host must write +# Address data in turn from LSB (REG[20h]) to MSB (REG[23h]). When +# REG[23h] was written, ER-TFTMC050-3 will write complete Main Image +# Start Address to the internal register in actually +_PWH_L = const(0x3A) # default 0x00 +_PWH_H = const(0x3B) + +# Graphic / Text Cursor Control Register +# bits 7: Gamma Correction Enable +# Gamma correction is the last output stage. +# 0: Disable +# 1: Enable +# bits 6 - 5: Gamma Table Select for Host Write Gamma Data +# 00b: Gamma table for Blue +# 01b: Gamma table for Green +# 10b: Gamma table for Red +# 11b: NA +# bits 4: Graphic Cursor Enable +# Graphic cursor will auto disable if VDIR (REG[12h] bit3) +# set as “1”. +# 0: Disable +# 1: Enable +# bits 3 - 2: Graphic Cursor Selection +# Select one from four graphic cursor types. (00b to 11b) +# 00b: Graphic Cursor Set 1 +# 01b: Graphic Cursor Set 2 +# 10b: Graphic Cursor Set 3 +# 11b: Graphic Cursor Set 4 +# bits 1: Text Cursor Enable +# Note: Text cursor & Graphic cursor cannot enable simultaneously. +# Graphic cursor has higher priority than Text cursor if +# enabled simultaneously. +# 0: Disable +# 1: Enable +# bits 0: Text Cursor Blinking Enable +# 0: Disable +# 1: Enable +_GTCCR = const(0x3C) # default 0x00 + +# Blink Time Control Register +# bits 7 - 0: Text Cursor Blink Time Setting +# 00h: 1 Frame Cycle Time +# 01h: 2 Frames Cycle Time +# 02h: 3 Frames Cycle Time +# ... +# FFh: 256 frames Cycle Time +_BTCR = const(0x3D) # default 0x00 + +# Text Cursor Horizontal Size Register +# bits 7 - 5: N/A +# bits 4 - 0: Text Cursor Horizontal Size Setting +# Note: When character is enlarged, the cursor setting will multiply +# the same times as the character enlargement. +# 00000b: 1 Pixel +# 00001b: 2 Pixels +# ... +# 11111b: 32 Pixels +_CURHS = const(0x3E) # default 0x07 + +# Text Cursor Vertical Size Register +# bits 7 - 5: N/A +# bits 4 - 0: Text Cursor Vertical Size Setting +# Unit: Pixel, Zero-based number. Value “0” means 1 pixel. +# Note: When character is enlarged, the cursor setting will multiply +# the same times as the character enlargement. +_CURVS = const(0x3F) # default 0x00 + +# Graphic Cursor Horizontal Position Register +# bits 12 - 0: Graphic Cursor Horizontal Position +# REG[40h] mapping to GCHP[7:0] +# REG[41h] bit[4:0] mapping to GCHP[12:8], bit[7:5] are not used +_GCHP_L = const(0x40) # default 0x00 +_GCHP_H = const(0x41) + +# Graphic Cursor Vertical Position Register +# bits 12 - 0: Graphic Cursor Vertical Position +# REG[42h] mapping to GCVP[7:0] +# REG[43h] bit[4:0] mapping to GCVP[12:8], bit[7:5] are not used. +_GCVP_L = const(0x42) # default 0x00 +_GCVP_H = const(0x43) + +# Graphic Cursor Color 0 +# bits 7 - 0: Graphic Cursor Color 0 with 256 Colors +# RGB Format [7:0] = RRRGGGBB +_GCC0 = const(0x44) # default 0x00 + +# Graphic Cursor Color 1 +# bits 7 - 0: Graphic Cursor Color 1 with 256 Colors +# RGB Format [7:0] = RRRGGGBB +_GCC1 = const(0x45) # default 0x00 + +# Canvas Start Address +# bits 31 - 0: Start Address of Canvas +# These Registers will be ignored if canvas in linear Addressing +# mode. +# REG[50h] mapping to CVSSA[7:0], bit[1:0] must be 0. +# REG[51h] mapping to CVSSA[15:8] +# REG[52h] mapping to CVSSA[23:16] +# REG[53h] mapping to CVSSA[31:24] +_CVSSA_1 = const(0x50) # default 0x00 +_CVSSA_2 = const(0x51) +_CVSSA_3 = const(0x52) +_CVSSA_4 = const(0x53) + +# Canvas Image Width +# bits 13 - 0: Canvas Image Width +# Width = Real Image Width +# These Registers will be ignored if canvas in linear +# Addressing mode. +# REG[54h] mapping to CVS_IMWTH[7:0], bit[1:0] must be 0. +# REG[55h] bit[5:0] mapping to CVS_IMWTH[13:8], bit[7:6] +# are not used. +_CVS_IMWTH_L = const(0x54) # default 0x00 +_CVS_IMWTH_H = const(0x55) # default 0x00 + +# Active Window Upper-Left Corner X-Coordinates +# bits 12 - 0: Active Window Upper-Left Corner X-Coordinates +# Unit: Pixel. The sum of X-axis coordinates plus Active Window width +# cannot large than 8,191. +# These Registers will be ignored if canvas in linear Addressing mode. +# REG[56h] mapping to AWUL_X[7:0] +# REG[57h] bit[4:0] mapping to AWUL_X[12:8], bit[7:5] are not used. +_AWUL_X_L = const(0x56) # default 0x00 +_AWUL_X_H = const(0x57) # default 0x00 + +# Active Window Upper-Left Corner Y-Coordinates +# bits 12 - 0: Active Window Upper-Left Corner Y-Coordinates +# Unit: Pixel. The sum of y-axis coordinates plus Active Window width +# cannot large than 8,191. +# These Registers will be ignored if canvas in linear Addressing mode. +# REG[58h] mapping to AWUL_Y[7:0] +# REG[59h] bit[4:0] mapping to AWUL_Y[12:8], bit[7:5] are not used. +_AWUL_Y_L = const(0x58) # default 0x00 +_AWUL_Y_H = const(0x59) # default 0x00 + +# Active Window Width +# bits 13 - 0: Active Window Width +# Unit: Pixel. The value is width. +# cannot large than 8,191. +# These Registers will be ignored if canvas in linear +# Addressing mode. +# REG[5Ah] mapping to AW_WTH[7:0] +# REG[5Bh] bit[5:0] mapping to AW_WTH[13:8], bit[7:6] +# are not used. +_AW_WTH_L = const(0x5A) # default 0x00 +_AW_WTH_H = const(0x5B) # default 0x00 + +# Active Window Height +# bits 13 - 0: Active Window Height +# Unit: Pixel. The value is height. +# cannot large than 8,191. +# These Registers will be ignored if canvas in linear +# Addressing mode. +# REG[5Ah] mapping to AW_WTH[7:0] +# REG[5Bh] bit[5:0] mapping to AW_WTH[13:8], bit[7:6] +# are not used. +_AW_HT_L = const(0x5C) # default 0x00 +_AW_HT_H = const(0x5D) # default 0x00 + +# Graphic Read/Write X-Coordinate Register +# bits 12/15 - 0: Set Graphic Read/Write X-Coordinate position +# When DPRAM in Linear mode: Write address [15:0], Unit: Byte. +# When DPRAM in Block mode: Write X-Coordinate [12:0], Unit: Pixel. +# REG[5Fh] mapping to CURH[7:0] +# REG[60h] bit[4:0] mapping to CURH[12:8], bit[7:5 +# are not used. +_CURH_L = const(0x5F) # default 0x00 +_CURH_H = const(0x60) # default 0x00 + +# Graphic Read/Write Y-Coordinate Register +# bits 12/31 - 0: Set Graphic Read/Write Y-Coordinate position +# When DPRAM in Linear mode: Write address [31:16], Unit: Byte. +# When DPRAM in Block mode: Write Y-Coordinate [12:0], Unit: Pixel. +# REG[61h] mapping to CURV[7:0] +# REG[62h] bit[4:0] mapping to CURV[12:8], bit[7:5 +# are not used. +_CURV_L = const(0x61) # default 0x00 +_CURV_H = const(0x62) # default 0x00 + +# Color Depth of Canvas & Active Window +# bits 7 - 4: N/A +# bits 3: Select What will Read Back from Graphic Read/Write +# Position Register +# 0: Read back Graphic Write position +# 1: Read back Graphic Read position (Pre-fetch Address) +# bits 2: Canvas Addressing Mode +# 0: Block mode (X-Y coordinates addressing) +# 1: Linear mode +# bits 1 - 0: Canvas Image’s Color Depth & Memory R/W Data Width +# In Block Mode: +# 00b: 8bpp +# 01b: 16bpp +# 1xb: 24bpp +# Note: Monochrome data can input with any one color depth depends +# on proper image width. +# In Linear Mode: +# 00: 8-bits memory data read/write. +# 01: 16-bits memory data read/write +_AW_COLOR = const(0x5E) # default 0x00 + +_AW_COLOR_CANVAS_MASK = const(0x03) +_AW_COLOR_CANVAS_8BPP = const(0x00) +_AW_COLOR_CANVAS_16BPP = const(0x01) +_AW_COLOR_CANVAS_24BPP = const(0x02) +_AW_COLOR_LINEAR_ADDR = const(0x04) +_AW_COLOR_BLOCK_ADDR = const(0x00) + +# PWM Prescaler Registe +# bits 7 - 0: PWM Prescaler Registe +# This register determine the pre-scaler value for Timer 0 and 1. +# The Base Frequency is: +# Core_Freq / (Prescaler + 1) +_PSCLR = const(0x84) # default 0x00 + +# PWM Clock Mux Register +# bits 7 - 6: Setup PWM Timer-1 Divisor +# (Select 2nd Clock Divider‟s MUX Input for PWM Timer-1) +# 00b: 1 +# 01b: 1/2 +# 10b: 1/4 +# 11b: 1/8 +# bits 5 - 4: Setup PWM Timer-0 Divisor +# (Select 2nd Clock Divider‟s MUX Input for PWM Timer-0) +# 00b: 1 +# 01b: 1/2 +# 10b: 1/4 +# 11b: 1/8 +# bits 3 - 2: PWM[1] Function Control +# 0xb: PWM[1] output system error flag +# (Scan FIFO POP error or Memory access out of range) +# 10b: PWM[1] output PWM timer 1 event or invert of PWM timer 0 +# 11b: PWM[1] output Oscillator Clock +# bits 1 - 0: PWM[0] Function Control +# 0xb: PWM[0] becomes GPIOC[7] +# 10b: PWM[0] output PWM Timer 0 +# 11b: PWM[0] output Core Clock (CCLK). +_PMUXR = const(0x85) # default 0x00 + +_PMUXR_TIMER1_DIV_MASK = const(0x60) +_PMUXR_TIMER1_DIV1 = const(0x00) +_PMUXR_TIMER1_DIV2 = const(0x40) +_PMUXR_TIMER1_DIV4 = const(0x80) +_PMUXR_TIMER1_DIV8 = const(0x60) +_PMUXR_TIMER0_DIV_MASK = const(0x30) +_PMUXR_TIMER0_DIV1 = const(0x00) +_PMUXR_TIMER0_DIV2 = const(0x10) +_PMUXR_TIMER0_DIV4 = const(0x20) +_PMUXR_TIMER0_DIV8 = const(0x30) +_PMUXR_PWM1_MASK = const(0x0C) +_PMUXR_PWM1_SYS_ERR = const(0x04) +_PMUXR_PWM1_TIMER1 = const(0x08) +_PMUXR_PWM1_OSC_CLOCK = const(0x0C) +_PMUXR_PWM0_MASK = const(0x03) +_PMUXR_PWM0_TIMER0 = const(0x02) +_PMUXR_PWM0_CORE_CLOCK = const(0x03) + +# PWM Configuration Register +# bits 7: N/A +# bits 6: PWM Timer-1 Output Inverter On/Off +# 0 = Inverter off +# 1 = Inverter on for PWM1 +# bits 5: PWM Timer-1 Auto Reload On/Off +# 0: One-Shot Mode +# 1: Interval Mode (Auto Reload) +# bits 4: PWM Timer-1 Start/Stop +# 0: Stop +# 1: Start +# bits 3: PWM Timer-0 Dead Zone Enable +# 0: Disable +# 1: Enable +# bits 2: PWM Timer-0 Output Inverter On/Off +# 0 = Inverter off +# 1 = Inverter on for PWM0 +# bits 1: PWM Timer-0 Auto Reload On/Off +# 0: One-Shot Mode +# 1: Interval Mode (Auto Reload) +# bits 0: PWM Timer-0 Start/Stop +# In Interval Mode, Host need program it as 0 to stop PWM timer. In +# One-shot Mode, this bit will auto clear. +# The Host may read this bit to know current PWMx is running or stopped. +# 0: Stop +# 1: Start + +_PCFGR = const(0x86) # default 0x02 + +_PCFGR_TIMER1_INVERT = const(0x40) +_PCFGR_TIMER1_RESTART_AUTO = const(0x20) +_PCFGR_TIMER1_START = const(0x10) +_PCFGR_TIMER0_DEAD_ZONE = const(0x08) +_PCFGR_TIMER0_INVERT = const(0x04) +_PCFGR_TIMER0_RESTART_AUTO = const(0x02) +_PCFGR_TIMER0_START = const(0x01) + + +# Timer-0 Dead Zone Length Register +# bits 7 - 0: Timer-0 Dead Zone Length Register +# These 8 bits determine the dead zone length. The 1 unit time of +# the dead zone length is equal to Timer 0. +_DZ_LENGTH = const(0x87) # default 0x00 + +# Timer-0 Compare Buffer Register +# bits 15 - 0: Timer-0 compare Buffer Register +# The Timer-0 Compare Buffer Register have a total of 16bits. When +# the counter is equal to or less than the value of this register, +# and if INV_ON bit is Off, then PWM1 output is high level. +# +# REG[88h] mapping to TCMPB0 [7:0] +# REG[89h] mapping to TCMPB0 [15:8] +_TCMPB0_L = const(0x88) # default 0x00 +_TCMPB0_H = const(0x89) + +# Timer-0 Count Buffer Register +# bits 15 - 0: Timer-0 Count Buffer Register [15:0] +# The Timer-0 count registers have a total of 16bit. When the +# counter down to 0 and the Reload_EN is enabled, the PWM will +# overloads the value of this register to the counter. When the +# PWM begins to count, the current count value can be read back +# through this register +# +# REG[8Ah] mapping to TCNTB0 [7:0] +# REG[8Bh] mapping to TCNTB0 [15:8] +_TCNTB0_L = const(0x8A) # default 0x00 +_TCNTB0_H = const(0x8B) + +# Timer-1 Compare Buffer Register +# bits 15 - 0: Timer-1 compare Buffer Register +# The Timer-1 Compare Buffer Register have a total of 16bits. When +# the counter is equal to or less than the value of this register, +# and if INV_ON bit is Off, then PWM1 output is high level. +# +# REG[8Ch] mapping to TCMPB1 [7:0] +# REG[8Dh] mapping to TCMPB1 [15:8] +_TCMPB1_L = const(0x8C) # default 0x00 +_TCMPB1_H = const(0x8D) + +# Timer-1 Count Buffer Register +# bits 15 - 0: Timer-1 Count Buffer Register [15:0] +# The Timer-1 count registers have a total of 16bit. When the +# counter down to 0 and the Reload_EN is enabled, the PWM will +# overloads the value of this register to the counter. When the +# PWM begins to count, the current count value can be read back +# through this register +# +# REG[8Eh] mapping to TCNTB1 [7:0] +# REG[8Fh] mapping to TCNTB1 [15:8] +_TCNTB1_L = const(0x8E) # default 0x00 +_TCNTB1_H = const(0x8F) + +# Power Management Register +# bits 7: Enter Power Saving State +# Note: There are 3 ways to wake up from power saving state: +# External interrupt event, Key Scan wakeup and Software +# wakeup. Write this bit to 0 will cause Software wakeup. +# It will be cleared until chip resume. MPU must wait until +# system quit from power saving state than allow to write +# other registers. User may check this bit or check status +# bit1 (power saving +# 0: Normal state or wake up from power saving state +# 1: Enter power saving state. +# bits 6 - 2: N/A +# bits 1 - 0: Power Saving Mode Definition +# 00b: NA +# 01b: Standby Mode, CCLK & PCLK will Stop. MCLK is +# provided by MPLL. +# 10b: Suspend Mode, CCLK & PCLK will Stop. MCLK is +# provided by OSC. +# 11b: Sleep Mode, All of Clocks and PLL will Stop. +_PMU = const(0xDF) # default 0x03 + +# SDRAM Attribute Register +# bits 7: SDRAM Power Saving +# 0: Execute power down command to enter power saving mode +# 1: Execute self refresh command to enter power saving mode +# bits 6: MUST BE 0 +# bits 5: SDRAM Bank Number, SDR_BANK +# Must set to 1 after reset. +# 1: 4 Banks +# bits 4 - 3: SDRAM Row Addressing, SDR_ROW +# Must set to 00 after reset. +# 00b: 2K (A0-A10) +# bits 2 - 0: SDRAM Column Addressing, SDR_COL +# Must set to 000 after reset. +# 000b: 256 (A0-A7) +# +# NOTE: 32Mb(4MB, 2Mx16) +# value: 0x20 +# description: +# Bank no:4 +# Row Size:2048 +# Column Size:256 +# +# Note: The value of register REG[E0h] must be set according to above table. +# Otherwise, the display of TFT panel will abnormal and the image +# is garbled. +_SDRAR = const(0xE0) # default 0x14 + +_SDRAR_4BANKS = const(0x20) + + +# SDRAM Mode Register & Extended Mode Register +# bits 7 - 3: Must keep 0. +# bits 2 - 0: SDRAM CAS latency, SDR_CASLAT +# Note: The suggest setting value of this register is 03h. +# This register was locked after SDR_INITDONE (REG[E4h] bit0) +# was set as 1. +# 010b: 2 SDRAM clock +# 011b: 3 SDRAM clock +# Others: Reserved +_SDRMD = const(0xE1) # default 0x03 + +_SDRMD_CASLAT_MASK = const(0x03) +_SDRMD_CASLAT_2 = const(0x02) +_SDRMD_CASLAT_3 = const(0x03) + + +# SDRAM Mode Register & Extended Mode Register +# bits 15 - 0: SDRAM Auto Refresh Interval +# The internal refresh time is determined according to the period +# specification of the SDRAM's refresh and the row size. For +# example, if the SDRAM frequency is 100MHz, SDRAM's refresh period +# Tref is 64ms, and the row size is 4,096, then the internal +# refresh time should be less than +# 64 x 10 - 3 / 4096 x 100 x 106 ~= 1562 = 61Ah.. +# Therefore the REG[E3h][ E2h] is set 030Dh. +# +# Note: If this register is set to 0000h, SDRAM automatic refresh +# will be prohibited. +# REG[E2h] mapping to SDR_REF [7:0]. +# REG[E3h] mapping to SDR_REF [15:8] +# +# NOTE: The Reference Setting of REG[E3h-E2h] +# model: ER-TFTMC0 50-3 +# REG[E3h]: 06h +# REG[E2h]: 1Ah +_SDR_REF_L = const(0xE2) # default 0x00 +_SDR_REF_H = const(0xE3) + +# SDRAM Control Register +# bits 7 - 4: Must keep 0. +# bits 3: Report Warning Condition +# Warning: condition are memory read cycle close to SDRAM maximum +# address boundary (may over maximum address minus 512 +# bytes) or out of range or SDRAM bandwidth insufficient to +# fulfill panel‟s frame rate, then this warning event will +# be latched, user could check this bit to do some +# judgments. That warning flag could be cleared by set this +# bit as 0. +# 0: Disable or Clear warning flag +# 1: Disable or Clear warning flag +# bits 2: SDRAM Timing Parameter Register Enable, SDR_PARAMEN +# 0: Disable Display RAM timing parameter registers +# 1: Enable Display RAM timing parameter registers +# bits 1: Enter Power Saving Mode, SDR_PSAVING +# 0 to 1 transition will enter power saving mode +# 1 to 0 transition will exit power saving mode +# bits 0: Start SDRAM Initialization Procedure, SDR_INITDONE +# 0 to 1 transition will execute Display RAM initialization +# procedure. Read value „1‟ means Display RAM is initialized and +# ready for access. Once it was written as 1, it cannot be +# rewrite as 0. +# 1 to 0 transition without have any operation. +# NOTE: “Write 1” will execute Display RAM initialization procedure. +_SDRCR = const(0xE4) # default 0x00 + +_SDRCR_INITDONE = const(0x01) + +# ************ NOT USED *************** + +# NOTE: The following Display RAM Timing Registers (REG[E0h-E3h]) are +# available only when SDR_PARAMEN (REG[E4] bit2) is set to 1. + +# SDRAM Timing Parameter 1 +# bits 7 - 4: Must keep 0. +# bits 3 - 0: Time from Load Mode Command to Active/Refresh Command (TMRD) +# 0000b: 1 SDRAM Clock +# 0001b: 2 SDRAM Clock +# 0010b: 3 SDRAM Clock +# ... +# 1111b: 16 SDRAM Clock +_SDRCTP1 = const(0xE0) # default 0x02 + +# SDRAM Timing Parameter 2 +# bits 7 - 4: Auto Refresh Period, TRFC +# 0h – Fh: 1 ~ 16 SDRAM Clock (As REG[E0h] bit[3:0]) +# bits 3 - 0: Time of Exit SELF Refresh-to-ACTIVE Command (TXSR) +# 0h – Fh: 1 ~ 16 SDRAM Clock +_SDRCTP2 = const(0xE1) # default 0x87 + +# SDRAM Timing Parameter 3 +# bits 7 - 4: Time of Pre-charge Command Period (TRP, 15/20ns) +# 0h – Fh: 1 ~ 16 SDRAM Clock +# bits 3 - 0: Time of WRITE Recovery Time (TWR) +# 0h – Fh: 1 ~ 16 SDRAM Clock +_SDRCTP3 = const(0xE2) # default 0x20 + +# SDRAM Timing Parameter 4 +# bits 7 - 4: Delay Time of Active-to-Read/Write (TRCD) +# 0h – Fh: 1 ~ 16 SDRAM Clock +# bits 3 - 0: Time of Active-to-Precharge (TRAS) +# 0h – Fh: 1 ~ 16 SDRAM Clock +_SDRCTP4 = const(0xE3) # default 0x26 +# ******************************* + + +def set_backlight(self, value): + self._write_reg(_PMUXR, self._pmuxr) + self._write_reg(_PSCLR, 19) + + self._pmuxr &= ~_PMUXR_TIMER1_DIV_MASK + + self._write_reg(_PMUXR, self._pmuxr) + + self._write_reg(_TCNTB1_L, 0x64) + self._write_reg(_TCNTB1_H, 0x00) + + value = min(100, max(0, int(value))) + self._backlight = value + + self._write_reg(_TCMPB1_L, value) + self._write_reg(_TCMPB1_H, 0x00) + + self._pcfgr |= _PCFGR_TIMER1_START + self._write_reg(_PCFGR, self._pcfgr) + + +def get_backlight(self): + return self._backlight + + +def init(self): + self._set_reg(_PPLLC1, 0x8A) + self._set_reg(_PPLLC2, 0x3C) + + self._set_reg(_MPLLC1, 0x8A) + self._set_reg(_MPLLC2, 0x84) + + self._set_reg(_CPLLC1, 0x8A) + self._set_reg(_CPLLC2, 0x84) + + self._set_reg(_SRR, _SSR_PLL) + time.sleep_ms(1) # NOQA + + self._pmuxr = _PMUXR_PWM1_TIMER1 | _PMUXR_PWM0_TIMER0 + self._set_reg(_PMUXR, self._pmuxr) + + self._pcfgr = _PCFGR_TIMER1_RESTART_AUTO | _PCFGR_TIMER0_RESTART_AUTO + self._set_reg(_PCFGR, self._pcfgr) + + # SDRAM + self._set_reg(_SDRAR, _SDRAR_4BANKS | 0x09) + self._set_reg(_SDRMD, _SDRMD_CASLAT_3) + + self._set_reg(_SDR_REF_L, 0xE6) + self._set_reg(_SDR_REF_H, 0x01) + self._set_reg(_SDRCR, _SDRCR_INITDONE) + + while self._wait_pin.value(): + time.sleep_ms(1) # NOQA + + time.sleep_ms(1) # NOQA + + color_size = lv.color_format_get_size(self._color_space) + if color_size not in (2, 3): # NOQA + raise RuntimeError( + 'LT7281 driver only supports 16bit and 24 bit color depths' + ) + + ccr_flag = _CCR_WAIT_MASK_ON + + if color_size == 2: + ccr_flag |= _CCR_16BIT_COLOR + else: + ccr_flag |= _CCR_24BIT_COLOR + + lanes = self._data_bus.get_lane_count() + if isinstance(self._data_bus, lcd_bus.I80Bus): + if lanes == 8: + ccr_flag |= _CCR_LANE8 + elif lanes == 16: + ccr_flag |= _CCR_LANE16 + else: + raise RuntimeError( + 'only 8 or 16 lanes is supported when using the I80Bus' + ) + + self._set_reg(_CCR, ccr_flag) + + self._macr = 0x00 + self._set_reg(_MACR, self._macr) + self._set_reg(_ICR, 0x00) + + self._dpcr = _DPCR_PCLK_INV | _DPCR_DISP_PWR | self._color_byte_order + + self._set_reg(_DPCR, self._dpcr) + + self._set_reg(_PCSR, _PCSR_HSYNC_IDLE_HIGH | _PCSR_HSYNC_IDLE_HIGH) + + if self.display_width < 8: + self._set_reg(_HDWR, 0x00) + self._set_reg(_HDWFTR, self.display_width) + else: + self._set_reg(_HDWR, int(self.display_width / 8) - 1) + self._set_reg(_HDWFTR, (self.display_width % 8) & 0xFF) + + self._set_reg(_VDHR_L, (self.display_height - 1) & 0xFF) + self._set_reg(_VDHR_H, ((self.display_height - 1) >> 8) & 0x07) + + if _H_BACK_PORCH < 8: + self._set_reg(_HNDR, 0x00) + self._set_reg(_HNDFTR, _H_BACK_PORCH & 0xFF) + else: + self._set_reg(_HNDR, int(_H_BACK_PORCH / 8) - 1) + self._set_reg(_HNDFTR, (_H_BACK_PORCH % 8) & 0xFF) + + if _H_FRONT_PORCH < 8: + self._set_reg(_HSTR, 0x00) + else: + self._set_reg(_HSTR, int(_H_FRONT_PORCH / 8) - 1) + + if _H_PULSE_WIDTH < 8: + self._set_reg(_HPWR, 0x00) + else: + self._set_reg(_HPWR, int(_H_PULSE_WIDTH / 8) - 1) + + self._set_reg(_VNDR_L, (_V_BACK_PORCH - 1) & 0xFF) + self._set_reg(0x1D, ((_V_BACK_PORCH - 1) >> 8) & 0x03) + + self._set_reg(_VSTR, (_V_FRONT_PORCH - 1) & 0xFF) + self._set_reg(_VPWR, (_V_PULSE_WIDTH - 1) & 0xFF) + + if color_size == 2: + self._set_reg(_MPWCTR, _MPWCTR_MAIN_COLOR_16BPP) + self._set_reg(_AW_COLOR, _AW_COLOR_CANVAS_16BPP) + self._set_reg(_MPWCTR, _MPWCTR_MAIN_COLOR_16BPP) + else: + self._set_reg(_MPWCTR, _MPWCTR_MAIN_COLOR_24BPP) + self._set_reg(_AW_COLOR, _AW_COLOR_CANVAS_24BPP) + self._set_reg(_MPWCTR, _MPWCTR_MAIN_COLOR_24BPP) diff --git a/api_drivers/common_api_drivers/display/lt7381/lt7381.py b/api_drivers/common_api_drivers/display/lt7381/lt7381.py new file mode 100644 index 00000000..a1d9621e --- /dev/null +++ b/api_drivers/common_api_drivers/display/lt7381/lt7381.py @@ -0,0 +1,239 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + +import time +from micropython import const # NOQA +import machine # NOQA + +import lvgl as lv +import display_driver_framework + + +BYTE_ORDER_RGB = 0x00 +BYTE_ORDER_RBG = 0x01 +BYTE_ORDER_GRB = 0x02 +BYTE_ORDER_GBR = 0x03 +BYTE_ORDER_BRG = 0x04 +BYTE_ORDER_BGR = 0x05 + +STATE_HIGH = display_driver_framework.STATE_HIGH +STATE_LOW = display_driver_framework.STATE_LOW +STATE_PWM = display_driver_framework.STATE_PWM + +_SRR = const(0x00) +_SSR_RST = const(0x40) + +_MRWDP = const(0x04) + +_CVSSA_1 = const(0x50) +_CVSSA_2 = const(0x51) +_CVSSA_3 = const(0x52) +_CVSSA_4 = const(0x53) + +_CVS_IMWTH_L = const(0x54) +_CVS_IMWTH_H = const(0x55) + +_AWUL_X_L = const(0x56) +_AWUL_X_H = const(0x57) + +_AWUL_Y_L = const(0x58) +_AWUL_Y_H = const(0x59) + +_AW_WTH_L = const(0x5A) +_AW_WTH_H = const(0x5B) + +_AW_HT_L = const(0x5C) +_AW_HT_H = const(0x5D) + +_CURH_L = const(0x5F) +_CURH_H = const(0x60) + +_CURV_L = const(0x61) +_CURV_H = const(0x62) + +_AW_COLOR = const(0x5E) +_AW_COLOR_CANVAS_MASK = const(0x03) +_AW_COLOR_CANVAS_8BPP = const(0x00) +_AW_COLOR_CANVAS_16BPP = const(0x01) +_AW_COLOR_CANVAS_24BPP = const(0x02) +_AW_COLOR_LINEAR_ADDR = const(0x04) +_AW_COLOR_BLOCK_ADDR = const(0x00) + +_DPCR = const(0x12) +_DPCR_VDIR_MASK = const(0x20) +_DPCR_VDIR_TOP_BOT = const(0x00) +_DPCR_VDIR_BOT_TOP = const(0x20) + +_MACR = const(0x02) +_MACR_W_MASK = const(0x06) +_MACR_W_LRTB = const(0x00) +_MACR_W_RLTB = const(0x02) +_MACR_W_TBLR = const(0x04) +_MACR_W_BTLR = const(0x06) + + +TYPE_ER_TFTMC050_3 = 0x01 + + +class LT7381(display_driver_framework.DisplayDriver): + WAIT_TIMEOUT = 100 + + def __init__( + self, + data_bus, + display_width, + display_height, + frame_buffer1=None, + frame_buffer2=None, + reset_pin=None, + reset_state=STATE_HIGH, + power_pin=None, + power_on_state=STATE_HIGH, + backlight_pin=None, + backlight_on_state=STATE_HIGH, + offset_x=0, + offset_y=0, + color_byte_order=BYTE_ORDER_RGB, + rgb565_byte_swap=False, + wait_pin=None, + wait_state=STATE_HIGH + ): + if wait_pin in (None, -1): + raise RuntimeError('wait pin is required') + + if not isinstance(wait_pin, int): + self._wait_pin = wait_pin + else: + self._wait_pin = machine.Pin(wait_pin, machine.Pin.IN) + + self._wait_state = wait_state + self._dpcr = 0x00 + self._macr = 0x00 + self._aw_color = 0x00 + self._pmuxr = 0x00 + self._pcfgr = 0x00 + self._backlight = 0 + + super().__init__( + data_bus=data_bus, + display_width=display_width, + display_height=display_height, + frame_buffer1=frame_buffer1, + frame_buffer2=frame_buffer2, + reset_pin=reset_pin, + reset_state=reset_state, + power_pin=power_pin, + power_on_state=power_on_state, + backlight_pin=backlight_pin, + backlight_on_state=backlight_on_state, + offset_x=offset_x, + offset_y=offset_y, + color_byte_order=color_byte_order, + color_space=lv.COLOR_FORMAT.RGB565, # NOQA + rgb565_byte_swap=rgb565_byte_swap, + ) + + def _on_size_change(self, _): + rotation = self._disp_drv.get_rotation() + if rotation == lv.DISP_ROTATION_90: + self._rotation = rotation + self.set_rotation(lv.DISP_ROTATION_0) + return + + self._width = self._disp_drv.get_horizontal_resolution() + self._height = self._disp_drv.get_vertical_resolution() + + if rotation == self._rotation: + return + + self._rotation = rotation + + if self._initilized: + self._dpcr &= ~_DPCR_VDIR_MASK + self._macr &= ~_MACR_W_MASK + + if rotation == lv.DISP_ROTATION_0: + self._dpcr |= _DPCR_VDIR_TOP_BOT + self._macr |= _MACR_W_LRTB + + elif rotation == lv.DISP_ROTATION_180: + self._dpcr |= _DPCR_VDIR_BOT_TOP + self._macr |= _MACR_W_RLTB + + elif rotation == lv.DISP_ROTATION_270: + self._dpcr |= _DPCR_VDIR_BOT_TOP + self._macr |= _MACR_W_TBLR + + self._write_reg(_DPCR, self._dpcr) + self._write_reg(_MACR, self._macr) + + def _write_reg(self, reg, param): + self._param_buf[0] = param + self.set_params(reg, self._param_mv[:1]) + + def set_invert_colors(self, value): + raise NotImplementedError + + def _wait(self): + start_time = time.ticks_ms() # NOQA + while ( + self._wait_pin.value() != self._wait_state and + time.ticks_diff(time.ticks_ms(), start_time) < self.WAIT_TIMEOUT # NOQA + ): + time.sleep_ms(1) # NOQA + + def reset(self): + if self._reset_pin is None: + self._write_reg(_SRR, _SSR_RST) + time.sleep_ms(20) # NOQA + else: + display_driver_framework.DisplayDriver.reset(self) + time.sleep_ms(50) # NOQA + + def _set_memory_location(self, x_start, y_start, x_end, y_end): + + # set active window start X/Y + self._write_reg(_AWUL_X_L, x_start & 0xFF) + self._write_reg(_AWUL_X_H, (x_start >> 8) & 0x0F) + self._write_reg(_AWUL_Y_L, y_start & 0xFF) + self._write_reg(_AWUL_Y_H, (y_start >> 8) & 0x0F) + + # set active window width and height + width = x_end - x_start + 1 + height = y_end - y_start + 1 + self.set_params(_AW_WTH_L, width & 0xFF) + self.set_params(_AW_WTH_H, (width >> 8) & 0xFF) + self.set_params(_AW_HT_L, height & 0xFF) + self.set_params(_AW_HT_H, (height >> 8) & 0xFF) + + # set cursor + self.set_params(_CURH_L, x_start & 0xff) + self.set_params(_CURH_H, (x_start >> 8) & 0xFF) + self.set_params(_CURV_L, y_start & 0xFF) + self.set_params(_CURV_H, (y_start >> 8) & 0xFF) + + return _MRWDP + + def _flush_cb(self, _, area, color_p): + x1 = area.x1 + self._offset_x + x2 = area.x2 + self._offset_x + + y1 = area.y1 + self._offset_y + y2 = area.y2 + self._offset_y + + size = ( + (x2 - x1 + 1) * + (y2 - y1 + 1) * + lv.color_format_get_size(self._color_space) + ) + + cmd = self._set_memory_location(x1, y1, x2, y2) + + self._wait() + + # we have to use the __dereference__ method because this method is + # what converts from the C_Array object the binding passes into a + # memoryview object that can be passed to the bus drivers + data_view = color_p.__dereference__(size) + + self._data_bus.tx_color(cmd, data_view, x1, y1, x2, y2, self._rotation, + self._disp_drv.flush_is_last()) diff --git a/api_drivers/common_api_drivers/display/lt768x/_lt768x_init.py b/api_drivers/common_api_drivers/display/lt768x/_lt768x_init.py index e69de29b..7a76c694 100644 --- a/api_drivers/common_api_drivers/display/lt768x/_lt768x_init.py +++ b/api_drivers/common_api_drivers/display/lt768x/_lt768x_init.py @@ -0,0 +1 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser diff --git a/api_drivers/common_api_drivers/display/lt768x/lt768x.py b/api_drivers/common_api_drivers/display/lt768x/lt768x.py index 4672aa93..f2ce35f5 100644 --- a/api_drivers/common_api_drivers/display/lt768x/lt768x.py +++ b/api_drivers/common_api_drivers/display/lt768x/lt768x.py @@ -1,4 +1,6 @@ -import ra8876 as _ra8876 +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + +import ra8876 as _ra8876 # NOQA STATE_HIGH = _ra8876.STATE_HIGH diff --git a/api_drivers/common_api_drivers/display/nt35510/_nt35510_init.py b/api_drivers/common_api_drivers/display/nt35510.wip/_nt35510_init.py similarity index 99% rename from api_drivers/common_api_drivers/display/nt35510/_nt35510_init.py rename to api_drivers/common_api_drivers/display/nt35510.wip/_nt35510_init.py index 07ad7045..dd2375b2 100644 --- a/api_drivers/common_api_drivers/display/nt35510/_nt35510_init.py +++ b/api_drivers/common_api_drivers/display/nt35510.wip/_nt35510_init.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + from micropython import const # NOQA import time diff --git a/api_drivers/common_api_drivers/display/nt35510/_nt35510_init_type1.py b/api_drivers/common_api_drivers/display/nt35510.wip/_nt35510_init_type1.py similarity index 78% rename from api_drivers/common_api_drivers/display/nt35510/_nt35510_init_type1.py rename to api_drivers/common_api_drivers/display/nt35510.wip/_nt35510_init_type1.py index f485d47d..570dbc96 100644 --- a/api_drivers/common_api_drivers/display/nt35510/_nt35510_init_type1.py +++ b/api_drivers/common_api_drivers/display/nt35510.wip/_nt35510_init_type1.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import _nt35510_init diff --git a/api_drivers/common_api_drivers/display/nt35510/_nt35510_init_type2.py b/api_drivers/common_api_drivers/display/nt35510.wip/_nt35510_init_type2.py similarity index 78% rename from api_drivers/common_api_drivers/display/nt35510/_nt35510_init_type2.py rename to api_drivers/common_api_drivers/display/nt35510.wip/_nt35510_init_type2.py index e93d00bd..54ab53be 100644 --- a/api_drivers/common_api_drivers/display/nt35510/_nt35510_init_type2.py +++ b/api_drivers/common_api_drivers/display/nt35510.wip/_nt35510_init_type2.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import _nt35510_init diff --git a/api_drivers/common_api_drivers/display/nt35510/nt35510.py b/api_drivers/common_api_drivers/display/nt35510.wip/nt35510.py similarity index 99% rename from api_drivers/common_api_drivers/display/nt35510/nt35510.py rename to api_drivers/common_api_drivers/display/nt35510.wip/nt35510.py index ba3af372..2938a87c 100644 --- a/api_drivers/common_api_drivers/display/nt35510/nt35510.py +++ b/api_drivers/common_api_drivers/display/nt35510.wip/nt35510.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import display_driver_framework from micropython import const # NOQA diff --git a/api_drivers/common_api_drivers/display/nt35510/sdkconfig b/api_drivers/common_api_drivers/display/nt35510.wip/sdkconfig similarity index 100% rename from api_drivers/common_api_drivers/display/nt35510/sdkconfig rename to api_drivers/common_api_drivers/display/nt35510.wip/sdkconfig diff --git a/api_drivers/common_api_drivers/display/nv3041a/_nv3041a_init.py b/api_drivers/common_api_drivers/display/nv3041a/_nv3041a_init.py index dd3cec54..af5509d3 100644 --- a/api_drivers/common_api_drivers/display/nv3041a/_nv3041a_init.py +++ b/api_drivers/common_api_drivers/display/nv3041a/_nv3041a_init.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + from micropython import const # NOQA import time import lvgl as lv diff --git a/api_drivers/common_api_drivers/display/nv3041a/nv3041a.py b/api_drivers/common_api_drivers/display/nv3041a/nv3041a.py index d34a79a3..cd3a921b 100644 --- a/api_drivers/common_api_drivers/display/nv3041a/nv3041a.py +++ b/api_drivers/common_api_drivers/display/nv3041a/nv3041a.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import display_driver_framework import rgb_display_framework # NOQA from micropython import const # NOQA @@ -113,7 +115,7 @@ def __init__( break except MemoryError: - frame_buffer1 = data_bus.free_framebuffer(frame_buffer1) + frame_buffer1 = data_bus.free_framebuffer(frame_buffer1) # NOQA if frame_buffer1 is None: raise MemoryError( @@ -197,7 +199,8 @@ def _flush_cb(self, _, area, color_p): data_view = color_p.__dereference__(size) - first_chunk = int(size / 10) + # Divide buffer in 2 chunks: + first_chunk = int(size / 2) self._data_bus.tx_color(self.__ramwr, data_view[:first_chunk], x1, y1, x2, y2, self._rotation, False) self._data_bus.tx_color(self.__ramwrc, data_view[first_chunk:], x1, y1, x2, y2, self._rotation, self._disp_drv.flush_is_last()) diff --git a/api_drivers/common_api_drivers/display/r61581/_r61581_init.py b/api_drivers/common_api_drivers/display/r61581/_r61581_init.py index 1424bbc2..47c8d3e8 100644 --- a/api_drivers/common_api_drivers/display/r61581/_r61581_init.py +++ b/api_drivers/common_api_drivers/display/r61581/_r61581_init.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import time from micropython import const # NOQA diff --git a/api_drivers/common_api_drivers/display/r61581/r61581.py b/api_drivers/common_api_drivers/display/r61581/r61581.py index cc13490f..2c65ef60 100644 --- a/api_drivers/common_api_drivers/display/r61581/r61581.py +++ b/api_drivers/common_api_drivers/display/r61581/r61581.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import display_driver_framework diff --git a/api_drivers/common_api_drivers/display/ra8876/_ra8876_init.py b/api_drivers/common_api_drivers/display/ra8876/_ra8876_init.py index e69de29b..7a76c694 100644 --- a/api_drivers/common_api_drivers/display/ra8876/_ra8876_init.py +++ b/api_drivers/common_api_drivers/display/ra8876/_ra8876_init.py @@ -0,0 +1 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser diff --git a/api_drivers/common_api_drivers/display/ra8876/ra8876.py b/api_drivers/common_api_drivers/display/ra8876/ra8876.py index 27f4cf4b..6c52a2f6 100644 --- a/api_drivers/common_api_drivers/display/ra8876/ra8876.py +++ b/api_drivers/common_api_drivers/display/ra8876/ra8876.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import time from micropython import const # NOQA import machine # NOQA @@ -205,15 +207,13 @@ def __init__( offset_x=offset_x, offset_y=offset_y, color_byte_order=color_byte_order, - color_space=lv.COLOR_FORMAT.RGB565, + color_space=lv.COLOR_FORMAT.RGB565, # NOQA rgb565_byte_swap=rgb565_byte_swap ) - def invert_colors(self, value): + def set_invert_colors(self, value): raise NotImplementedError - invert_colors = property(None, invert_colors) - @property def orientation(self): raise NotImplementedError @@ -224,21 +224,21 @@ def orientation(self, value): def _wait(self): if self._wait_pin is not None: - start_time = time.ticks_ms() + start_time = time.ticks_ms() # NOQA while ( self._wait_pin.value() != self._wait_state and - time.ticks_diff(time.ticks_ms(), start_time) < self.WAIT_TIMEOUT + time.ticks_diff(time.ticks_ms(), start_time) < self.WAIT_TIMEOUT # NOQA ): - time.sleep_ms(1) + time.sleep_ms(1) # NOQA def reset(self): if self._reset_pin is None: self.set_params(_SRR) - time.sleep_ms(20) + time.sleep_ms(20) # NOQA else: display_driver_framework.DisplayDriver.reset(self) - time.sleep_ms(50) + time.sleep_ms(50) # NOQA def init( # NOQA self, @@ -254,9 +254,9 @@ def init( # NOQA vstr=12, # vertical start position vpwr=10, # VSYNC pulse width ): - time.sleep_ms(100) + time.sleep_ms(100) # NOQA self.reset() - time.sleep_ms(100) + time.sleep_ms(100) # NOQA self._wait() buf = self._param_buf @@ -348,10 +348,10 @@ def init( # NOQA # reconfigure PLL generator buf[0] = 0x00 self.set_params(_CCR, mv) - time.sleep_us(10) + time.sleep_us(10) # NOQA buf[0] = 0x80 self.set_params(_CCR, mv) - time.sleep_us(10) + time.sleep_us(10) # NOQA # configure SDRAM if dram_ic == IS42SM16160D: @@ -400,7 +400,7 @@ def init( # NOQA self.set_params(_SDRCR, mv) self._wait() - time.sleep_ms(10) + time.sleep_ms(10) # NOQA # set chip config register lane_count = self._data_bus.get_lane_count() diff --git a/api_drivers/common_api_drivers/display/rgb_display/rgb_display.py b/api_drivers/common_api_drivers/display/rgb_display/rgb_display.py index 92e8b64c..a960a165 100644 --- a/api_drivers/common_api_drivers/display/rgb_display/rgb_display.py +++ b/api_drivers/common_api_drivers/display/rgb_display/rgb_display.py @@ -1,4 +1,6 @@ -import rgb_display_framework +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + +import rgb_display_framework # NOQA import lvgl as lv diff --git a/api_drivers/common_api_drivers/display/rm67162/_rm67162_init.py b/api_drivers/common_api_drivers/display/rm67162/_rm67162_init.py new file mode 100644 index 00000000..7fb59b46 --- /dev/null +++ b/api_drivers/common_api_drivers/display/rm67162/_rm67162_init.py @@ -0,0 +1,130 @@ +# Copyright (c) 2025 0ut4t1m3 +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + + +from micropython import const # NOQA +import lvgl as lv +import time + + +_SLPOUT = const(0x11) +_SWRESET = const(0x01) +_INVON = const(0x21) +_INVOFF = const(0x20) + +_DISPOFF = const(0x28) +_DISPON = const(0x29) + + +_CASET = const(0x2A) +_RASET = const(0x2B) + +_RAMWR = const(0x2C) +_TEOFF = const(0x34) +_MADCTL = const(0x36) + +# Set Color Enhance +_IMGEHCCTR = const(0x58) + +# Set Color Enhance 1 +_CESLRCTR_L = const(0x5A) +_CESLRCTR_H = const(0x5B) + +_COLMOD = const(0x3A) +_RGB565 = const(0x75) # 16bit/pixel (65,536 colors) +_RGB888 = const(0x77) # 24bit/pixel (16.7M colors) + +# Write Display Brightness +# 0 to 255 +_WRDISBV = const(0x51) + +# Write Display Control +_WRCTRLD = const(0x53) +_BCTRL = const(0x20) +_DD = const(0x08) + +# Set Dual SPI Mode +_SetDSPIMode = const(0xC4) +_DSPI_EN = const(0x21) + +# CMD Mode Switch +# 0x00 == user mode +_CMDMode = const(0xFE) + +# High Brightness Mode +# 0x00 disable +# 0x02 enable +_SETHBM = const(0xB0) + + +def init(self): + self._br_val = 0 + + buf = self._param_buf + mv = self._param_mv + + time.sleep_ms(120) # NOQA + self.set_params(_SWRESET) + time.sleep_ms(120) # NOQA + + num_lanes = self._data_bus.get_lane_count() + if num_lanes == 2: + buf[0] = _DSPI_EN + self.set_params(_SetDSPIMode, mv[:1]) + elif num_lanes not in (1, 8): + raise RuntimeError('display only supports I8080 8 lane, SPI and DUAL SPI') + + self.set_params(_SLPOUT) + time.sleep_ms(120) # NOQA + + buf[0] = 0x05 + self.set_params(_CMDMode, mv[:1]) + + self.set_params(0x05, mv[:1]) + + buf[0] = 0x01 + self.set_params(_CMDMode, mv[:1]) + + buf[0] = 0x25 + self.set_params(0x73, mv[:1]) + + buf[0] = 0x00 + self.set_params(_CMDMode, mv[:1]) + + self.set_params(_TEOFF) + + buf[0] = ( + self._madctl( + self._color_byte_order, + self._ORIENTATION_TABLE # NOQA + ) + ) + self.set_params(_MADCTL, mv[:1]) + + color_size = lv.color_format_get_size(self._color_space) + if color_size == 2: # NOQA + buf[0] = _RGB565 + elif color_size == 3: + buf[0] = _RGB888 + else: + raise RuntimeError( + f'{self.__class__.__name__} IC only supports ' + 'RGB565 and RGB888' + ) + + self.set_params(_COLMOD, mv[:1]) + + buf[0] = _BCTRL | _DD + self.set_params(_WRCTRLD, mv[:1]) + + buf[0] = 0x7F + self.set_params(_CESLRCTR_H, mv[:1]) + + buf[0] = 0xFF + self.set_params(_CESLRCTR_L, mv[:1]) + + buf[0] = 0x00 + self.set_params(_IMGEHCCTR, mv[:1]) + self.set_params(_WRDISBV, mv[:1]) + self.set_params(_SETHBM, mv[:1]) + self.set_params(_DISPON) diff --git a/api_drivers/common_api_drivers/display/rm67162/rm67162.py b/api_drivers/common_api_drivers/display/rm67162/rm67162.py new file mode 100644 index 00000000..2aa86938 --- /dev/null +++ b/api_drivers/common_api_drivers/display/rm67162/rm67162.py @@ -0,0 +1,149 @@ +# Copyright (c) 2025 0ut4t1m3 +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + + +from micropython import const # NOQA +import display_driver_framework +import lvgl as lv + + +STATE_HIGH = display_driver_framework.STATE_HIGH +STATE_LOW = display_driver_framework.STATE_LOW +STATE_PWM = display_driver_framework.STATE_PWM + +BYTE_ORDER_RGB = display_driver_framework.BYTE_ORDER_RGB +BYTE_ORDER_BGR = display_driver_framework.BYTE_ORDER_BGR + +_MADCTL_MY = const(0x80) # Decreasing in vertical 10000000 +_MADCTL_MX = const(0x60) # Increasing in horizontal 01100000 +_MADCTL_MV = const(0x20) # x, y = y, x 00100000 +_MADCTL_MYRS = const(0x01) # mirror y 00000001 +_MADCTL_MXRS = const(0x02) # mirror x 00000010 + +# Write Display Brightness +# 0 to 255 +_WRDISBV = const(0x51) + +# Set Color Enhance +_IMGEHCCTR = const(0x58) +_SLR_EN = const(0x04) # Sunlight Readable +# Sunlight Readable Level values are 0, 1, and 3 + +# Set Color Enhance 1 +_CESLRCTR_L = const(0x5A) +_CESLRCTR_H = const(0x5B) + +# High Brightness Mode +# 0x00 disable +# 0x02 enable +_SETHBM = const(0xB0) +_HBM_EN = const(0x02) + + +class RM67162(display_driver_framework.DisplayDriver): + _ORIENTATION_TABLE = ( + _MADCTL_MX, + _MADCTL_MYRS | _MADCTL_MXRS | _MADCTL_MX & ~_MADCTL_MV, + _MADCTL_MY | _MADCTL_MXRS | _MADCTL_MX, + _MADCTL_MY | _MADCTL_MYRS | _MADCTL_MXRS + ) + + def __init__( + self, + data_bus, + display_width, + display_height, + frame_buffer1=None, + frame_buffer2=None, + reset_pin=None, + reset_state=STATE_HIGH, + power_pin=None, + power_on_state=STATE_HIGH, + backlight_pin=None, + backlight_on_state=STATE_HIGH, + offset_x=0, + offset_y=0, + color_byte_order=BYTE_ORDER_RGB, + color_space=lv.COLOR_FORMAT.RGB888, # NOQA + rgb565_byte_swap=False + ): + + self.__brightness = 0 + self.__sunlight = 0 + self.__ambient = 0x7FFF + self.__high_brightness = 0x00 + + super().__init__( + data_bus=data_bus, + display_width=display_width, + display_height=display_height, + frame_buffer1=frame_buffer1, + frame_buffer2=frame_buffer2, + reset_pin=reset_pin, + reset_state=reset_state, + power_pin=power_pin, + power_on_state=power_on_state, + backlight_pin=backlight_pin, + backlight_on_state=backlight_on_state, + offset_x=offset_x, + offset_y=offset_y, + color_byte_order=color_byte_order, + color_space=color_space, + rgb565_byte_swap=rgb565_byte_swap + ) + + def set_brightness(self, val): + # convert the value from a 0.0 - 100.0 scale to a 0 - 255 scale + val = int(val * 255 / 100) + # clamp the balue so it is 0 - 255 + val = max(min(val, 255), 0) + + self.__brightness = val + self._param_buf[0] = val + + self.set_params(_WRDISBV, self._param_mv[:1]) + + def get_brightness(self): + return round(self.__brightness / 255.0 * 100.0, 2) + + def set_ambient_light_level(self, val): + val = int(val * 65535 / 100) + val = max(min(val, 65535), 0) + + self.__ambient = val + self._param_buf[0] = val >> 8 + self.set_params(_CESLRCTR_H, self._param_mv[:1]) + + self._param_buf[0] = val & 0xFF + self.set_params(_CESLRCTR_L, self._param_mv[:1]) + + def get_amblent_light_level(self): + return round(self.__ambient / 65535.0 * 100.0, 2) + + def set_sunlight_enhance(self, val): + if val == -1: + self.__sunlight &= ~_SLR_EN + else: + val = min(val, 3) + self.__sunlight = _SLR_EN | val + + self._param_buf[0] = self.__sunlight + self.set_params(_IMGEHCCTR, self._param_mv[:1]) + + def get_sunlight_enhance(self): + if self.__sunlight & _SLR_EN: + return self.__sunlight & ~_SLR_EN + + return -1 + + def set_high_brightness(self, val): + if val: + self.__high_brightness |= _HBM_EN + else: + self.__high_brightness &= ~_HBM_EN + + self._param_buf[0] = self.__high_brightness + self.set_params(_SETHBM, self._param_mv[:1]) + + def get_high_brightness(self): + return bool(self.__high_brightness & _HBM_EN) diff --git a/api_drivers/common_api_drivers/display/rm68120/_rm68120_init.py b/api_drivers/common_api_drivers/display/rm68120/_rm68120_init.py index 18886e28..1ba2c673 100644 --- a/api_drivers/common_api_drivers/display/rm68120/_rm68120_init.py +++ b/api_drivers/common_api_drivers/display/rm68120/_rm68120_init.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import time from micropython import const # NOQA diff --git a/api_drivers/common_api_drivers/display/rm68120/rm68120.py b/api_drivers/common_api_drivers/display/rm68120/rm68120.py index 036bf239..afd7ecb4 100644 --- a/api_drivers/common_api_drivers/display/rm68120/rm68120.py +++ b/api_drivers/common_api_drivers/display/rm68120/rm68120.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import display_driver_framework from micropython import const # NOQA diff --git a/api_drivers/common_api_drivers/display/rm68140/_rm68140_init.py b/api_drivers/common_api_drivers/display/rm68140/_rm68140_init.py index 37c16fb4..576108e9 100644 --- a/api_drivers/common_api_drivers/display/rm68140/_rm68140_init.py +++ b/api_drivers/common_api_drivers/display/rm68140/_rm68140_init.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + from micropython import const # NOQA import time diff --git a/api_drivers/common_api_drivers/display/rm68140/rm68140.py b/api_drivers/common_api_drivers/display/rm68140/rm68140.py index 90e19382..466651d8 100644 --- a/api_drivers/common_api_drivers/display/rm68140/rm68140.py +++ b/api_drivers/common_api_drivers/display/rm68140/rm68140.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import display_driver_framework diff --git a/api_drivers/common_api_drivers/display/s6d02a1/_s6d02a1_init.py b/api_drivers/common_api_drivers/display/s6d02a1/_s6d02a1_init.py index 92282cf2..845663ac 100644 --- a/api_drivers/common_api_drivers/display/s6d02a1/_s6d02a1_init.py +++ b/api_drivers/common_api_drivers/display/s6d02a1/_s6d02a1_init.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import time from micropython import const # NOQA diff --git a/api_drivers/common_api_drivers/display/s6d02a1/s6d02a1.py b/api_drivers/common_api_drivers/display/s6d02a1/s6d02a1.py index 750c7556..e34e27d1 100644 --- a/api_drivers/common_api_drivers/display/s6d02a1/s6d02a1.py +++ b/api_drivers/common_api_drivers/display/s6d02a1/s6d02a1.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import display_driver_framework diff --git a/api_drivers/common_api_drivers/display/sdl_display/sdl_display.py b/api_drivers/common_api_drivers/display/sdl_display/sdl_display.py index 4349ed78..4ddbcb7f 100644 --- a/api_drivers/common_api_drivers/display/sdl_display/sdl_display.py +++ b/api_drivers/common_api_drivers/display/sdl_display/sdl_display.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import lvgl as lv # NOQA import display_driver_framework from micropython import const # NOQA diff --git a/api_drivers/common_api_drivers/display/spd2010/_spd2010_init.py b/api_drivers/common_api_drivers/display/spd2010/_spd2010_init.py new file mode 100644 index 00000000..8af0ee05 --- /dev/null +++ b/api_drivers/common_api_drivers/display/spd2010/_spd2010_init.py @@ -0,0 +1,1239 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + +from micropython import const # NOQA +import time +import lvgl as lv + + +_COLMOD = const(0x3A) + + +def init(self): + param_buf = self._param_buf + param_mv = self._param_mv + + color_size = lv.color_format_get_size(self._color_space) + + if color_size == 2: # NOQA + colmod = 0x55 + elif color_size == 3: + colmod = 0x77 + else: + raise RuntimeError( + 'SPD2010 IC only supports ' + 'lv.COLOR_FORMAT.RGB888 and lv.COLOR_FORMAT.RGB565' + ) + + param_buf[:3] = bytearray([0x20, 0x10, 0x00]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[0] = colmod + self.set_params(_COLMOD, param_mv[:1]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x10]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[0] = 0x11 + self.set_params(0x0C, param_mv[:1]) + + param_buf[0] = 0x02 + self.set_params(0x10, param_mv[:1]) + + param_buf[0] = 0x11 + self.set_params(0x11, param_mv[:1]) + + param_buf[0] = 0x42 + self.set_params(0x15, param_mv[:1]) + + param_buf[0] = 0x11 + self.set_params(0x16, param_mv[:1]) + + param_buf[0] = 0x02 + self.set_params(0x1A, param_mv[:1]) + + param_buf[0] = 0x11 + self.set_params(0x1B, param_mv[:1]) + + param_buf[0] = 0x80 + self.set_params(0x61, param_mv[:1]) + + param_buf[0] = 0x80 + self.set_params(0x62, param_mv[:1]) + + param_buf[0] = 0x44 + self.set_params(0x54, param_mv[:1]) + + param_buf[0] = 0x88 + self.set_params(0x58, param_mv[:1]) + + param_buf[0] = 0xcc + self.set_params(0x5C, param_mv[:1]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x10]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[0] = 0x80 + self.set_params(0x20, param_mv[:1]) + + param_buf[0] = 0x81 + self.set_params(0x21, param_mv[:1]) + + param_buf[0] = 0x31 + self.set_params(0x22, param_mv[:1]) + + param_buf[0] = 0x20 + self.set_params(0x23, param_mv[:1]) + + param_buf[0] = 0x11 + self.set_params(0x24, param_mv[:1]) + + param_buf[0] = 0x11 + self.set_params(0x25, param_mv[:1]) + + param_buf[0] = 0x12 + self.set_params(0x26, param_mv[:1]) + + param_buf[0] = 0x12 + self.set_params(0x27, param_mv[:1]) + + param_buf[0] = 0x80 + self.set_params(0x30, param_mv[:1]) + + param_buf[0] = 0x81 + self.set_params(0x31, param_mv[:1]) + + param_buf[0] = 0x31 + self.set_params(0x32, param_mv[:1]) + + param_buf[0] = 0x20 + self.set_params(0x33, param_mv[:1]) + + param_buf[0] = 0x11 + self.set_params(0x34, param_mv[:1]) + + param_buf[0] = 0x11 + self.set_params(0x35, param_mv[:1]) + + param_buf[0] = 0x12 + self.set_params(0x36, param_mv[:1]) + + param_buf[0] = 0x12 + self.set_params(0x37, param_mv[:1]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x10]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[0] = 0x11 + self.set_params(0x41, param_mv[:1]) + + param_buf[0] = 0x22 + self.set_params(0x42, param_mv[:1]) + + param_buf[0] = 0x33 + self.set_params(0x43, param_mv[:1]) + + param_buf[0] = 0x11 + self.set_params(0x49, param_mv[:1]) + + param_buf[0] = 0x22 + self.set_params(0x4A, param_mv[:1]) + + param_buf[0] = 0x33 + self.set_params(0x4B, param_mv[:1]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x15]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[0] = 0x00 + self.set_params(0x00, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x01, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x02, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x03, param_mv[:1]) + + param_buf[0] = 0x10 + self.set_params(0x04, param_mv[:1]) + + param_buf[0] = 0x0C + self.set_params(0x05, param_mv[:1]) + + param_buf[0] = 0x23 + self.set_params(0x06, param_mv[:1]) + + param_buf[0] = 0x22 + self.set_params(0x07, param_mv[:1]) + + param_buf[0] = 0x21 + self.set_params(0x08, param_mv[:1]) + + param_buf[0] = 0x20 + self.set_params(0x09, param_mv[:1]) + + param_buf[0] = 0x33 + self.set_params(0x0A, param_mv[:1]) + + param_buf[0] = 0x32 + self.set_params(0x0B, param_mv[:1]) + + param_buf[0] = 0x34 + self.set_params(0x0C, param_mv[:1]) + + param_buf[0] = 0x35 + self.set_params(0x0D, param_mv[:1]) + + param_buf[0] = 0x01 + self.set_params(0x0E, param_mv[:1]) + + param_buf[0] = 0x01 + self.set_params(0x0F, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x20, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x21, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x22, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x23, param_mv[:1]) + + param_buf[0] = 0x0C + self.set_params(0x24, param_mv[:1]) + + param_buf[0] = 0x10 + self.set_params(0x25, param_mv[:1]) + + param_buf[0] = 0x20 + self.set_params(0x26, param_mv[:1]) + + param_buf[0] = 0x21 + self.set_params(0x27, param_mv[:1]) + + param_buf[0] = 0x22 + self.set_params(0x28, param_mv[:1]) + + param_buf[0] = 0x23 + self.set_params(0x29, param_mv[:1]) + + param_buf[0] = 0x33 + self.set_params(0x2A, param_mv[:1]) + + param_buf[0] = 0x32 + self.set_params(0x2B, param_mv[:1]) + + param_buf[0] = 0x34 + self.set_params(0x2C, param_mv[:1]) + + param_buf[0] = 0x35 + self.set_params(0x2D, param_mv[:1]) + + param_buf[0] = 0x01 + self.set_params(0x2E, param_mv[:1]) + + param_buf[0] = 0x01 + self.set_params(0x2F, param_mv[:1]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x16]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[0] = 0x00 + self.set_params(0x00, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x01, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x02, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x03, param_mv[:1]) + + param_buf[0] = 0x08 + self.set_params(0x04, param_mv[:1]) + + param_buf[0] = 0x04 + self.set_params(0x05, param_mv[:1]) + + param_buf[0] = 0x19 + self.set_params(0x06, param_mv[:1]) + + param_buf[0] = 0x18 + self.set_params(0x07, param_mv[:1]) + + param_buf[0] = 0x17 + self.set_params(0x08, param_mv[:1]) + + param_buf[0] = 0x16 + self.set_params(0x09, param_mv[:1]) + + param_buf[0] = 0x33 + self.set_params(0x0A, param_mv[:1]) + + param_buf[0] = 0x32 + self.set_params(0x0B, param_mv[:1]) + + param_buf[0] = 0x34 + self.set_params(0x0C, param_mv[:1]) + + param_buf[0] = 0x35 + self.set_params(0x0D, param_mv[:1]) + + param_buf[0] = 0x01 + self.set_params(0x0E, param_mv[:1]) + + param_buf[0] = 0x01 + self.set_params(0x0F, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x20, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x21, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x22, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x23, param_mv[:1]) + + param_buf[0] = 0x04 + self.set_params(0x24, param_mv[:1]) + + param_buf[0] = 0x08 + self.set_params(0x25, param_mv[:1]) + + param_buf[0] = 0x16 + self.set_params(0x26, param_mv[:1]) + + param_buf[0] = 0x17 + self.set_params(0x27, param_mv[:1]) + + param_buf[0] = 0x18 + self.set_params(0x28, param_mv[:1]) + + param_buf[0] = 0x19 + self.set_params(0x29, param_mv[:1]) + + param_buf[0] = 0x33 + self.set_params(0x2A, param_mv[:1]) + + param_buf[0] = 0x32 + self.set_params(0x2B, param_mv[:1]) + + param_buf[0] = 0x34 + self.set_params(0x2C, param_mv[:1]) + + param_buf[0] = 0x35 + self.set_params(0x2D, param_mv[:1]) + + param_buf[0] = 0x01 + self.set_params(0x2E, param_mv[:1]) + + param_buf[0] = 0x01 + self.set_params(0x2F, param_mv[:1]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x12]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[0] = 0x99 + self.set_params(0x00, param_mv[:1]) + + param_buf[0] = 0x28 + self.set_params(0x2A, param_mv[:1]) + + param_buf[0] = 0x0f + self.set_params(0x2B, param_mv[:1]) + + param_buf[0] = 0x16 + self.set_params(0x2C, param_mv[:1]) + + param_buf[0] = 0x28 + self.set_params(0x2D, param_mv[:1]) + + param_buf[0] = 0x0f + self.set_params(0x2E, param_mv[:1]) + + param_buf[:3] = bytearray([0x20, 0x10, 0xA0]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[0] = 0xdc + self.set_params(0x08, param_mv[:1]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x45]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[0] = 0x9C + self.set_params(0x01, param_mv[:1]) + + param_buf[0] = 0x9C + self.set_params(0x03, param_mv[:1]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x42]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[0] = 0x2c + self.set_params(0x05, param_mv[:1]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x11]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[0] = 0x01 + self.set_params(0x50, param_mv[:1]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x00]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[:4] = bytearray([0x00, 0x00, 0x01, 0x9B]) + self.set_params(0x2A, param_mv[:4]) + + param_buf[:4] = bytearray([0x00, 0x00, 0x01, 0x9B]) + self.set_params(0x2B, param_mv[:4]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x40]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[0] = 0x00 + self.set_params(0x86, param_mv[:1]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x00]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x12]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[0] = 0x66 + self.set_params(0x0D, param_mv[:1]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x17]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[0] = 0x3c + self.set_params(0x39, param_mv[:1]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x31]) + self.set_params(0xff, param_mv[:3]) + + param_buf[0] = 0x03 + self.set_params(0x38, param_mv[:1]) + + param_buf[0] = 0xf0 + self.set_params(0x39, param_mv[:1]) + + param_buf[0] = 0x03 + self.set_params(0x36, param_mv[:1]) + + param_buf[0] = 0xe8 + self.set_params(0x37, param_mv[:1]) + + param_buf[0] = 0x03 + self.set_params(0x34, param_mv[:1]) + + param_buf[0] = 0xCF + self.set_params(0x35, param_mv[:1]) + + param_buf[0] = 0x03 + self.set_params(0x32, param_mv[:1]) + + param_buf[0] = 0xBA + self.set_params(0x33, param_mv[:1]) + + param_buf[0] = 0x03 + self.set_params(0x30, param_mv[:1]) + + param_buf[0] = 0xA2 + self.set_params(0x31, param_mv[:1]) + + param_buf[0] = 0x03 + self.set_params(0x2e, param_mv[:1]) + + param_buf[0] = 0x95 + self.set_params(0x2f, param_mv[:1]) + + param_buf[0] = 0x03 + self.set_params(0x2c, param_mv[:1]) + + param_buf[0] = 0x7e + self.set_params(0x2d, param_mv[:1]) + + param_buf[0] = 0x03 + self.set_params(0x2a, param_mv[:1]) + + param_buf[0] = 0x62 + self.set_params(0x2b, param_mv[:1]) + + param_buf[0] = 0x03 + self.set_params(0x28, param_mv[:1]) + + param_buf[0] = 0x44 + self.set_params(0x29, param_mv[:1]) + + param_buf[0] = 0x02 + self.set_params(0x26, param_mv[:1]) + + param_buf[0] = 0xfc + self.set_params(0x27, param_mv[:1]) + + param_buf[0] = 0x02 + self.set_params(0x24, param_mv[:1]) + + param_buf[0] = 0xd0 + self.set_params(0x25, param_mv[:1]) + + param_buf[0] = 0x02 + self.set_params(0x22, param_mv[:1]) + + param_buf[0] = 0x98 + self.set_params(0x23, param_mv[:1]) + + param_buf[0] = 0x02 + self.set_params(0x20, param_mv[:1]) + + param_buf[0] = 0x6f + self.set_params(0x21, param_mv[:1]) + + param_buf[0] = 0x02 + self.set_params(0x1e, param_mv[:1]) + + param_buf[0] = 0x32 + self.set_params(0x1f, param_mv[:1]) + + param_buf[0] = 0x01 + self.set_params(0x1c, param_mv[:1]) + + param_buf[0] = 0xf6 + self.set_params(0x1d, param_mv[:1]) + + param_buf[0] = 0x01 + self.set_params(0x1a, param_mv[:1]) + + param_buf[0] = 0xb8 + self.set_params(0x1b, param_mv[:1]) + + param_buf[0] = 0x01 + self.set_params(0x18, param_mv[:1]) + + param_buf[0] = 0x6E + self.set_params(0x19, param_mv[:1]) + + param_buf[0] = 0x01 + self.set_params(0x16, param_mv[:1]) + + param_buf[0] = 0x41 + self.set_params(0x17, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x14, param_mv[:1]) + + param_buf[0] = 0xfd + self.set_params(0x15, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x12, param_mv[:1]) + + param_buf[0] = 0xCf + self.set_params(0x13, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x10, param_mv[:1]) + + param_buf[0] = 0x98 + self.set_params(0x11, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x0e, param_mv[:1]) + + param_buf[0] = 0x89 + self.set_params(0x0f, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x0c, param_mv[:1]) + + param_buf[0] = 0x79 + self.set_params(0x0d, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x0a, param_mv[:1]) + + param_buf[0] = 0x67 + self.set_params(0x0b, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x08, param_mv[:1]) + + param_buf[0] = 0x55 + self.set_params(0x09, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x06, param_mv[:1]) + + param_buf[0] = 0x3F + self.set_params(0x07, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x04, param_mv[:1]) + + param_buf[0] = 0x28 + self.set_params(0x05, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x02, param_mv[:1]) + + param_buf[0] = 0x0E + self.set_params(0x03, param_mv[:1]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x00]) + self.set_params(0xff, param_mv[:3]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x32]) + self.set_params(0xff, param_mv[:3]) + + param_buf[0] = 0x03 + self.set_params(0x38, param_mv[:1]) + + param_buf[0] = 0xf0 + self.set_params(0x39, param_mv[:1]) + + param_buf[0] = 0x03 + self.set_params(0x36, param_mv[:1]) + + param_buf[0] = 0xe8 + self.set_params(0x37, param_mv[:1]) + + param_buf[0] = 0x03 + self.set_params(0x34, param_mv[:1]) + + param_buf[0] = 0xCF + self.set_params(0x35, param_mv[:1]) + + param_buf[0] = 0x03 + self.set_params(0x32, param_mv[:1]) + + param_buf[0] = 0xBA + self.set_params(0x33, param_mv[:1]) + + param_buf[0] = 0x03 + self.set_params(0x30, param_mv[:1]) + + param_buf[0] = 0xA2 + self.set_params(0x31, param_mv[:1]) + + param_buf[0] = 0x03 + self.set_params(0x2e, param_mv[:1]) + + param_buf[0] = 0x95 + self.set_params(0x2f, param_mv[:1]) + + param_buf[0] = 0x03 + self.set_params(0x2c, param_mv[:1]) + + param_buf[0] = 0x7e + self.set_params(0x2d, param_mv[:1]) + + param_buf[0] = 0x03 + self.set_params(0x2a, param_mv[:1]) + + param_buf[0] = 0x62 + self.set_params(0x2b, param_mv[:1]) + + param_buf[0] = 0x03 + self.set_params(0x28, param_mv[:1]) + + param_buf[0] = 0x44 + self.set_params(0x29, param_mv[:1]) + + param_buf[0] = 0x02 + self.set_params(0x26, param_mv[:1]) + + param_buf[0] = 0xfc + self.set_params(0x27, param_mv[:1]) + + param_buf[0] = 0x02 + self.set_params(0x24, param_mv[:1]) + + param_buf[0] = 0xd0 + self.set_params(0x25, param_mv[:1]) + + param_buf[0] = 0x02 + self.set_params(0x22, param_mv[:1]) + + param_buf[0] = 0x98 + self.set_params(0x23, param_mv[:1]) + + param_buf[0] = 0x02 + self.set_params(0x20, param_mv[:1]) + + param_buf[0] = 0x6f + self.set_params(0x21, param_mv[:1]) + + param_buf[0] = 0x02 + self.set_params(0x1e, param_mv[:1]) + + param_buf[0] = 0x32 + self.set_params(0x1f, param_mv[:1]) + + param_buf[0] = 0x01 + self.set_params(0x1c, param_mv[:1]) + + param_buf[0] = 0xf6 + self.set_params(0x1d, param_mv[:1]) + + param_buf[0] = 0x01 + self.set_params(0x1a, param_mv[:1]) + + param_buf[0] = 0xb8 + self.set_params(0x1b, param_mv[:1]) + + param_buf[0] = 0x01 + self.set_params(0x18, param_mv[:1]) + + param_buf[0] = 0x6E + self.set_params(0x19, param_mv[:1]) + + param_buf[0] = 0x01 + self.set_params(0x16, param_mv[:1]) + + param_buf[0] = 0x41 + self.set_params(0x17, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x14, param_mv[:1]) + + param_buf[0] = 0xfd + self.set_params(0x15, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x12, param_mv[:1]) + + param_buf[0] = 0xCf + self.set_params(0x13, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x10, param_mv[:1]) + + param_buf[0] = 0x98 + self.set_params(0x11, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x0e, param_mv[:1]) + + param_buf[0] = 0x89 + self.set_params(0x0f, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x0c, param_mv[:1]) + + param_buf[0] = 0x79 + self.set_params(0x0d, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x0a, param_mv[:1]) + + param_buf[0] = 0x67 + self.set_params(0x0b, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x08, param_mv[:1]) + + param_buf[0] = 0x55 + self.set_params(0x09, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x06, param_mv[:1]) + + param_buf[0] = 0x3F + self.set_params(0x07, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x04, param_mv[:1]) + + param_buf[0] = 0x28 + self.set_params(0x05, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x02, param_mv[:1]) + + param_buf[0] = 0x0E + self.set_params(0x03, param_mv[:1]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x00]) + self.set_params(0xff, param_mv[:3]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x11]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[0] = 0x01 + self.set_params(0x60, param_mv[:1]) + + param_buf[0] = 0x03 + self.set_params(0x65, param_mv[:1]) + + param_buf[0] = 0x38 + self.set_params(0x66, param_mv[:1]) + + param_buf[0] = 0x04 + self.set_params(0x67, param_mv[:1]) + + param_buf[0] = 0x34 + self.set_params(0x68, param_mv[:1]) + + param_buf[0] = 0x03 + self.set_params(0x69, param_mv[:1]) + + param_buf[0] = 0x03 + self.set_params(0x61, param_mv[:1]) + + param_buf[0] = 0x38 + self.set_params(0x62, param_mv[:1]) + + param_buf[0] = 0x04 + self.set_params(0x63, param_mv[:1]) + + param_buf[0] = 0x34 + self.set_params(0x64, param_mv[:1]) + + param_buf[0] = 0x11 + self.set_params(0x0A, param_mv[:1]) + + param_buf[0] = 0x20 + self.set_params(0x0B, param_mv[:1]) + + param_buf[0] = 0x20 + self.set_params(0x0c, param_mv[:1]) + + param_buf[0] = 0x06 + self.set_params(0x55, param_mv[:1]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x42]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[0] = 0x3D + self.set_params(0x05, param_mv[:1]) + + param_buf[0] = 0x03 + self.set_params(0x06, param_mv[:1]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x00]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x12]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[0] = 0xDC + self.set_params(0x1F, param_mv[:1]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x17]) + self.set_params(0xff, param_mv[:3]) + + param_buf[0] = 0xAA + self.set_params(0x11, param_mv[:1]) + + param_buf[0] = 0x12 + self.set_params(0x16, param_mv[:1]) + + param_buf[0] = 0xC3 + self.set_params(0x0B, param_mv[:1]) + + param_buf[0] = 0x0E + self.set_params(0x10, param_mv[:1]) + + param_buf[0] = 0xAA + self.set_params(0x14, param_mv[:1]) + + param_buf[0] = 0xA0 + self.set_params(0x18, param_mv[:1]) + + param_buf[0] = 0x80 + self.set_params(0x1A, param_mv[:1]) + + param_buf[0] = 0x80 + self.set_params(0x1F, param_mv[:1]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x11]) + self.set_params(0xff, param_mv[:3]) + + param_buf[0] = 0xEE + self.set_params(0x30, param_mv[:1]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x12]) + self.set_params(0xff, param_mv[:3]) + + param_buf[0] = 0x0F + self.set_params(0x15, param_mv[:1]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x2D]) + self.set_params(0xff, param_mv[:3]) + + param_buf[0] = 0x3E + self.set_params(0x01, param_mv[:1]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x40]) + self.set_params(0xff, param_mv[:3]) + + param_buf[0] = 0xC4 + self.set_params(0x83, param_mv[:1]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x12]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[0] = 0xCC + self.set_params(0x00, param_mv[:1]) + + param_buf[0] = 0xA0 + self.set_params(0x36, param_mv[:1]) + + param_buf[0] = 0x2D + self.set_params(0x2A, param_mv[:1]) + + param_buf[0] = 0x1e + self.set_params(0x2B, param_mv[:1]) + + param_buf[0] = 0x26 + self.set_params(0x2C, param_mv[:1]) + + param_buf[0] = 0x2D + self.set_params(0x2D, param_mv[:1]) + + param_buf[0] = 0x1e + self.set_params(0x2E, param_mv[:1]) + + param_buf[0] = 0xE6 + self.set_params(0x1F, param_mv[:1]) + + param_buf[:3] = bytearray([0x20, 0x10, 0xA0]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[0] = 0xE6 + self.set_params(0x08, param_mv[:1]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x12]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[0] = 0x0F + self.set_params(0x10, param_mv[:1]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x18]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[0] = 0x01 + self.set_params(0x01, param_mv[:1]) + + param_buf[0] = 0x1E + self.set_params(0x00, param_mv[:1]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x43]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[0] = 0x04 + self.set_params(0x03, param_mv[:1]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x18]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[0] = 0x01 + self.set_params(0x3A, param_mv[:1]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x50]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[0] = 0x08 + self.set_params(0x05, param_mv[:1]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x00]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x50]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[0] = 0xA6 + self.set_params(0x00, param_mv[:1]) + + param_buf[0] = 0xA6 + self.set_params(0x01, param_mv[:1]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x00]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x50]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[0] = 0x55 + self.set_params(0x08, param_mv[:1]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x00]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x10]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[0] = 0x43 + self.set_params(0x0B, param_mv[:1]) + + param_buf[0] = 0x12 + self.set_params(0x0C, param_mv[:1]) + + param_buf[0] = 0x01 + self.set_params(0x10, param_mv[:1]) + + param_buf[0] = 0x12 + self.set_params(0x11, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x15, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x16, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x1A, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x1B, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x61, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x62, param_mv[:1]) + + param_buf[0] = 0x11 + self.set_params(0x51, param_mv[:1]) + + param_buf[0] = 0x55 + self.set_params(0x55, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x58, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x5C, param_mv[:1]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x10]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[0] = 0x81 + self.set_params(0x20, param_mv[:1]) + + param_buf[0] = 0x82 + self.set_params(0x21, param_mv[:1]) + + param_buf[0] = 0x72 + self.set_params(0x22, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x30, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x31, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x32, param_mv[:1]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x10]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[0] = 0x44 + self.set_params(0x44, param_mv[:1]) + + param_buf[0] = 0x55 + self.set_params(0x45, param_mv[:1]) + + param_buf[0] = 0x66 + self.set_params(0x46, param_mv[:1]) + + param_buf[0] = 0x77 + self.set_params(0x47, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x49, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x4A, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x4B, param_mv[:1]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x17]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[0] = 0x00 + self.set_params(0x37, param_mv[:1]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x15]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[0] = 0x08 + self.set_params(0x04, param_mv[:1]) + + param_buf[0] = 0x04 + self.set_params(0x05, param_mv[:1]) + + param_buf[0] = 0x1C + self.set_params(0x06, param_mv[:1]) + + param_buf[0] = 0x1A + self.set_params(0x07, param_mv[:1]) + + param_buf[0] = 0x18 + self.set_params(0x08, param_mv[:1]) + + param_buf[0] = 0x16 + self.set_params(0x09, param_mv[:1]) + + param_buf[0] = 0x05 + self.set_params(0x24, param_mv[:1]) + + param_buf[0] = 0x09 + self.set_params(0x25, param_mv[:1]) + + param_buf[0] = 0x17 + self.set_params(0x26, param_mv[:1]) + + param_buf[0] = 0x19 + self.set_params(0x27, param_mv[:1]) + + param_buf[0] = 0x1B + self.set_params(0x28, param_mv[:1]) + + param_buf[0] = 0x1D + self.set_params(0x29, param_mv[:1]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x16]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[0] = 0x09 + self.set_params(0x04, param_mv[:1]) + + param_buf[0] = 0x05 + self.set_params(0x05, param_mv[:1]) + + param_buf[0] = 0x1D + self.set_params(0x06, param_mv[:1]) + + param_buf[0] = 0x1B + self.set_params(0x07, param_mv[:1]) + + param_buf[0] = 0x19 + self.set_params(0x08, param_mv[:1]) + + param_buf[0] = 0x17 + self.set_params(0x09, param_mv[:1]) + + param_buf[0] = 0x04 + self.set_params(0x24, param_mv[:1]) + + param_buf[0] = 0x08 + self.set_params(0x25, param_mv[:1]) + + param_buf[0] = 0x16 + self.set_params(0x26, param_mv[:1]) + + param_buf[0] = 0x18 + self.set_params(0x27, param_mv[:1]) + + param_buf[0] = 0x1A + self.set_params(0x28, param_mv[:1]) + + param_buf[0] = 0x1C + self.set_params(0x29, param_mv[:1]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x18]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[0] = 0x02 + self.set_params(0x1F, param_mv[:1]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x11]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[0] = 0x99 + self.set_params(0x15, param_mv[:1]) + + param_buf[0] = 0x99 + self.set_params(0x16, param_mv[:1]) + + param_buf[0] = 0x88 + self.set_params(0x1C, param_mv[:1]) + + param_buf[0] = 0x88 + self.set_params(0x1D, param_mv[:1]) + + param_buf[0] = 0x88 + self.set_params(0x1E, param_mv[:1]) + + param_buf[0] = 0xf0 + self.set_params(0x13, param_mv[:1]) + + param_buf[0] = 0x34 + self.set_params(0x14, param_mv[:1]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x12]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[0] = 0x89 + self.set_params(0x12, param_mv[:1]) + + param_buf[0] = 0x06 + self.set_params(0x06, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x18, param_mv[:1]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x11]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[0] = 0x00 + self.set_params(0x0A, param_mv[:1]) + + param_buf[0] = 0xF0 + self.set_params(0x0B, param_mv[:1]) + + param_buf[0] = 0xF0 + self.set_params(0x0c, param_mv[:1]) + + param_buf[0] = 0x10 + self.set_params(0x6A, param_mv[:1]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x00]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x11]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[0] = 0x70 + self.set_params(0x08, param_mv[:1]) + + param_buf[0] = 0x00 + self.set_params(0x09, param_mv[:1]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x00]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[0] = 0x00 + self.set_params(0x35, param_mv[:1]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x12]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[0] = 0x70 + self.set_params(0x21, param_mv[:1]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x2D]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[0] = 0x00 + self.set_params(0x02, param_mv[:1]) + + param_buf[:3] = bytearray([0x20, 0x10, 0x00]) + self.set_params(0xFF, param_mv[:3]) + + param_buf[0] = 0x00 + self.set_params(0x11, param_mv[:1]) + + time.sleep_ms(120) # NOQA diff --git a/api_drivers/common_api_drivers/display/spd2010/spd2010.py b/api_drivers/common_api_drivers/display/spd2010/spd2010.py new file mode 100644 index 00000000..7d50c866 --- /dev/null +++ b/api_drivers/common_api_drivers/display/spd2010/spd2010.py @@ -0,0 +1,202 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + +import display_driver_framework +import rgb_display_framework # NOQA +from micropython import const # NOQA +import lcd_bus +import lvgl as lv +import gc + + +STATE_HIGH = display_driver_framework.STATE_HIGH +STATE_LOW = display_driver_framework.STATE_LOW +STATE_PWM = display_driver_framework.STATE_PWM + +BYTE_ORDER_RGB = display_driver_framework.BYTE_ORDER_RGB +BYTE_ORDER_BGR = display_driver_framework.BYTE_ORDER_BGR + +_WRITE_CMD = const(0x02) +_WRITE_COLOR = const(0x32) + +_RASET = const(0x2B) +_CASET = const(0x2A) +_RAMWR = const(0x2C) + + +class SPD2010(display_driver_framework.DisplayDriver): + + _ORIENTATION_TABLE = () + + def _madctl(self, colormode, rotations, rotation=None): + if rotation is None: + rotation = ~self._rotation + + rotation = ~rotation + value = colormode + + if rotation: + value |= 0x03 + + return value + + def set_rotation(self, value): + + if value not in (lv.DISPLAY_ROTATION._0, lv.DISPLAY_ROTATION._180): # NOQA + print('This rotation is not supported, only 0 and 180 is supported') + return + + self._disp_drv.set_rotation(value) + + @staticmethod + def __quad_spi_cmd_modifier(cmd): + cmd <<= 8 + cmd |= _WRITE_CMD << 24 + return cmd + + @staticmethod + def __quad_spi_color_cmd_modifier(cmd): + cmd <<= 8 + cmd |= _WRITE_COLOR << 24 + return cmd + + @staticmethod + def __dummy_cmd_modifier(cmd): + return cmd + + def __init__( + self, + data_bus, + display_width, + display_height, + frame_buffer1=None, + frame_buffer2=None, + reset_pin=None, + reset_state=STATE_HIGH, + power_pin=None, + power_on_state=STATE_HIGH, + backlight_pin=None, + backlight_on_state=STATE_HIGH, + offset_x=0, + offset_y=0, + color_byte_order=BYTE_ORDER_RGB, + color_space=lv.COLOR_FORMAT.RGB888, # NOQA + rgb565_byte_swap=False, # NOQA + ): + num_lanes = data_bus.get_lane_count() + + if num_lanes == 4: + self.__cmd_modifier = self.__quad_spi_cmd_modifier + self.__color_cmd_modifier = self.__quad_spi_color_cmd_modifier + _cmd_bits = 32 + + # we need to override the default handling for creating the frame + # buffer is using a quad spi bus. we don't want it to create + # partial buffers for the quad SPI display + + buf_size = display_width * display_height * lv.color_format_get_size(color_space) + + if frame_buffer1 is None: + gc.collect() + + for flags in ( + lcd_bus.MEMORY_INTERNAL | lcd_bus.MEMORY_DMA, + lcd_bus.MEMORY_SPIRAM | lcd_bus.MEMORY_DMA, + lcd_bus.MEMORY_INTERNAL, + lcd_bus.MEMORY_SPIRAM + ): + try: + frame_buffer1 = ( + data_bus.allocate_framebuffer(buf_size, flags) + ) + + if (flags | lcd_bus.MEMORY_DMA) == flags: + frame_buffer2 = ( + data_bus.allocate_framebuffer(buf_size, flags) + ) + + break + except MemoryError: + frame_buffer1 = data_bus.free_framebuffer(frame_buffer1) # NOQA + + if frame_buffer1 is None: + raise MemoryError( + f'Unable to allocate memory for frame buffer ({buf_size})' # NOQA + ) + + if len(frame_buffer1) != buf_size: + raise ValueError('incorrect framebuffer size') + else: + self.__cmd_modifier = self.__dummy_cmd_modifier + self.__color_cmd_modifier = self.__dummy_cmd_modifier + _cmd_bits = 8 + + # store these so we do not have to keep on converting them + self.__ramwr = self.__color_cmd_modifier(_RAMWR) + self.__caset = self.__cmd_modifier(_CASET) + self.__raset = self.__cmd_modifier(_RASET) + + super().__init__( + data_bus, + display_width, + display_height, + frame_buffer1, + frame_buffer2, + reset_pin, + reset_state, + power_pin, + power_on_state, + backlight_pin, + backlight_on_state, + offset_x, + offset_y, + color_byte_order, + color_space, # NOQA + # we don't need to sue RGB565 byte swap so we override it + rgb565_byte_swap=False, + _cmd_bits=_cmd_bits, + _param_bits=8, + _init_bus=True + ) + + def _flush_ready_cb(self, *_): + # since there are 2 transfers that take place we need to + # make sure that flush ready is only called after the second part + # of the buffer has sent. + self._disp_drv.flush_ready() + + def set_params(self, cmd, params=None): + cmd = self.__cmd_modifier(cmd) + self._data_bus.tx_param(cmd, params) + + def _set_memory_location(self, x1: int, y1: int, x2: int, y2: int): + param_buf = self._param_buf # NOQA + + param_buf[0] = (x1 >> 8) & 0xFF + param_buf[1] = x1 & 0xFF + param_buf[2] = (x2 >> 8) & 0xFF + param_buf[3] = x2 & 0xFF + + self._data_bus.tx_param(self.__caset, self._param_mv) + + param_buf[0] = (y1 >> 8) & 0xFF + param_buf[1] = y1 & 0xFF + param_buf[2] = (y2 >> 8) & 0xFF + param_buf[3] = y2 & 0xFF + + self._data_bus.tx_param(self.__raset, self._param_mv) + + def _flush_cb(self, _, area, color_p): + x1 = area.x1 + self._offset_x + x2 = area.x2 + self._offset_x + + y1 = area.y1 + self._offset_y + y2 = area.y2 + self._offset_y + + self._set_memory_location(x1, y1, x2, y2) + + width = x2 - x1 + 1 + height = y2 - y1 + 1 + size = width * height * lv.color_format_get_size(self._color_space) + + data_view = color_p.__dereference__(size) + self._data_bus.tx_color(self.__ramwr, data_view, x1, y1, x2, y2, self._rotation, False) diff --git a/api_drivers/common_api_drivers/display/ssd1306/_ssd1306_init.py b/api_drivers/common_api_drivers/display/ssd1306/_ssd1306_init.py index b44a298c..c8888042 100644 --- a/api_drivers/common_api_drivers/display/ssd1306/_ssd1306_init.py +++ b/api_drivers/common_api_drivers/display/ssd1306/_ssd1306_init.py @@ -1,9 +1,10 @@ -from micropython import const +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + +from micropython import const # NOQA _SET_CONTRAST = const(0x81) _SET_ENTIRE_ON = const(0xA4) _SET_NORM_INV = const(0xA6) -_SET_DISP = const() _DISP_OFF = const(0xAE) _DISP_ON = const(0xAF) _SET_MEM_ADDR = const(0x20) diff --git a/api_drivers/common_api_drivers/display/ssd1306/ssd1306.py b/api_drivers/common_api_drivers/display/ssd1306/ssd1306.py index 43ba1e90..2ed8ff59 100644 --- a/api_drivers/common_api_drivers/display/ssd1306/ssd1306.py +++ b/api_drivers/common_api_drivers/display/ssd1306/ssd1306.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + from micropython import const # NOQA import display_driver_framework @@ -12,7 +14,6 @@ _SET_CONTRAST = const(0x81) _SET_NORM_INV = const(0xA6) -_SET_DISP = const() _DISP_OFF = const(0xAE) _DISP_ON = const(0xAF) _SET_COL_ADDR = const(0x21) @@ -70,7 +71,7 @@ def __init__( break except MemoryError: - frame_buffer1 = data_bus.free_framebuffer(frame_buffer1) + frame_buffer1 = data_bus.free_framebuffer(frame_buffer1) # NOQA if frame_buffer1 is None: raise MemoryError( @@ -117,7 +118,7 @@ def get_power(self): return self._power def set_power(self, value): - self._power = bool(value) + self._power = bool(value) # NOQA if self._power: self.set_params(_DISP_ON) diff --git a/api_drivers/common_api_drivers/display/ssd1351/_ssd1351_init.py b/api_drivers/common_api_drivers/display/ssd1351/_ssd1351_init.py index 385d8310..06526d4b 100644 --- a/api_drivers/common_api_drivers/display/ssd1351/_ssd1351_init.py +++ b/api_drivers/common_api_drivers/display/ssd1351/_ssd1351_init.py @@ -1,4 +1,4 @@ - +# Copyright (c) 2024 - 2025 Kevin G. Schlosser def init(self): param_buf = bytearray(14) diff --git a/api_drivers/common_api_drivers/display/ssd1351/ssd1351.py b/api_drivers/common_api_drivers/display/ssd1351/ssd1351.py index 9526ade5..6d37947f 100644 --- a/api_drivers/common_api_drivers/display/ssd1351/ssd1351.py +++ b/api_drivers/common_api_drivers/display/ssd1351/ssd1351.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + from micropython import const # NOQA import display_driver_framework diff --git a/api_drivers/common_api_drivers/display/ssd1963/_ssd1963_init_type1.py b/api_drivers/common_api_drivers/display/ssd1963/_ssd1963_init_type1.py index b2ab9589..80abada0 100644 --- a/api_drivers/common_api_drivers/display/ssd1963/_ssd1963_init_type1.py +++ b/api_drivers/common_api_drivers/display/ssd1963/_ssd1963_init_type1.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import time from micropython import const # NOQA @@ -14,14 +16,14 @@ def init(self): param_buf[0] = 0x01 self.set_params(0xE0, param_mv[:1]) - time.sleep_ms(10) + time.sleep_ms(10) # NOQA param_buf[0] = 0x03 self.set_params(0xE0, param_mv[:1]) - time.sleep_ms(10) + time.sleep_ms(10) # NOQA self.set_params(0x01) - time.sleep_ms(100) + time.sleep_ms(100) # NOQA param_buf[0] = 0x01 param_buf[1] = 0x1F param_buf[2] = 0xFF @@ -62,13 +64,13 @@ def init(self): param_buf[1] = 0x01 self.set_params(0xB8, param_mv[:2]) - param_buf[0] = 0x21 | TFT_MAD_COLOR_ORDER + param_buf[0] = 0x21 # | TFT_MAD_COLOR_ORDER self.set_params(0x36, param_mv[:1]) param_buf[0] = 0x00 self.set_params(0xF0, param_mv[:1]) - time.sleep_ms(1) + time.sleep_ms(1) # NOQA param_buf[0] = 0x0f param_buf[1] = 0x01 self.set_params(0xB8, param_mv[:2]) diff --git a/api_drivers/common_api_drivers/display/ssd1963/_ssd1963_init_type2.py b/api_drivers/common_api_drivers/display/ssd1963/_ssd1963_init_type2.py index cb8787e4..e4627583 100644 --- a/api_drivers/common_api_drivers/display/ssd1963/_ssd1963_init_type2.py +++ b/api_drivers/common_api_drivers/display/ssd1963/_ssd1963_init_type2.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import time from micropython import const # NOQA @@ -14,14 +16,14 @@ def init(self): param_buf[0] = 0x01 self.set_params(0xE0, param_mv[:1]) - time.sleep_ms(10) + time.sleep_ms(10) # NOQA param_buf[0] = 0x03 self.set_params(0xE0, param_mv[:1]) - time.sleep_ms(10) + time.sleep_ms(10) # NOQA self.set_params(0x01) - time.sleep_ms(100) + time.sleep_ms(100) # NOQA param_buf[0] = 0x03 param_buf[1] = 0xFF param_buf[2] = 0xFF @@ -62,13 +64,13 @@ def init(self): param_buf[1] = 0x01 self.set_params(0xB8, param_mv[:2]) - param_buf[0] = 0x21 | TFT_MAD_COLOR_ORDER + param_buf[0] = 0x21 # | TFT_MAD_COLOR_ORDER self.set_params(0x36, param_mv[:1]) param_buf[0] = 0x00 self.set_params(0xF0, param_mv[:1]) - time.sleep_ms(1) + time.sleep_ms(1) # NOQA param_buf[0] = 0x0f param_buf[1] = 0x01 self.set_params(0xB8, param_mv[:2]) diff --git a/api_drivers/common_api_drivers/display/ssd1963/_ssd1963_init_type3.py b/api_drivers/common_api_drivers/display/ssd1963/_ssd1963_init_type3.py index 6064510e..7e003005 100644 --- a/api_drivers/common_api_drivers/display/ssd1963/_ssd1963_init_type3.py +++ b/api_drivers/common_api_drivers/display/ssd1963/_ssd1963_init_type3.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import time from micropython import const # NOQA @@ -14,14 +16,14 @@ def init(self): param_buf[0] = 0x01 self.set_params(0xE0, param_mv[:1]) - time.sleep_ms(10) + time.sleep_ms(10) # NOQA param_buf[0] = 0x03 self.set_params(0xE0, param_mv[:1]) - time.sleep_ms(10) + time.sleep_ms(10) # NOQA self.set_params(0x01) - time.sleep_ms(100) + time.sleep_ms(100) # NOQA param_buf[0] = 0x04 param_buf[1] = 0x93 param_buf[2] = 0xE0 @@ -62,13 +64,13 @@ def init(self): param_buf[1] = 0x01 self.set_params(0xB8, param_mv[:2]) - param_buf[0] = 0x21 | TFT_MAD_COLOR_ORDER + param_buf[0] = 0x21 # | TFT_MAD_COLOR_ORDER self.set_params(0x36, param_mv[:1]) param_buf[0] = 0x00 self.set_params(0xF0, param_mv[:1]) - time.sleep_ms(10) + time.sleep_ms(10) # NOQA param_buf[0] = 0 param_buf[1] = 0 param_buf[2] = (479 & 0xFF00) >> 8 diff --git a/api_drivers/common_api_drivers/display/ssd1963/_ssd1963_init_type4.py b/api_drivers/common_api_drivers/display/ssd1963/_ssd1963_init_type4.py index 688b7160..ab0e1ae1 100644 --- a/api_drivers/common_api_drivers/display/ssd1963/_ssd1963_init_type4.py +++ b/api_drivers/common_api_drivers/display/ssd1963/_ssd1963_init_type4.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import time from micropython import const # NOQA @@ -14,14 +16,14 @@ def init(self): param_buf[0] = 0x01 self.set_params(0xE0, param_mv[:1]) - time.sleep_ms(10) + time.sleep_ms(10) # NOQA param_buf[0] = 0x03 self.set_params(0xE0, param_mv[:1]) - time.sleep_ms(10) + time.sleep_ms(10) # NOQA self.set_params(0x01) - time.sleep_ms(100) + time.sleep_ms(100) # NOQA param_buf[0] = 0x03 param_buf[1] = 0x33 param_buf[2] = 0x33 @@ -62,7 +64,7 @@ def init(self): param_buf[0] = 0x01 self.set_params(0xBA, param_mv[:1]) - param_buf[0] = 0x21 | TFT_MAD_COLOR_ORDER + param_buf[0] = 0x21 # | TFT_MAD_COLOR_ORDER self.set_params(0x36, param_mv[:1]) param_buf[0] = 0x00 @@ -74,7 +76,7 @@ def init(self): param_buf[3] = 0x01 self.set_params(0xBC, param_mv[:4]) - time.sleep_ms(10) + time.sleep_ms(10) # NOQA self.set_params(0x29) param_buf[0] = 0x06 diff --git a/api_drivers/common_api_drivers/display/ssd1963/ssd1963.py b/api_drivers/common_api_drivers/display/ssd1963/ssd1963.py index f0a04e37..af31eeca 100644 --- a/api_drivers/common_api_drivers/display/ssd1963/ssd1963.py +++ b/api_drivers/common_api_drivers/display/ssd1963/ssd1963.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import display_driver_framework @@ -16,5 +18,3 @@ class SSD1963(display_driver_framework.DisplayDriver): pass - - diff --git a/api_drivers/common_api_drivers/display/st7565/_st7565_init.py b/api_drivers/common_api_drivers/display/st7565/_st7565_init.py index 5ff0c740..254efc2c 100644 --- a/api_drivers/common_api_drivers/display/st7565/_st7565_init.py +++ b/api_drivers/common_api_drivers/display/st7565/_st7565_init.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + from micropython import const # NOQA import time diff --git a/api_drivers/common_api_drivers/display/st7565/st7565.py b/api_drivers/common_api_drivers/display/st7565/st7565.py index ea635934..31e981c8 100644 --- a/api_drivers/common_api_drivers/display/st7565/st7565.py +++ b/api_drivers/common_api_drivers/display/st7565/st7565.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import display_driver_framework diff --git a/api_drivers/common_api_drivers/display/st7701/_st7701_type1.py b/api_drivers/common_api_drivers/display/st7701/_st7701_type1.py index 064646a1..6315b02c 100644 --- a/api_drivers/common_api_drivers/display/st7701/_st7701_type1.py +++ b/api_drivers/common_api_drivers/display/st7701/_st7701_type1.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import time diff --git a/api_drivers/common_api_drivers/display/st7701/_st7701_type10.py b/api_drivers/common_api_drivers/display/st7701/_st7701_type10.py index 749fd795..651d9264 100644 --- a/api_drivers/common_api_drivers/display/st7701/_st7701_type10.py +++ b/api_drivers/common_api_drivers/display/st7701/_st7701_type10.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import time diff --git a/api_drivers/common_api_drivers/display/st7701/_st7701_type11.py b/api_drivers/common_api_drivers/display/st7701/_st7701_type11.py index ae47ba34..7f272318 100644 --- a/api_drivers/common_api_drivers/display/st7701/_st7701_type11.py +++ b/api_drivers/common_api_drivers/display/st7701/_st7701_type11.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import time diff --git a/api_drivers/common_api_drivers/display/st7701/_st7701_type12.py b/api_drivers/common_api_drivers/display/st7701/_st7701_type12.py index 0e7f8162..2e6a91c9 100644 --- a/api_drivers/common_api_drivers/display/st7701/_st7701_type12.py +++ b/api_drivers/common_api_drivers/display/st7701/_st7701_type12.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import time diff --git a/api_drivers/common_api_drivers/display/st7701/_st7701_type13.py b/api_drivers/common_api_drivers/display/st7701/_st7701_type13.py index a7788f59..9880b978 100644 --- a/api_drivers/common_api_drivers/display/st7701/_st7701_type13.py +++ b/api_drivers/common_api_drivers/display/st7701/_st7701_type13.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import time diff --git a/api_drivers/common_api_drivers/display/st7701/_st7701_type14.py b/api_drivers/common_api_drivers/display/st7701/_st7701_type14.py index 0d808a70..9f0ae78f 100644 --- a/api_drivers/common_api_drivers/display/st7701/_st7701_type14.py +++ b/api_drivers/common_api_drivers/display/st7701/_st7701_type14.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import time diff --git a/api_drivers/common_api_drivers/display/st7701/_st7701_type15.py b/api_drivers/common_api_drivers/display/st7701/_st7701_type15.py index 7aa2c340..0365f6cf 100644 --- a/api_drivers/common_api_drivers/display/st7701/_st7701_type15.py +++ b/api_drivers/common_api_drivers/display/st7701/_st7701_type15.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import time diff --git a/api_drivers/common_api_drivers/display/st7701/_st7701_type16.py b/api_drivers/common_api_drivers/display/st7701/_st7701_type16.py index 470340f5..ebf629d4 100644 --- a/api_drivers/common_api_drivers/display/st7701/_st7701_type16.py +++ b/api_drivers/common_api_drivers/display/st7701/_st7701_type16.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import time diff --git a/api_drivers/common_api_drivers/display/st7701/_st7701_type17.py b/api_drivers/common_api_drivers/display/st7701/_st7701_type17.py index 0d8abf3c..74e3f336 100644 --- a/api_drivers/common_api_drivers/display/st7701/_st7701_type17.py +++ b/api_drivers/common_api_drivers/display/st7701/_st7701_type17.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import time @@ -73,7 +75,7 @@ def init(self): param_buf[0] = 0x78 self.set_params(0xC2, param_mv[:1]) - time.sleep_ms(20) + time.sleep_ms(20) # NOQA param_buf[:3] = bytearray([0x00, 0x1B, 0x02]) self.set_params(0xE0, param_mv[:3]) diff --git a/api_drivers/common_api_drivers/display/st7701/_st7701_type2.py b/api_drivers/common_api_drivers/display/st7701/_st7701_type2.py index 608c227d..dc76d2d1 100644 --- a/api_drivers/common_api_drivers/display/st7701/_st7701_type2.py +++ b/api_drivers/common_api_drivers/display/st7701/_st7701_type2.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import time diff --git a/api_drivers/common_api_drivers/display/st7701/_st7701_type3.py b/api_drivers/common_api_drivers/display/st7701/_st7701_type3.py index 394b5884..4fc3989c 100644 --- a/api_drivers/common_api_drivers/display/st7701/_st7701_type3.py +++ b/api_drivers/common_api_drivers/display/st7701/_st7701_type3.py @@ -1,4 +1,6 @@ -import time +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + +import time def init(self): diff --git a/api_drivers/common_api_drivers/display/st7701/_st7701_type4.py b/api_drivers/common_api_drivers/display/st7701/_st7701_type4.py index a37ce745..6f50dbc4 100644 --- a/api_drivers/common_api_drivers/display/st7701/_st7701_type4.py +++ b/api_drivers/common_api_drivers/display/st7701/_st7701_type4.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import time diff --git a/api_drivers/common_api_drivers/display/st7701/_st7701_type5.py b/api_drivers/common_api_drivers/display/st7701/_st7701_type5.py index 01d1491d..ef9c12fe 100644 --- a/api_drivers/common_api_drivers/display/st7701/_st7701_type5.py +++ b/api_drivers/common_api_drivers/display/st7701/_st7701_type5.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import time diff --git a/api_drivers/common_api_drivers/display/st7701/_st7701_type6.py b/api_drivers/common_api_drivers/display/st7701/_st7701_type6.py index 574eb182..9bd98c69 100644 --- a/api_drivers/common_api_drivers/display/st7701/_st7701_type6.py +++ b/api_drivers/common_api_drivers/display/st7701/_st7701_type6.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import time diff --git a/api_drivers/common_api_drivers/display/st7701/_st7701_type7.py b/api_drivers/common_api_drivers/display/st7701/_st7701_type7.py index b30946b2..3f5f9cd4 100644 --- a/api_drivers/common_api_drivers/display/st7701/_st7701_type7.py +++ b/api_drivers/common_api_drivers/display/st7701/_st7701_type7.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import time diff --git a/api_drivers/common_api_drivers/display/st7701/_st7701_type8.py b/api_drivers/common_api_drivers/display/st7701/_st7701_type8.py index 3d4a5be0..9299f293 100644 --- a/api_drivers/common_api_drivers/display/st7701/_st7701_type8.py +++ b/api_drivers/common_api_drivers/display/st7701/_st7701_type8.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import time diff --git a/api_drivers/common_api_drivers/display/st7701/_st7701_type9.py b/api_drivers/common_api_drivers/display/st7701/_st7701_type9.py index e0d9fc02..33378544 100644 --- a/api_drivers/common_api_drivers/display/st7701/_st7701_type9.py +++ b/api_drivers/common_api_drivers/display/st7701/_st7701_type9.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import time diff --git a/api_drivers/common_api_drivers/display/st7701/st7701.py b/api_drivers/common_api_drivers/display/st7701/st7701.py index 4e15f452..0009587a 100644 --- a/api_drivers/common_api_drivers/display/st7701/st7701.py +++ b/api_drivers/common_api_drivers/display/st7701/st7701.py @@ -1,8 +1,10 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + from micropython import const # NOQA import lvgl as lv # NOQA import lcd_bus # NOQA -import rgb_display_framework +import rgb_display_framework # NOQA STATE_HIGH = rgb_display_framework.STATE_HIGH diff --git a/api_drivers/common_api_drivers/display/st7735/_st7735_init_type1.py b/api_drivers/common_api_drivers/display/st7735/_st7735_init_type1.py index 9db88202..1c598649 100644 --- a/api_drivers/common_api_drivers/display/st7735/_st7735_init_type1.py +++ b/api_drivers/common_api_drivers/display/st7735/_st7735_init_type1.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import time from micropython import const # NOQA diff --git a/api_drivers/common_api_drivers/display/st7735/_st7735_init_type2.py b/api_drivers/common_api_drivers/display/st7735/_st7735_init_type2.py index b67c7efc..106d281f 100644 --- a/api_drivers/common_api_drivers/display/st7735/_st7735_init_type2.py +++ b/api_drivers/common_api_drivers/display/st7735/_st7735_init_type2.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import time from micropython import const # NOQA diff --git a/api_drivers/common_api_drivers/display/st7735/_st7735_init_type3.py b/api_drivers/common_api_drivers/display/st7735/_st7735_init_type3.py index 4f68c069..985ef8c5 100644 --- a/api_drivers/common_api_drivers/display/st7735/_st7735_init_type3.py +++ b/api_drivers/common_api_drivers/display/st7735/_st7735_init_type3.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import time from micropython import const # NOQA diff --git a/api_drivers/common_api_drivers/display/st7735/st7735.py b/api_drivers/common_api_drivers/display/st7735/st7735.py index edb0b693..599dd7ff 100644 --- a/api_drivers/common_api_drivers/display/st7735/st7735.py +++ b/api_drivers/common_api_drivers/display/st7735/st7735.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + from micropython import const # NOQA import display_driver_framework @@ -43,4 +45,4 @@ def init(self, type): # NOQA _MADCTL_MY | _MADCTL_MX, _MADCTL_MV | _MADCTL_MX ) - display_driver_framework.DisplayDriver.init(self, type) + display_driver_framework.DisplayDriver.init(self, type) # NOQA diff --git a/api_drivers/common_api_drivers/display/st7789/_st7789_init.py b/api_drivers/common_api_drivers/display/st7789/_st7789_init.py index cf61a3d6..42a21135 100644 --- a/api_drivers/common_api_drivers/display/st7789/_st7789_init.py +++ b/api_drivers/common_api_drivers/display/st7789/_st7789_init.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import time from micropython import const # NOQA diff --git a/api_drivers/common_api_drivers/display/st7789/st7789.py b/api_drivers/common_api_drivers/display/st7789/st7789.py index 0a94caf0..26b9b3a5 100644 --- a/api_drivers/common_api_drivers/display/st7789/st7789.py +++ b/api_drivers/common_api_drivers/display/st7789/st7789.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + from micropython import const # NOQA import display_driver_framework import lcd_bus @@ -76,4 +78,3 @@ def __init__( _param_bits=8, _init_bus=True ) - diff --git a/api_drivers/common_api_drivers/display/st7796/_st7796_init.py b/api_drivers/common_api_drivers/display/st7796/_st7796_init.py index 55bce822..ffb7b5e0 100644 --- a/api_drivers/common_api_drivers/display/st7796/_st7796_init.py +++ b/api_drivers/common_api_drivers/display/st7796/_st7796_init.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import time from micropython import const # NOQA diff --git a/api_drivers/common_api_drivers/display/st7796/st7796.py b/api_drivers/common_api_drivers/display/st7796/st7796.py index d2f682d0..aac6486b 100644 --- a/api_drivers/common_api_drivers/display/st7796/st7796.py +++ b/api_drivers/common_api_drivers/display/st7796/st7796.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + from micropython import const # NOQA import display_driver_framework diff --git a/micropy_updates/esp32/machine_i2c.c b/api_drivers/common_api_drivers/frozen/machine_i2c.c similarity index 70% rename from micropy_updates/esp32/machine_i2c.c rename to api_drivers/common_api_drivers/frozen/machine_i2c.c index 5e20bc9d..326becde 100644 --- a/micropy_updates/esp32/machine_i2c.c +++ b/api_drivers/common_api_drivers/frozen/machine_i2c.c @@ -1,28 +1,6 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2019 Damien P. George - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ +// Copyright (c) 2016 Damien P. George +// Copyright (c) 2024 - 2025 Kevin G. Schlosser + #include "py/runtime.h" #include "py/mphal.h" @@ -39,6 +17,9 @@ #if MICROPY_PY_MACHINE_I2C || MICROPY_PY_MACHINE_SOFTI2C #include "../../../../micropy_updates/common/mp_i2c_common.h" + #include "sdkconfig.h" + + #define MP_MACHINE_I2C_FLAG_WRITE2 (0x08) #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32S3 #define SCLK_I2C_FREQ XTAL_CLK_FREQ @@ -65,6 +46,17 @@ xSemaphoreGive(self->lock.handle); \ } + #if CONFIG_LCD_ENABLE_DEBUG_LOG + #define I2C_DEBUG_PRINT(...) mp_printf(&mp_plat_print, __VA_ARGS__); + #else + #define I2C_DEBUG_PRINT(...) + #endif + + #define RAISE_VALUE_ERROR(msg, ...) \ + mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT(msg), __VA_ARGS__) + + + // ********************** machine.I2C.Bus ************************ @@ -106,7 +98,8 @@ } - static void i2c_bus_init_internal(mp_machine_hw_i2c_bus_obj_t *self, uint32_t freq, uint32_t timeout_us) + static void i2c_bus_init_internal(mp_machine_hw_i2c_bus_obj_t *self, + uint32_t freq, uint32_t timeout_us) { i2c_bus_deinit_internal(self); @@ -123,7 +116,9 @@ int timeout = SCLK_I2C_FREQ / 1000000 * timeout_us; - i2c_set_timeout(self->port, (timeout > I2C_LL_MAX_TIMEOUT) ? I2C_LL_MAX_TIMEOUT : timeout); + i2c_set_timeout(self->port, + (timeout > I2C_LL_MAX_TIMEOUT) ? I2C_LL_MAX_TIMEOUT : timeout); + i2c_driver_install(self->port, I2C_MODE_MASTER, 0, 0, 0); self->active = 1; @@ -131,7 +126,7 @@ static int i2c_bus_transfer(mp_obj_base_t *self_in, uint16_t addr, size_t n, - mp_machine_i2c_buf_t *bufs, unsigned int flags) + mp_machine_i2c_buf_t *bufs, unsigned int flags) { mp_machine_hw_i2c_bus_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -150,12 +145,22 @@ ++bufs; } + if (flags & MP_MACHINE_I2C_FLAG_WRITE2) { + i2c_master_start(cmd); + i2c_master_write_byte(cmd, addr << 1, true); + i2c_master_write(cmd, bufs->buf, bufs->len, true); + data_len += bufs->len; + --n; + ++bufs; + } + i2c_master_start(cmd); i2c_master_write_byte(cmd, addr << 1 | (flags & MP_MACHINE_I2C_FLAG_READ), true); for (; n--; ++bufs) { if (flags & MP_MACHINE_I2C_FLAG_READ) { - i2c_master_read(cmd, bufs->buf, bufs->len, n == 0 ? I2C_MASTER_LAST_NACK : I2C_MASTER_ACK); + i2c_master_read(cmd, bufs->buf, bufs->len, + n == 0 ? I2C_MASTER_LAST_NACK : I2C_MASTER_ACK); } else { if (bufs->len != 0) { i2c_master_write(cmd, bufs->buf, bufs->len, true); @@ -168,8 +173,8 @@ i2c_master_stop(cmd); } - // TODO proper timeout - esp_err_t err = i2c_master_cmd_begin(self->port, cmd, 100 * (1 + data_len) / portTICK_PERIOD_MS); + esp_err_t err = i2c_master_cmd_begin(self->port, cmd, + 100 * (1 + data_len) / portTICK_PERIOD_MS); i2c_cmd_link_delete(cmd); if (self->use_locks == 1) I2C_BUS_LOCK_RELEASE(self); @@ -199,36 +204,37 @@ } - static mp_obj_t i2c_bus_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - // MP_MACHINE_I2C_CHECK_FOR_LEGACY_SOFTI2C_CONSTRUCTION(n_args, n_kw, all_args); + static mp_obj_t i2c_bus_make_new(const mp_obj_type_t *type, size_t n_args, + size_t n_kw, const mp_obj_t *all_args) + { + + enum { ARG_host, ARG_scl, ARG_sda, ARG_freq, + ARG_use_locks, ARG_pullup, ARG_timeout }; - // Parse args - enum { ARG_host, ARG_scl, ARG_sda, ARG_freq, ARG_use_locks, ARG_pullup, ARG_timeout }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_host, MP_ARG_REQUIRED | MP_ARG_INT }, - { MP_QSTR_scl, MP_ARG_REQUIRED | MP_ARG_INT }, - { MP_QSTR_sda, MP_ARG_REQUIRED | MP_ARG_INT }, - { MP_QSTR_freq, MP_ARG_INT, { .u_int = 400000} }, + { MP_QSTR_host, MP_ARG_INT | MP_ARG_REQUIRED }, + { MP_QSTR_scl, MP_ARG_INT | MP_ARG_REQUIRED }, + { MP_QSTR_sda, MP_ARG_INT | MP_ARG_REQUIRED }, + { MP_QSTR_freq, MP_ARG_INT, { .u_int = 400000 } }, { MP_QSTR_use_locks, MP_ARG_BOOL, { .u_bool = false } }, { MP_QSTR_pullup, MP_ARG_BOOL, { .u_bool = false } }, { MP_QSTR_timeout, MP_ARG_INT, { .u_int = DEFAULT_I2C_TIMEOUT_US } }, }; 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); + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, + MP_ARRAY_SIZE(allowed_args), allowed_args, args); - // Get I2C bus int i2c_id = (int)args[ARG_host].u_int; if (!(I2C_NUM_0 <= i2c_id && i2c_id < I2C_NUM_MAX)) { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("I2C(%u) doesn't exist"), i2c_id); + RAISE_VALUE_ERROR("I2C(%u) doesn't exist", i2c_id); } - // Get static peripheral object mp_machine_hw_i2c_bus_obj_t *self = (mp_machine_hw_i2c_bus_obj_t *)&machine_hw_i2c_obj[i2c_id]; if (self->base.type != NULL) { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("I2C host is already in use (%u)"), i2c_id); + RAISE_VALUE_ERROR("I2C host is already in use (%u)", i2c_id); } - // Created for the first time, set default pins + self->base.type = &mp_machine_hw_i2c_bus_type; self->port = (uint8_t)i2c_id; self->active = 0; @@ -271,7 +277,7 @@ static size_t get_memaddr_buf(uint8_t *memaddr_buf, uint32_t memaddr, uint8_t addrsize) { size_t memaddr_len = 0; if ((addrsize & 7) != 0 || addrsize > 32) { - mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("invalid mem address size (%u)"), addrsize); + RAISE_VALUE_ERROR("invalid mem address size (%u)", addrsize); } for (int16_t i = addrsize - 8; i >= 0; i -= 8) { @@ -282,48 +288,39 @@ } - static int device_read(mp_machine_hw_i2c_device_obj_t *self, uint16_t addr, uint32_t memaddr, - uint8_t addrsize, uint8_t *buf, size_t len) + static int device_read(mp_machine_hw_i2c_device_obj_t *self, uint16_t addr, + uint32_t memaddr, uint8_t addrsize, uint8_t *buf, size_t len) { if (self->bus == NULL) return -1; - mp_obj_base_t *bus = (mp_obj_base_t *)self->bus; - - // Create buffer with memory address uint8_t memaddr_buf[4]; size_t memaddr_len = get_memaddr_buf(&memaddr_buf[0], memaddr, addrsize); - // Create partial write and read buffers mp_machine_i2c_buf_t bufs[2] = { {.len = memaddr_len, .buf = memaddr_buf}, {.len = len, .buf = buf}, }; - // Do write+read I2C transfer - return i2c_bus_transfer(bus, addr, 2, bufs, + return i2c_bus_transfer((mp_obj_base_t *)self->bus, addr, 2, bufs, MP_MACHINE_I2C_FLAG_WRITE1 | MP_MACHINE_I2C_FLAG_READ | MP_MACHINE_I2C_FLAG_STOP); } - static int device_write(mp_machine_hw_i2c_device_obj_t *self, uint16_t addr, uint32_t memaddr, - uint8_t addrsize, const uint8_t *buf, size_t len) + static int device_write(mp_machine_hw_i2c_device_obj_t *self, uint16_t addr, + uint32_t memaddr, uint8_t addrsize, const uint8_t *buf, size_t len) { if (self->bus == NULL) return -1; - mp_obj_base_t *bus = (mp_obj_base_t *)self->bus; - - // Create buffer with memory address uint8_t memaddr_buf[4]; size_t memaddr_len = get_memaddr_buf(&memaddr_buf[0], memaddr, addrsize); - // Create partial write buffers mp_machine_i2c_buf_t bufs[2] = { {.len = memaddr_len, .buf = memaddr_buf}, {.len = len, .buf = (uint8_t *)buf}, }; - // Do I2C transfer - return i2c_bus_transfer(bus, addr, 2, bufs, MP_MACHINE_I2C_FLAG_STOP); + return i2c_bus_transfer((mp_obj_base_t *)self->bus, addr, 2, + bufs, MP_MACHINE_I2C_FLAG_STOP); } @@ -332,11 +329,8 @@ { if (self->bus == NULL) return -1; - mp_obj_base_t *bus = (mp_obj_base_t *)self->bus; - mp_machine_i2c_buf_t buf = {.len = len, .buf = dest}; - - return i2c_bus_transfer(bus, addr, 1, + return i2c_bus_transfer((mp_obj_base_t *)self->bus, addr, 1, &buf, MP_MACHINE_I2C_FLAG_READ | (stop ? MP_MACHINE_I2C_FLAG_STOP : 0)); } @@ -346,11 +340,9 @@ { if (self->bus == NULL) return -1; - mp_obj_base_t *bus = (mp_obj_base_t *)self->bus; - mp_machine_i2c_buf_t buf = {.len = len, .buf = (uint8_t *)src}; - - return i2c_bus_transfer(bus, addr, 1, &buf, stop ? MP_MACHINE_I2C_FLAG_STOP : 0); + return i2c_bus_transfer((mp_obj_base_t *)self->bus, addr, 1, + &buf, stop ? MP_MACHINE_I2C_FLAG_STOP : 0); } @@ -372,7 +364,8 @@ } self->bus->device_count--; - self->bus->devices = m_realloc(self->bus->devices, self->bus->device_count * sizeof(mp_machine_hw_i2c_device_obj_t *)); + self->bus->devices = m_realloc(self->bus->devices, + self->bus->device_count * sizeof(mp_machine_hw_i2c_device_obj_t *)); self->bus = NULL; } @@ -398,7 +391,8 @@ }; 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_arg_parse_all(n_args, pos_args, kw_args, + MP_ARRAY_SIZE(allowed_args), allowed_args, args); mp_machine_hw_i2c_device_obj_t *self = MP_OBJ_TO_PTR(args[ARG_self].u_obj); @@ -408,16 +402,50 @@ mp_buffer_info_t read_bufinfo; mp_get_buffer_raise(args[ARG_write_buf].u_obj, &read_bufinfo, MP_BUFFER_WRITE); - int ret = device_writeto(self, self->device_id, (uint8_t *)write_bufinfo.buf, write_bufinfo.len, false); - if (ret < 0) { - mp_raise_OSError(-ret); + uint8_t * write_buf = (uint8_t *)write_bufinfo.buf; + uint32_t memaddr = 0; + + if ((self->reg_bits & 7) != 0 || self->reg_bits > 32) { + RAISE_VALUE_ERROR("invalid mem address size (%u)", self->reg_bits); } - ret = device_readfrom(self, self->device_id, (uint8_t *)read_bufinfo.buf, read_bufinfo.len, true); - if (ret < 0) { - mp_raise_OSError(-ret); + for (int i=(int)(self->reg_bits / 8);i>-1;i--) { + memaddr |= (uint32_t)(write_buf[i] << ((~i + (int)(self->reg_bits / 8)) * 8)); } + uint8_t memaddr_buf[4]; + size_t memaddr_len = get_memaddr_buf(&memaddr_buf[0], memaddr, self->reg_bits); + + size_t num_bufs = 2; + + unsigned int flags = ( + MP_MACHINE_I2C_FLAG_WRITE1 | + MP_MACHINE_I2C_FLAG_READ | + MP_MACHINE_I2C_FLAG_STOP + ); + + mp_machine_i2c_buf_t bufs[3] = { + {.len = memaddr_len, .buf = memaddr_buf}, + {.len = 0, .buf = NULL}, + {.len = 0, .buf = NULL} + }; + + if ((size_t)(self->reg_bits / 8) < write_bufinfo.len) { + bufs[1].buf = write_buf + (self->reg_bits / 8); + bufs[1].len = write_bufinfo.len - (size_t)(self->reg_bits / 8); + num_bufs += 1; + flags |= MP_MACHINE_I2C_FLAG_WRITE2; + } + + bufs[num_bufs - 1].buf = read_bufinfo.buf; + bufs[num_bufs - 1].len = read_bufinfo.len; + + if (self->bus == NULL) mp_raise_OSError(1); + + int ret = i2c_bus_transfer((mp_obj_base_t *)self->bus, + self->device_id, num_bufs, bufs, flags); + + if (ret < 0) mp_raise_OSError(-ret); return mp_const_none; } @@ -430,11 +458,13 @@ static const mp_arg_t allowed_args[] = { { MP_QSTR_self, MP_ARG_OBJ | MP_ARG_REQUIRED }, { MP_QSTR_memaddr, MP_ARG_INT | MP_ARG_REQUIRED }, - { MP_QSTR_num_bytes, MP_ARG_INT | MP_ARG_KW_ONLY, { .u_int = -1 } }, + { MP_QSTR_num_bytes, MP_ARG_INT | MP_ARG_KW_ONLY, { .u_int = -1 } }, { MP_QSTR_buf, 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); + mp_arg_parse_all(n_args, pos_args, kw_args, + MP_ARRAY_SIZE(allowed_args), allowed_args, args); mp_machine_hw_i2c_device_obj_t *self = MP_OBJ_TO_PTR(args[ARG_self].u_obj); @@ -445,11 +475,10 @@ mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[ARG_buf].u_obj, &bufinfo, MP_BUFFER_WRITE); - ret = device_read(self, self->device_id, memaddr, self->reg_bits, (uint8_t *)bufinfo.buf, bufinfo.len); - if (ret < 0) { - mp_raise_OSError(-ret); - } + ret = device_read(self, self->device_id, memaddr, self->reg_bits, + (uint8_t *)bufinfo.buf, bufinfo.len); + if (ret < 0) mp_raise_OSError(-ret); return mp_const_none; } else { int num_bytes = (int)args[ARG_num_bytes].u_int; @@ -458,11 +487,10 @@ vstr_init_len(&vstr, num_bytes); // do the transfer - ret = device_read(self, self->device_id, memaddr, self->reg_bits, (uint8_t *)vstr.buf, vstr.len); - if (ret < 0) { - mp_raise_OSError(-ret); - } + ret = device_read(self, self->device_id, memaddr, self->reg_bits, + (uint8_t *)vstr.buf, vstr.len); + if (ret < 0) mp_raise_OSError(-ret); return mp_obj_new_bytes_from_vstr(&vstr); } } @@ -474,12 +502,13 @@ { enum { ARG_self, ARG_memaddr, ARG_buf }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_self, MP_ARG_OBJ | MP_ARG_REQUIRED }, - { MP_QSTR_memaddr, MP_ARG_INT | MP_ARG_REQUIRED }, - { MP_QSTR_buf, MP_ARG_OBJ | MP_ARG_REQUIRED }, + { MP_QSTR_self, MP_ARG_OBJ | MP_ARG_REQUIRED }, + { MP_QSTR_memaddr, MP_ARG_INT | MP_ARG_REQUIRED }, + { MP_QSTR_buf, MP_ARG_OBJ | MP_ARG_REQUIRED }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + mp_arg_parse_all(n_args, pos_args, kw_args, + MP_ARRAY_SIZE(allowed_args), allowed_args, args); mp_machine_hw_i2c_device_obj_t *self = MP_OBJ_TO_PTR(args[ARG_self].u_obj); @@ -488,11 +517,10 @@ mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[ARG_buf].u_obj, &bufinfo, MP_BUFFER_READ); - int ret = device_write(self, self->device_id, memaddr, self->reg_bits, (uint8_t *)bufinfo.buf, bufinfo.len); - if (ret < 0) { - mp_raise_OSError(-ret); - } + int ret = device_write(self, self->device_id, memaddr, self->reg_bits, + (uint8_t *)bufinfo.buf, bufinfo.len); + if (ret < 0) mp_raise_OSError(-ret); return mp_const_none; } @@ -503,12 +531,13 @@ { enum { ARG_self, ARG_num_bytes, ARG_buf }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_self, MP_ARG_OBJ | MP_ARG_REQUIRED }, - { MP_QSTR_num_bytes, MP_ARG_INT | MP_ARG_KW_ONLY, { .u_int = -1 } }, - { MP_QSTR_buf, MP_ARG_OBJ | MP_ARG_KW_ONLY, { .u_obj = mp_const_none }}, + { MP_QSTR_self, MP_ARG_OBJ | MP_ARG_REQUIRED }, + { MP_QSTR_num_bytes, MP_ARG_INT | MP_ARG_KW_ONLY, { .u_int = -1 } }, + { MP_QSTR_buf, 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); + mp_arg_parse_all(n_args, pos_args, kw_args, + MP_ARRAY_SIZE(allowed_args), allowed_args, args); mp_machine_hw_i2c_device_obj_t *self = MP_OBJ_TO_PTR(args[ARG_self].u_obj); @@ -518,10 +547,10 @@ mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[ARG_buf].u_obj, &bufinfo, MP_BUFFER_WRITE); - ret = device_readfrom(self, self->device_id, (uint8_t *)bufinfo.buf, bufinfo.len, true); - if (ret < 0) { - mp_raise_OSError(-ret); - } + ret = device_readfrom(self, self->device_id, + (uint8_t *)bufinfo.buf, bufinfo.len, true); + + if (ret < 0) mp_raise_OSError(-ret); return mp_const_none; } else { @@ -531,11 +560,10 @@ vstr_init_len(&vstr, num_bytes); // do the transfer - ret = device_readfrom(self, self->device_id, (uint8_t *)vstr.buf, vstr.len, true); - if (ret < 0) { - mp_raise_OSError(-ret); - } + ret = device_readfrom(self, self->device_id, + (uint8_t *)vstr.buf, vstr.len, true); + if (ret < 0) mp_raise_OSError(-ret); return mp_obj_new_bytes_from_vstr(&vstr); } } @@ -543,7 +571,8 @@ static MP_DEFINE_CONST_FUN_OBJ_KW(i2c_device_read_obj, 1, i2c_device_read); - static mp_obj_t i2c_device_write(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) + static mp_obj_t i2c_device_write(size_t n_args, const mp_obj_t *pos_args, + mp_map_t *kw_args) { enum { ARG_self, ARG_buf }; static const mp_arg_t allowed_args[] = { @@ -551,7 +580,8 @@ { MP_QSTR_buf, MP_ARG_OBJ | MP_ARG_REQUIRED } }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + mp_arg_parse_all(n_args, pos_args, kw_args, + MP_ARRAY_SIZE(allowed_args), allowed_args, args); mp_machine_hw_i2c_device_obj_t *self = MP_OBJ_TO_PTR(args[ARG_self].u_obj); @@ -559,7 +589,8 @@ mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[ARG_buf].u_obj, &bufinfo, MP_BUFFER_READ); - int ret = device_writeto(self, self->device_id, (uint8_t *)bufinfo.buf, bufinfo.len, true); + int ret = device_writeto(self, self->device_id, + (uint8_t *)bufinfo.buf, bufinfo.len, true); if (ret < 0) { mp_raise_OSError(-ret); } @@ -570,25 +601,21 @@ static MP_DEFINE_CONST_FUN_OBJ_KW(i2c_device_write_obj, 2, i2c_device_write); - mp_obj_t i2c_device_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + mp_obj_t i2c_device_make_new(const mp_obj_type_t *type, size_t n_args, + size_t n_kw, const mp_obj_t *all_args) + { // Parse args enum { ARG_bus, ARG_dev_id, ARG_reg_bits }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_bus, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_dev_id, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT }, - { MP_QSTR_reg_bits, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = 8 } } + { MP_QSTR_bus, MP_ARG_KW_ONLY | MP_ARG_OBJ | MP_ARG_REQUIRED }, + { MP_QSTR_dev_id, MP_ARG_KW_ONLY | MP_ARG_INT | MP_ARG_REQUIRED }, + { MP_QSTR_reg_bits, MP_ARG_KW_ONLY | MP_ARG_INT, { .u_int = 8 } } }; 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 - ); + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, + MP_ARRAY_SIZE(allowed_args), allowed_args, args); // create new object mp_machine_hw_i2c_device_obj_t *self = m_new_obj(mp_machine_hw_i2c_device_obj_t); @@ -599,7 +626,9 @@ self->reg_bits = (uint8_t)args[ARG_reg_bits].u_int; self->bus->device_count++; - self->bus->devices = m_realloc(self->bus->devices, self->bus->device_count * sizeof(mp_machine_hw_i2c_device_obj_t *)); + self->bus->devices = m_realloc(self->bus->devices, + self->bus->device_count * sizeof(mp_machine_hw_i2c_device_obj_t *)); + self->bus->devices[self->bus->device_count - 1] = self; return MP_OBJ_FROM_PTR(self); @@ -632,8 +661,8 @@ // ********************** machine.I2C ************************ static const mp_rom_map_elem_t i2c_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_I2C) }, - { MP_ROM_QSTR(MP_QSTR_Bus), (mp_obj_t)&mp_machine_hw_i2c_bus_type }, + { MP_ROM_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_I2C) }, + { MP_ROM_QSTR(MP_QSTR_Bus), (mp_obj_t)&mp_machine_hw_i2c_bus_type }, { MP_ROM_QSTR(MP_QSTR_Device), (mp_obj_t)&mp_machine_hw_i2c_device_type } }; diff --git a/micropy_updates/common/mp_i2c_common.h b/api_drivers/common_api_drivers/frozen/mp_i2c_common.h similarity index 96% rename from micropy_updates/common/mp_i2c_common.h rename to api_drivers/common_api_drivers/frozen/mp_i2c_common.h index e3a5b359..cbc8b2c7 100644 --- a/micropy_updates/common/mp_i2c_common.h +++ b/api_drivers/common_api_drivers/frozen/mp_i2c_common.h @@ -1,3 +1,5 @@ +// Copyright (c) 2024 - 2025 Kevin G. Schlosser + #include #include "py/obj.h" diff --git a/api_drivers/common_api_drivers/frozen/other/i2c.py b/api_drivers/common_api_drivers/frozen/other/i2c.py index 093c00ae..4944f461 100644 --- a/api_drivers/common_api_drivers/frozen/other/i2c.py +++ b/api_drivers/common_api_drivers/frozen/other/i2c.py @@ -1,144 +1,134 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import machine -# for backwards compatability -I2C = machine.I2C - -# -# -# class I2C(object): -# class Bus(object): -# -# def __init__(self, host, scl, sda, freq=400000, use_locks=False, pullup=False): -# -# if pullup: -# scl = machine.Pin(scl, pull=machine.Pin.PULL_UP) -# sda = machine.Pin(sda, pull=machine.Pin.PULL_UP) -# else: -# scl = machine.Pin(scl) -# sda = machine.Pin(sda) -# -# self._bus = machine.I2C( -# host, -# scl=scl, -# sda=sda, -# freq=freq -# ) -# -# if use_locks: -# import _thread -# self._lock = _thread.allocate_lock() -# else: -# class Lock(object): -# -# @staticmethod -# def acquire(): -# pass -# -# @staticmethod -# def release(): -# pass -# -# @staticmethod -# def is_locked(): -# return False -# -# self._lock = Lock -# -# def __enter__(self): -# self._lock.acquire() -# return self -# -# def __exit__(self, exc_type, exc_val, exc_tb): -# self._lock.release() -# -# def scan(self): -# self._lock.acquire() -# data = self._bus.scan() -# self._lock.release() -# return data -# -# def start(self): -# self._bus.start() -# -# def stop(self): -# self._bus.stop() -# -# def readinto(self, buf, nack=True): -# self._bus.readinto(buf, nack) -# -# def write(self, buf): -# self._bus.write(buf) -# -# def readfrom(self, addr, nbytes, stop=True): -# return self._bus.readfrom(addr, nbytes, stop) -# -# def readfrom_into(self, addr, buf, stop=True): -# self._bus.readfrom_into(addr, buf, stop) -# -# def writeto(self, addr, buf, stop=True): -# self._bus.writeto(addr, buf, stop) -# -# def writevto(self, addr, vector, stop=True): -# self._bus.writevto(addr, vector, stop) -# -# def readfrom_mem(self, addr, memaddr, nbytes, addrsize=8): -# return self._bus.readfrom_mem(addr, memaddr, -# nbytes, addrsize=addrsize) -# -# def readfrom_mem_into(self, addr, memaddr, buf, addrsize=8): -# self._bus.readfrom_mem_into(addr, memaddr, buf, addrsize=addrsize) -# -# def writeto_mem(self, addr, memaddr, buf, addrsize=8): -# self._bus.writeto_mem(addr, memaddr, buf, addrsize=addrsize) -# -# class Device(object): -# -# def __init__(self, bus, dev_id, reg_bits=8): -# self._bus = bus -# self.dev_id = dev_id -# self._reg_bits = reg_bits -# -# def write_readinto(self, write_buf, read_buf): -# memaddr = 0 -# -# for i in range(int(self._reg_bits / 8) - 1, -1, -1): -# memaddr |= write_buf[i] << ((~i + int(self._reg_bits / 8)) * 8) -# -# self.read_mem(memaddr, buf=read_buf) -# -# def read_mem(self, memaddr, num_bytes=None, buf=None): -# with self._bus: -# if num_bytes is not None: -# return self._bus.readfrom_mem( -# self.dev_id, -# memaddr, -# num_bytes, -# addrsize=self._reg_bits -# ) -# else: -# self._bus.readfrom_mem_into( -# self.dev_id, -# memaddr, -# buf, -# addrsize=self._reg_bits -# ) -# return -# -# def write_mem(self, memaddr, buf): -# with self._bus: -# self._bus.writeto_mem( -# self.dev_id, -# memaddr, -# buf, -# addrsize=self._reg_bits -# ) -# -# def read(self, num_bytes=None, buf=None): -# with self._bus: -# if num_bytes is not None: -# return self._bus.readfrom(self.dev_id, num_bytes) -# else: -# self._bus.readfrom_into(self.dev_id, buf) -# -# def write(self, buf): -# self._bus.writeto(self.dev_id, buf) + +class I2C(object): + class Bus(object): + + def __init__(self, host, scl, sda, freq=400000, use_locks=False): + self._bus = machine.I2C( + host, + scl=machine.Pin(scl), + sda=machine.Pin(sda), + freq=freq + ) + + if use_locks: + import _thread + self._lock = _thread.allocate_lock() + else: + class Lock(object): + + @staticmethod + def acquire(): + pass + + @staticmethod + def release(): + pass + + @staticmethod + def is_locked(): + return False + + self._lock = Lock + + def __enter__(self): + self._lock.acquire() + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + self._lock.release() + + def scan(self): + self._lock.acquire() + data = self._bus.scan() + self._lock.release() + return data + + def start(self): + self._bus.start() + + def stop(self): + self._bus.stop() + + def readinto(self, buf, nack=True): + self._bus.readinto(buf, nack) + + def write(self, buf): + self._bus.write(buf) + + def readfrom(self, addr, nbytes, stop=True): + return self._bus.readfrom(addr, nbytes, stop) + + def readfrom_into(self, addr, buf, stop=True): + self._bus.readfrom_into(addr, buf, stop) + + def writeto(self, addr, buf, stop=True): + self._bus.writeto(addr, buf, stop) + + def writevto(self, addr, vector, stop=True): + self._bus.writevto(addr, vector, stop) + + def readfrom_mem(self, addr, memaddr, nbytes, addrsize=8): + return self._bus.readfrom_mem(addr, memaddr, + nbytes, addrsize=addrsize) + + def readfrom_mem_into(self, addr, memaddr, buf, addrsize=8): + self._bus.readfrom_mem_into(addr, memaddr, buf, addrsize=addrsize) + + def writeto_mem(self, addr, memaddr, buf, addrsize=8): + self._bus.writeto_mem(addr, memaddr, buf, addrsize=addrsize) + + class Device(object): + + def __init__(self, bus, dev_id, reg_bits=8): + self._bus = bus + self.dev_id = dev_id + self._reg_bits = reg_bits + + def write_readinto(self, write_buf, read_buf): + memaddr = 0 + + for i in range(int(self._reg_bits / 8) - 1, -1, -1): + memaddr |= write_buf[i] << ((~i + int(self._reg_bits / 8)) * 8) + + self.read_mem(memaddr, buf=read_buf) + + def read_mem(self, memaddr, num_bytes=None, buf=None): + with self._bus: + if num_bytes is not None: + return self._bus.readfrom_mem( + self.dev_id, + memaddr, + num_bytes, + addrsize=self._reg_bits + ) + else: + self._bus.readfrom_mem_into( + self.dev_id, + memaddr, + buf, + addrsize=self._reg_bits + ) + return + + def write_mem(self, memaddr, buf): + with self._bus: + self._bus.writeto_mem( + self.dev_id, + memaddr, + buf, + addrsize=self._reg_bits + ) + + def read(self, num_bytes=None, buf=None): + with self._bus: + if num_bytes is not None: + return self._bus.readfrom(self.dev_id, num_bytes) + else: + self._bus.readfrom_into(self.dev_id, buf) + + def write(self, buf): + self._bus.writeto(self.dev_id, buf) diff --git a/api_drivers/common_api_drivers/frozen/other/spi3wire.py b/api_drivers/common_api_drivers/frozen/other/spi3wire.py index 3e105af9..f9980327 100644 --- a/api_drivers/common_api_drivers/frozen/other/spi3wire.py +++ b/api_drivers/common_api_drivers/frozen/other/spi3wire.py @@ -1,3 +1,4 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser # ******* NOTICE ******** # This module is no longer used. diff --git a/api_drivers/common_api_drivers/frozen/other/task_handler.py b/api_drivers/common_api_drivers/frozen/other/task_handler.py index c7615f70..67c85fa3 100644 --- a/api_drivers/common_api_drivers/frozen/other/task_handler.py +++ b/api_drivers/common_api_drivers/frozen/other/task_handler.py @@ -1,3 +1,7 @@ +# MIT license; Copyright (c) 2021 Amir Gonnen +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + + import lvgl as lv # NOQA import micropython # NOQA import sys diff --git a/api_drivers/common_api_drivers/indev/axs15231.py b/api_drivers/common_api_drivers/indev/axs15231.py new file mode 100644 index 00000000..99bbf228 --- /dev/null +++ b/api_drivers/common_api_drivers/indev/axs15231.py @@ -0,0 +1,80 @@ +# Based on the work by straga (https://github.com/straga) +# https://github.com/straga/micropython_lcd/blob/master/device/JC3248W535/driver/axs15231b/axs15231_touch.py +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + +from micropython import const # NOQA +import pointer_framework + + +# Constants +_AXS_MAX_TOUCH_NUMBER = const(1) +_AXS_TOUCH_POINT_NUM = const(1) +I2C_ADDR = 0x3B +BITS = 8 + + +class TouchRecord: + def __init__(self): + self.gesture = 0 + self.num = 0 + self.x = 0 + self.y = 0 + self.event = 0 + + +class AXS15231(pointer_framework.PointerDriver): + + def __init__( + self, + device, + touch_cal=None, + startup_rotation=lv.DISPLAY_ROTATION._0, # NOQA + debug=False + ): + self._device = device + + super().__init__(touch_cal, startup_rotation, debug) + + self._tx_buf = bytearray( + [0xB5, 0xAB, 0xA5, 0x5A, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00] + ) + self._tx_mv = memoryview(self._tx_buf) + + self._rx_buf = bytearray(8) + self._rx_mv = memoryview(self._rx_buf) + + def _read_data(self): + self._device.write(self._tx_mv) + self._device.read(buf=self._rx_mv) + + touch_points = [] + data = self._rx_buf + + num_points = data[_AXS_TOUCH_POINT_NUM] + + if num_points and num_points <= _AXS_MAX_TOUCH_NUMBER: + for i in range(num_points): + offset = i * 6 + record = TouchRecord() + record.gesture = data[offset] + record.num = data[offset + 1] + record.x = ((data[offset + 2] & 0x0F) << 8) | data[offset + 3] + record.y = ((data[offset + 4] & 0x0F) << 8) | data[offset + 5] + record.event = (data[offset + 2] >> 6) & 0x03 + touch_points.append(record) + + return touch_points + + def _get_coords(self): + touch_data = self._read_data() + + if touch_data: + x = touch_data[0].x + y = touch_data[0].y + + if touch_data[0].event == 1: + return self.RELEASED, x, y + + return self.PRESSED, x, y + else: + return None diff --git a/api_drivers/common_api_drivers/indev/cst328.py b/api_drivers/common_api_drivers/indev/cst328.py index d3b20682..6f7dc029 100644 --- a/api_drivers/common_api_drivers/indev/cst328.py +++ b/api_drivers/common_api_drivers/indev/cst328.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + from micropython import const # NOQA import pointer_framework import time @@ -5,7 +7,7 @@ I2C_ADDR = 0x1A -BITS = 8 +BITS = 16 # 4 byte read # PROJECT_ID = byte2 << 8 | byte3 @@ -75,10 +77,10 @@ def __init__( device, reset_pin=None, touch_cal=None, - startup_rotation=pointer_framework.lv.DISPLAY_ROTATION._0, + startup_rotation=pointer_framework.lv.DISPLAY_ROTATION._0, # NOQA debug=False ): - self._tx_buf = bytearray(2) + self._tx_buf = bytearray(3) self._tx_mv = memoryview(self._tx_buf) self._rx_buf = bytearray(6) self._rx_mv = memoryview(self._rx_buf) diff --git a/api_drivers/common_api_drivers/indev/cst340.py.wip b/api_drivers/common_api_drivers/indev/cst340.py.wip new file mode 100644 index 00000000..4c3c53a0 --- /dev/null +++ b/api_drivers/common_api_drivers/indev/cst340.py.wip @@ -0,0 +1,28 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + +0x8140 Product ID +0x8141 Product ID +0x8142 Product ID +0x8143 Product ID + + +0x8144 Firmware version +0x8145 Firmware version + +0x8146 x coordinate resolution +0x8147 x coordinate resolution + +0x8148 y coordinate resolution +0x8149 y coordinate resolution + +0x814A Vendor_id + +0x814E buffer status | large detect | Reserved | HaveKey | number of touch points + +0x8158 point 1 x coordinate +0x8159 point 1 x coordinate + +0x815A point 1 y coordinate +0x815B point 1 y coordinate + + diff --git a/api_drivers/common_api_drivers/indev/cst816s.py b/api_drivers/common_api_drivers/indev/cst816s.py index 0489e14e..38ac366b 100644 --- a/api_drivers/common_api_drivers/indev/cst816s.py +++ b/api_drivers/common_api_drivers/indev/cst816s.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + from micropython import const # NOQA import pointer_framework import time @@ -169,7 +171,7 @@ def __init__( device, reset_pin=None, touch_cal=None, - startup_rotation=pointer_framework.lv.DISPLAY_ROTATION._0, + startup_rotation=pointer_framework.lv.DISPLAY_ROTATION._0, # NOQA debug=False ): self._tx_buf = bytearray(2) @@ -259,9 +261,9 @@ def wake_up(self): self._write_reg(_DisAutoSleep, 0x00) time.sleep_ms(10) # NOQA - self._write_reg(_DisAutoSleep, 0x01) + self._write_reg(_DisAutoSleep, 0xFE) time.sleep_ms(50) # NOQA - self._write_reg(_DisAutoSleep, 0x01) + self._write_reg(_DisAutoSleep, 0xFE) time.sleep_ms(50) # NOQA self._write_reg(_DisAutoSleep, int(not auto_sleep)) @@ -275,7 +277,7 @@ def auto_sleep(self, en): if en: self._write_reg(_DisAutoSleep, 0x00) else: - self._write_reg(_DisAutoSleep, 0x01) + self._write_reg(_DisAutoSleep, 0xFE) def hw_reset(self): if self._reset_pin is None: diff --git a/api_drivers/common_api_drivers/indev/evdev/button.py b/api_drivers/common_api_drivers/indev/evdev/button.py index e403f955..c0854908 100644 --- a/api_drivers/common_api_drivers/indev/evdev/button.py +++ b/api_drivers/common_api_drivers/indev/evdev/button.py @@ -1,3 +1,4 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser import struct import select diff --git a/api_drivers/common_api_drivers/indev/evdev/devices.py b/api_drivers/common_api_drivers/indev/evdev/devices.py index 0edd9638..ab7461ea 100644 --- a/api_drivers/common_api_drivers/indev/evdev/devices.py +++ b/api_drivers/common_api_drivers/indev/evdev/devices.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + from micropython import const import struct import os diff --git a/api_drivers/common_api_drivers/indev/evdev/fnctl.py b/api_drivers/common_api_drivers/indev/evdev/fnctl.py index 535e16b2..d2441b81 100644 --- a/api_drivers/common_api_drivers/indev/evdev/fnctl.py +++ b/api_drivers/common_api_drivers/indev/evdev/fnctl.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import ffi # NOQA import os import ffilib # NOQA diff --git a/api_drivers/common_api_drivers/indev/evdev/joystick.py b/api_drivers/common_api_drivers/indev/evdev/joystick.py index e49a8e11..523e040b 100644 --- a/api_drivers/common_api_drivers/indev/evdev/joystick.py +++ b/api_drivers/common_api_drivers/indev/evdev/joystick.py @@ -1,4 +1,4 @@ - +# Copyright (c) 2024 - 2025 Kevin G. Schlosser import struct import select diff --git a/api_drivers/common_api_drivers/indev/evdev/keyboard.py b/api_drivers/common_api_drivers/indev/evdev/keyboard.py index 10389fea..5010e12b 100644 --- a/api_drivers/common_api_drivers/indev/evdev/keyboard.py +++ b/api_drivers/common_api_drivers/indev/evdev/keyboard.py @@ -1,4 +1,4 @@ - +# Copyright (c) 2024 - 2025 Kevin G. Schlosser import struct import select diff --git a/api_drivers/common_api_drivers/indev/evdev/mouse.py b/api_drivers/common_api_drivers/indev/evdev/mouse.py index ee6c42dd..b7e4a572 100644 --- a/api_drivers/common_api_drivers/indev/evdev/mouse.py +++ b/api_drivers/common_api_drivers/indev/evdev/mouse.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + ''' # LVGL indev driver for evdev mouse device # (for the unix micropython port) diff --git a/api_drivers/common_api_drivers/indev/evdev/mousewheel.py b/api_drivers/common_api_drivers/indev/evdev/mousewheel.py index b461fe58..61a1aaa5 100644 --- a/api_drivers/common_api_drivers/indev/evdev/mousewheel.py +++ b/api_drivers/common_api_drivers/indev/evdev/mousewheel.py @@ -1,3 +1,4 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser import struct import select diff --git a/api_drivers/common_api_drivers/indev/focaltech_touch.py b/api_drivers/common_api_drivers/indev/focaltech_touch.py index 4b7ed5a9..5e0f6d1a 100644 --- a/api_drivers/common_api_drivers/indev/focaltech_touch.py +++ b/api_drivers/common_api_drivers/indev/focaltech_touch.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + from micropython import const # NOQA import pointer_framework import machine # NOQA @@ -57,7 +59,7 @@ def __init__( self._read_reg(_PANEL_ID_REG) print("Touch Device ID: 0x%02x" % self._rx_buf[0]) - ven_id = self._rx_buf[0] + ven_id = self._rx_buf[0] # NOQA self._read_reg(_CHIPID_REG) print("Touch Chip ID: 0x%02x" % self._rx_buf[0]) diff --git a/api_drivers/common_api_drivers/indev/ft5x06.py b/api_drivers/common_api_drivers/indev/ft5x06.py index 63c336df..f205cd7b 100644 --- a/api_drivers/common_api_drivers/indev/ft5x06.py +++ b/api_drivers/common_api_drivers/indev/ft5x06.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + # FT5206/FT5306/FT5406 from micropython import const # NOQA diff --git a/api_drivers/common_api_drivers/indev/ft5x16.py b/api_drivers/common_api_drivers/indev/ft5x16.py index aaf770b0..17025dfc 100644 --- a/api_drivers/common_api_drivers/indev/ft5x16.py +++ b/api_drivers/common_api_drivers/indev/ft5x16.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + # FT5216/FT5316 from micropython import const # NOQA diff --git a/api_drivers/common_api_drivers/indev/ft5x26.py b/api_drivers/common_api_drivers/indev/ft5x26.py index 122b902d..4ba036ea 100644 --- a/api_drivers/common_api_drivers/indev/ft5x26.py +++ b/api_drivers/common_api_drivers/indev/ft5x26.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + # FT5426DQ8/FT5526EEZ from micropython import const # NOQA diff --git a/api_drivers/common_api_drivers/indev/ft5x36.py b/api_drivers/common_api_drivers/indev/ft5x36.py index f3ba99a5..90adc06c 100644 --- a/api_drivers/common_api_drivers/indev/ft5x36.py +++ b/api_drivers/common_api_drivers/indev/ft5x36.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + from micropython import const # NOQA import focaltech_touch import pointer_framework diff --git a/api_drivers/common_api_drivers/indev/ft5x46.py b/api_drivers/common_api_drivers/indev/ft5x46.py index 6724b6d1..bb34b783 100644 --- a/api_drivers/common_api_drivers/indev/ft5x46.py +++ b/api_drivers/common_api_drivers/indev/ft5x46.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + # FT5346/FT5446/FT5446S from micropython import const # NOQA diff --git a/api_drivers/common_api_drivers/indev/ft6x06.py b/api_drivers/common_api_drivers/indev/ft6x06.py index 7c9b010c..837b7440 100644 --- a/api_drivers/common_api_drivers/indev/ft6x06.py +++ b/api_drivers/common_api_drivers/indev/ft6x06.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + # FT6206/FT6306 from micropython import const # NOQA diff --git a/api_drivers/common_api_drivers/indev/ft6x36.py b/api_drivers/common_api_drivers/indev/ft6x36.py index a4d23d2e..b85c8ae2 100644 --- a/api_drivers/common_api_drivers/indev/ft6x36.py +++ b/api_drivers/common_api_drivers/indev/ft6x36.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + # FT6236/FT6336/FT6436/FT6436L from micropython import const # NOQA diff --git a/api_drivers/common_api_drivers/indev/gsl1680.py b/api_drivers/common_api_drivers/indev/gsl1680.py new file mode 100644 index 00000000..53355f83 --- /dev/null +++ b/api_drivers/common_api_drivers/indev/gsl1680.py @@ -0,0 +1,87 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + +from micropython import const # NOQA +import pointer_framework +import machine # NOQA +import time + +_DATA_REG = const(0x80) +_STATUS_REG = const(0xE0) +_PAGE_REG = const(0xF0) + +I2C_ADDR = 0x40 +BITS = 8 + + +class GSL1680(pointer_framework.PointerDriver): + + def _read_reg(self, reg, num_bytes=None, buf=None): + self._tx_buf[0] = reg >> 8 + self._tx_buf[1] = reg & 0xFF + if num_bytes is not None: + self._device.write_readinto(self._tx_mv[:2], self._rx_mv[:num_bytes]) + else: + self._device.write_readinto(self._tx_mv[:2], buf) + + def _write_reg(self, reg, value=None, buf=None): + if value is not None: + self._tx_buf[0] = value + self._device.write_mem(reg, self._tx_mv[:1]) + elif buf is not None: + self._device.write_mem(reg, buf) + + def __init__( + self, + device, + wake_pin, + touch_cal=None, + startup_rotation=pointer_framework.lv.DISPLAY_ROTATION._0, # NOQA + debug=False + ): + self._tx_buf = bytearray(4) + self._tx_mv = memoryview(self._tx_buf) + self._rx_buf = bytearray(24) + self._rx_mv = memoryview(self._rx_buf) + + self._device = device + + if isinstance(wake_pin, int): + wake_pin = machine.Pin(wake_pin, machine.Pin.OUT) + + self._wake_pin = wake_pin + + self._wake_up() + time.sleep_ms(50) # NOQA + self._write_reg(_STATUS_REG, 0x88) + time.sleep_ms(10) # NOQA + self._write_reg(0xE4, 0x04) + time.sleep_ms(5) # NOQA + self._tx_buf[:4] = bytearray([0x00, 0x00, 0x00, 0x00]) + self._write_reg(0xBC, buf=self._tx_mv[:4]) + time.sleep_ms(5) # NOQA + self._write_reg(0xE0, 0x00) + + super().__init__( + touch_cal=touch_cal, startup_rotation=startup_rotation, debug=debug + ) + + def _wake_up(self): + # toggle wake pin + self._wake_pin.value(1) + time.sleep_ms(1) # NOQA + self._wake_pin.value(0) + time.sleep_ms(1) # NOQA + self._wake_pin.value(1) + time.sleep_ms(1) # NOQA + + def _get_coords(self): + self._wake_up() + self._read_reg(_DATA_REG, buf=self._rx_mv) + data = self._rx_buf + + touch_count = data[0] + if touch_count > 0: + x = ((data[5] << 8) & 0xF) | data[4] + y = ((data[7] << 8) & 0xF) | data[6] + + return self.RELEASED, x, y diff --git a/api_drivers/common_api_drivers/indev/gt911.py b/api_drivers/common_api_drivers/indev/gt911.py index deafd1cc..612c26cc 100644 --- a/api_drivers/common_api_drivers/indev/gt911.py +++ b/api_drivers/common_api_drivers/indev/gt911.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + # this driver uses a special i2c bus implimentation I have written. # This implimentation takes into consideration the ESP32 and it having # threading available. It also has some convience methods built into it diff --git a/api_drivers/common_api_drivers/indev/gt911_extension.py b/api_drivers/common_api_drivers/indev/gt911_extension.py index 10889f7b..3d504c4d 100644 --- a/api_drivers/common_api_drivers/indev/gt911_extension.py +++ b/api_drivers/common_api_drivers/indev/gt911_extension.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + from micropython import const # NOQA diff --git a/api_drivers/common_api_drivers/indev/gt911_settings_gui.py b/api_drivers/common_api_drivers/indev/gt911_settings_gui.py index 345a17ba..57f0eff7 100644 --- a/api_drivers/common_api_drivers/indev/gt911_settings_gui.py +++ b/api_drivers/common_api_drivers/indev/gt911_settings_gui.py @@ -1,3 +1,4 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser import lvgl as lv # NOQA diff --git a/api_drivers/common_api_drivers/indev/sdl_keyboard.py b/api_drivers/common_api_drivers/indev/sdl_keyboard.py index aaf93a8a..ab6c67aa 100644 --- a/api_drivers/common_api_drivers/indev/sdl_keyboard.py +++ b/api_drivers/common_api_drivers/indev/sdl_keyboard.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + from micropython import const # NOQA import lvgl as lv import micropython # NQQA # NOQA @@ -163,14 +165,14 @@ def __init__(self, *args, **kwargs): # NOQA self.__current_state = self.RELEASED self.group = lv.group_create() - self.group.set_default() + self.group.set_default() # NOQA self.set_group(self.group) - self.set_mode(lv.INDEV_MODE.EVENT) + self.set_mode(lv.INDEV_MODE.EVENT) # NOQA self._py_disp_drv._data_bus.register_keypad_callback(self._keypad_cb) # NOQA def set_mode(self, mode): - self._indev_drv.set_mode(mode) + self._indev_drv.set_mode(mode) # NOQA def _keypad_cb(self, *args): _, state, key, mod = args @@ -199,21 +201,21 @@ def _keypad_cb(self, *args): else: mapping = { KEYPAD_0: KEY_INSERT, - KEYPAD_1: lv.KEY.END, - KEYPAD_2: lv.KEY.DOWN, - KEYPAD_3: lv.KEY.PREV, - KEYPAD_4: lv.KEY.LEFT, + KEYPAD_1: lv.KEY.END, # NOQA + KEYPAD_2: lv.KEY.DOWN, # NOQA + KEYPAD_3: lv.KEY.PREV, # NOQA + KEYPAD_4: lv.KEY.LEFT, # NOQA KEYPAD_5: KEY_5, - KEYPAD_6: lv.KEY.RIGHT, - KEYPAD_7: lv.KEY.HOME, - KEYPAD_8: lv.KEY.UP, - KEYPAD_9: lv.KEY.NEXT, - KEYPAD_PERIOD: lv.KEY.DEL, + KEYPAD_6: lv.KEY.RIGHT, # NOQA + KEYPAD_7: lv.KEY.HOME, # NOQA + KEYPAD_8: lv.KEY.UP, # NOQA + KEYPAD_9: lv.KEY.NEXT, # NOQA + KEYPAD_PERIOD: lv.KEY.DEL, # NOQA KEYPAD_DIVIDE: KEY_SLASH, KEYPAD_MULTIPLY: KEY_ASTERISK, KEYPAD_MINUS: KEY_MINUS, KEYPAD_PLUS: KEY_PLUS, - KEYPAD_ENTER: lv.KEY.ENTER, + KEYPAD_ENTER: lv.KEY.ENTER, # NOQA KEYPAD_EQUALS: KEY_EQUALS } @@ -222,19 +224,19 @@ def _keypad_cb(self, *args): return else: mapping = { - KEY_BACKSPACE: lv.KEY.BACKSPACE, - KEY_TAB: lv.KEY.NEXT, - KEY_RETURN: lv.KEY.ENTER, - KEY_ESCAPE: lv.KEY.ESC, - KEY_DELETE: lv.KEY.DEL, - KEY_UP: lv.KEY.UP, - KEY_DOWN: lv.KEY.DOWN, - KEY_RIGHT: lv.KEY.RIGHT, - KEY_LEFT: lv.KEY.LEFT, - KEY_HOME: lv.KEY.HOME, - KEY_END: lv.KEY.END, - KEY_PAGEDOWN: lv.KEY.PREV, - KEY_PAGEUP: lv.KEY.NEXT + KEY_BACKSPACE: lv.KEY.BACKSPACE, # NOQA + KEY_TAB: lv.KEY.NEXT, # NOQA + KEY_RETURN: lv.KEY.ENTER, # NOQA + KEY_ESCAPE: lv.KEY.ESC, # NOQA + KEY_DELETE: lv.KEY.DEL, # NOQA + KEY_UP: lv.KEY.UP, # NOQA + KEY_DOWN: lv.KEY.DOWN, # NOQA + KEY_RIGHT: lv.KEY.RIGHT, # NOQA + KEY_LEFT: lv.KEY.LEFT, # NOQA + KEY_HOME: lv.KEY.HOME, # NOQA + KEY_END: lv.KEY.END, # NOQA + KEY_PAGEDOWN: lv.KEY.PREV, # NOQA + KEY_PAGEUP: lv.KEY.NEXT # NOQA } self.__last_key = mapping.get(key, key) diff --git a/api_drivers/common_api_drivers/indev/sdl_pointer.py b/api_drivers/common_api_drivers/indev/sdl_pointer.py index f491ac15..1abccdab 100644 --- a/api_drivers/common_api_drivers/indev/sdl_pointer.py +++ b/api_drivers/common_api_drivers/indev/sdl_pointer.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + from micropython import const # NOQA import pointer_framework import lvgl as lv # NOQA @@ -7,10 +9,10 @@ class SDLPointer(pointer_framework.PointerDriver): def __init__( self, - *args, + *_, startup_rotation=pointer_framework.lv.DISPLAY_ROTATION._0, # NOQA debug=False, - **kwargs + **__ ): # NOQA super().__init__( touch_cal=None, startup_rotation=startup_rotation, debug=debug @@ -23,12 +25,12 @@ def __init__( self.__wheel_y = 0 self.__scroll_obj = None self.__button_state = self.RELEASED - self.set_mode(lv.INDEV_MODE.EVENT) + self.set_mode(lv.INDEV_MODE.EVENT) # NOQA self._py_disp_drv._data_bus.register_mouse_callback(self._mouse_cb) # NOQA def set_mode(self, mode): - self._indev_drv.set_mode(mode) + self._indev_drv.set_mode(mode) # NOQA def _get_object(self): if not self.__wheel_x and not self.__wheel_y: @@ -45,14 +47,14 @@ def _get_object(self): obj = lv.indev_search_obj(self._disp_drv.get_layer_bottom(), point) if obj: - dir_flags = obj.get_scroll_dir() + dir_flags = obj.get_scroll_dir() # NOQA - if self.__wheel_x and dir_flags | lv.DIR.HOR == dir_flags: + if self.__wheel_x and dir_flags | lv.DIR.HOR == dir_flags: # NOQA pass else: self.__wheel_x = 0 - if self.__wheel_y and dir_flags | lv.DIR.VER == dir_flags: + if self.__wheel_y and dir_flags | lv.DIR.VER == dir_flags: # NOQA pass else: self.__wheel_y = 0 diff --git a/api_drivers/common_api_drivers/indev/stmpe610.py b/api_drivers/common_api_drivers/indev/stmpe610.py index 592180bf..2098b414 100644 --- a/api_drivers/common_api_drivers/indev/stmpe610.py +++ b/api_drivers/common_api_drivers/indev/stmpe610.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + from micropython import const # NOQA import i2c diff --git a/api_drivers/common_api_drivers/indev/xpt2046.py b/api_drivers/common_api_drivers/indev/xpt2046.py index 7e85c6c5..782f5229 100644 --- a/api_drivers/common_api_drivers/indev/xpt2046.py +++ b/api_drivers/common_api_drivers/indev/xpt2046.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + from micropython import const # NOQA import micropython # NOQA import machine # NOQA diff --git a/api_drivers/common_api_drivers/io_expander/axp192.py.wip b/api_drivers/common_api_drivers/io_expander/axp192.py.wip new file mode 100644 index 00000000..c83326b2 --- /dev/null +++ b/api_drivers/common_api_drivers/io_expander/axp192.py.wip @@ -0,0 +1,3348 @@ +from micropython import const # NOQA +import io_expander_framework +import lcd_utils + + +# mcu: ESP32 +# flash: 16mb +# psram: 8mb +# touch ic: CHSC6540 +# sdcard reader +# speaker: NS4168 (i2s) +# rtc: BM8563 +# power management: AXP192 +# display ic: ILI9342C (320x240) + + +# uart +# rx: gpio3 +# tx: gpio1 + +# flash +# CS: gpio11 +# MISO: gpio7 +# MOSI: gpio8 +# SCK: gpio6 +# HOLD: gpio9 +# WP: gpio10 + +# PSRAM +# MOSI: gpio8 +# MISO: gpio7 +# DATA2: gpio10 +# DATA3: gpio9 +# SCK: gpio17 +# CS: gpio16 + +# RTC (I2C) +# SCL: gpio22 +# SDA: gpio21 +# INT: PWRKEY +# PWR: PMU LDO1 + +# RS485 +# RX: gpio27 +# TX: gpio19 + +# RESET?? +# gpio25? + + +# SDCARD (SPI) +# MISO: gpio38 +# MOSI:gpio23 +# SCK: gpio18 +# CS: gpio4 + +# speaker +# LRCK: gpio0 +# BCLK: gpio12 +# DATA: gpio2 +# ENABLE: PMU IO2 + +# Mic +# DATA: gpio34 +# CLK: gpio0 + +# PMU (I2C) +# SDA: gpio21 +# SCK: gpio22 +# GPIO1: TP Reset +# GPIO2: Speaker Enable +# GPIO4: LCD Reset + + +# 2 channel DAC +# G25 +# G25/DAC: gpio25 + +# 2 channel DAC +# G26 +# G26/DAC: gpio26 + + +# 10 channel ADC +# G0/2/4/12-15/25-27 +# G0: gpio0 +# G1/TXD0: gpio1 +# G2: gpio2 +# G3/RXD0: gpio3 + + +# G13/RXD2: gpio13 +# G14/TXD2: gpio14 + +# G18/SCK: gpio18 +# G23/MOSI: gpio23 + + +# G19: gpio19 +# G27: gpio27 +# G21/SDA: gpio21 +# G22/SCL: gpio22 + +# 8 channel ADC +# G32-39 +# G32/SDA: gpio32 +# G33/SCL: gpio33 +# G34/ADC: gpio34 +# G35/ADC: gpio35 +# G36/ADC: gpio36 + +# G38/MISO: gpio38 + +# EXT: + +# SYS: + +# LCD +# MOSI: gpio23 +# SCK: gpio18 +# CS: gpio5 +# DC: gpio15 +# BL: PMU LDO3 +# PWR: PMU LDO2 +# RST: PMU IO4 + +# Touch +# SCK: gpio39 +# SCL: gpio22 +# SDA: gpio21 + + +# I2C Bus There are 2 I2C busses +# bus 1 +# SCL: gpio22 +# SDC: gpio21 +# shared with Touch, BUS.SYS, PMU, RTC + +# bus2 +# SDA: gpio32 +# SCL: gpio33 +# shared with BUS-EXT + +# define CONFIG_I2S_BCK_PIN 12 +# define CONFIG_I2S_LRCK_PIN 0 +# define CONFIG_I2S_DATA_PIN 2 +# define CONFIG_I2S_DATA_IN_PIN 34 + +# define Speak_I2S_NUMBER I2S_NUM_0 +# define MODE_MIC 0 +# define MODE_SPK 1 +# define I2S_DATA_LEN 60 +# define TFT_LED_PIN 32 +# define TFT_DC_PIN 27 +# define TFT_CS_PIN 14 +# define TFT_MOSI_PIN 23 +# define TFT_CLK_PIN 18 +# define TFT_RST_PIN 33 +# define TFT_MISO_PIN 19 +# define TFCARD_CS_PIN 4 + + +# define AXP_ADDR 0X34 + +# freq = 400000 +# +# +# class AXP192(object): +# +# def __init__(self, ): +# self._tx_buf = bytearray(3) +# self._tx_mv = memoryview(self._tx_buf) +# +# self._rx_buf = bytearray(3) +# self._rx_mv = memoryview(self._rx_buf) +# +# self._write_1_byte(0x30, (self._read_8_bits(0x30) & 0x04) | 0X02) +# +# # //AXP192 GPIO1:OD OUTPUT ( GPIO1 = Touch RST ) +# self._write_1_byte(0x92, self._read_8_bits(0x92) & 0xf8) +# +# # //AXP192 GPIO2:OD OUTPUT +# self._write_1_byte(0x93, self._read_8_bits(0x93) & 0xf8) +# +# # //AXP192 RTC CHG +# self._write_1_byte(0x35, (self._read_8_bits(0x35) & 0x1c) | 0xa2) +# +# self.set_esp_voltage(3350) +# +# self.set_lcd_voltage(2800) +# +# # //Periph power voltage preset (LCD_logic, SD card) +# self.set_ldo_voltage(2, 3300) +# +# # // LCD backlight ( for Tough ) +# self.set_ldo_voltage(3, 3000) +# +# self.set_lcd_enable(2, True) +# self.set_ldo_enable(3, True) +# +# self.set_charge_current(100) +# +# # //AXP192 GPIO4 +# self._write_1_byte(0X95, (self._read_8_bits(0x95) & 0x72) | 0X84) +# +# self._write_1_byte(0X36, 0X4C) +# +# self._write_1_byte(0x82,0xff) +# +# self.set_lcd_reset(0) +# delay(100) +# self.set_lcd_reset(1) +# delay(100) +# +# +# # // bus power mode_output +# # // axp: check v-bus status +# if self._read_8_bits(0x00) & 0x08: +# self._write_1_byte(0x30, self._read_8_bits(0x30) | 0x80) +# # // if v-bus can use, disable M-Bus 5V output to input +# self.set_bus_power_mode(_kMBusModeInput) +# else: +# # // if not, enable M-Bus 5V output +# self.set_bus_power_mode(_kMBusModeOutput) +# +# +# def _read_8_bits(self, reg): +# self._tx_buf[0] = reg +# +# self._device.write_readinto( +# self._tx_mv[:1], +# self._rx_mv[:1] +# ) +# return self._rx_buf[0] +# +# def _read_12_bits(self, reg): +# self._tx_buf[0] = reg +# +# self._device.write_readinto( +# self._tx_mv[:2], +# self._rx_mv[:2] +# ) +# +# return (self._rx_buf[0] << 4) + self._rx_buf[1] +# +# def _read_13_bits(self, reg): +# self._tx_buf[0] = reg +# +# self._device.write_readinto( +# self._tx_mv[:2], +# self._rx_mv[:2] +# ) +# +# return (self._rx_buf[0] << 5) + self._rx_buf[1] +# +# def _read_16_bits(self, reg): +# self._tx_buf[0] = reg +# +# self._device.write_readinto( +# self._tx_mv[:2], +# self._rx_mv[:2] +# ) +# +# return (self._rx_buf[0] << 8) | self._rx_buf[1] +# +# def _read_24_bits(self, reg): +# self._tx_buf[0] = reg +# +# self._device.write_readinto( +# self._tx_mv[:3], +# self._rx_mv[:3] +# ) +# +# return (self._rx_buf[0] << 16) | (self._rx_buf[1] << 8) | self._rx_buf[2] +# +# +# def _read_32_bits(self, reg): +# self._tx_buf[0] = reg +# +# self._device.write_readinto( +# self._tx_mv[:4], +# self._rx_mv[:4] +# ) +# +# return (self._rx_buf[0] << 24) | (self._rx_buf[1] << 16) | (self._rx_buf[2] << 8) | self._rx_buf[3] +# +# def _write_1_byte(self, reg, value): +# self._tx_buf[0] = reg +# self._tx_buf[1] = value +# self._device.write(self._tx_mv[:2]) +# +# def set_screen_brightness(self, brightness): +# brightness = int((brightness / 100.0) * 12) +# brightness = max(0, min(12, brightness)) +# buf = self._read_8_bits(0x28) +# self._write_1_byte(0x28, ((buf & 0x0f) | (brightness << 4))) +# +# +# def get_bat_state(self): +# return bool(self._read_8_bits(0x01) | 0x20) +# +# def enable_coulomb_counter(self, en): +# if en: +# self._write_1_byte(0xB8, 0x80) +# else: +# self._write_1_byte(0xB8, 0x00) +# + +''' + def stop_coulomb_counter(self): + self._write_1_byte(0xB8, 0xC0); +} + + def clear_coulomb_counter(self): + self._write_1_byte(0xB8, 0xA0); +} + + def get_coulomb_charge_Data(self): + return Read32bit(0xB0); +} + + def get_coulomb_discharge_data(self): + return Read32bit(0xB4); +} + + def get_coulomb_data(self): + + uint32_t coin = 0; + uint32_t coout = 0; + + coin = GetCoulombchargeData(); + coout = GetCoulombdischargeData(); + + //c = 65536 * current_LSB * (coin - coout) / 3600 / ADC rate + //Adc rate can be read from 84H ,change this variable if you change the ADC reate + float ccc = 65536 * 0.5 * (coin - coout) / 3600.0 / 25.0; + return ccc; +} + +// Cut all power, except for LDO1 (RTC) + def power_off(self): + self._write_1_byte(0x32, Read8bit(0x32) | 0b10000000); +} + + def set_sdc_state(self, state): + // Enable / Disable all ADCs + self._write_1_byte(0x82, state ? 0xff : 0x00); +} + + def prepare_to_sleep(self): + // Disable ADCs + SetAdcState(false); + + // Turn LED off + TouchReset(false); + + // Turn LCD backlight off + SetLDOEnable(3, false); +} + +// Get current battery level + def get_battery_level(self): + const float batVoltage = GetBatVoltage(); + const float batPercentage = + (batVoltage < 3.248088) + ? (0) + : (batVoltage - 3.120712) * 100; + return (batPercentage <= 100) ? batPercentage : 100; +} + + def restore_from_light_sleep(self): + // Turn LCD backlight on + SetDCDC3(true); + + // Turn LED on + TouchReset(true); + + // Enable ADCs + SetLDOEnable(3, true); +} + + def get_warning_level(self): + Wire1.beginTransmission(0x34); + Wire1.write(0x47); + Wire1.endTransmission(); + Wire1.requestFrom(0x34, 1); + uint8_t buf = Wire1.read(); + return (buf & 0x01); +} + +// -- sleep + def deep_sleep(time_in_us): + PrepareToSleep(); + + if (time_in_us > 0) + { + esp_sleep_enable_timer_wakeup(time_in_us); + } + else + { + esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_TIMER); + } + (time_in_us == 0) ? esp_deep_sleep_start() : esp_deep_sleep(time_in_us); + + // Never reached - after deep sleep ESP32 restarts +} + + def light_sleep(time_in_us): + PrepareToSleep(); + + if (time_in_us > 0) + { + esp_sleep_enable_timer_wakeup(time_in_us); + } + else + { + esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_TIMER); + } + esp_light_sleep_start(); + + RestoreFromLightSleep(); +} + + def get_warning_level(self): + return Read8bit(0x47) & 0x01; +} + + def get_battery_voltage(self): + float ADCLSB = 1.1 / 1000.0; + uint16_t ReData = Read12Bit(0x78); + return ReData * ADCLSB; +} + + def get_battery_current(self): + float ADCLSB = 0.5; + uint16_t CurrentIn = Read13Bit(0x7A); + uint16_t CurrentOut = Read13Bit(0x7C); + return (CurrentIn - CurrentOut) * ADCLSB; +} + + def get_vin_voltage(self): + float ADCLSB = 1.7 / 1000.0; + uint16_t ReData = Read12Bit(0x56); + return ReData * ADCLSB; +} + + def get_vin_current(self): + float ADCLSB = 0.625; + uint16_t ReData = Read12Bit(0x58); + return ReData * ADCLSB; +} + + def get_vbus_voltage(self): + float ADCLSB = 1.7 / 1000.0; + uint16_t ReData = Read12Bit(0x5A); + return ReData * ADCLSB; +} + + def get_vbus_current(self): + float ADCLSB = 0.375; + uint16_t ReData = Read12Bit(0x5C); + return ReData * ADCLSB; +} + + def get_temp_in_axp192(self): + float ADCLSB = 0.1; + const float OFFSET_DEG_C = -144.7; + uint16_t ReData = Read12Bit(0x5E); + return OFFSET_DEG_C + ReData * ADCLSB; +} + + def get_battery_power(self): + float VoltageLSB = 1.1; + float CurrentLCS = 0.5; + uint32_t ReData = Read24bit(0x70); + return VoltageLSB * CurrentLCS * ReData / 1000.0; +} + + def get_battery_charge_current(self): + float ADCLSB = 0.5; + uint16_t ReData = Read12Bit(0x7A); + return ReData * ADCLSB; +} + + def get_aps_voltage(self): + float ADCLSB = 1.4 / 1000.0; + uint16_t ReData = Read12Bit(0x7E); + return ReData * ADCLSB; +} + + def get_battery_coulomb_input(self): + uint32_t ReData = Read32bit(0xB0); + return ReData * 65536 * 0.5 / 3600 / 25.0; +} + + def get_battery_coulomb_out(self): + uint32_t ReData = Read32bit(0xB4); + return ReData * 65536 * 0.5 / 3600 / 25.0; +} + + def set_coulomb_clear(self): +{ + Write1Byte(0xB8, 0x20); +} + + def set_ldo2(state): + uint8_t buf = Read8bit(0x12); + if (State == true) + buf = (1 << 2) | buf; + else + buf = ~(1 << 2) & buf; + Write1Byte(0x12, buf); +} + + def set_dcdc3(state): + uint8_t buf = Read8bit(0x12); + if (State == true) + buf = (1 << 1) | buf; + else + buf = ~(1 << 1) & buf; + self._write_1_byte(0x12, buf); +} + + def axp_in_state(self): + return Read8bit(0x00); +} + + def is_ac_in(self): + return ( Read8bit(0x00) & 0x80 ) ? true : false; +} + + def is_charging(self): + return ( Read8bit(0x00) & 0x04 ) ? true : false; +} + + def is_vbus(self): + return ( Read8bit(0x00) & 0x20 ) ? true : false; +} + + def set_ldo_voltage(number, voltage): + voltage = (voltage > 3300) ? 15 : (voltage / 100) - 18; + switch (number) + { + //uint8_t reg, data; + case 2: + self._write_1_byte(0x28, (Read8bit(0x28) & 0X0F) | (voltage << 4)); + break; + case 3: + self._write_1_byte(0x28, (Read8bit(0x28) & 0XF0) | voltage); + break; + } +} + + def set_dc_voltage(number, voltage): + uint8_t addr; + if (number > 2) + return; + voltage = (voltage < 700) ? 0 : (voltage - 700) / 25; + switch (number) + { + case 0: + addr = 0x26; + break; + case 1: + addr = 0x25; + break; + case 2: + addr = 0x27; + break; + } + self._write_1_byte(addr, (Read8bit(addr) & 0X80) | (voltage & 0X7F)); +} + + def set_esp_voltage(voltage): + if (voltage >= 3000 && voltage <= 3400) + { + SetDCVoltage(0, voltage); + } +} + + def set_lcd_voltage(voltage): + if (voltage >= 2500 && voltage <= 3300) + { + SetDCVoltage(2, voltage); + } +} + + def set_ldo_enable(number, state): + + uint8_t mark = 0x01; + if ((number < 2) || (number > 3)) + return; + + mark <<= number; + if (state) + { + self._write_1_byte(0x12, (Read8bit(0x12) | mark)); + } + else + { + self._write_1_byte(0x12, (Read8bit(0x12) & (~mark))); + } +} + + def set_lcd_reset(state) +{ + uint8_t reg_addr = 0x96; + uint8_t gpio_bit = 0x02; + uint8_t data; + data = Read8bit(reg_addr); + + if (state) + { + data |= gpio_bit; + } + else + { + data &= ~gpio_bit; + } + + self._write_1_byte(reg_addr, data); +} + + def set_bus_power_mode(state) +{ + uint8_t data; + if (state == 0) + { + data = Read8bit(0x91); + self._write_1_byte(0x91, (data & 0X0F) | 0XF0); + + data = Read8bit(0x90); + self._write_1_byte(0x90, (data & 0XF8) | 0X02); //set GPIO0 to LDO OUTPUT , pullup N_VBUSEN to disable supply from BUS_5V + + data = Read8bit(0x91); + + data = Read8bit(0x12); //read reg 0x12 + self._write_1_byte(0x12, data | 0x40); //set EXTEN to enable 5v boost + } + else + { + data = Read8bit(0x12); //read reg 0x10 + self._write_1_byte(0x12, data & 0XBF); //set EXTEN to disable 5v boost + + //delay(2000); + + data = Read8bit(0x90); + self._write_1_byte(0x90, (data & 0xF8) | 0X01); //set GPIO0 to float , using enternal pulldown resistor to enable supply from BUS_5VS + } +} + + def touch_reset(state): + uint8_t reg_addr=0x94; + uint8_t data; + data=Read8bit(reg_addr); + + if(state) + { + data|=0X02; + } + else + { + data=data&0XFD; + } + + self._write_1_byte(reg_addr,data); +} + +//set led state(GPIO high active,set 1 to enable amplifier) + def set_speaker_enable(state): + uint8_t reg_addr=0x94; + uint8_t gpio_bit=0x04; + uint8_t data; + data=Read8bit(reg_addr); + + if(state) + { + data|=gpio_bit; + } + else + { + data&=~gpio_bit; + } + + self._write_1_byte(reg_addr,data); +} + + def set_charge_current(state): + uint8_t data = Read8bit(0x33); + data &= 0xf0; + data = data | ( state & 0x0f ); + self._write_1_byte(0x33,data); +} + + ''' + + +TIME_0_032S = 0x00 # 32ms +TIME_0_064S = 0x01 # 64ms +TIME_0_128S = 0x02 # 128ms +TIME_0_500S = 0x03 # 500ms +TIME_0_512S = 0x04 # 512ms +TIME_1_000S = 0x05 +TIME_1_500S = 0x06 +TIME_2_000S = 0x07 +TIME_2_500S = 0x08 +TIME_3_000S = 0x09 +TIME_4_000S = 0x0A +TIME_6_000S = 0x0B +TIME_8_000S = 0x0C +TIME_10_000S = 0x0D + +TIME_0_500H = 0x00 # 30 minutes +TIME_0_666H = 0x01 # 40 minutes +TIME_0_833H = 0x02 # 50 minutes +TIME_1_000H = 0x03 +TIME_7_000H = 0x04 +TIME_8_000H = 0x05 +TIME_9_000H = 0x06 +TIME_10_000H = 0x07 + + +# Power Status Register +# READ +# bit 7: ACIN presence indication +# 0: ACIN does not exist +# 1: ACIN does exist +# bit 6: Indicates whether ACIN is available +# 0: not available +# 1: available +# bit 5: VBUS presence indication +# 0: VBUS not present +# 1: VBUS present +# bit 4: Indicates whether VBUS is available +# 0: not available +# 1: available +# bit 3: Indicates whether VBUS is greater than VHOLD before use +# bit 2: Indicates the direction of battery current +# 0: battery is discharging +# 1: battery is charging +# bit 1: Indicates whether the ACIN and VBUS inputs are shorted on the PCB +# 0: not shorted +# 1: shorted +# bit 0: Indicates whether the boot source is ACIN or VBUS +# 0: The boot source is not ACIN/VBUS +# 1: The boot source is ACIN/VBUS +_STATUS = const(0x00) + + +# Power Mode/Charging Status Register +# READ +# bit 7: Indicates whether AXP192 is overheated +# 0: Not overheated +# 1: Overheated +# bit 6: Charging Instructions +# 0: Not charging or charging completed +# 1: Charging +# bit 5: Battery status indicator +# 0: No battery is connected to AXP192 +# 1: Battery is already connected to AXP192 +# bit 4: Reserved, cannot be changed +# 0: +# 1: +# bit 3: Indicates whether the battery enters activation mode +# 0: Not in battery activation mode +# 1: In battery activation mode +# bit 2: Indicates whether the charging current is less than the expected current +# 0: The actual charging current is equal to the expected current +# 1: The actual charging current is less than the expected current +# bit 1: AXP192 power on/off mode indication +# 0: Mode A +# 1: Mode B +# bit 0: Reserved, cannot be changed +# 0: +# 1: + +POWER_MODE_A = 0 +POWER_MODE_B = 1 + +_MODE_CHGSTATUS = const(0x01) + + +# USB OTG VBUS status indication +# READ +# bit 2: Indicates whether VBUS is valid +# 0: invalid +# 1: valid +# bit 1: Indicates whether VBUS Session A/B is valid +# 0: invalid +# 1: valid +# bit 0: Indicates Session End status +# 0: invalid +# 1: valid +_OTG_STATUS = const(0x02) + +_IC_MODEL = const(0x03) + + +_DATA_BUFFER1 = const(0x04) +_DATA_BUFFER2 = const(0x05) +_DATA_BUFFER3 = const(0x06) +_DATA_BUFFER4 = const(0x07) +_DATA_BUFFER5 = const(0x08) +_DATA_BUFFER6 = const(0x09) +_DATA_BUFFER7 = const(0x0A) +_DATA_BUFFER8 = const(0x0B) +_DATA_BUFFER9 = const(0x0C) +_DATA_BUFFERA = const(0x0D) +_DATA_BUFFERB = const(0x0E) +_DATA_BUFFERC = const(0x0F) + + +# EXTEN & DC-DC2 Switch Control Register +# READ/WRITE +# bit 2: EXTEN switch control 1 +# 0: Close +# 1: Open +# bit 0: DC-DC2 switch control +# 0: Close +# 1: Open +_SWITCH_CTRL_1 = const(0x10) + + +# DC-DC1/3 & LDO2/3 Switch Control Register +# READ/WRITE +# bit 6: EXTEN switch control +# 0: Close +# 1: Open +# bit 4: DC-DC2 switch control +# 0: Close +# 1: Open +# bit 3: LDO3 switch control +# 0: Close +# 1: Open +# bit 2: LDO2 switch control +# 0: Close +# 1: Open +# bit 1: DC-DC3 switch control +# 0: Close +# 1: Open +# bit 0: DC-DC1 switch control +# 0: Close +# 1: Open +_SWITCH_CTRL_2 = const(0x12) + + +# DC-DC2 Voltage Setting Register +# READ/WRITE +# bits 0 - 5: 0.7 - 2.275V, 0.25v increments +# 0.7 = 0 0 0 0 0 0x00 +# 2.275 = 1 1 1 1 1 0x1F +_DC2_VLT_SETTING = const(0x23) + + +# DC-DC2 voltage slope parameter setting register +# READ/WRITE +# bit 2: DC-DC2 VRC enable control +# 0: Close +# 1: Open +# bit 0: DC-DC2 VRC voltage rise slope control +# 0: 25mV/15.625us=1.6mV/us +# 1: 25mV/31.250us=0.8mV/us +# TODO +_DC2_VLT_SLOPE = const(0x25) + + +# DC-DC1 Voltage Setting Register +# READ/WRITE +# bits 0 - 6: 0.7 - 3.5V, 0.25v increments +# 0.7 = 0 0 0 0 0 0 0x00 +# 3.5 = 1 1 1 1 1 1 0x3F +_DC1_VLT_SETTING = const(0x26) + + +# DC-DC3 Voltage Setting Register +# READ/WRITE +# bits 0 - 6: 0.7 - 3.5V, 0.25v increments +# 0.7 = 0 0 0 0 0 0 0x00 +# 3.5 = 1 1 1 1 1 1 0x3F +_DC3_VLT_SETTING = const(0x27) + + +# LDO2/3 voltage setting register +# bits 4 - 7: LDO2 1.8 - 3.3V, 0.1v increments +# 1.8 = 0 0 0 0 0x00 +# 3.3 = 1 1 1 1 0x0F +# bits 0 - 3: LDO3 1.8 - 3.3V, 0.1v increments +# 1.8 = 0 0 0 0 0x00 +# 3.3 = 1 1 1 1 0x0F +# READ/WRITE +_LDO_VLT_SETTING_1 = const(0x28) +_LDO_VLT_SETTING_2 = const(0x29) + + +# VBUS-IPSOUT path setting register +# READ/WRITE +# bit 7: VBUS-IPSOUT channel selection control signal when VBUS is available +# 0: Whether to open this path is determined by N_VBUSEN pin +# 1: VBUS-IPSOUT path can be selected to be open regardless of the state of N_VBUSEN +# bit 6: VBUS VHOLD voltage limit control +# 0: No pressure limit +# 1: Pressure limit +# bit 3 - 5: VHOLD Setting +# 000: 4.0V +# 001: 4.1V +# 010: 4.2V +# 011: 4.3V +# 100: 4.4V +# 101: 4.5V +# 110: 4.6V +# 111: 4.7V +# bit 1: VBUS current limit control enable signal +# 0: Close +# 1: Open +# bit 0: VBUS current limit control is turned on when the current limit selection +# 0:500mA +# 1:100mA +# BIT 7 NEEDS RESEARCH *** +VHOLD_LIMIT_NO_PRESSURE = 0x00 +VHOLD_LIMIT_PRESSURE = 0x01 + +VBUS_CUR_LIMIT_500MA = 0x00 +VBUS_CUR_LIMIT_100MA = 0x01 + +_VBUS_IPS_SETTING = const(0x30) + + +# VOFF shutdown voltage setting register +# READ/WRITE +# bit 3: In Sleep mode, enable the PWRON short press wake-up function +# 0: Short press wake-up function is disabled +# 1: Short press to wake up the function +# bit 2 - 0: VOFF setting +# 000: 2.6V +# 001: 2.7V +# 010: 2.8V +# 011: 2.9V +# 100: 3.0V +# 101: 3.1V +# 110: 3.2V +# 111: 3.3V +_VOFF_SETTING = const(0x31) + + +# Shutdown, battery detection, CHGLED control register +# READ/WRITE +# bit 7: Shutdown control in mode A +# bit 6: Battery monitoring function setting +# 0: Disable +# 1: Enable +# bit 5 - 4: CHGLED pin function setting +# 00: high impedance +# 01: 25% 1Hz flicker +# 10: 25% 4Hz flicker +# 11: Output low level +# bit 3: CHGLED pin control settings +# 0: Controlled by charging function +# 1: Controlled by register REG 32HBit[5:4] +# bit 1 - 0: N_OE changes from low to high and then AXP192 shuts down and delays +# 00: 0.5S +# 01: 1S +# 10: 2S +# 11: 3S +# BIT 7 NEEDS RESEARCH *** +CHRG_LED_HIGH_IMP = 0x00 +CHRG_LED_1HZ = 0x01 +CHRG_LED_4HZ = 0x02 +CHRG_LED_LOW = 0x03 + +_SETTINGS_1 = const(0x32) + + +# Charge control register 1 +# READ/WRITE +# bit 7: Charging function enable control bit, including internal channel and external channel +# 0: Off +# 1: On +# bit 6 - 5: Charging target voltage setting +# 00: 4.1V +# 01: 4.15V +# 10: 4.2V +# 11: 4.36V +# bit 4: Charging end current setting +# 0: Charging ends when the charging current is less than 10% of the setting value +# 1: Charging ends when the charging current is less than 15% of the setting value +# bit 3 - 0: Internal path charging current setting +# 0000: 100mA +# 0001: 190mA +# 0010: 280mA +# 0011: 360mA +# 0100: 450mA +# 0101: 550mA +# 0110: 630mA +# 0111: 700mA +# 1000: 780mA +# 1001: 880mA +# 1010: 960mA +# 1011: 1000mA +# 1100: 1080mA +# 1101: 1160mA +# 1110: 1240mA +# 1111: 1320mA +# +CHARGE_4_1V = 0x00 +CHARGE_4_15V = 0x01 +CHARGE_4_2V = 0x02 +CHARGE_4_36V = 0x03 + +CHARGE_END_10 = 0x00 +CHARGE_END_15 = 0x01 + +_CHARGE_CTRL_1 = const(0x33) + + +# Charge control register 2 +# READ/WRITE +# bit 7 - 6: Precharge timeout setting +# 00: 30min +# 01: 40min +# 10: 50min +# 11: 60min +# bit 5 - 3: External path charging current setting +# Range 300-1000mA, 100mA/step +# 000: 300ma +# 001: 400ma +# ... +# 111: 1000ma +# bit 2: External path enable setting during charging +# 0: Close +# 1: Open +# bit 1 - 0: Timeout setting in constant current mode +# 00: 7 Hours +# 01: 8 Hours +# 10: 9 Hours +# 11: 10 Hours +_CHARGE_CTRL_2 = const(0x34) + + +# Backup battery charge control register +# READ/WRITE +# bit 7: Backup battery charging enable control +# 0: Close +# 1: Open +# bit 6 - 5: Backup battery charging target voltage setting +# 00: 3.1V +# 01: 3.0V +# 10: 3.0V +# 11: 2.5V +# bit 1 - 0: Backup battery charge current setting +# 00: 50uA +# 01: 100uA +# 10: 200uA +# 11: 400uA + +BACKUP_CHRG_3_1V = 0x00 +BACKUP_CHRG_3_0V = 0x01 +BACKUP_CHRG_2_5V = 0x03 + +_CHARGE_CTRL_3 = const(0x35) + +''' +mapping = { + TIME_0_128S: 0x00, + TIME_0_512S: 0x01, + TIME_1_000S: 0x02, + TIME_2_000S: 0x03 +} + + +mapping = { + TIME_1_000S: 0x00, + TIME_1_500S: 0x01, + TIME_2_000S: 0x02, + TIME_2_500S: 0x03 +} + + +mapping = { + TIME_0_032S: 0x00, + TIME_0_064S: 0x01 +} + + +mapping = { + TIME_4_000S: 0x00, + TIME_6_000S: 0x01, + TIME_8_000S: 0x02, + TIME_10_000S: 0x03 +} + +''' + +# PEK parameter setting register +# READ/WRITE +# bit 7 - 6: Power-on time setting +# 00: 128mS +# 01: 512mS +# 10: 1S +# 11: 2S +# bit 5 - 5: Long press time setting +# 00: 1S +# 01: 1.5S +# 10: 2S +# 11: 2.5S +# bit 3: Automatic shutdown function setting when the key press time is longer than the shutdown time +# 0: Close +# 1: Open +# bit 2: PWROK signal delay after power on completion +# 0: 32mS +# 1: 64mS +# bit 1 - 0: Shutdown time setting +# 00: 4S +# 01: 6S +# 10: 8S +# 11: 10S +# TODO ***************** +_PEK_SETTINGS = const(0x36) + + +# DCDC converter operating frequency setting register +# READ/WRITE +# bit 3 - 0: DC-DC switching frequency setting +# Each level changes by 5%, the default value is 1.5MHz +# 0000: 995133hz +# 0001: 1047508hz +# 0010: 1102639hz +# 0011: 1160672hz +# 0100: 1221760hz +# 0101: 1286063hz +# 0110: 1353750hz +# 0111: 1425000hz +# 1000: 1500000hz +# 1001: 1575000hz +# 1010: 1653750hz +# 1011: 1736437hz +# 1100: 1823258hz +# 1101: 1914420hz +# 1110: 2010141hz +# 1111: 2110648hz + +DCDC_FREQ_995133HZ = 0x00 +DCDC_FREQ_1047508HZ = 0x01 +DCDC_FREQ_1102639HZ = 0x02 +DCDC_FREQ_1160672HZ = 0x03 +DCDC_FREQ_1221760HZ = 0x04 +DCDC_FREQ_1286063HZ = 0x05 +DCDC_FREQ_1353750HZ = 0x06 +DCDC_FREQ_1425000HZ = 0x07 +DCDC_FREQ_1500000HZ = 0x08 +DCDC_FREQ_1575000HZ = 0x09 +DCDC_FREQ_1653750HZ = 0x0A +DCDC_FREQ_1736437HZ = 0x0B +DCDC_FREQ_1823258HZ = 0x0C +DCDC_FREQ_1914420HZ = 0x0D +DCDC_FREQ_2010141HZ = 0x0E +DCDC_FREQ_2110648HZ = 0x0F + +# TODO ***************** +_DCDC_FREQ = const(0x37) + + +# Battery VLTF-charge battery charging low temperature threshold setting +# READ/WRITE +# bit 7 - 0: Battery low temperature threshold setting during charging, MM*10H, when M=A5H corresponds to 2.112V +# Corresponding voltage 0V~3.264V +# VLTF-charge = M *10H * 0.0008V +# setter: value = int(round(voltage / (0x10 * 0.0008))) +# getter: voltage = round(value * 0x10 * 0.0008, 4) +# TODO ***************** +_VLTF_CHRG_LOW_TEMP = const(0x38) + + +# Battery VHTF-charge battery charging high temperature threshold setting +# READ/WRITE +# bit 7 - 0: Battery high temperature threshold setting during charging, NN*10H, when N=1FH, corresponding to 0.397V; +# Corresponding voltage 0V~3.264V +# VHTF-charge = N *10H * 0.0008V +# setter: value = int(round(voltage / (0x10 * 0.0008))) +# getter: voltage = round(value * 0x10 * 0.0008, 4) +# TODO ***************** +_VHTF_CHRG_HIGH_TEMP = const(0x39) + + +# APS low power Level 1 setting register +# READ/WRITE +# bit 7 - 0: APS Low Power Setting Level 1 +# TODO ***************** +_APS_LOW_PWR_1 = const(0x3A) + +# APS low power Level2 setting register +# READ/WRITE +# bit 7 - 0: APS low power setting level 2 +# APS voltage corresponding to REG 0x3A and REG 0x3B is set to the following relationship (assuming the register value is n): +# Vwarning = 2.8672 + 1.4mV * n * 4 +# TODO ***************** +_APS_LOW_PWR_2 = const(0x3B) + + +# Battery VLTF-discharge battery discharge low temperature threshold setting +# READ/WRITE +# bit 7 - 0: Battery low temperature threshold setting during discharge, MM*10H, when M=FCH, it corresponds to 3.226V; +# Corresponding voltage 0V~3.264V +# VLTF-discharge = M * 0x10 * 0.0008V + +# setter: value = int(round(voltage / (0x10 * 0.0008))) +# getter: voltage = round(value * 0x10 * 0.0008, 4) +# TODO ***************** +_VLTF_DCHRG_LOW_TEMP = const(0x3C) + + +# Battery VHTF-discharge battery discharge high temperature threshold setting +# READ/WRITE +# bit 7 - 0: Battery high temperature threshold setting during discharge, NN * 0x10, when N = 0x16, corresponding to 0.282V; +# The voltage should be 0V~3.264V +# VLTF-discharge = N * 0x10 * 0.0008V +# setter: value = int(round(voltage / (0x10 * 0.0008))) +# getter: voltage = round(value * 0x10 * 0.0008, 4) +# TODO ***************** +_VHTF_DCHRG_HIGH_TEMP = const(0x3D) + + +# DCDC working mode setting register +# READ/WRITE +# bit 3: DC-DC1 working mode control +# 0: PFM/PWM automatic switching +# 1: Fixed PWM +# bit 2: DC-DC2 working mode control +# 0: PFM/PWM automatic switching +# 1: Fixed PWM +# bit 1: DC-DC3 working mode control +# 0: PFM/PWM automatic switching +# 1: Fixed PWM + +# @property +# def dcdc1_pwm_fixed_working_mode(self): +# pass + +# @dcdc1_pwm_fixed_working_mode.setter +# def dcdc1_pwm_fixed_working_mode(self, value): +# int(value) + +PWM_AUTO = 0x00 +PWM_FIXED = 0x01 +# TODO ***************** +_DCDC_MODE = const(0x80) + + +# ADC Enable Setting Register 1 +# READ/WRITE +# bit 7: Battery voltage ADC enable default 1 +# 0: diabled +# 1: enabled +# bit 6: Battery current ADC enable default 0 +# 0: diabled +# 1: enabled +# bit 5: ACIN voltage ADC enable default 0 +# 0: diabled +# 1: enabled +# bit 4: ACIN current ADC enable default 0 +# 0: diabled +# 1: enabled +# bit 3: VBUS voltage ADC enable default 0 +# 0: diabled +# 1: enabled +# bit 2: VBUS current ADC enable default 0 +# 0: diabled +# 1: enabled +# bit 1: APS voltage ADC enable default 1 +# 0: diabled +# 1: enabled +# bit 0: TS pin ADC function enable default 1 +# 0: diabled +# 1: enabled +_ADC_EN_1 = const(0x82) + + +# ADC Enable Setting Register 2 +# READ/WRITE +# bit 7: AXP192 internal temperature monitoring ADC enable +# 0: disable +# 1: enable +# bit 3: GPIO0 ADC function enable +# 0: disable +# 1: enable +# bit 2: GPIO1 ADC function enable +# 0: disable +# 1: enable +# bit 1: GPIO2 ADC function enable +# 0: disable +# 1: enable +# bit 0: GPIO3 ADC function enable +# 0: disable +# 1: enable +_ADC_EN_2 = const(0x83) + + +# ADC sampling rate setting, TS pin control register +# READ/WRITE +# bit 7 - 6: ADC sampling rate setting +# 00: 25hz +# 01: 50hz +# 10: 100hz +# 11: 200hz +# bit 5 - 4: TS pin output current setting +# 00: 20uA +# 01: 40uA +# 10: 60uA +# 11: 80uA +# bit 2: TS pin function selection +# 0: Battery temperature monitoring function +# 1: External independent ADC input path +# bit 1 - 0: TS pin current output mode setting +# 00: off +# 01: Output current during charging +# 10: ADC sampling input, can save power +# 11: Always open +# TODO ***************** +_ADC_SAMP_TS_PIN = const(0x84) + + +# GPIO [3:0] input range setting register +# READ/WRITE +# bit 3: GPIO3 ADC input range +# 0: 0 - 2.0475V +# 1: 0.7 - 2.7475V +# bit 2: GPIO2 ADC input range +# 0: 0 - 2.0475V +# 1: 0.7 - 2.7475V +# bit 1: GPIO1 ADC input range +# 0: 0 - 2.0475V +# 1: 0.7 - 2.7475V +# bit 0: GPIO0 ADC input range +# 0: 0 - 2.0475V +# 1: 0.7 - 2.7475V +_GPIO_INPT_RNG = const(0x85) + + +# GPIO1 ADC IRQ rising edge threshold setting +# READ/WRITE +# bit 7 - 0: One LSB is 8mV +# TODO ***************** +_GPIO1_ADC_IRQ_RISE = const(0x86) + + +# GPIO1 ADC IRQ falling edge threshold setting +# READ/WRITE +# bit 7 - 0: One LSB is 8mV +# TODO ***************** +_GPIO1_ADC_IRQ_FALL = const(0x87) + + +# timer control register +# READ/WRITE +# bit 7: Timer timed out +# Write 1 to clear the state +# bit 6 - 0: Set the timing time in minutes +# Write 0 to disable timer +# TODO ***************** +_TIMER_CTRL = const(0x8A) + + +# VBUS monitoring setting register +# READ/WRITE +# bit 5 - 4: VBUS effective voltage setting +# 00: 4.0V +# 01: 4.15V +# 10: 4.45V +# 11: 4.55V +# bit 3: VBUS Valid detection function setting: +# 0: Disable +# 1: Enable +# bit 2: VBUS Session detection function setting: +# 0: Disable +# 1: Enable +# bit 1: Discharge VBUS discharge function setting +# 0: turn off the discharge resistor of VBUS +# 1: use the discharge resistor of VBUS +# bit 0: Charge VBUS charging function settings +# 0: Disconnect the VBUS charging resistor +# 1: Use the VBUS charging resistor to charge VBUS + +VBUS_VLTG_4_00 = 0x00 +VBUS_VLTG_4_15 = 0x01 +VBUS_VLTG_4_45 = 0x02 +VBUS_VLTG_4_55 = 0x03 + +_VBUS_MONITOR = const(0x8B) + + +# Over temperature shutdown control register +# READ/WRITE +# bit 2: AXP192 internal over temperature shutdown function setting +# 0: Do not shut down +# 1: Shut down +_OVER_TEMP_SHUT_CTRL = const(0x8F) + + +# Group 2, GPIO control + +# GPIO0 Control Register +# READ/WRITE +# bit 2 - 0: GPIO0 pin function setting +# 000: NMOS open drain output +# 001: General input function +# 010: Low Noise LDO +# 100: ADC input +# 101: Output low +# 110: Floating +# 111: Floating +_GPIO0_CTRL_1 = const(0x90) + + +# GPIO0 LDO mode output voltage setting register +# READ/WRITE +# bits 7 - 4: GPIO0 Output voltage setting in LDO mode +# 0000: 1.8V +# 0001: 1.9V +# 0010: 2.0V +# 0011: 2.1V +# 0100: 2.2V +# 0101: 2.3V +# 0110: 2.4V +# 0111: 2.5V +# 1000: 2.6V +# 1001: 2.7V +# 1010: 2.8V +# 1011: 2.9V +# 1100: 3.0V +# 1101: 3.1V +# 1110: 3.2V +# 1111: 3.3V +_GPIO0_CTRL_2 = const(0x91) + + +# GPIO1 Control Register +# READ/WRITE +# bit 2 - 0: GPIO1 pin function setting +# 000: NMOS open drain output +# 001: General input function +# 010: PWM1 output, high level is VINT, no You can add a pull-down resistor less than 100K +# 100: ADC input +# 101: Output low +# 110: Floating +# 111: Floating +_GPIO1_CTRL = const(0x92) + + +# GPIO2 Control Register +# bit 2 - 0: GPIO2 pin function setting +# 000: NMOS open drain output +# 001: General input function +# 010: PWM2 output, high level is VINT, no You can add a pull-down resistor less than 100K +# 100: ADC input +# 101: Output low +# 110: Floating +# 111: Floating +# READ/WRITE +_GPIO2_CTRL = const(0x93) + + +# GPIO[2:0] signal status register +# READ/WRITE +# bit 6: GPIO2 input status +# 0: Input low level +# 1: Input high level +# bit 5: GPIO1 input status +# 0: Input low level +# 1: Input high level +# bit 4: GPIO0 input status +# 0: Input low level +# 1: Input high level +# bit 2: GPIO2 output settings +# 0: Output low level, grounded NMOS is turned on +# 1: Output floating, grounded NMOS off +# bit 1: GPIO1 output settings +# 0: Output low level, grounded NMOS is turned on +# 1: Output floating, grounded NMOS off +# bit 0: GPIO0 output setting +# 0: Output low level, grounded NMOS is turned on +# 1: Output floating, grounded NMOS off +_GPIO_SIG_STATUS_1 = const(0x94) + + +# GPIO[4:3] function control register +# READ/WRITE +# bit 7: GPIO[4:3] control +# 1: GPIO function +# bit 3 - 2: GPIO4 pin function setting +# 00: External charging control +# 01:NMOS open drain output port 4 +# 10: General purpose input port 4 +# 11: Undefined +# bit 1 - 0: GPIO3 pin function setting +# 00: External charging control +# 01:NMOS open drain output port 3 +# 10: General purpose input port 3 +# 11: ADC Input +_GPIO_FUNC_CTRL = const(0x95) + + +# GPIO[4:3] signal status register +# READ/WRITE +# bit 5: GPIO4 input status +# 0: Input low level +# 1: Input high level +# bit 4: GPIO3 input status +# 0: Input low level +# 1: Input high level + +# bit 1: GPIO4 output setting +# 0: Output low level, NMOS is turned on +# 1: Floating, NMOS off +# bit 0: GPIO3 output setting +# 0: Output low level, NMOS is turned on +# 1: Floating, NMOS off +_GPIO_SIG_STATUS_2 = const(0x96) + + +# GPIO[2:0] pull-down control register +# READ/WRITE +# bit 2: Pull-down resistor control when GPIO2 is used as input +# 0: turn off the pull-down resistor +# 1: Use a pull-down resistor +# bit 1: Pull-down resistor control when GPIO1 is used as input +# 0: turn off the pull-down resistor +# 1: Use a pull-down resistor +# bit 0: Pull-down resistor control when GPIO0 is used as input +# 0: turn off the pull-down resistor +# 1: Use a pull-down resistor +_GPIO_PULL_DOWN = const(0x97) + + +# PWM1 frequency setting register +# READ/WRITE +# bit 7 - 0: PWM1 output frequency setting X +_PWM1_FREQ_X = const(0x98) + + +# PWM1 Duty Cycle Setting Register 1 +# READ/WRITE +# bit 7 - 0: PWM1 duty cycle setting Y1 +_PMW1_DUTY_Y1 = const(0x99) + +# PWM1 duty cycle setting register 2 +# READ/WRITE +# bit 7 - 6: PWM1 duty cycle setting Y2 +_PMW1_DUTY_Y2 = const(0x9A) + + +# PWM2 frequency setting register +# READ/WRITE +# bit 7 - 0: PWM2 output frequency setting X +_PWM2_FREQ_X = const(0x9B) + + +# PWM2 duty cycle setting register 1 +# READ/WRITE +# bit 7 - 0: PWM2 duty cycle setting Y1 +_PMW2_DUTY_Y1 = const(0x9C) + +# PWM2 duty cycle setting register 2 +# READ/WRITE +# bit 7 - 6: PWM2 duty cycle setting Y2 +_PMW2_DUTY_Y2 = const(0x9D) + +# ****************** +# Note: PWM output frequency = 2.25MHz / (X+1) / Y1 +# PWM output duty cycle = Y2 / Y1 +# ****************** + + +# N_RSTO (GPIO5) Control Register +# READ/WRITE +# bit 7: N_RSTO pin function setting +# 0: N_RSTO, LDO1 status monitoring +# 1: General input and output port 5 +# bit 6: N_RSTO is used as general purpose input and output port 5 setting +# 0: NMOS open drain output +# 1: general input function +# bit 5: N_RSTO as output port 5 settings +# 0: Output low level, NMOS is turned on +# 1: Floating, NMOS is turned off +# bit 4: Status of N_RSTO as input port 5 +# 0: input low level +# 1: input high level +# TODO +GPIO5_CTRL = const(0x9E) + + +# Group 3, Interrupt Control + +# IRQ Enable Control Register 1 +# READ/WRITE +# bit 7: ACIN overvoltage IRQ enable +# bit 6: ACIN access IRQ enable +# bit 5: ACIN OUT IRQ ENABLE +# bit 4: VBUS overvoltage IRQ enable +# bit 3: VBUS access IRQ enable +# bit 2: VBUS removed IRQ enable +# bit 1: VBUS is available but less than VHOLDIRQ Enable +# bit 0: reserved cannot be changed +_INT_CTRL_1 = const(0x40) + + +# IRQ Enable Control Register 2 +# READ/WRITE +# bit 7: Battery connected IRQ Enable +# bit 6: Battery removed IRQ enable +# bit 5: Battery activation mode IRQ Enable +# bit 4: Exit battery activation mode IRQ Enable +# bit 3: Charging IRQ Enable +# bit 2: Charging completed IRQ Enable +# bit 1: Battery over temperature IRQ Enable +# bit 0: Battery under temperature IRQ Enable +_INT_CTRL_2 = const(0x41) + + +# IRQ Enable Control Register 3 +# READ/WRITE +# bit 7: AXP192 internal over temperature IRQ enable +# bit 6: charging current is less than the set current IRQ enable +# bit 5: DC-DC1 output voltage is less than the set value IRQ enabled +# bit 4: DC-DC2 output voltage is less than the set value IRQ enabled +# bit 3: DC-DC3 output voltage is less than the set value IRQ enable +# bit 2: reserved +# bit 1: Short key IRQ enable +# bit 0: Long key IRQ enable +_INT_CTRL_3 = const(0x42) + + +# IRQ Enable Control Register 4 +# READ/WRITE +# bit 7: N_OE Power on IRQ enable +# bit 6: N_OE Shutdown IRQ Enable +# bit 5: VBUS Valid IRQ Enable +# bit 4: VBUS Invalid IRQ Enable +# bit 3: VBUS Session A/B IRQ Enable +# bit 2: VBUS Session End IRQ Enable +# bit 1: reserved +# bit 0: APS Low Voltage IRQ Enable +_INT_CTRL_4 = const(0x43) + + +# IRQ Enable Control Register 5 +# READ/WRITE +# bit 7: Timer timeout IRQ Enable +# bit 6: reserved +# bit 5: reserved +# bit 4: reserved +# bit 3: reserved +# bit 2: GPIO2 input edge triggered IRQ enable +# bit 1: GPIO1 input edge triggered IRQ enable +# bit 0: GPIO0 input edge triggered IRQ enable +_INT_CTRL_5 = const(0x4A) + + +# IRQ Status Register 1 +# READ/WRITE +# bit 7: ACIN overvoltage IRQ status +# bit 6: ACIN access IRQ status +# bit 5: ACIN moves out of IRQ state +# bit 4: VBUS overvoltage IRQ status +# bit 3: VBUS access IRQ status +# bit 2: VBUS moves out of IRQ state +# bit 1: VBUS is available but less than VHOLDIRQ status +# bit 0: reserved +_INT_STATUS_1 = const(0x44) + + +# IRQ Status Register 2 +# READ/WRITE +# bit 7: Battery connected IRQ status +# bit 6: Battery removed IRQ status +# bit 5: Battery activation mode IRQ status +# bit 4: Exit battery activation mode IRQ status +# bit 3: Charging IRQ status +# bit 2: Charging completed IRQ status +# bit 1: Battery over temperature IRQ status +# bit 0: Battery under temperature IRQ status +_INT_STATUS_2 = const(0x45) + + +# IRQ Status Register 3 +# READ/WRITE +# bit 7: AXP192 Internal over temperature IRQ status +# bit 6: Charging current is less than the set current IRQ status +# bit 5: DC-DC1 output voltage is less than the set value IRQ status +# bit 4: DC-DC2 output voltage is less than the set value IRQ status +# bit 3: DC-DC3 output voltage is less than the set value IRQ status +# bit 2: reserved +# bit 1: Short key IRQ status +# bit 0: Long key IRQ status +_INT_STATUS_3 = const(0x46) + + +# IRQ Status Register 4 +# READ/WRITE +# bit 7: N_OE Power on IRQ status +# bit 6: N_OE Shutdown IRQ status +# bit 5: VBUS valid IRQ status +# bit 4: VBUS Invalid IRQ status +# bit 3: VBUS Session A/B IRQ status +# bit 2: VBUS Session End IRQ status +# bit 1: reserved +# bit 0: APS low voltage IRQ state +# APS voltage is lower than Warning Level2 and then set, +# exceeding Warning Level1 Will be cleared to 0 +_INT_STATUS_4 = const(0x47) + + +# IRQ Status Register 5 +# READ/WRITE +# bit 7: Timer timeout IRQ status +# bit 6: reserved +# bit 5: reserved +# bit 4: reserved +# bit 3: reserved +# bit 2: GPIO2 input edge trigger IRQ status +# bit 1: GPIO1 input edge trigger IRQ status +# bit 0: GPIO0 input edge trigger IRQ status +_INT_STATUS_5 = const(0x4D) + + +# Group 4, ADC data class +# These are all READ + +# ACIN voltage ADC data high 8 bits +_ACIN_VLTS_H = const(0x56) + +# ACIN voltage ADC data lower 4 bits +_ACIN_VLTS_L = const(0x57) + +# TODO +# ACIN voltage ADC data 12 bit resolution +# ((REG 0x56) << 4) + (REG 0x57) + + +# ACIN current ADC data high 8 bits +_ACIN_CURR_H = const(0x58) + +# ACIN current ADC data lower 4 bits +_ACIN_CURR_L = const(0x59) + +# TODO +# ACIN current ADC data 12 bit resolution +# ((REG 0x58) << 4) + (REG 0x59) + + +# VBUS voltage ADC data high 8 bits +_VBUS_VLTS_H = const(0x5A) + +# VBUS voltage ADC data lower 4 bits +_VBUS_VLTS_L = const(0x5B) + +# TODO +# VBUS voltage ADC data 12 bit resolution +# ((REG 0x5A) << 4) + (REG 0x5B) + + +# VBUS current ADC data high 8 bits +_VBUS_CURR_H = const(0x5C) + +# VBUS current ADC data lower 4 bits +_VBUS_CURR_L = const(0x5D) + +# TODO +# VBUS current ADC data 12 bit resolution +# ((REG 0x5C) << 4) + (REG 0x5D) + + +# AXP192 internal temperature monitoring ADC data high 8 bits +_TEMP_H = const(0x5E) + +# AXP192 internal temperature monitoring ADC data lower 4 bits +_TEMP_L = const(0x5F) + +# TODO +# AXP192 internal temperature monitoring ADC data 12 bit resolution +# ((REG 0x5E) << 4) + (REG 0x5F) + + +# TS input ADC data high 8 bits, default monitoring battery temperature +_TS_INPUT_H = const(0x62) + +# TS input ADC data lower 4 bits, default monitoring battery temperature +_TS_INPUT_L = const(0x63) + +# TODO +# TS input ADC data 12 bit resolution +# ((REG 0x62) << 4) + (REG 0x63) + + +# GPIO0 voltage ADC data high 8 bits +_GPIO0_VLTS_H = const(0x64) + +# GPIO0 voltage ADC data lower 4 bits +_GPIO0_VLTS_L = const(0x65) + +# GPIO0 voltage ADC data 12 bit resolution +# ((REG 0x64) << 4) + (REG 0x65) + + +# GPIO1 voltage ADC data high 8 bits +_GPIO1_VLTS_H = const(0x66) + + +# GPIO1 voltage ADC data lower 4 bits +_GPIO1_VLTS_L = const(0x67) + + +# GPIO1 voltage ADC data 12 bit resolution +# ((REG 0x66) << 4) + (REG 0x67) + + +# GPIO2 voltage ADC data high 8 bits +_GPIO2_VLTS_H = const(0x68) + +# GPIO2 voltage ADC data lower 4 bits +_GPIO2_VLTS_L = const(0x69) + + +# GPIO2 voltage ADC data 12 bit resolution +# ((REG 0x68) << 4) + (REG 0x69) + + +# GPIO3 voltage ADC data high 8 bits +_GPIO3_VLTS_H = const(0x6A) + + +# GPIO3 voltage ADC data lower 4 bits +_GPIO3_VLTS_L = const(0x6B) + +# GPIO3 voltage ADC data 12 bit resolution +# ((REG 0x6A) << 4) + (REG 0x6B) + + +# Battery instantaneous power high 8 bits +_BAT_PWR_H = const(0x70) + +# Battery instantaneous power medium 8 bits +_BAT_PWR_M = const(0x71) + +# Battery instantaneous power low 8 bits +_BAT_PWR_L = const(0x72) + +# TODO +# Battery instantaneous power 24 bit resolution +# ((REG 0x70) << 16) | ((REG 0x71) << 8) | (REG 0x72) + + +# Battery voltage high 8 bits +_BAT_VLTS_H = const(0x78) + +# Battery voltage low 4 bits +_BAT_VLTS_L = const(0x79) + +# TODO +# Battery voltage 12 bit resolution +# ((REG 0x78) << 4) + (REG 0x79) + + +# Battery charge current high 8 bits +_BAT_CHRG_CURR_H = const(0x7A) + +# Battery charge current low 5 bits +_BAT_CHRG_CURR_L = const(0x7B) + +# TODO +# Battery charge current 13 bit resolution +# ((REG 0x7A) << 5) + (REG 0x7B) + + +# Battery discharge current high 8 bits +_BAT_DCHRG_CURR_H = const(0x7C) + +# Battery discharge current low 5 bits +_BAT_DCHRG_CURR_L = const(0x7D) + +# TODO +# Battery discharge current 13 bit resolution +# ((REG 0x7C) << 5) + (REG 0x7D) + + +# APS voltage high 8 bits +_APS_VLTS_H = const(0x7E) + +# APS voltage low 4 bits +_APS_VLTS_L = const(0x7F) + +# TODO +# APS voltage 12 bit resolution +# ((REG 0x7E) << 4) + (REG 0x7F) + + +# READ/WRITE +# Battery Charge Coulomb Counter Data Register [31:24] +_BAT_CHRG_COUNTER_1 = const(0xB0) + +# Battery Charge Coulomb Counter Data Register [23:16] +_BAT_CHRG_COUNTER_2 = const(0xB1) + +# Battery Charge Coulomb Counter Data Register [15:8] +_BAT_CHRG_COUNTER_3 = const(0xB2) + +# Battery Charge Coulomb Counter Data Register [7:0] +_BAT_CHRG_COUNTER_4 = const(0xB3) + +# TODO +# Battery Charge Coulomb Counter Data 32 bits +# ((REG 0xB0) << 24) | ((REG 0xB1) << 16) | ((REG 0xB2) << 8) | (REG 0xB3) + + +# Battery Discharge Coulomb Counter Data Register [31:24] +_BAT_DCHRG_COUNTER_1 = const(0xB4) + +# Battery Discharge Coulomb Counter Data Register [23:16] +_BAT_DCHRG_COUNTER_2 = const(0xB5) + +# Battery Discharge Coulomb Counter Data Register [15:8] +_BAT_DCHRG_COUNTER_3 = const(0xB6) + +# Battery Discharge Coulomb Counter Data Register [7:0] +_BAT_DCHRG_COUNTER_4 = const(0xB7) +# TODO +# Battery Discharge Coulomb Counter Data 32 bits +# ((REG 0xB4) << 24) | ((REG 0xB5) << 16) | ((REG 0xB6) << 8) | (REG 0xB7) + + +# TODO +# Coulomb Counter Control Register +# READ/WRITE +# bit 7: Coulomb meter switch control +# bit 6: Coulomb meter pause control +# 0: N/A +# 1: pause the coulomb counting +# bit 5: Clear coulomb meter control, +# 0: N/A +# 1: clear the coulomb meter +_COUNTER_CTRL = const(0xB8) + + +# Coulomb calculation method: +# C = 65536 * current LSB * (charging coulomb counter value - discharging coulomb counter value) / 3600 / ADC sampling +# +# Among them: ADC sampling rate refers to the setting of REG84H; +# current LSB is 0.5mA; +# the unit of calculation result is mAh. + + +EXIO0 = 0 +EXIO1 = 1 +EXIO2 = 2 +EXIO3 = 3 +EXIO4 = 4 + + +class Pin(io_expander_framework.Pin): + # IRQ Status Register 5 + # READ/WRITE + # bit 7: Timer timeout IRQ status + # bit 6: reserved + # bit 5: reserved + # bit 4: reserved + # bit 3: reserved + # bit 2: GPIO2 input edge trigger IRQ status + # bit 1: GPIO1 input edge trigger IRQ status + # bit 0: GPIO0 input edge trigger IRQ status + _INT_STATUS_5 = const(0x4D) + + def __init__(self, id, device, mode=-1, pull=-1, value=None): # NOQA + + if id not in (EXIO0, EXIO1, EXIO2, EXIO3, EXIO4): + raise ValueError(f"GPIO (EXIO) {id} is not supported for this IC") + + self._device = device + + if mode == -1: + mode = self.IN + + self._direction = -1 + + self._pwm = None + self._adc = None + self._irq = None + + io_expander_framework.Pin.__init__(self, id=id, mode=mode, pull=pull, value=value) + + device._gpios[self._id] = self # NOQA + + def deinit(self): + if self._pwm is not None: + self._pwm.deinit() + if self._adc is not None: + self._adc.deinit() + if self._irq is not None: + value = self._device.read(_INT_CTRL_5) + if self._id == EXIO0: + value &= ~0x01 + elif self._id == EXIO1: + value &= ~0x02 + elif self._id == EXIO2: + value &= ~0x04 + + self._device.write(_INT_CTRL_5, value) + self._irq = None + + def __del__(self): + self.deinit() + del self._device._gpios[self.id] # NOQA + + def _set_irq(self, handler, trigger): # NOQA + + if handler is not None and self._id not in (EXIO0, EXIO1, EXIO2): + raise ValueError(f"IRQ is not supported for GPIO (EXIO) {self._id}") + + value = self._device.read(_INT_CTRL_5) + + if handler is None: + if self._id == EXIO0: + value &= ~0x01 + elif self._id == EXIO1: + value &= ~0x02 + elif self._id == EXIO2: + value &= ~0x04 + else: + if self._id == EXIO0: + value |= 0x01 + elif self._id == EXIO1: + value |= 0x02 + elif self._id == EXIO2: + value |= 0x04 + + self._device.write(_INT_CTRL_5, value) + self._irq = handler + + def _set_dir(self, direction): + if direction == self.IN: + if self._id == EXIO0: + value = self._device.read(_GPIO0_CTRL_1) & 0xF8 + value |= 0x01 + self._device.write(_GPIO0_CTRL_1, value) + elif self._id == EXIO1: + value = self._device.read(_GPIO1_CTRL) & 0xF8 + value |= 0x01 + self._device.write(_GPIO1_CTRL, value) + elif self._id == EXIO2: + value = self._device.read(_GPIO2_CTRL) & 0xF8 + value |= 0x01 + self._device.write(_GPIO2_CTRL, value) + elif self._id == EXIO3: + value = self._device.read(_GPIO_FUNC_CTRL) & 0xFC + value |= 0x02 + self._device.write(_GPIO_FUNC_CTRL, value) + elif self._id == EXIO4: + value = self._device.read(_GPIO_FUNC_CTRL) & 0xF3 + value |= 0x08 + self._device.write(_GPIO_FUNC_CTRL, value) + + elif direction == self.OUT: + if self._id == EXIO0: + value = self._device.read(_GPIO0_CTRL_1) & 0xF8 + value |= 0x05 + self._device.write(_GPIO0_CTRL_1, value) + elif self._id == EXIO1: + value = self._device.read(_GPIO1_CTRL) & 0xF8 + value |= 0x05 + self._device.write(_GPIO1_CTRL, value) + elif self._id == EXIO2: + value = self._device.read(_GPIO2_CTRL) & 0xF8 + value |= 0x05 + self._device.write(_GPIO2_CTRL, value) + else: + raise ValueError(f'OUT is not supported for GPIO (EXIO) {self._id}') + + elif direction == self.OPEN_DRAIN: + if self._id == EXIO0: + value = self._device.read(_GPIO0_CTRL_1) & 0xF8 + self._device.write(_GPIO0_CTRL_1, value) + elif self._id == EXIO1: + value = self._device.read(_GPIO1_CTRL) & 0xF8 + self._device.write(_GPIO1_CTRL, value) + elif self._id == EXIO2: + value = self._device.read(_GPIO2_CTRL) & 0xF8 + self._device.write(_GPIO2_CTRL, value) + elif self._id == EXIO3: + value = self._device.read(_GPIO_FUNC_CTRL) & 0xFC + value |= 0x02 + self._device.write(_GPIO_FUNC_CTRL, value) + elif self._id == EXIO4: + value = self._device.read(_GPIO_FUNC_CTRL) & 0xF3 + value |= 0x08 + self._device.write(_GPIO_FUNC_CTRL, value) + else: + raise ValueError(str(direction)) + + self._direction = direction + + def _set_pull(self, pull): + + if self._id not in (EXIO0, EXIO1, EXIO1) and pull is not None and pull != self.PULL_DOWN: + raise ValueError(f'"PULL_DOWN" is not supported for GPIO (EXIO) {self._id}') + + if pull is None: + if self._id == EXIO0: + value = self._device.read(_GPIO_PULL_DOWN) + value &= ~0x01 + self._device.write(_GPIO_PULL_DOWN, value) + elif self._id == EXIO1: + value = self._device.read(_GPIO_PULL_DOWN) + value &= ~0x02 + self._device.write(_GPIO_PULL_DOWN, value) + elif self._id == EXIO2: + value = self._device.read(_GPIO_PULL_DOWN) + value &= ~0x04 + self._device.write(_GPIO_PULL_DOWN, value) + + elif pull == self.PULL_DOWN: + if self._id == EXIO0: + value = self._device.read(_GPIO_PULL_DOWN) + value |= 0x01 + self._device.write(_GPIO_PULL_DOWN, value) + elif self._id == EXIO1: + value = self._device.read(_GPIO_PULL_DOWN) + value |= 0x02 + self._device.write(_GPIO_PULL_DOWN, value) + elif self._id == EXIO2: + value = self._device.read(_GPIO_PULL_DOWN) + value |= 0x04 + self._device.write(_GPIO_PULL_DOWN, value) + + def _set_level(self, level): + if level: + if self._direction == self.OPEN_DRAIN: + if self._id == EXIO0: + value = self._device.read(_GPIO_SIG_STATUS_1) + value |= 0x01 + self._device.write(_GPIO_SIG_STATUS_1, value) + elif self._id == EXIO1: + value = self._device.read(_GPIO_SIG_STATUS_1) + value |= 0x02 + self._device.write(_GPIO_SIG_STATUS_1, value) + elif self._id == EXIO2: + value = self._device.read(_GPIO_SIG_STATUS_1) + value |= 0x04 + self._device.write(_GPIO_SIG_STATUS_1, value) + elif self._id == EXIO3: + value = self._device.read(_GPIO_SIG_STATUS_2) + value |= 0x01 + self._device.write(_GPIO_SIG_STATUS_2, value) + elif self._id == EXIO4: + value = self._device.read(_GPIO_SIG_STATUS_2) + value |= 0x02 + self._device.write(_GPIO_SIG_STATUS_2, value) + elif self._direction == self.OUT: + if self._id == EXIO0: + if isinstance(level, bool) or level == 1: + level = 0xF0 + else: + level = int(lcd_utils.remap(float(level), 1.8, 3.3, 0.0, 15.0)) << 4 + + value = self._device.read(_GPIO0_CTRL_2) & 0x0F + value |= level + self._device.write(_GPIO0_CTRL_2, value) + + value = self._device.read(_GPIO0_CTRL_1) & 0xF8 + value |= 0x02 + self._device.write(_GPIO0_CTRL_1, value) + + elif self._id == EXIO1: + value = self._device.read(_GPIO_SIG_STATUS_1) + value |= 0x06 + self._device.write(_GPIO_SIG_STATUS_1, value) + + elif self._id == EXIO2: + value = self._device.read(_GPIO_SIG_STATUS_1) + value |= 0x06 + self._device.write(_GPIO_SIG_STATUS_1, value) + else: + if self._direction == self.OPEN_DRAIN: + if self._id == EXIO0: + value = self._device.read(_GPIO_SIG_STATUS_1) + value &= ~0x01 + self._device.write(_GPIO_SIG_STATUS_1, value) + elif self._id == EXIO1: + value = self._device.read(_GPIO_SIG_STATUS_1) + value &= ~0x02 + self._device.write(_GPIO_SIG_STATUS_1, value) + elif self._id == EXIO2: + value = self._device.read(_GPIO_SIG_STATUS_1) + value &= ~0x04 + self._device.write(_GPIO_SIG_STATUS_1, value) + elif self._id == EXIO3: + value = self._device.read(_GPIO_SIG_STATUS_2) + value &= ~0x01 + self._device.write(_GPIO_SIG_STATUS_2, value) + elif self._id == EXIO4: + value = self._device.read(_GPIO_SIG_STATUS_2) + value &= ~0x02 + self._device.write(_GPIO_SIG_STATUS_2, value) + + elif self._direction == self.OUT: + if self._id == EXIO0: + value = self._device.read(_GPIO0_CTRL_1) + value |= 0x05 + self._device.write(_GPIO0_CTRL_1, value) + elif self._id == EXIO1: + value = self._device.read(_GPIO1_CTRL) + value |= 0x05 + self._device.write(_GPIO1_CTRL, value) + elif self._id == EXIO2: + value = self._device.read(_GPIO2_CTRL) + value |= 0x05 + self._device.write(_GPIO2_CTRL, value) + + def _get_level(self): + if self._id == EXIO0: + value = self._device.read(_GPIO_SIG_STATUS_1) & 0x08 + elif self._id == EXIO1: + value = self._device.read(_GPIO_SIG_STATUS_1) & 0x10 + elif self._id == EXIO2: + value = self._device.read(_GPIO_SIG_STATUS_1) & 0x20 + elif self._id == EXIO3: + value = self._device.read(_GPIO_SIG_STATUS_2) & 0x08 + elif self._id == EXIO4: + value = self._device.read(_GPIO_SIG_STATUS_2) & 0x10 + else: + raise ValueError(f"not supported for GPIO (EXIO) {self._id}") + + return int(bool(value)) + + +class ADC(io_expander_framework.ADC): + + ATTN_0DB = 0 # 0 - 2.0475V + ATTN_2_5DB = 1 # 0.7 - 2.7475V + + WIDTH_9BIT = 0 + WIDTH_10BIT = 1 + WIDTH_11BIT = 2 + WIDTH_12BIT = 3 + WIDTH_13BIT = 4 + + def __init__(self, pin: Pin, attn=-1): + self._device = pin._device # NOQA + super().__init__(pin=pin, attn=attn) + + self._width = self.WIDTH_12BIT + + if pin._id == EXIO0: # NOQA + self._device.write(_GPIO0_CTRL_1, (self._device.read(_GPIO0_CTRL_1) & 0xF8) | 0x04) + self._device.write(_ADC_EN_2, (self._device.read(_ADC_EN_2) & 0xF0) | 0x08) + if pin._id == EXIO1: # NOQA + self._device.write(_GPIO1_CTRL, (self._device.read(_GPIO1_CTRL) & 0xF8) | 0x04) + self._device.write(_ADC_EN_2, (self._device.read(_ADC_EN_2) & 0xF0) | 0x04) + elif pin._id == EXIO2: # NOQA + self._device.write(_GPIO2_CTRL, (self._device.read(_GPIO2_CTRL) & 0xF8) | 0x04) + self._device.write(_ADC_EN_2, (self._device.read(_ADC_EN_2) & 0xF0) | 0x02) + elif pin._id == EXIO3: # NOQA + self._device.write(_GPIO_FUNC_CTRL, (self._device.read(_GPIO_FUNC_CTRL) & 0xFC) | 0x03) + self._device.write(_ADC_EN_2, (self._device.read(_ADC_EN_2) & 0xF0) | 0x01) + else: + pin._adc = None + raise ValueError(f"ADC is not supported for GPIO (EXIO) {self._pin._id}") # NOQA + + def deinit(self) -> None: + if self._pin._id == EXIO0: # NOQA + self._device.write(_GPIO0_CTRL_1, (self._device.read(_GPIO0_CTRL_1) & 0xF8) | 0x06) + self._device.write(_ADC_EN_2, (self._device.read(_ADC_EN_2) & 0xF0) & ~0x08) + if self._pin._id == EXIO1: # NOQA + self._device.write(_GPIO1_CTRL, (self._device.read(_GPIO1_CTRL) & 0xF8) | 0x06) + self._device.write(_ADC_EN_2, (self._device.read(_ADC_EN_2) & 0xF0) & ~0x04) + elif self._pin._id == EXIO2: # NOQA + self._device.write(_GPIO2_CTRL, (self._device.read(_GPIO2_CTRL) & 0xF8) | 0x06) + self._device.write(_ADC_EN_2, (self._device.read(_ADC_EN_2) & 0xF0) & ~0x02) + elif self._pin._id == EXIO3: # NOQA + self._device.write(_GPIO_FUNC_CTRL, (self._device.read(_GPIO_FUNC_CTRL) & 0xFC) | 0x02) + self._device.write(_ADC_EN_2, (self._device.read(_ADC_EN_2) & 0xF0) & ~0x01) + else: + raise ValueError(f"not supported for GPIO (EXIO) {self._pin._id}") # NOQA + + super().deinit() + + def __del__(self): + self.deinit() + + def attn(self, attn=-1): + if attn in (self.ATTN_0DB, self.ATTN_2_5DB): + value = self._device.read(_GPIO_INPT_RNG) & 0xF0 + if self._pin._id == EXIO0: # NOQA + value &= ~self.ATTN_2_5DB + value |= attn + elif self._pin._id == EXIO1: # NOQA + value &= ~(self.ATTN_2_5DB << 1) + value |= attn << 1 + elif self._pin._id == EXIO2: # NOQA + value &= ~(self.ATTN_2_5DB << 2) + value |= attn << 2 + elif self._pin._id == EXIO3: # NOQA + value &= ~(self.ATTN_2_5DB << 3) + value |= attn << 3 + else: + raise ValueError(f"not supported for GPIO (EXIO) {self._pin._id}") # NOQA + + self._attn = attn + self._device.write(value) + + def read_uv(self): + value = self.read() + + if self._width == self.WIDTH_9BIT: + old_max = 0x01FF + elif self._width == self.WIDTH_10BIT: + old_max = 0x03FF + elif self._width == self.WIDTH_11BIT: + old_max = 0x07FF + elif self._width == self.WIDTH_12BIT: + old_max = 0x0FFF + elif self._width == self.WIDTH_13BIT: + old_max = 0x1FFF + else: + raise ValueError("not supported for GPIO (EXIO) {self.id}") + + if self._attn == self.ATTN_0DB: + new_min = 0.0 + new_max = 2.0475 + elif self._attn == self.ATTN_2_5DB: + new_min = 0.7 + new_max = 2.7475 + else: + raise ValueError(f"not supported for GPIO (EXIO) {self._pin._id}") # NOQA + + return round(lcd_utils.remap(float(value), 0.0, float(old_max), new_min, new_max), 4) + + def read(self): + if self._pin._id == EXIO0: # NOQA + byte_h = self._device.read(_GPIO0_VLTS_H) + byte_l = self._device.read(_GPIO0_VLTS_L) + elif self._pin._id == EXIO1: # NOQA + byte_h = self._device.read(_GPIO1_VLTS_H) + byte_l = self._device.read(_GPIO1_VLTS_L) + elif self._pin._id == EXIO2: # NOQA + byte_h = self._device.read(_GPIO2_VLTS_H) + byte_l = self._device.read(_GPIO2_VLTS_L) + elif self._pin._id == EXIO3: # NOQA + byte_h = self._device.read(_GPIO3_VLTS_H) + byte_l = self._device.read(_GPIO3_VLTS_L) + else: + raise ValueError(f"not supported for GPIO (EXIO) {self._pin._id}") # NOQA + + value = (byte_h << 4) + byte_l + + if self._width == self.WIDTH_9BIT: + value = lcd_utils.remap(value, 0x0000, 0x0FFF, 0x0000, 0x01FF) + elif self._width == self.WIDTH_10BIT: + value = lcd_utils.remap(value, 0x0000, 0x0FFF, 0x0000, 0x03FF) + elif self._width == self.WIDTH_11BIT: + value = lcd_utils.remap(value, 0x0000, 0x0FFF, 0x0000, 0x07FF) + elif self._width == self.WIDTH_12BIT: + # device default + pass + elif self._width == self.WIDTH_13BIT: + value = lcd_utils.remap(value, 0x0000, 0x0FFF, 0x0000, 0x1FFF) + else: + raise ValueError(f"not supported for GPIO (EXIO) {self._pin._id}") # NOQA + + return value + + +class PWM(io_expander_framework.PWM): + + def __init__(self, pin: Pin, freq=-1, duty=-1): + + self._device = pin._device # NOQA + + super().__init__(pin=pin, freq=freq, duty=duty) + + if pin._id == EXIO1: # NOQA + self._device.write((self._device.read(_GPIO1_CTRL) & 0xF8) | 0x02) + elif pin._id == EXIO2: # NOQA + self._device.write((self._device.read(_GPIO2_CTRL) & 0xF8) | 0x02) + else: + pin._pwm = None + raise ValueError(f"PWM is not supported for GPIO (EXIO) {self._pin._id}") # NOQA + + + def init(self, freq: int = -1, duty: int = -1): # NOQA + if duty != -1: + self.duty(duty) + + def deinit(self) -> None: + if self._pin._id == EXIO1: # NOQA + self._device.write((self._device.read(_GPIO1_CTRL) & 0xF8) | 0x06) + elif self._pin._id == EXIO2: # NOQA + self._device.write((self._device.read(_GPIO2_CTRL) & 0xF8) | 0x06) + else: + raise ValueError(f"not supported for GPIO (EXIO) {self._pin._id}") # NOQA + + super().deinit() + + def __del__(self): + self.deinit() + + def freq(self, freq: int = -1): + raise NotImplementedError(f"not supported for GPIO (EXIO) {self._pin._id}") # NOQA + + def duty(self, duty: int = -1): + if duty == -1: + if self._pin._id == EXIO1: # NOQA + value = self._device.read(_PMW1_DUTY_Y2) + elif self._pin._id == EXIO2: # NOQA + value = self._device.read(_PMW2_DUTY_Y2) + else: + raise ValueError(f"not supported for GPIO (EXIO) {self._pin._id}") # NOQA + + return value + else: + duty = min(255, max(0, duty)) + + if self._pin._id == EXIO1: # NOQA + self._device.write(_PMW1_DUTY_Y1, 0xFF) + self._device.write(_PMW1_DUTY_Y2, duty) + self._device.write((self._device.read(_GPIO1_CTRL) & 0xF8) | 0x02) + elif self._pin._id == EXIO2: # NOQA + self._device.write(_PMW2_DUTY_Y1, 0xFF) + self._device.write(_PMW2_DUTY_Y2, duty) + self._device.write((self._device.read(_GPIO2_CTRL) & 0xF8) | 0x02) + else: + raise ValueError(f"not supported for GPIO (EXIO) {self._pin._id}") # NOQA + + +class AXP192: + + def _write(self, reg, value): + pass + + def _read(self, reg): + return 0x00 + + @property + def is_acin_present(self): + value = self._read(_STATUS) + return bool(value & 0x80) + + @property + def is_acin_available(self): + value = self._read(_STATUS) + return bool(value & 0x40) + + @property + def is_vbus_present(self): + value = self._read(_STATUS) + return bool(value & 0x20) + + @property + def is_vbus_available(self): + value = self._read(_STATUS) + return bool(value & 0x10) + + @property + def is_vbus_greater_vhold(self): + value = self._read(_STATUS) + return bool(value & 0x08) + + @property + def is_charging(self): + value = self._read(_STATUS) + return bool(value & 0x04) + + @property + def is_acin_and_vbus_shorted(self): + value = self._read(_STATUS) + return bool(value & 0x02) + + @property + def is_boost_source_acin_vbus(self): + value = self._read(_STATUS) + return bool(value & 0x01) + + @property + def is_ic_overheated(self): + value = self._read(_MODE_CHGSTATUS) + return bool(value & 0x80) + + @property + def is_commanded_charging(self): + value = self._read(_MODE_CHGSTATUS) + return bool(value & 0x40) + + @property + def is_battery_connected(self): + value = self._read(_MODE_CHGSTATUS) + return bool(value & 0x20) + + @property + def is_battery_activation_mode(self): + value = self._read(_MODE_CHGSTATUS) + return bool(value & 0x08) + + @property + def is_charging_current_low(self): + value = self._read(_MODE_CHGSTATUS) + return bool(value & 0x04) + + @property + def power_mode(self): + """ + POWER_MODE_A + POWER_MODE_B + """ + value = self._read(_MODE_CHGSTATUS) + return value & 0x02 + + @property + def is_vbus_valid(self): + value = self._read(_OTG_STATUS) + return bool(value & 0x04) + + @property + def is_vbus_session_valid(self): + value = self._read(_OTG_STATUS) + return bool(value & 0x02) + + @property + def is_vbus_session_end(self): + value = self._read(_OTG_STATUS) + return bool(value & 0x01) + + @property + def extern_switch_state(self): + value = self._read(_SWITCH_CTRL_1) + return not bool(value & 0x04) + + @extern_switch_state.setter + def extern_switch_state(self, state): + value = self._read(_SWITCH_CTRL_1) & ~0x04 + state = int(not state) << 1 + value |= state + self._write(_SWITCH_CTRL_1, value) + + @property + def dc_dc2_switch_state(self): + value = self._read(_SWITCH_CTRL_1) + return not bool(value & 0x01) + + @dc_dc2_switch_state.setter + def dc_dc2_switch_state(self, state): + value = self._read(_SWITCH_CTRL_1) & ~0x01 + value |= int(not state) + self._write(_SWITCH_CTRL_1, value) + + @property + def extern_switch_control(self): + value = self._read(_SWITCH_CTRL_2) + return not bool(value & 0x40) + + @extern_switch_control.setter + def extern_switch_control(self, state): + value = self._read(_SWITCH_CTRL_2) & ~0x40 + state = int(not state) << 6 + value |= state + self._write(_SWITCH_CTRL_2, value) + + @property + def dc_dc2_switch_control(self): + value = self._read(_SWITCH_CTRL_2) + return not bool(value & 0x10) + + @dc_dc2_switch_control.setter + def dc_dc2_switch_control(self, state): + value = self._read(_SWITCH_CTRL_2) & ~0x10 + value |= int(not state) << 4 + self._write(_SWITCH_CTRL_2, value) + + @property + def ldo3_switch_control(self): + value = self._read(_SWITCH_CTRL_2) + return not bool(value & 0x08) + + @ldo3_switch_control.setter + def ldo3_switch_control(self, state): + value = self._read(_SWITCH_CTRL_2) & ~0x08 + value |= int(not state) << 3 + self._write(_SWITCH_CTRL_2, value) + + @property + def ldo2_switch_control(self): + value = self._read(_SWITCH_CTRL_2) + return not bool(value & 0x04) + + @ldo2_switch_control.setter + def ldo2_switch_control(self, state): + value = self._read(_SWITCH_CTRL_2) & ~0x04 + value |= int(not state) << 2 + self._write(_SWITCH_CTRL_2, value) + + @property + def dc_dc3_switch_control(self): + value = self._read(_SWITCH_CTRL_2) + return not bool(value & 0x02) + + @dc_dc3_switch_control.setter + def dc_dc3_switch_control(self, state): + value = self._read(_SWITCH_CTRL_2) & ~0x02 + value |= int(not state) << 1 + self._write(_SWITCH_CTRL_2, value) + + @property + def dc_dc1_switch_control(self): + value = self._read(_SWITCH_CTRL_2) + return not bool(value & 0x02) + + @dc_dc1_switch_control.setter + def dc_dc1_switch_control(self, state): + value = self._read(_SWITCH_CTRL_2) & ~0x01 + value |= int(not state) + self._write(_SWITCH_CTRL_2, value) + + @property + def dc_dc2_volts(self): + """ + 0.7 - 2.275 in 0.25 increments + """ + value = self._read(_DC2_VLT_SETTING) & 0x1F + volts = lcd_utils.remap(float(value), 0.0, 31.0, 0.7, 2.275) + return round(volts, 3) + + @dc_dc2_volts.setter + def dc_dc2_volts(self, volts): + """ + 0.7 - 2.275 in 0.25 increments + """ + volts = min(2.275, (max(0.7, float(volts)))) + volts = lcd_utils.remap(float(volts), 0.7, 2.275, 0.0, 31.0) + volts = int(volts) + value = self._read(_DC2_VLT_SETTING) & 0xE0 + value |= volts + self._write(_DC2_VLT_SETTING, value) + + @property + def dc_dc1_volts(self): + """ + 0.7 - 3.5 in 0.25 increments + """ + value = self._read(_DC1_VLT_SETTING) & 0x3F + volts = lcd_utils.remap(float(value), 0.0, 63.0, 0.7, 3.5) + return round(volts, 2) + + @dc_dc1_volts.setter + def dc_dc1_volts(self, volts): + """ + 0.7 - 3.5 in 0.25 increments + """ + volts = min(3.5, (max(0.7, float(volts)))) + volts = lcd_utils.remap(float(volts), 0.7, 3.5, 0.0, 63.0) + volts = int(volts) + value = self._read(_DC1_VLT_SETTING) & 0xC0 + value |= volts + self._write(_DC1_VLT_SETTING, value) + + @property + def dc_dc3_volts(self): + """ + 0.7 - 3.5 in 0.25 increments + """ + value = self._read(_DC3_VLT_SETTING) & 0x3F + volts = lcd_utils.remap(float(value), 0.0, 63.0, 0.7, 3.5) + return round(volts, 2) + + @dc_dc3_volts.setter + def dc_dc3_volts(self, volts): + """ + 0.7 - 3.5 in 0.25 increments + """ + volts = min(3.5, (max(0.7, float(volts)))) + volts = lcd_utils.remap(float(volts), 0.7, 3.5, 0.0, 63.0) + volts = int(volts) + value = self._read(_DC3_VLT_SETTING) & 0xC0 + value |= volts + self._write(_DC3_VLT_SETTING, value) + + @property + def ldo2_volts(self): + """ + 1.8 - 3.3 in 0.1 increments + """ + value = self._read(_LDO_VLT_SETTING_1) >> 4 + volts = lcd_utils.remap(float(value), 0.0, 15.0, 1.8, 3.3) + return round(volts, 2) + + @ldo2_volts.setter + def ldo2_volts(self, volts): + """ + 1.8 - 3.3 in 0.1 increments + """ + volts = min(3.3, (max(1.8, float(volts)))) + volts = lcd_utils.remap(float(volts), 1.8, 3.3, 0.0, 15.0) + volts = int(volts) << 4 + value = self._read(_LDO_VLT_SETTING_1) & 0x0F + value |= volts + self._write(_LDO_VLT_SETTING_1, value) + + @property + def ldo3_volts(self): + """ + 1.8 - 3.3 in 0.1 increments + """ + value = self._read(_LDO_VLT_SETTING_1) & 0x0F + volts = lcd_utils.remap(float(value), 0.0, 15.0, 1.8, 3.3) + return round(volts, 2) + + @ldo3_volts.setter + def ldo3_volts(self, volts): + """ + 1.8 - 3.3 in 0.1 increments + """ + volts = min(3.3, (max(1.8, float(volts)))) + volts = lcd_utils.remap(float(volts), 1.8, 3.3, 0.0, 15.0) + volts = int(volts) + value = self._read(_LDO_VLT_SETTING_1) & 0xF0 + value |= volts + self._write(_LDO_VLT_SETTING_1, value) + + @property + def vbus_vhold_limit_control(self): + """ + VHOLD_LIMIT_NO_PRESSURE + VHOLD_LIMIT_PRESSURE + """ + value = self._read(_VBUS_IPS_SETTING) & 0x40 + return bool(value) + + @vbus_vhold_limit_control.setter + def vbus_vhold_limit_control(self, en): + """ + VHOLD_LIMIT_NO_PRESSURE + VHOLD_LIMIT_PRESSURE + """ + value = self._read(_VBUS_IPS_SETTING) & ~0x40 + value |= int(bool(en)) << 6 + self._write(_VBUS_IPS_SETTING, value) + + @property + def vbus_vhold_volts(self): + """ + 4.0 to 4.7 in 0.1 increments + """ + value = self._read(_VBUS_IPS_SETTING) & 0x38 + value >>= 3 + + volts = lcd_utils.remap(float(value), 0.0, 7.0, 4.0, 4.7) + return round(volts, 1) + + @vbus_vhold_volts.setter + def vbus_vhold_volts(self, volts): + """ + 4.0 to 4.7 in 0.1 increments + """ + value = self._read(_VBUS_IPS_SETTING) + value &= ~0x38 + volts = min(4.7, max(4.0, float(volts))) + volts = lcd_utils.remap(volts, 4.0, 4.7, 0.0, 7.0) + volts = int(volts) << 3 + value |= volts + self._write(_VBUS_IPS_SETTING, value) + + @property + def vbus_current_limit_enable(self): + value = self._read(_VBUS_IPS_SETTING) & 0x02 + return bool(value) + + @vbus_current_limit_enable.setter + def vbus_current_limit_enable(self, en): + value = self._read(_VBUS_IPS_SETTING) & ~0x02 + value |= int(bool(en)) << 1 + self._write(_VBUS_IPS_SETTING, value) + + @property + def vbus_current_limit(self): + """ + VBUS_CUR_LIMIT_500MA + VBUS_CUR_LIMIT_100MA + """ + value = self._read(_VBUS_IPS_SETTING) & 0x01 + return value + + @vbus_current_limit.setter + def vbus_current_limit(self, limit): + """ + VBUS_CUR_LIMIT_500MA + VBUS_CUR_LIMIT_100MA + """ + value = self._read(_VBUS_IPS_SETTING) & ~0x01 + value |= limit & 0x01 + self._write(_VBUS_IPS_SETTING, value) + + @property + def voff_volts(self): + """ + 2.6 - 3.3 in 0.1 increments + """ + value = self._read(_VOFF_SETTING) & 0x07 + volts = lcd_utils.remap(float(value), 0.0, 7.0, 2.6, 3.3) + return round(volts, 1) + + @voff_volts.setter + def voff_volts(self, volts): + """ + 2.6 - 3.3 in 0.1 increments + """ + value = self._read(_VOFF_SETTING) + value &= ~0x07 + volts = max(2.6, min(3.3, float(volts))) + volts = lcd_utils.remap(volts, 2.6, 3.3, 0.0, 7.0) + value |= int(volts) + self._write(_VOFF_SETTING, value) + + @property + def wake_up_short_press_enable(self): + value = self._read(_VOFF_SETTING) & 0x08 + return bool(value) + + @wake_up_short_press_enable.setter + def wake_up_short_press_enable(self, en): + value = self._read(_VOFF_SETTING) + value &= ~0x08 + value |= int(bool(en)) << 3 + self._write(_VOFF_SETTING, value) + + @property + def battery_monitoring_enable(self): + value = self._read(_SETTINGS_1) & 0x40 + return bool(value) + + @battery_monitoring_enable.setter + def battery_monitoring_enable(self, en): + value = self._read(_SETTINGS_1) + value &= ~0x40 + value |= int(bool(en)) << 6 + self._write(_SETTINGS_1, value) + + @property + def chrg_led_pin_output(self): + """ + CHRG_LED_HIGH_IMP + CHRG_LED_1HZ + CHRG_LED_4HZ + CHRG_LED_LOW + """ + value = self._read(_SETTINGS_1) & 0x30 + return value >> 4 + + @chrg_led_pin_output.setter + def chrg_led_pin_output(self, setting): + """ + CHRG_LED_HIGH_IMP + CHRG_LED_1HZ + CHRG_LED_4HZ + CHRG_LED_LOW + """ + value = self._read(_SETTINGS_1) + value &= ~0x30 + value |= setting << 4 + self._write(_SETTINGS_1, value) + + @property + def chrg_led_reg_ctrl_enable(self): + value = self._read(_SETTINGS_1) & 0x08 + return bool(value) + + @chrg_led_reg_ctrl_enable.setter + def chrg_led_reg_ctrl_enable(self, setting): + value = self._read(_SETTINGS_1) + value &= ~0x08 + value |= int(bool(setting)) << 3 + self._write(_SETTINGS_1, value) + + @property + def n_oe_shutdown_delay(self): + """ + TIME_0_500S + TIME_1_000S + TIME_2_000S + TIME_3_000S + """ + mapping = { + 0x00: TIME_0_500S, + 0x01: TIME_1_000S, + 0x02: TIME_2_000S, + 0x03: TIME_3_000S + } + + value = self._read(_SETTINGS_1) & 0x03 + return mapping.get(value) + + @n_oe_shutdown_delay.setter + def n_oe_shutdown_delay(self, delay): + """ + TIME_0_500S + TIME_1_000S + TIME_2_000S + TIME_3_000S + """ + value = self._read(_SETTINGS_1) + value &= ~0x03 + + mapping = { + TIME_0_500S: 0x00, + TIME_1_000S: 0x01, + TIME_2_000S: 0x02, + TIME_3_000S: 0x03 + } + + delay = mapping.get(delay, None) + if delay is None: + raise ValueError + + value |= delay + self._write(_SETTINGS_1, value) + + @property + def charging_enable(self): + value = self._read(_CHARGE_CTRL_1) & 0x80 + return bool(value) + + @charging_enable.setter + def charging_enable(self, setting): + value = self._read(_CHARGE_CTRL_1) + value &= ~0x80 + value |= int(bool(setting)) << 7 + self._write(_CHARGE_CTRL_1, value) + + @property + def charging_target_vlts(self): + """ + CHARGE_4_1V + CHARGE_4_15V + CHARGE_4_2V + CHARGE_4_36V + """ + value = self._read(_CHARGE_CTRL_1) & 0x60 + return value >> 5 + + @charging_target_vlts.setter + def charging_target_vlts(self, volts): + """ + CHARGE_4_1V + CHARGE_4_15V + CHARGE_4_2V + CHARGE_4_36V + """ + value = self._read(_CHARGE_CTRL_1) + value &= ~0x60 + value |= volts << 5 + self._write(_CHARGE_CTRL_1, value) + + @property + def charging_current(self): + """ + 100 - 1320 + """ + value = self._read(_CHARGE_CTRL_1) & 0x0F + + mapping = { + 0: 100, 1: 190, 2: 280, 3: 360, 4: 450, 5: 550, + 6: 630, 7: 700, 8: 780, 9: 880, 10: 960, 11: 1000, + 12: 1080, 13: 1160, 14: 1240, 15: 1320 + } + return mapping.get(value) + + @charging_current.setter + def charging_current(self, curr): + """ + 100 - 1320 + """ + value = self._read(_CHARGE_CTRL_1) + value &= ~0x0F + + curr = max(100, min(1320, curr)) + curr = int((((curr - 100) * 15) / (1320 - 100))) + value |= curr + self._write(_CHARGE_CTRL_1, value) + + @property + def precharge_timeout(self): + """ + TIME_0_500H + TIME_0_666H + TIME_0_833H + TIME_1_000H + """ + + mapping = { + 0x00: TIME_0_500H, + 0x01: TIME_0_666H, + 0x02: TIME_0_833H, + 0x03: TIME_1_000H + } + + value = self._read(_CHARGE_CTRL_2) & 0xC0 + return mapping.get(value >> 6) + + @precharge_timeout.setter + def precharge_timeout(self, timeout): + """ + TIME_0_500H + TIME_0_666H + TIME_0_833H + TIME_1_000H + """ + + mapping = { + TIME_0_500H: 0x00, + TIME_0_666H: 0x01, + TIME_0_833H: 0x02, + TIME_1_000H: 0x03 + } + value = self._read(_CHARGE_CTRL_2) + value &= ~0xC0 + value |= mapping.get(timeout) << 6 + self._write(_CHARGE_CTRL_2, value) + + @property + def extn_path_chrg_current(self): + """ + 300 - 1000 in 100 increments + """ + value = self._read(_CHARGE_CTRL_2) & 0x07 + mapping = { + 0: 300, + 1: 400, + 2: 500, + 3: 600, + 4: 700, + 5: 800, + 6: 900, + 7: 1000 + } + return mapping.get(value >> 3) + + @extn_path_chrg_current.setter + def extn_path_chrg_current(self, curr): + """ + 300 - 1000 in 100 increments + """ + value = self._read(_CHARGE_CTRL_2) + value &= ~0x07 + curr = max(300, min(1000, curr)) + curr = int((((curr - 300) * 7) / (1000 - 300))) + value |= curr << 3 + self._write(_CHARGE_CTRL_2, value) + + @property + def extn_path_chrg_enable(self): + value = self._read(_CHARGE_CTRL_2) & 0x04 + return bool(value) + + @extn_path_chrg_enable.setter + def extn_path_chrg_enable(self, en): + value = self._read(_CHARGE_CTRL_2) + value &= ~0x04 + value |= int(bool(en)) << 2 + self._write(_CHARGE_CTRL_2, value) + + @property + def const_current_timeout(self): + """ + TIME_7_000H + TIME_8_000H + TIME_9_000H + TIME_10_000H + """ + + mapping = { + 0x00: TIME_7_000H, + 0x01: TIME_8_000H, + 0x02: TIME_9_000H, + 0x03: TIME_10_000H + } + + value = self._read(_CHARGE_CTRL_2) & 0x03 + return mapping.get(value) + + @const_current_timeout.setter + def const_current_timeout(self, timeout): + """ + TIME_7_000H + TIME_8_000H + TIME_9_000H + TIME_10_000H + """ + + mapping = { + TIME_7_000H: 0x00, + TIME_8_000H: 0x01, + TIME_9_000H: 0x02, + TIME_10_000H: 0x03 + } + + value = self._read(_CHARGE_CTRL_2) + value &= ~0x03 + value |= mapping.get(timeout) + self._write(_CHARGE_CTRL_2, value) + + @property + def backup_batt_chrg_enable(self): + value = self._read(_CHARGE_CTRL_3) & 0x80 + return bool(value) + + @backup_batt_chrg_enable.setter + def backup_batt_chrg_enable(self, en): + value = self._read(_CHARGE_CTRL_3) + value &= ~0x80 + value |= int(bool(en)) << 7 + self._write(_CHARGE_CTRL_3, value) + + @property + def backup_batt_chrg_target_vlts(self): + """ + BACKUP_CHRG_3_1V + BACKUP_CHRG_3_0V + BACKUP_CHRG_2_5V + """ + value = self._read(_CHARGE_CTRL_3) & 0x60 + return value >> 5 + + @backup_batt_chrg_target_vlts.setter + def backup_batt_chrg_target_vlts(self, setting): + """ + BACKUP_CHRG_3_1V + BACKUP_CHRG_3_0V + BACKUP_CHRG_2_5V + """ + value = self._read(_CHARGE_CTRL_3) + value &= ~0x60 + value |= setting << 5 + self._write(_CHARGE_CTRL_3, value) + + @property + def backup_batt_chrg_current(self): + """ + 50 - 400 + """ + value = self._read(_CHARGE_CTRL_3) & 0x03 + mapping = {0: 50, 1: 100, 2: 200, 3: 400} + return mapping.get(value) + + @backup_batt_chrg_current.setter + def backup_batt_chrg_current(self, curr): + """ + 50 - 400 + """ + value = self._read(_CHARGE_CTRL_3) + value &= ~0x03 + curr = max(50, min(400, curr)) + value |= int((((curr - 50) * 3) / (400 - 50))) + self._write(_CHARGE_CTRL_3, value) + + @property + def bat_vltg_adc_enable(self): + value = self._read(_ADC_EN_1) & 0x80 + return bool(value) + + @bat_vltg_adc_enable.setter + def bat_vltg_adc_enable(self, en): + value = self._read(_ADC_EN_1) + value &= ~0x80 + value |= int(bool(en)) << 7 + self._write(_ADC_EN_1, value) + + @property + def bat_curr_adc_enable(self): + value = self._read(_ADC_EN_1) & 0x40 + return bool(value) + + @bat_curr_adc_enable.setter + def bat_curr_adc_enable(self, en): + value = self._read(_ADC_EN_1) + value &= ~0x40 + value |= int(bool(en)) << 6 + self._write(_ADC_EN_1, value) + + @property + def acin_vltg_adc_enable(self): + value = self._read(_ADC_EN_1) & 0x20 + return bool(value) + + @acin_vltg_adc_enable.setter + def acin_vltg_adc_enable(self, en): + value = self._read(_ADC_EN_1) + value &= ~0x20 + value |= int(bool(en)) << 5 + self._write(_ADC_EN_1, value) + + @property + def acin_curr_adc_enable(self): + value = self._read(_ADC_EN_1) & 0x10 + return bool(value) + + @acin_curr_adc_enable.setter + def acin_curr_adc_enable(self, en): + value = self._read(_ADC_EN_1) + value &= ~0x10 + value |= int(bool(en)) << 4 + self._write(_ADC_EN_1, value) + + @property + def vbus_vltg_adc_enable(self): + value = self._read(_ADC_EN_1) & 0x08 + return bool(value) + + @vbus_vltg_adc_enable.setter + def vbus_vltg_adc_enable(self, en): + value = self._read(_ADC_EN_1) + value &= ~0x08 + value |= int(bool(en)) << 3 + self._write(_ADC_EN_1, value) + + @property + def vbus_curr_adc_enable(self): + value = self._read(_ADC_EN_1) & 0x04 + return bool(value) + + @vbus_curr_adc_enable.setter + def vbus_curr_adc_enable(self, en): + value = self._read(_ADC_EN_1) + value &= ~0x04 + value |= int(bool(en)) << 2 + self._write(_ADC_EN_1, value) + + @property + def aps_vltg_adc_enable(self): + value = self._read(_ADC_EN_1) & 0x02 + return bool(value) + + @aps_vltg_adc_enable.setter + def aps_vltg_adc_enable(self, en): + value = self._read(_ADC_EN_1) + value &= ~0x02 + value |= int(bool(en)) << 1 + self._write(_ADC_EN_1, value) + + @property + def ts_pin_vltg_adc_enable(self): + value = self._read(_ADC_EN_1) & 0x01 + return bool(value) + + @ts_pin_vltg_adc_enable.setter + def ts_pin_vltg_adc_enable(self, en): + value = self._read(_ADC_EN_1) + value &= ~0x01 + value |= int(bool(en)) + self._write(_ADC_EN_1, value) + + @property + def temp_adc_enable(self): + value = self._read(_ADC_EN_2) & 0x80 + return bool(value) + + @temp_adc_enable.setter + def temp_adc_enable(self, en): + value = self._read(_ADC_EN_2) + value &= ~0x80 + value |= int(bool(en)) << 7 + self._write(_ADC_EN_2, value) + + @property + def vbus_effective_vlts(self): + """ + VBUS_VLTG_4_00 + VBUS_VLTG_4_15 + VBUS_VLTG_4_45 + VBUS_VLTG_4_55 + """ + value = self._read(_VBUS_MONITOR) & 0x30 + return value >> 4 + + @vbus_effective_vlts.setter + def vbus_effective_vlts(self, setting): + """ + VBUS_VLTG_4_00 + VBUS_VLTG_4_15 + VBUS_VLTG_4_45 + VBUS_VLTG_4_55 + """ + value = self._read(_VBUS_MONITOR) + value &= ~0x30 + value |= setting << 4 + self._write(_VBUS_MONITOR, value) + + @property + def vbus_valid_detection_enable(self): + value = self._read(_VBUS_MONITOR) & 0x08 + return bool(value) + + @vbus_valid_detection_enable.setter + def vbus_valid_detection_enable(self, en): + value = self._read(_VBUS_MONITOR) + value &= ~0x08 + value |= int(bool(en)) << 3 + self._write(_VBUS_MONITOR, value) + + @property + def vbus_session_detection_enable(self): + value = self._read(_VBUS_MONITOR) & 0x04 + return bool(value) + + @vbus_session_detection_enable.setter + def vbus_session_detection_enable(self, en): + value = self._read(_VBUS_MONITOR) + value &= ~0x04 + value |= int(bool(en)) << 2 + self._write(_VBUS_MONITOR, value) + + @property + def vbus_dchrg_resistor_enable(self): + value = self._read(_VBUS_MONITOR) & 0x02 + return bool(value) + + @vbus_dchrg_resistor_enable.setter + def vbus_dchrg_resistor_enable(self, en): + value = self._read(_VBUS_MONITOR) + value &= ~0x02 + value |= int(bool(en)) << 1 + self._write(_VBUS_MONITOR, value) + + @property + def vbus_chrg_resistor_enable(self): + value = self._read(_VBUS_MONITOR) & 0x01 + return bool(value) + + @vbus_chrg_resistor_enable.setter + def vbus_chrg_resistor_enable(self, en): + value = self._read(_VBUS_MONITOR) + value &= ~0x01 + value |= int(bool(en)) + self._write(_VBUS_MONITOR, value) + + @property + def temp_over_shutdown_enable(self): + value = self._read(_OVER_TEMP_SHUT_CTRL) & 0x04 + return bool(value) + + @temp_over_shutdown_enable.setter + def temp_over_shutdown_enable(self, en): + value = self._read(_OVER_TEMP_SHUT_CTRL) + value &= ~0x04 + value |= int(bool(en)) << 2 + self._write(_OVER_TEMP_SHUT_CTRL, value) diff --git a/api_drivers/common_api_drivers/io_expander/ch422g.py b/api_drivers/common_api_drivers/io_expander/ch422g.py new file mode 100644 index 00000000..1c65cd34 --- /dev/null +++ b/api_drivers/common_api_drivers/io_expander/ch422g.py @@ -0,0 +1,122 @@ +from micropython import const # NOQA +import io_expander_framework +import i2c + + +EXIO1 = 0x01 +EXIO2 = 0x02 +EXIO3 = 0x03 +EXIO4 = 0x04 +EXIO5 = 0x05 +EXIO6 = 0x06 +EXIO7 = 0x07 +EXIO8 = 0x08 + + +I2C_ADDR = 0x24 # 36 00100100 +BITS = 8 + +_CH422G_REG_IN = const(0x26) # 38 00100110 +_CH422G_REG_OUT = const(0x38) # 56 00111000 + +_REG_INPUT = const(0) +_REG_OUTPUT = const(1) +_REG_DIRECTION = const(2) + + +class Pin(io_expander_framework.Pin): + _output_states = 0x00 + _i2c_bus: i2c.I2C.Bus = None + _reg_in: i2c.I2C.Device = None + _reg_out: i2c.I2C.Device = None + _reg_int_pins = [] + + @classmethod + def set_device(cls, device): + if cls._device is not None: + raise ValueError('device has already been set') + + cls._device = device + + cls._reg_in = i2c.I2C.Device( + bus=device._bus, # NOQA + dev_id=_CH422G_REG_IN + ) + cls._reg_out = i2c.I2C.Device( + bus=device._bus, # NOQA + dev_id=_CH422G_REG_OUT + ) + + @property + def __bit(self): + return 1 << self._id + + @property + def _mode(self): + return 1 + + @_mode.setter + def _mode(self, value): + pass + + def _write_reg(self, reg, value): + if reg == _REG_OUTPUT: + value &= 0xFF + + self._buf[0] = 0x01 + Pin._device.write(self._mv[:1]) + + self._buf[0] = value + # _i2c_device.write_mem(_CH422G_REG_OUT, self._mv[:1]) + Pin._reg_out.write(self._mv[:1]) + self._output = value + + elif reg == _REG_DIRECTION: + value &= 0xFF + self._mode = value + + def _read_reg(self, reg): + if reg == _REG_INPUT: + # _i2c_device.read_mem(_CH422G_REG_IN, buf=self._mv[:1]) + Pin._reg_in.read(buf=self._mv[:1]) + return self._buf[0] + elif reg == _REG_OUTPUT: + return self._output + elif reg == _REG_DIRECTION: + return self._mode + + def _set_dir(self, direction): + if direction == self.OPEN_DRAIN: + raise ValueError('OPEN_DRAIN is not supported') + + def _set_level(self, level): + if self._mode == self.OUT: + if level: + # 3. High level && Set 0 to output high + # 4. Low level && Set 0 to output low + states = Pin._output_states & ~self.__bit + else: + # 1. High level && Set 1 to output high + # 2. Low level && Set 1 to output low + states = Pin._output_states | self.__bit + + # Write to reg only when different */ + if states != Pin._output_states: + self._write_reg(_REG_OUTPUT, states) + Pin._output_states = states + + def _get_level(self): + if self._mode == self.IN: + states = ~self._read_reg(_REG_INPUT) + elif self._mode == self.OUT: + states = Pin._output_states + else: + raise ValueError('Unsupported pin mode') + + return int(bool(states & self.__bit)) + + def _set_irq(self, handler, trigger): + pass + + def _set_pull(self, pull): + pass diff --git a/api_drivers/common_api_drivers/io_expander/ht8574.py b/api_drivers/common_api_drivers/io_expander/ht8574.py deleted file mode 100644 index 2a35cdba..00000000 --- a/api_drivers/common_api_drivers/io_expander/ht8574.py +++ /dev/null @@ -1,64 +0,0 @@ -import io_expander_framework - - -EXIO1 = 1 -EXIO2 = 2 -EXIO3 = 3 -EXIO4 = 4 -EXIO5 = 5 -EXIO6 = 6 -EXIO7 = 7 -EXIO8 = 8 - - -BITS = 8 - - -class Pin(io_expander_framework.Pin): - _output_states = 0xFF - - _device = None - - @classmethod - def set_device(cls, device): - if cls._device is not None: - raise ValueError('device has already been set') - - cls._device = device - - def __init__(self, id, mode=-1, value=None): # NOQA - if Pin._device is None: - raise RuntimeError('The expander device has not been set') - - super().__init__(id, mode, value) - - @property - def __bit(self): - return 1 << self._id - - def __read_reg(self): - self._buf[0] = 0 - self._device.read(buf=self._mv[:1]) - return self._buf[0] - - def __write_reg(self, value): - self._buf[0] = value & 0xFF - self._device.write(buf=self._mv[:1]) - - def _set_dir(self, direction): - pass - - def _set_level(self, level): - if level: - Pin._output_states |= self.__bit - else: - Pin._output_states &= ~self.__bit - - self.__write_reg(Pin._output_states) - - def _get_level(self): - if self._mode == self.IN: - states = self.__read_reg() - return (states >> self._id) & 0x1 - else: - return (Pin._output_states >> self._id) & 0x1 diff --git a/api_drivers/common_api_drivers/io_expander/ht8574a.py b/api_drivers/common_api_drivers/io_expander/ht8574a.py new file mode 100644 index 00000000..b52c4d0a --- /dev/null +++ b/api_drivers/common_api_drivers/io_expander/ht8574a.py @@ -0,0 +1,69 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + +import io_expander_framework +import machine + + +EXIO1 = 0x01 +EXIO2 = 0x02 +EXIO3 = 0x03 +EXIO4 = 0x04 +EXIO5 = 0x05 +EXIO6 = 0x06 +EXIO7 = 0x07 +EXIO8 = 0x08 + + +# 0x70, 0x72, 0x74, 0x76, 0x78, 0x7A, 0x7C, 0x7E +I2C_ADDR = 0x70 +BITS = 8 + + +class Pin(io_expander_framework.Pin): + _output_states = 0xFF + _reg_int_pins = [] + + @property + def __bit(self): + return 1 << self._id + + def __read_reg(self): + self._buf[0] = 0 + Pin._device.read(buf=self._mv[:1]) + return self._buf[0] + + def __write_reg(self, value): + self._buf[0] = value & 0xFF + Pin._device.write(buf=self._mv[:1]) + + def _set_dir(self, direction): + if direction == self.OPEN_DRAIN: + raise ValueError('OPEN_DRAIN is not supported') + + def _set_level(self, level): + if self._mode == self.OUT: + if level: + states = Pin._output_states | self.__bit + else: + states = Pin._output_states & ~self.__bit + + # 0nly set if there is an actual change + if states != Pin._output_states: + self.__write_reg(Pin._output_states) + Pin._output_states = states + + def _get_level(self): + if self._mode == self.IN: + states = self.__read_reg() + elif self.mode == self.OUT: + states = Pin._output_states + else: + raise ValueError('Unsupported pin mode') + + return int(bool(states & self.__bit)) + + def _set_irq(self, handler, trigger): + pass + + def _set_pull(self, pull): + pass diff --git a/api_drivers/common_api_drivers/io_expander/ht8574b.py b/api_drivers/common_api_drivers/io_expander/ht8574b.py new file mode 100644 index 00000000..64b3caf0 --- /dev/null +++ b/api_drivers/common_api_drivers/io_expander/ht8574b.py @@ -0,0 +1,68 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + +import io_expander_framework + + +EXIO1 = 0x01 +EXIO2 = 0x02 +EXIO3 = 0x03 +EXIO4 = 0x04 +EXIO5 = 0x05 +EXIO6 = 0x06 +EXIO7 = 0x07 +EXIO8 = 0x08 + + +# 0x40, 0x42, 0x44, 0x46, 0x48, 0x4A, 0x4C, 0x4E +I2C_ADDR = 0x40 +BITS = 8 + + +class Pin(io_expander_framework.Pin): + _output_states = 0xFF + _reg_int_pins = [] + + @property + def __bit(self): + return 1 << self._id + + def __read_reg(self): + self._buf[0] = 0 + Pin._device.read(buf=self._mv[:1]) + return self._buf[0] + + def __write_reg(self, value): + self._buf[0] = value & 0xFF + Pin._device.write(buf=self._mv[:1]) + + def _set_dir(self, direction): + if direction == self.OPEN_DRAIN: + raise ValueError('OPEN_DRAIN is not supported') + + def _set_level(self, level): + if self._mode == self.OUT: + if level: + states = Pin._output_states | self.__bit + else: + states = Pin._output_states & ~self.__bit + + # 0nly set if there is an actual change + if states != Pin._output_states: + self.__write_reg(Pin._output_states) + Pin._output_states = states + + def _get_level(self): + if self._mode == self.IN: + states = self.__read_reg() + elif self.mode == self.OUT: + states = Pin._output_states + else: + raise ValueError('Unsupported pin mode') + + return int(bool(states & self.__bit)) + + def _set_irq(self, handler, trigger): + pass + + def _set_pull(self, pull): + pass diff --git a/api_drivers/common_api_drivers/io_expander/tca9535.py b/api_drivers/common_api_drivers/io_expander/tca9535.py index 5db4c1d1..73580630 100644 --- a/api_drivers/common_api_drivers/io_expander/tca9535.py +++ b/api_drivers/common_api_drivers/io_expander/tca9535.py @@ -1,23 +1,25 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + from micropython import const # NOQA import io_expander_framework -EXIO1 = 1 -EXIO2 = 2 -EXIO3 = 3 -EXIO4 = 4 -EXIO5 = 5 -EXIO6 = 6 -EXIO7 = 7 -EXIO8 = 8 -EXIO9 = 9 -EXIO10 = 10 -EXIO11 = 11 -EXIO12 = 12 -EXIO13 = 13 -EXIO14 = 14 -EXIO15 = 15 -EXIO16 = 16 +EXIO1 = 0x01 +EXIO2 = 0x02 +EXIO3 = 0x03 +EXIO4 = 0x04 +EXIO5 = 0x05 +EXIO6 = 0x06 +EXIO7 = 0x07 +EXIO8 = 0x08 +EXIO9 = 0x09 +EXIO10 = 0x0A +EXIO11 = 0x0B +EXIO12 = 0x0C +EXIO13 = 0x0D +EXIO14 = 0x0E +EXIO15 = 0x0F +EXIO16 = 0x10 _INPUT_PORT_REG = const(0x00) _OUTPUT_PORT_REG = const(0x02) @@ -30,23 +32,9 @@ class Pin(io_expander_framework.Pin): - _config_reg = 0 - _output_reg = 0 - - _device = None - - @classmethod - def set_device(cls, device): - if cls._device is not None: - raise ValueError('device has already been set') - - cls._device = device - - def __init__(self, id, mode=-1, value=None): # NOQA - if Pin._device is None: - raise RuntimeError('The expander device has not been set') - - super().__init__(id, mode, value) + _config_settings = 0x00 + _output_states = 0x00 + _reg_int_pins = [] @property def __bit(self): @@ -55,34 +43,48 @@ def __bit(self): def __read_reg(self, reg): self._buf[0] = 0 self._buf[1] = 0 - self._device.read_mem(reg, buf=self._mv) + Pin._device.read_mem(reg, buf=self._mv) return self._buf[0] << 8 | self._buf[1] def __write_reg(self, reg, value): self._buf[0] = value >> 8 & 0xFF self._buf[1] = value & 0xFF - self._device.write_mem(reg, buf=self._mv) + Pin._device.write_mem(reg, buf=self._mv) def _set_dir(self, direction): - if direction: - Pin._config_reg &= ~self.__bit + if direction == self.OUT: + Pin._config_settings &= ~self.__bit + elif direction == self.IN: + Pin._config_settings |= self.__bit else: - Pin._config_reg |= self.__bit + raise ValueError('OPEN_DRAIN is not supported') - self.__write_reg(_CONFIGURATION_REG, Pin._config_reg) + self.__write_reg(_CONFIGURATION_REG, Pin._config_settings) def _set_level(self, level): - if level: - Pin._output_reg |= self.__bit - else: - Pin._output_reg &= ~self.__bit + if self._mode == self.OUT: + if level: + states = Pin._output_states | self.__bit + else: + states = Pin._output_states & ~self.__bit - self.__write_reg(_OUTPUT_PORT_REG, Pin._output_reg) + # 0nly set if there is an actual change + if states != Pin._output_states: + self.__write_reg(_OUTPUT_PORT_REG, Pin._output_states) + Pin._output_states = states def _get_level(self): - if self._mode == self.OUT: - Pin._output_reg = self.__read_reg(_OUTPUT_PORT_REG) - return (Pin._output_reg >> self._id) & 0x1 + if self._mode == self.IN: + states = self.__read_reg(_INPUT_PORT_REG) + elif self._mode == self.OUT: + states = Pin._output_states else: - val = self.__read_reg(_INPUT_PORT_REG) - return (val >> self._id) & 0x1 + raise ValueError('Unsupported pin mode') + + return int(bool(states & self.__bit)) + + def _set_irq(self, handler, trigger): + pass + + def _set_pull(self, pull): + pass diff --git a/api_drivers/common_api_drivers/io_expander/tca9554.py b/api_drivers/common_api_drivers/io_expander/tca9554.py index e7f04c34..8b2d6443 100644 --- a/api_drivers/common_api_drivers/io_expander/tca9554.py +++ b/api_drivers/common_api_drivers/io_expander/tca9554.py @@ -1,15 +1,17 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + from micropython import const # NOQA import io_expander_framework -EXIO1 = 1 -EXIO2 = 2 -EXIO3 = 3 -EXIO4 = 4 -EXIO5 = 5 -EXIO6 = 6 -EXIO7 = 7 -EXIO8 = 8 +EXIO1 = 0x01 +EXIO2 = 0x02 +EXIO3 = 0x03 +EXIO4 = 0x04 +EXIO5 = 0x05 +EXIO6 = 0x06 +EXIO7 = 0x07 +EXIO8 = 0x08 _INPUT_PORT_REG = const(0x00) @@ -17,33 +19,24 @@ _POLARITY_INVERSION_REG = const(0x04) _CONFIGURATION_REG = const(0x06) -# 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, or 0x27 I2C_ADDR = 0x20 BITS = 8 +# 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26 or 0x27 +I2C_TCA9554_ADDR = 0x20 -class Pin(io_expander_framework.Pin): - _config_reg = 0 - _output_reg = 0 - - _device = None - - @classmethod - def set_device(cls, device): - if cls._device is not None: - raise ValueError('device has already been set') - - cls._device = device +# 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E or 0x3F +I2C_TCA9554A_ADDR = 0x38 - def __init__(self, id, mode=-1, value=None): # NOQA - if Pin._device is None: - raise RuntimeError('The expander device has not been set') - super().__init__(id, mode, value) +class Pin(io_expander_framework.Pin): + _config_settings = 0x00 + _output_states = 0x00 + _reg_int_pins = [] @property def __bit(self): - return 1 << self._id + return 1 << (self._id - 1) def __read_reg(self, reg): self._buf[0] = 0 @@ -57,25 +50,39 @@ def __write_reg(self, reg, value): self._device.write_mem(reg, buf=self._mv) def _set_dir(self, direction): - if direction: - Pin._config_reg &= ~self.__bit + if direction == self.OUT: + Pin._config_settings &= ~self.__bit + elif direction == self.IN: + Pin._config_settings |= self.__bit else: - Pin._config_reg |= self.__bit + raise ValueError('OPEN_DRAIN is not supported') - self.__write_reg(_CONFIGURATION_REG, Pin._config_reg) + self.__write_reg(_CONFIGURATION_REG, Pin._config_settings) def _set_level(self, level): - if level: - Pin._output_reg |= self.__bit - else: - Pin._output_reg &= ~self.__bit + if self._mode == self.OUT: + if level: + states = Pin._output_states | self.__bit + else: + states = Pin._output_states & ~self.__bit - self.__write_reg(_OUTPUT_PORT_REG, Pin._output_reg) + # 0nly set if there is an actual change + if states != Pin._output_states: + self.__write_reg(_OUTPUT_PORT_REG, Pin._output_states) + Pin._output_states = states def _get_level(self): - if self._mode == self.OUT: - Pin._output_reg = self.__read_reg(_OUTPUT_PORT_REG) - return (Pin._output_reg >> self._id) & 0x1 + if self._mode == self.IN: + states = self.__read_reg(_INPUT_PORT_REG) + elif self._mode == self.OUT: + states = Pin._output_states else: - val = self.__read_reg(_INPUT_PORT_REG) - return (val >> self._id) & 0x1 + raise ValueError('Unsupported pin mode') + + return int(bool(states & self.__bit)) + + def _set_irq(self, handler, trigger): + pass + + def _set_pull(self, pull): + pass diff --git a/api_drivers/py_api_drivers/frozen/display/display_driver_framework.py b/api_drivers/py_api_drivers/frozen/display/display_driver_framework.py index 7afb98df..50be0921 100644 --- a/api_drivers/py_api_drivers/frozen/display/display_driver_framework.py +++ b/api_drivers/py_api_drivers/frozen/display/display_driver_framework.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import micropython # NOQA import time import gc diff --git a/api_drivers/py_api_drivers/frozen/display/rgb_display_framework.py b/api_drivers/py_api_drivers/frozen/display/rgb_display_framework.py index ce1edc77..e83482c0 100644 --- a/api_drivers/py_api_drivers/frozen/display/rgb_display_framework.py +++ b/api_drivers/py_api_drivers/frozen/display/rgb_display_framework.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import lvgl as lv import display_driver_framework diff --git a/api_drivers/py_api_drivers/frozen/indev/_indev_base.py b/api_drivers/py_api_drivers/frozen/indev/_indev_base.py index 968b8233..b9945f61 100644 --- a/api_drivers/py_api_drivers/frozen/indev/_indev_base.py +++ b/api_drivers/py_api_drivers/frozen/indev/_indev_base.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import lvgl as lv # NOQA import display_driver_framework diff --git a/api_drivers/py_api_drivers/frozen/indev/button_framework.py b/api_drivers/py_api_drivers/frozen/indev/button_framework.py index 06a0ef6b..7787ed04 100644 --- a/api_drivers/py_api_drivers/frozen/indev/button_framework.py +++ b/api_drivers/py_api_drivers/frozen/indev/button_framework.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import lvgl as lv # NOQA import _indev_base diff --git a/api_drivers/py_api_drivers/frozen/indev/encoder_framework.py b/api_drivers/py_api_drivers/frozen/indev/encoder_framework.py index 0a7db5a2..25ac0df8 100644 --- a/api_drivers/py_api_drivers/frozen/indev/encoder_framework.py +++ b/api_drivers/py_api_drivers/frozen/indev/encoder_framework.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import lvgl as lv # NOQA import _indev_base diff --git a/api_drivers/py_api_drivers/frozen/indev/keypad_framework.py b/api_drivers/py_api_drivers/frozen/indev/keypad_framework.py index 31fb7d2f..3b9b0d5b 100644 --- a/api_drivers/py_api_drivers/frozen/indev/keypad_framework.py +++ b/api_drivers/py_api_drivers/frozen/indev/keypad_framework.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import lvgl as lv # NOQA import _indev_base import display_driver_framework @@ -51,34 +53,13 @@ def _read(self, drv, data): # NOQA key = self._get_key() if key is None: # ignore no key - if self._current_state != lv.INDEV_STATE.RELEASED: # NOQA - self._current_state = lv.INDEV_STATE.RELEASED # NOQA - res = True - else: - res = False - - data.key = self._last_key - data.state = self._current_state - data.continue_reading = False - return res - - state, key = key - - self._last_key = key - - if self._current_state == state == lv.INDEV_STATE.RELEASED: # NOQA - res = False - data.continue_reading = False + state = self.RELEASED + key = self._last_key else: - res = True - data.continue_reading = True - - self._current_state = state - - data.key = self._last_key - data.state = self._current_state + state, key = key - return res + data.key = self._last_key = key + data.state = self._current_state = state def get_type(self): return self._indev_drv.get_type() # NOQA diff --git a/api_drivers/py_api_drivers/frozen/indev/pointer_framework.py b/api_drivers/py_api_drivers/frozen/indev/pointer_framework.py index e13a118d..079c8359 100644 --- a/api_drivers/py_api_drivers/frozen/indev/pointer_framework.py +++ b/api_drivers/py_api_drivers/frozen/indev/pointer_framework.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import lvgl as lv # NOQA import _indev_base import micropython # NOQA diff --git a/api_drivers/py_api_drivers/frozen/indev/touch_calibration/touch_cal_data.py b/api_drivers/py_api_drivers/frozen/indev/touch_calibration/touch_cal_data.py index b208c482..a5e3e814 100644 --- a/api_drivers/py_api_drivers/frozen/indev/touch_calibration/touch_cal_data.py +++ b/api_drivers/py_api_drivers/frozen/indev/touch_calibration/touch_cal_data.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import struct diff --git a/api_drivers/py_api_drivers/frozen/indev/touch_calibration/touch_calibrate.py b/api_drivers/py_api_drivers/frozen/indev/touch_calibration/touch_calibrate.py index 4a00a88b..dae7d53b 100644 --- a/api_drivers/py_api_drivers/frozen/indev/touch_calibration/touch_calibrate.py +++ b/api_drivers/py_api_drivers/frozen/indev/touch_calibration/touch_calibrate.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import lvgl as lv # NOQA import time diff --git a/api_drivers/py_api_drivers/frozen/io_expander/io_expander_framework.py b/api_drivers/py_api_drivers/frozen/io_expander/io_expander_framework.py index e9ce3a81..be585ad5 100644 --- a/api_drivers/py_api_drivers/frozen/io_expander/io_expander_framework.py +++ b/api_drivers/py_api_drivers/frozen/io_expander/io_expander_framework.py @@ -1,32 +1,134 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser +import machine +import lcd_utils + class Pin(object): IN = 0x00 OUT = 0x01 + OPEN_DRAIN = 0x02 + + IRQ_RISING = 0x01 + IRQ_FALLING = 0x02 + + PULL_UP = 0x01 + PULL_DOWN = 0x02 + + _int_pin = None + _reg_int_pins = [] + + _device = None + + @classmethod + def _int_cb(cls, _): + for ext_pin in cls._reg_int_pins: + ext_pin._interrupt_cb() # NOQA + + def _interrupt_cb(self): + if self._irq is None: + # sanity check + return + + value = self.value() + if value == self._irq_input_state: + return + + self._irq_input_state = value + + handler, trigger = self._irq + + if value and trigger & self.IRQ_RISING: + handler(self) + + elif not value and trigger & self.IRQ_FALLING: + handler(self) + + @classmethod + def set_int_pin(cls, pin_num, pull=-1): + if cls._int_pin is not None: + raise ValueError('Interrupt pin has already been set') + + try: + cls._int_cb(None) + except NotImplementedError: + raise NotImplementedError + except: # NOQA + pass + + if pull == -1: + int_pin = machine.Pin(pin_num, machine.Pin.IN) + else: + int_pin = machine.Pin(pin_num, machine.Pin.IN, pull=pull) + + int_pin.irq( + cls._int_cb, + machine.Pin.IRQ_FALLING + ) + cls._int_pin = int_pin + + @classmethod + def set_device(cls, device): + if cls._device is not None: + raise ValueError('device has already been set') + + cls._device = device + + def __init__(self, id, mode=-1, pull=-1, value=-1): # NOQA + if Pin._device is None: + raise RuntimeError('The expander device has not been set') - def __init__(self, id, mode=-1, value=None): # NOQA self._id = id self._mode = 0 self._buf = bytearray(2) self._mv = memoryview(self._buf) - self.init(mode, value) + self._adc = None + self._pwm = None + self._irq = None + self._irq_input_state = 0 + + self.init(mode, pull, value) - def init(self, mode=-1, value=None): + def init(self, mode=-1, pull=-1, value=-1): if mode != -1: self._set_dir(mode) self._mode = mode - if value is not None: + if pull is None or pull != -1: + self._set_pull(pull) + + if value != -1: self._set_level(value) - def value(self, x=None): - if x is not None: + def irq(self, handler, trigger=IRQ_RISING | IRQ_FALLING): + if self._mode == self.IN: + if self.__class__._int_pin is None: + raise ValueError( + 'You need to call Pin.set_int_pin(pin_num) ' + 'before setting the pins IRQ' + ) + + self._irq_input_state = self.value() + self._set_irq(handler, trigger=trigger) + + if handler is None: + self._irq = None + if self in self.__class__._reg_int_pins: + self.__class__._reg_int_pins.remove(self) + else: + if self not in self.__class__._reg_int_pins: + self.__class__._reg_int_pins.append(self) + + self._irq = (handler, trigger) + + def value(self, x=-1): + if x != -1: self._set_level(x) else: return self._get_level() - def __call__(self, x=None): - if x is not None: + def __call__(self, x=-1): + if x != -1: self._set_level(x) else: return self._get_level() @@ -43,12 +145,18 @@ def low(self): def high(self): self.value(1) - def mode(self, mode=None): - if mode is None: + def mode(self, mode=-1): + if mode == -1: return self._mode self.init(mode=mode) + def _set_irq(self, handler, trigger): + raise NotImplementedError + + def _set_pull(self, pull): + raise NotImplementedError + def _set_dir(self, direction): raise NotImplementedError @@ -57,3 +165,144 @@ def _set_level(self, level): def _get_level(self): raise NotImplementedError + + +class PWM: + def __init__(self, pin: Pin, freq: int = -1, duty=-1): + if pin._pwm is not None: # NOQA + raise RuntimeError('you can only start PWM a single time for a pin') + + if pin._adc is not None: # NOQA + raise RuntimeError('You cannot set a pin to be both PWM and ADC at the same time') + + if pin._irq is not None: # NOQA + raise RuntimeError('You cannot have a pin set to be an output and an input at the same time') + + self._pin = pin + self.init(freq, duty=duty) + pin._pwm = self + + def init(self, freq=-1, duty=-1): + raise NotImplementedError + + def deinit(self): + self._pin._pwm = None + + def freq(self, freq=-1): + raise NotImplementedError + + def duty(self, duty=-1): + raise NotImplementedError + + +class ADC: + # 511 + WIDTH_9BIT = 0 + # 1023 + WIDTH_10BIT = 1 + # 2047 + WIDTH_11BIT = 2 + # 4095 + WIDTH_12BIT = 3 + # 8191 + WIDTH_13BIT = 4 + + # 1.1V + ATTN_0DB = 0 + # 1.5V + ATTN_2_5DB = 1 + # 2.2V + ATTN_6DB = 2 + # 3.9V + ATTN_11DB = 3 + + _min_read = 0 + _max_read = 0 + + def __init__(self, pin: Pin, atten=-1): + if pin._adc is not None: # NOQA + raise RuntimeError('you can only start ADC a single time for a pin') + + if pin._pwm is not None: # NOQA + raise RuntimeError('You cannot set a pin to be both ADC and PWM at the same time') + + if pin._irq is not None: # NOQA + raise RuntimeError('You cannot have a pin set to be an output and an input at the same time') + + self._pin = pin + + self._width = 0 + self._atten = 0 + + self.init(atten=atten) + + pin._adc = self + + def init(self, atten=-1): + self._init(atten=atten) + self.atten(atten) + + def _init(self, atten): + raise NotImplementedError + + def deinit(self): + self._pin._adc = None + + def read_uv(self): + value = self.read() + + if self._width == self.WIDTH_9BIT: + old_max = 511.0 + elif self._width == self.WIDTH_10BIT: + old_max = 1023.0 + elif self._width == self.WIDTH_11BIT: + old_max = 2047.0 + elif self._width == self.WIDTH_12BIT: + old_max = 4095.0 + else: # self.WIDTH_13BIT + old_max = 8191.0 + + if self._atten == self.ATTN_0DB: + new_max = 1.1 + elif self._atten == self.ATTN_2_5DB: + new_max = 1.5 + elif self._atten == self.ATTN_6DB: + new_max = 2.2 + else: # self.ATTN_11DB + new_max = 3.9 + + value = lcd_utils.remap(value, 0.0, old_max, 0.0, new_max) + + return value + + def atten(self, atten=-1): + if atten == -1: + return self._atten + else: + self._atten = atten + + def width(self, width=-1): + if width != -1: + self._width = width + + def read(self): + value = self._read() + + if self._width == self.WIDTH_9BIT: + new_max = 511 + elif self._width == self.WIDTH_10BIT: + new_max = 1023 + elif self._width == self.WIDTH_11BIT: + new_max = 2047 + elif self._width == self.WIDTH_12BIT: + new_max = 4095 + else: # self.WIDTH_13BIT + new_max = 8191 + + value = lcd_utils.remap(value, self._min_read, + self._max_read, 0, new_max) + + return value + + def _read(self): + raise NotImplementedError diff --git a/api_drivers/py_api_drivers/fs_driver.py b/api_drivers/py_api_drivers/fs_driver.py index 74893a3a..fa187be3 100644 --- a/api_drivers/py_api_drivers/fs_driver.py +++ b/api_drivers/py_api_drivers/fs_driver.py @@ -1,10 +1,11 @@ -''' -Original author: mhepp(https://forum.lvgl.io/u/mhepp/summary) -''' +# Original author: mhepp(https://forum.lvgl.io/u/mhepp/summary) +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import lvgl as lv import struct + def _fs_open_cb(drv, path, mode): if mode == lv.FS_MODE.WR: diff --git a/builder/__init__.py b/builder/__init__.py index df5a38af..f1c5672f 100644 --- a/builder/__init__.py +++ b/builder/__init__.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import shutil import sys import os @@ -9,7 +11,13 @@ _windows_env = None +DO_NOT_SCRUB_BUILD_FOLDER = False + + def scrub_build_folder(): + if DO_NOT_SCRUB_BUILD_FOLDER: + return + for f in os.listdir('build'): f = os.path.join('build', f) for pattern in ('.h', 'manifest.py', '.board'): @@ -248,6 +256,13 @@ def generate_manifest( ) ] + toml_gen_driver = f'{script_dir}/build/display.py' + if os.path.exists(toml_gen_driver): + print(toml_gen_driver) + file_path, file_name = os.path.split(toml_gen_driver) + entry = f"freeze('{file_path}', '{file_name}')" + manifest_files.append(entry) + for file in frozen_manifest_files: if not os.path.exists(file): raise RuntimeError(f'File not found "{file}"') @@ -266,6 +281,49 @@ def generate_manifest( entry = f"freeze('{file_path}', '{file_name}')" manifest_files.append(entry) + if 'all' in io_expanders: + io_expanders.remove('all') + path = f'{script_dir}/api_drivers/common_api_drivers/io_expander' + + for file in os.listdir(path): + if '.wip' in file: + continue + + if file.endswith('.py'): + name = file[:-3] + io_expanders.append(name) + + if 'all' in indevs: + indevs.remove('all') + path = f'{script_dir}/api_drivers/common_api_drivers/indev' + for file in os.listdir(path): + if '.wip' in file: + continue + + if ( + file == 'focaltech_touch.py' or + file == 'evdev' or + 'extension' in file or + 'settings' in file + ): + continue + + if file.endswith('.py'): + name = file[:-3] + indevs.append(name) + + if 'all' in displays: + displays.remove('all') + path = f'{script_dir}/api_drivers/common_api_drivers/display' + for file in os.listdir(path): + if file.endswith('.py'): + continue + + if '.wip' in file: + continue + + displays.append(file) + for file in io_expanders: if not os.path.exists(file): tmp_file = ( @@ -280,11 +338,12 @@ def generate_manifest( file_path, file_name = os.path.split(tmp_file) entry = f"freeze('{file_path}', '{file_name}')" - manifest_files.append(entry) else: print(file) file_path, file_name = os.path.split(file) entry = f"freeze('{file_path}', '{file_name}')" + + if entry not in manifest_files: manifest_files.append(entry) for file in indevs: @@ -305,7 +364,9 @@ def generate_manifest( print(focaltech_touch) directory, file_name = os.path.split(focaltech_touch) entry = f"freeze('{directory}', '{file_name}')" - manifest_files.append(entry) + + if entry not in manifest_files: + manifest_files.append(entry) file = tmp_file @@ -316,12 +377,16 @@ def generate_manifest( if os.path.exists(extension): print(extension) entry = f"freeze('{directory}', '{extension_file}')" - manifest_files.append(entry) + + if entry not in manifest_files: + manifest_files.append(entry) print(file) file_path, file_name = os.path.split(file) entry = f"freeze('{file_path}', '{file_name}')" - manifest_files.append(entry) + + if entry not in manifest_files: + manifest_files.append(entry) display_paths = [] @@ -343,12 +408,14 @@ def generate_manifest( print(os.path.join(tmp_file, file_name)) entry = f"freeze('{tmp_file}', '{file_name}')" - manifest_files.append(entry) + if entry not in manifest_files: + manifest_files.append(entry) else: print(file) file_path, file_name = os.path.split(file) entry = f"freeze('{file_path}', '{file_name}')" - manifest_files.append(entry) + if entry not in manifest_files: + manifest_files.append(entry) manifest_files = '\n'.join(manifest_files) diff --git a/builder/esp32.py b/builder/esp32.py index b0ef9c4d..34d748e8 100644 --- a/builder/esp32.py +++ b/builder/esp32.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import os import shutil import sys @@ -526,31 +528,6 @@ def esp32_args(extra_args): def parse_args(extra_args, lv_cflags, brd): global board - global custom_board_path - - esp_argParser = ArgumentParser(prefix_chars='-') - esp_argParser.add_argument( - '--custom-board-path', - dest='custom_board_path', - default=None, - action='store' - ) - esp_args, extra_args = esp_argParser.parse_known_args(extra_args) - - custom_board_path = esp_args.custom_board_path - - if custom_board_path is not None: - if not os.path.exists(custom_board_path): - raise RuntimeError( - 'Supplied custom board path does not exist.' - ) - parent_folder_name = os.path.split(custom_board_path)[-1] - - dst_path = f'lib/micropython/ports/esp32/boards/{parent_folder_name}' - shutil.copytree(custom_board_path, dst_path) - - if brd is None: - brd = parent_folder_name if brd is None: brd = 'ESP32_GENERIC' @@ -1091,6 +1068,10 @@ def update_mpconfigport(): if custom_board_path is None: repl_data = [ + '#ifndef USB_SERIAL_JTAG_PACKET_SZ_BYTES', + '#define USB_SERIAL_JTAG_PACKET_SZ_BYTES (64)', + '#endif', + '', '#ifdef MICROPY_HW_UART_REPL_BAUD', '#undef MICROPY_HW_UART_REPL_BAUD', '#endif', @@ -1118,7 +1099,8 @@ def update_mpconfigport(): '#ifdef MICROPY_HW_ESP_USB_SERIAL_JTAG', '#undef MICROPY_HW_ESP_USB_SERIAL_JTAG', '#endif', - f'#define MICROPY_HW_ESP_USB_SERIAL_JTAG ({int(enable_jtag_repl.lower() == "y")})' + f'#define MICROPY_HW_ESP_USB_SERIAL_JTAG ({int(enable_jtag_repl.lower() == "y")})', + '#define USB_SERIAL_JTAG_PACKET_SZ_BYTES (64)' ]) repl_data.extend([ @@ -1215,7 +1197,6 @@ def update_main(): '#include "../../../../ext_mod/lcd_bus/esp32_include/i2c_bus.h"', '#include "../../../../ext_mod/spi3wire/include/spi3wire.h"', '#include "../../../../micropy_updates/common/mp_spi_common.h"', - '#include "../../../../micropy_updates/common/mp_i2c_common.h"', '', '#if MICROPY_BLUETOOTH_NIMBLE' ] @@ -1244,8 +1225,6 @@ def update_main(): ' mp_spi3wire_deinit_all();', ' ', ' mp_machine_hw_spi_bus_deinit_all();' - ' ', - ' mp_machine_hw_i2c_bus_deinit_all();' ] data = data.replace( @@ -1315,7 +1294,7 @@ def build_sdkconfig(*args): for itm in ( 15, 16, 20, 24, 26, 30, 32, 40, 48, 60, 64, 80, 120 ): - base_config.append(f'CONFIG_ESPTOOLPY__FLASHFREQ_{itm}M=n') + base_config.append(f'CONFIG_ESPTOOLPY_FLASHFREQ_{itm}M=n') elif 'SPIRAM_SPEED' in arg: for itm in (20, 26, 40, 80, 120): base_config.append(f'CONFIG_SPIRAM_SPEED_{itm}M=n') @@ -1490,7 +1469,7 @@ def compile(*args): # NOQA espressif_path = os.path.expanduser('~/.espressif') - for ver in ('3.8', '3.9', '3.10', '3.11', '3.12'): + for ver in ('3.8', '3.9', '3.10', '3.11', '3.12', '3.13'): python_path = ( f'{espressif_path}/python_env/' f'idf{IDF_VER[:-2]}_py{ver}_env/bin' @@ -1509,8 +1488,9 @@ def compile(*args): # NOQA build_name = f'build-{board}' - if board_variant: - build_name += f'-{board_variant}' + if custom_board_path is None: + if board_variant: + build_name += f'-{board_variant}' full_file_path = ( f'{SCRIPT_DIR}/lib/micropython/ports/esp32/{build_name}' @@ -1529,9 +1509,12 @@ def compile(*args): # NOQA scrub_build_folder() - build_bin_file = f'build/lvgl_micropy_{build_name[6:]}-{flash_size}' - if oct_flash: - build_bin_file += '_OCTFLASH' + if custom_board_path is None: + build_bin_file = f'build/lvgl_micropy_{build_name[6:]}-{flash_size}' + if oct_flash: + build_bin_file += '_OCTFLASH' + else: + build_bin_file = f'build/lvgl_micropy_{build_name[6:]}' build_bin_file += '.bin' build_bin_file = os.path.abspath(build_bin_file) diff --git a/builder/macOS.py b/builder/macOS.py index 9cbd5b7d..d31c6eb0 100644 --- a/builder/macOS.py +++ b/builder/macOS.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import os import sys from .unix import ( @@ -10,8 +12,8 @@ mpy_cross as _mpy_cross ) - from . import unix +from . import spawn unix.REAL_PORT = 'macOS' @@ -56,7 +58,82 @@ def build_sdl(_): unix.build_sdl = build_sdl +def is_homebrew_arm(cmd): + ret_val, output = spawn(cmd, out_to_screen=False) + if ret_val: + if cmd[0][0] == '/opt/homebrew/bin/brew': + raise RuntimeError('Unable to locate homebrew installation') + + return is_homebrew_arm([['/opt/homebrew/bin/brew', 'config']]) + + data = {line.split(':', 1)[0].strip(): line.split(':', 1)[1].strip() for + line in output.split('\n')} + + if 'macOS' not in data: + raise RuntimeError('Unable to determine Homebrew CPU type') + + if 'arm64' in data['macOS']: + if 'Rosetta 2' not in data: + if cmd[0][0] != '/opt/homebrew/bin/brew': + return is_homebrew_arm([['/opt/homebrew/bin/brew', 'config']]) + + raise RuntimeError('Unable to determine Homebrew platform') + + if data['Rosetta 2'] == 'true': + if cmd[0][0] != '/opt/homebrew/bin/brew': + return is_homebrew_arm([['/opt/homebrew/bin/brew', 'config']]) + + raise RuntimeError('Unable to locate Homebrew for Arm processors.') + + return True, cmd[0][0] + + return False, cmd[0][0] + + def submodules(): + is_arm, brew_path = is_homebrew_arm([['brew', 'config']]) + + if is_arm: + ret, out = spawn([[brew_path, 'info', 'libffi']], out_to_screen=False) + if ret: + print(out) + sys.exit(ret) + + if 'Installed\n' not in out: + print(out) + raise RuntimeError('libffi is not installed') + + out = out.split('Installed\n', 1)[-1] + alt_path = out.split('(', 1)[0].strip().split('Cellar', 1)[0] + + if 'export LDFLAGS=' in out: + out = out.split('export LDFLAGS="', 1)[-1] + ldflags = out.split('"', 1)[0] + else: + ldflags = f'"-L{alt_path}opt/libffi/lib"' + + if 'export CPPFLAGS=' in out: + out = out.split('export CPPFLAGS="', 1)[-1] + cflags = out.split('"', 1)[0] + else: + cflags = f'"-I{alt_path}opt/libffi/include"' + + ret, out = spawn([[brew_path, 'info', 'sdl2']], out_to_screen=False) + + if ret: + print(out) + sys.exit(ret) + + if 'Installed\n' not in out: + print(out) + raise RuntimeError('sdl2 is not installed') + + ldflags += f' "-L{alt_path}lib"' + cflags += f' "-I{alt_path}include"' + + os.environ['LDFLAGS'] = f'{ldflags}' + os.environ['CFLAGS'] = f'{cflags}' + berkeley_db = os.path.abspath('lib/micropython/lib/berkeley-db-1.xx/README') if not os.path.exists(berkeley_db): diff --git a/builder/nrf.py b/builder/nrf.py index c703136c..4867e101 100644 --- a/builder/nrf.py +++ b/builder/nrf.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import os import sys from . import spawn diff --git a/builder/raspberry_pi.py b/builder/raspberry_pi.py index 84d956fb..edb29cef 100644 --- a/builder/raspberry_pi.py +++ b/builder/raspberry_pi.py @@ -1,3 +1,4 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser import os diff --git a/builder/renesas.py b/builder/renesas.py index 1cbe60e2..6622c980 100644 --- a/builder/renesas.py +++ b/builder/renesas.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import os import sys from . import spawn diff --git a/builder/rp2.py b/builder/rp2.py index a8c7784a..c3397c4d 100644 --- a/builder/rp2.py +++ b/builder/rp2.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import os import sys from argparse import ArgumentParser diff --git a/builder/stm32.py b/builder/stm32.py index 4bbc0572..a17cc2e8 100644 --- a/builder/stm32.py +++ b/builder/stm32.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import os import sys from . import spawn diff --git a/builder/toml_reader.py b/builder/toml_reader.py new file mode 100644 index 00000000..86ba9f4d --- /dev/null +++ b/builder/toml_reader.py @@ -0,0 +1,527 @@ +import os + +try: + import toml +except ImportError: + raise RuntimeError( + 'The toml library is needed to use this feature.\n' + 'Please run "pip3 install toml" and then restart your build' + ) + +used_imports = [] +global_variable_names = [] + + +class TOMLMeta(type): + + def __call__(cls, name, parent=None, **kwargs): + if name and name == 'conditional': + return TOMLConditional(name, None, **kwargs) + + children = {} + for key, value in list(kwargs.items()): + if isinstance(value, dict): + children[key] = value + del kwargs[key] + + instance = super().__call__(name, parent=parent, **kwargs) + + for child_name, child_data in children.items(): + child = TOMLObject(child_name, parent=instance, **child_data) + instance.add_child(child) + + return instance + + +class TOMLObject(metaclass=TOMLMeta): + + def __init__(self, name, parent=None, **kwargs): + if parent is not None and parent.name == 'MCU': + self.build_args = kwargs + self.mcu = name + + paren = parent.parent + while paren.parent is not None: + paren = parent.parent + + paren.mcu_obj = TOMLmcu(self) + else: + self.mcu = None + + self.mcu_obj = None + self.name = name + self.parent = parent + self.__kwargs = kwargs + self.__children = [] + self.imports = [] + + def add_child(self, child): + if child.name != 'MCU': + self.__children.append(child) + + def __getattr__(self, item): + if item in self.__dict__: + return self.__dict__[item] + + if item in self.__kwargs: + return self.__kwargs[item] + + raise AttributeError(item) + + @property + def fqn(self): + if self.parent is not None and self.parent.name == 'Pin': + return self.name + ' = ' + self.parent.fqn + + if self.__kwargs: + if 'params' in self.__kwargs or 'value' in self.__kwargs: + return self.parent.fqn + '.' + self.name + + return self.name + ' = ' + self.parent.fqn + + if self.name == 'RGBDisplay': + return 'rgb_display.RGBDisplay' + + if self.name == 'SDLDisplay': + return 'sdl_display.SDLDisplay' + + if self.name == 'SDLPointer': + return 'sdl_pointer.SDLPointer' + + if self.name == 'I2C': + return 'i2c.I2C' + + if self.name == 'Spi3Wire': + return 'spi3wire.Spi3Wire' + + if self.name == 'SPI': + return 'machine.SPI' + + if self.name == 'SDCard': + return 'machine.SDCard' + + if self.name.lower() in display_drivers: + return self.name.lower() + '.' + self.name + + if self.name.lower() in indev_drivers: + return self.name.lower() + '.' + self.name + + if self.name in io_expanders: + return self.name + + if self.name in ('I80Bus', 'SPIBus', 'I2CBus', 'RGBBus'): + return 'lcd_bus.' + self.name + + if self.parent is None: + return None + + if self.parent.name: + return self.parent.fqn + '.' + self.name + + return self.name + + @property + def var_names(self): + if self.__kwargs: + fqn = self.fqn + + if '=' in fqn: + return [fqn.split('=')[0].strip()] + + return [] + + var_names = [] + + for child in self.__children: + if isinstance(child, TOMLConditional): + continue + + var_names.extend(child.var_names) + + return var_names + + @property + def constants(self): + res = [] + + if not self.__children: + for key, value in list(self.__kwargs.items()): + if not isinstance(value, int) or key == 'value': + continue + + name = self.name.upper() + + key_upper = key.upper() + if name not in key_upper: + key_upper = name + '_' + key_upper + + res.append(f'_{key_upper} = const({value})') + self.__kwargs[key] = f'_{key_upper}' + else: + for child in self.__children: + if isinstance(child, TOMLConditional): + continue + + res.extend(child.constants) + + return res + + def __str__(self): + if self.parent is None: + global_variable_names.extend(self.var_names) + + output = [] + output.extend(self.constants) + + for child in self.__children: + if isinstance(child, TOMLConditional): + output.append('') + + elif child.name not in global_variable_names: + module = child.fqn.split('.')[0] + if module not in self.imports and module not in used_imports: + self.imports.append(module) + used_imports.append(module) + output.extend(['', f'import {module}', '']) + + output.append(str(child)) + if isinstance(child, TOMLConditional): + output.append('') + + if output: + output = [ + 'from micropython import const', + 'import lvgl as lv', + '', + '' + ] + output + + return '\n'.join(output) + + if self.__children and not self.__kwargs: + output = [str(child) for child in self.__children] + return '\n'.join(output) + + fqn = self.fqn + + if len(self.__kwargs) == 1: + key = list(self.__kwargs.keys())[0] + if key == 'params': + output = '' + for param in self.__kwargs[key]: + if isinstance(param, str) and '.' in param: + mod = param.split('.', 1)[0] + if ( + mod not in used_imports and + mod not in global_variable_names and ( + mod in display_drivers or + mod in indev_drivers or + mod in io_expanders + ) + ): + output += f'import {mod}\n\n' + used_imports.append(mod) + + params = ', '.join(str(itm) for itm in self.__kwargs[key]) + output += f'{fqn}({params})' + return output + else: + output = '' + if ( + isinstance(self.__kwargs[key], str) and + '.' in self.__kwargs[key] + ): + mod = self.__kwargs[key].split('.', 1)[0] + if ( + mod not in used_imports and + mod not in global_variable_names and ( + mod in display_drivers or + mod in indev_drivers or + mod in io_expanders + ) + ): + output += f'import {mod}\n\n' + used_imports.append(mod) + + if key == 'value': + output += f'{fqn} = ' + str(self.__kwargs[key]) + else: + output += f'{fqn}({key}={str(self.__kwargs[key])})' + + return output + else: + output = [] + + for v in self.__kwargs.values(): + if not (isinstance(v, str) and '.' in v): + continue + + mod = v.split('.', 1)[0] + if ( + mod not in used_imports and + mod not in global_variable_names and ( + mod in display_drivers or + mod in indev_drivers or + mod in io_expanders + ) + ): + output.append(f'import {mod}') + used_imports.append(mod) + if output: + output.append('') + + params = ',\n'.join(f' {k}={str(v)}' for k, v in self.__kwargs.items() if not isinstance(v, dict)) + if params: + output.append(f'{fqn}(\n{params}\n)\n') + else: + raise RuntimeError + + for child in self.__children: + output.append(self.name + '.' + str(child).split('.', 2)[-1]) + + if len(output) > 2: + output.append('') + + return '\n'.join(output) + + +class TOMLConditionalObject: + + def __init__(self, name, parent=None, **kwargs): + self.name = name + self.parent = parent + self.__children = [] + + for key, value in list(kwargs.items())[:]: + if isinstance(value, dict): + self.__children.append(TOMLConditionalObject(key, self, **value)) + del kwargs[key] + + self.__kwargs = kwargs + + def get_conditional(self): + if 'not_equal' in self.__kwargs: + return f'{self.name} != {self.__kwargs["not_equal"]}' + elif 'equal' in self.__kwargs: + return f'{self.name} == {self.__kwargs["equal"]}' + elif 'greater_than' in self.__kwargs: + return f'{self.name} > {self.__kwargs["greater_than"]}' + elif 'less_than' in self.__kwargs: + return f'{self.name} < {self.__kwargs["less_than"]}' + elif 'greater_than_or_equal' in self.__kwargs: + return f'{self.name} >= {self.__kwargs["greater_than_or_equal"]}' + elif 'less_than_or_equal' in self.__kwargs: + return f'{self.name} <= {self.__kwargs["less_than_or_equal"]}' + elif 'is' in self.__kwargs: + return f'{self.name} is {self.__kwargs["is"]}' + elif 'is_not' in self.__kwargs: + return f'{self.name} is not {self.__kwargs["is_not"]}' + elif 'in' in self.__kwargs: + return f'{self.name} in {self.__kwargs["in"]}' + elif 'not_in' in self.__kwargs: + return f'{self.name} not in {self.__kwargs["not_in"]}' + else: + for child in self.__children: + res = child.get_conditional() + if res is not None: + return f'{self.name}.{res}' + + def is_conditional(self): + cond = self.get_conditional() + return cond is not None and not cond.startswith(f'{self.name}.') + + def get_objects(self): + res = [] + + base_conditional = self.parent + while not isinstance(base_conditional, TOMLConditional): + base_conditional = base_conditional.parent + + if self.is_conditional(): + for child in self.__children: + res.extend(child.get_objects()) + else: + if 'value' in self.__kwargs: + names = [] + parent = self.parent + while parent.name and not isinstance(parent, TOMLConditional): + names.insert(0, parent.name) + parent = parent.parent + + while names and not base_conditional.has_variable_name('.'.join(names)): + names.pop(0) + + names.append(self.name) + var_name = '.'.join(names) + base_conditional.add_variable_name(var_name) + res.append(f'{var_name} = {self.__kwargs["value"]}') + + elif 'params' in self.__kwargs: + params = ', '.join(str(item) for item in self.__kwargs['params']) + if self.name == 'del': + res.append(f'{self.name} {params}') + else: + res.append(f'{self.name}({params})') + + return res + + for child in self.__children: + lines = child.get_objects() + + for line in lines: + if ' = ' in line: + var_name = line.split(' = ', 1)[0] + if base_conditional.has_variable_name(var_name): + res.append(line) + continue + else: + try: + func_name = line.split('(', 1)[0] + if base_conditional.has_variable_name(func_name): + res.append(line) + continue + + func_name = func_name.split('.', 1)[0] + if base_conditional.has_variable_name(func_name): + res.append(line) + continue + except IndexError: + pass + + if line.startswith('del '): + res.append(line) + else: + res.append(f'{self.name}.{line}') + return res + + def is_variable(self): + return 'value' in self.__kwargs + + def is_function(self): + return 'params' in self.__kwargs + + +class TOMLConditional: + + def __init__(self, name, parent=None, **kwargs): + self.name = name + self.parent = parent + self.__children = [] + self.__variable_names = [] + + for key, value in list(kwargs.items())[:]: + if isinstance(value, dict): + self.__children.append(TOMLConditionalObject(key, self, **value)) + del kwargs[key] + + self.__kwargs = kwargs + + code = [] + for child in self.__children: + cond = child.get_conditional() + if cond is not None: + code.append(f'if {cond}:') + break + else: + raise RuntimeError('Unable to locate conditional argument') + + for child in self.__children: + code.extend([f' {line}' for line in child.get_objects()]) + + self.__code = '\n'.join(code) + + def add_variable_name(self, name): + if name not in self.__variable_names: + self.__variable_names.append(name) + + def has_variable_name(self, name): + return name in self.__variable_names + + def __str__(self): + return self.__code + + +class TOMLmcu: + + def __init__(self, mcu): + name = mcu.mcu + build_args = mcu.build_args + + command = [name] + for arg, value in build_args.items(): + if arg.islower(): + build_arg = '--' + arg.replace('_', '-') + if isinstance(value, bool) and not value: + raise SyntaxError( + 'optionless build commands must be set to "true"\n' + f'if they are used in the toml file. ({arg} = {repr(value)})' + ) + else: + build_arg = arg + + if not isinstance(value, bool): + build_arg = f'{build_arg}={value}' + + command.append(build_arg) + + self.build_command = command + + +base_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) + +display_driver_path = os.path.join(base_path, 'api_drivers/common_api_drivers/display') +indev_driver_path = os.path.join(base_path, 'api_drivers/common_api_drivers/indev') +io_expander_path = os.path.join(base_path, 'api_drivers/common_api_drivers/io_expander') + + +display_drivers = [file for file in os.listdir(display_driver_path) if not file.endswith('.wip') and not file.endswith('.py')] +indev_drivers = [file[:-3] for file in os.listdir(indev_driver_path) if file.endswith('.py')] +io_expanders = [file[:-3] for file in os.listdir(io_expander_path) if file.endswith('.py')] + + +def run(toml_path, output_file): + + if not os.path.exists(toml_path): + raise RuntimeError(f'inable to locate .toml ({toml_path})') + + try: + with open(toml_path, 'r') as f: + toml_data = toml.load(f) + + toml_obj = TOMLObject('', **toml_data) + + t_data = str(toml_obj) + + if t_data: + with open(output_file, 'w') as f: + f.write(t_data) + + displays = [f'DISPLAY={item}' for item in toml_obj.imports if item in display_drivers] + indevs = [f'INDEV={item}' for item in toml_obj.imports if item in indev_drivers] + expanders = [f'EXPANDER={item}' for item in toml_obj.imports if item in io_expanders] + + if toml_obj.mcu_obj is None: + build_command = [] + else: + build_command = toml_obj.mcu_obj.build_command + + for display in displays[:]: + if display not in build_command: + build_command.append(display) + + for indev in indevs[:]: + if indev not in build_command: + build_command.append(indev) + + for expander in expanders[:]: + if expander not in build_command: + build_command.append(expander) + + return build_command + + except OSError as err: + raise RuntimeError(f'Unable to write data to {output_file}') from err + except Exception as err: # NOQA + raise SyntaxError(f'Unable to parse .toml file ({toml_path})') from err + + diff --git a/builder/unix.py b/builder/unix.py index aa69076c..c6ff94fd 100644 --- a/builder/unix.py +++ b/builder/unix.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import os import sys import shutil diff --git a/builder/windows.py b/builder/windows.py index 347a29e6..5a031adb 100644 --- a/builder/windows.py +++ b/builder/windows.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import sys import os import uuid diff --git a/button_framework.pyi b/button_framework.pyi index 46ec808e..54a69ca2 100644 --- a/button_framework.pyi +++ b/button_framework.pyi @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + from typing import Optional, TYPE_CHECKING import _indev_base diff --git a/custom_board_and_toml_examples/MY_CUSTOM_BOARD/board.json b/custom_board_and_toml_examples/MY_CUSTOM_BOARD/board.json new file mode 100644 index 00000000..bc389865 --- /dev/null +++ b/custom_board_and_toml_examples/MY_CUSTOM_BOARD/board.json @@ -0,0 +1,6 @@ +{ + "mcu": "esp32s3", + "product": "Custom ESP32-S3 display board", + "url": "https://www.come_manufacturer.com/board.html", + "vendor": "Vendor name of board" +} diff --git a/custom_board_and_toml_examples/MY_CUSTOM_BOARD/mpconfigboard.cmake b/custom_board_and_toml_examples/MY_CUSTOM_BOARD/mpconfigboard.cmake new file mode 100644 index 00000000..acca1ea8 --- /dev/null +++ b/custom_board_and_toml_examples/MY_CUSTOM_BOARD/mpconfigboard.cmake @@ -0,0 +1,17 @@ +set(IDF_TARGET esp32s3) + +set(SDKCONFIG_DEFAULTS + boards/sdkconfig.base + ${SDKCONFIG_IDF_VERSION_SPECIFIC} + boards/sdkconfig.usb + boards/sdkconfig.ble + boards/sdkconfig.spiram_sx + boards/sdkconfig.spiram_oct + boards/sdkconfig.240mhz + boards/MY_CUSTOM_BOARD/sdkconfig.board +) + +list(APPEND MICROPY_DEF_BOARD + MICROPY_HW_BOARD_NAME="custom ESP32 board" +) + diff --git a/custom_board_and_toml_examples/MY_CUSTOM_BOARD/mpconfigboard.h b/custom_board_and_toml_examples/MY_CUSTOM_BOARD/mpconfigboard.h new file mode 100644 index 00000000..a8425a38 --- /dev/null +++ b/custom_board_and_toml_examples/MY_CUSTOM_BOARD/mpconfigboard.h @@ -0,0 +1,11 @@ +#ifndef MICROPY_HW_BOARD_NAME +// Can be set by mpconfigboard.cmake. +#define MICROPY_HW_BOARD_NAME "Custom ESP32S3 board" +#endif +#define MICROPY_HW_MCU_NAME "ESP32S3" + +// Enable UART REPL for modules that have an external USB-UART and don't use native USB. +#define MICROPY_HW_ENABLE_UART_REPL (1) + +#define MICROPY_HW_I2C0_SCL (9) +#define MICROPY_HW_I2C0_SDA (8) diff --git a/custom_board_and_toml_examples/MY_CUSTOM_BOARD/my_custom_board.toml b/custom_board_and_toml_examples/MY_CUSTOM_BOARD/my_custom_board.toml new file mode 100644 index 00000000..7f5a3e99 --- /dev/null +++ b/custom_board_and_toml_examples/MY_CUSTOM_BOARD/my_custom_board.toml @@ -0,0 +1,59 @@ + +[MCU.esp32] +BOARD = "MY_CUSTOM_BOARD" + + +[I80Bus.display_bus] +data0 = 9 +data1 = 46 +data2 = 3 +data3 = 8 +data4 = 18 +data5 = 17 +data6 = 16 +data7 = 15 +dc = 0 +wr = 47 +cs = -1 +freq = 20000000 + + +[I2C.Bus.i2c_bus] +host = 0 +scl = 5 +sda = 6 +freq = 100000 + + +[I2C.Device.indev_device] +bus = "i2c_bus" +dev_id = "ft6x36.I2C_ADDR" +reg_bits = "ft6x36.BITS" + + +[ST7796.display] +data_bus = "display_bus" +display_width = 320 +display_height = 480 +backlight_pin = 45 +color_byte_order = "st7789.BYTE_ORDER_BGR" +color_space = "lv.COLOR_FORMAT.RGB565" +rgb565_byte_swap = true + +[ST7796.display.init] +params = [] + +[FT6x36.indev] +device = "indev_device" + +[display.set_color_inversion] +params = [true] + +[display.set_rotation] +params = ["lv.DISPLAY_ROTATION._90"] + +[display.set_backlight] +params = [100] + +[task_handler.TaskHandler] +params=[] diff --git a/custom_board_and_toml_examples/MY_CUSTOM_BOARD/partitions.csv b/custom_board_and_toml_examples/MY_CUSTOM_BOARD/partitions.csv new file mode 100644 index 00000000..c26f12f4 --- /dev/null +++ b/custom_board_and_toml_examples/MY_CUSTOM_BOARD/partitions.csv @@ -0,0 +1,7 @@ +# Notes: the offset of the partition table itself is set in +# $IDF_PATH/components/partition_table/Kconfig.projbuild. +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 0x6000, +phy_init, data, phy, 0xf000, 0x1000, +factory, app, factory, 0x10000, 0x2F0000, +vfs, data, fat, 0x300000, 0x1D00000, diff --git a/custom_board_and_toml_examples/MY_CUSTOM_BOARD/sdkconfig.board b/custom_board_and_toml_examples/MY_CUSTOM_BOARD/sdkconfig.board new file mode 100644 index 00000000..f0945283 --- /dev/null +++ b/custom_board_and_toml_examples/MY_CUSTOM_BOARD/sdkconfig.board @@ -0,0 +1,29 @@ +CONFIG_IDF_EXPERIMENTAL_FEATURES=y + +CONFIG_FREERTOS_HZ=1000 +CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y + +CONFIG_ESPTOOLPY_FLASHMODE_QIO=y +CONFIG_ESPTOOLPY_FLASHFREQ_120M=y +CONFIG_ESPTOOLPY_FLASHSIZE_32MB=y + +CONFIG_SPIRAM_SPEED_120M=y +CONFIG_SPIRAM_IGNORE_NOTFOUND=n +CONFIG_SPIRAM_RODATA=y +CONFIG_SPIRAM_FETCH_INSTRUCTIONS=y + +CONFIG_ESP32S3_DATA_CACHE_LINE_64B=y +CONFIG_COMPILER_OPTIMIZATION_PERF=y + +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="boards/MY_CUSTOM_BOARD/partitions.csv" + +CONFIG_LWIP_LOCAL_HOSTNAME="my_custom_board" + +CONFIG_TINYUSB_DESC_USE_ESPRESSIF_VID=n +CONFIG_TINYUSB_DESC_USE_DEFAULT_PID=n +CONFIG_TINYUSB_DESC_CUSTOM_VID=0x2341 +CONFIG_TINYUSB_DESC_CUSTOM_PID=0x056B +CONFIG_TINYUSB_DESC_MANUFACTURER_STRING="MyCustomBoard" +CONFIG_TINYUSB_DESC_PRODUCT_STRING="Custom ESP32" + diff --git a/custom_board_and_toml_examples/README.md b/custom_board_and_toml_examples/README.md new file mode 100644 index 00000000..a58e8446 --- /dev/null +++ b/custom_board_and_toml_examples/README.md @@ -0,0 +1,156 @@ + + +### *Custom Boards* +___________________ + + +I added the ability to provide a path to a custom board. There are a few requirememnts for +this to work properly. The best bet is to look at the files in the `custom_board_and_toml_examples/MY_CUSTOM_BOARD` +folder to see what files are needed and to also get an idea of the kind of information that +is in the files. + +***NOTE***: There are only 2 options that get used when supplying a custom board. The first one + is the build target and the second is the `--custom-board-path` command. ALL others + are ignored. The reason they are ignored is because you have the ability to set things + in the files for the custom board. + + +The path needs to point to the folder that holds the board specification files. Here is a list of required files. + +* `board.json`: This file outlines what the board is. At a minimum the file needs to contain the following. + ``` + { + "mcu": "{MCU}" + } + ``` + where `{MCU}` is one of the follwing: + + * esp32 + * esp32s2 + * esp32s3 + * esp32c3 + * esp32c6 + +* `sdkconfig.board`: This file contains all of the ESP-IDF specific config settings. If you don't know + what needs to be set in here then please ask me for assistance. +* `mpconfigboard.h`: MicroPython config settings. If you don't know what needs to be set in here then + please ask me for assistance. +* `mpconfigboard.cmake`: Build script. At a minimum the following should be in the build script. + `{MCU}` is replaced with one of the options from the list of MCU's above. + `{BOARD_CONATINING_FOLDER}` if the name of the folder these files are located in. +``` +set(IDF_TARGET {MCU}) + +set(SDKCONFIG_DEFAULTS + boards/sdkconfig.base + ${SDKCONFIG_IDF_VERSION_SPECIFIC} + boards/{BOARD_CONATINING_FOLDER}/sdkconfig.board +) +``` + +* `partition.csv`: This file dictates what the partitions are supposed to be on the ESP32. As for assistance + If you do not know how to create one of these. + +***NOTE***: The `.toml` file in the custom board example is NOT a requirement. I do strongly suggest using it + since it will tie everything together. You can specify all of the display and indev bits and pieces. + see [TOML Example](#toml-example) for further information. + + +### *TOML Example* +__________________ + +Here is an example of what you would put inside of the `.toml` file. +I will go over each section below. + + [MCU.esp32] + BOARD = "ESP32_GENERIC_S3" + BOARD_VARIANT = "SPIRAM_OCT" + octal_flash = true + flash_size = 16 + enable_jtag_repl = 'n' + enable_cdc_repl = 'n' + enable_uart_repl = 'y' + uart_repl_bitrate = 115200 + + [I80Bus.display_bus] + data0 = 9 + data1 = 46 + data2 = 3 + data3 = 8 + data4 = 18 + data5 = 17 + data6 = 16 + data7 = 15 + dc = 0 + wr = 47 + cs = -1 + freq = 20000000 + + [I2C.Bus.i2c_bus] + host = 0 + scl = 5 + sda = 6 + freq = 100000 + + [I2C.Device.indev_device] + bus = "i2c_bus" + dev_id = "ft6x36.I2C_ADDR" + reg_bits = "ft6x36.BITS" + + [ST7796.display] + data_bus = "display_bus" + display_width = 320 + display_height = 480 + backlight_pin = 45 + color_byte_order = "st7789.BYTE_ORDER_BGR" + color_space = "lv.COLOR_FORMAT.RGB565" + rgb565_byte_swap = true + + [ST7796.display.init] + params = [] + + [FT6x36.indev] + device = "indev_device" + + [display.set_color_inversion] + params = [true] + + [display.set_rotation] + params = ["lv.DISPLAY_ROTATION._90"] + + [display.set_backlight] + params = [100] + + [task_handler.TaskHandler] + params=[] + + + +* `[MCU.{target}]`: `{target}` is the build target you want to use. In the example above we are using `esp32` + The parameters that immediatly follow are almost the same as what you would use for build commands + when entering them from the command line. There are a few rules for how those commands get enetered. + + * options that star with `--` need to have the `--` removed and all `-`'s in the name need to be change to `_`. + * options are cas esensitive + * options that take a string value need to be wrapped in double quotes (`"value"`) + * options that do not take any value *MUST* have the value set to `true` + * options like `DISPLAY` and `INDEV` which are able to be repeated cannot be repeated (yet). That means you can onmly + supply a single display or indev. You only need to supply the `DISPLAY` and `INDEV` if you are not wanting to automatically + build the startup script. + + + [MCU.esp32] + BOARD = "ESP32_GENERIC_S3" + BOARD_VARIANT = "SPIRAM_OCT" + octal_flash = true + flash_size = 16 + enable_jtag_repl = 'n' + enable_cdc_repl = 'n' + enable_uart_repl = 'y' + uart_repl_bitrate = 115200 + +* `[{display bus}.{variable name}]`: `[I80Bus.display_bus]`, That heading section gets turnmed into `display_bus = lcd_bus.I80Bus(...)`. + The variable name you will use when passing the display bus instance to the display driver. I will + go into that more later on. The list of options below this heading are the parameters that get passed. + These options MUST match the names of the parameters for the class being used. +* `[I2C.Bus.{variable name}]` and `[I2C.Device.{variable_name}]` \ No newline at end of file diff --git a/custom_board_and_toml_examples/toml_example/example_build_toml.toml b/custom_board_and_toml_examples/toml_example/example_build_toml.toml new file mode 100644 index 00000000..02c7c6f0 --- /dev/null +++ b/custom_board_and_toml_examples/toml_example/example_build_toml.toml @@ -0,0 +1,67 @@ + +[MCU.esp32] +BOARD = "ESP32_GENERIC_S3" +BOARD_VARIANT = "SPIRAM_OCT" +octal_flash = true +flash_size = 16 +enable_jtag_repl = 'n' +enable_cdc_repl = 'n' +enable_uart_repl = 'y' +uart_repl_bitrate = 115200 + + + +[I80Bus.display_bus] +data0 = 9 +data1 = 46 +data2 = 3 +data3 = 8 +data4 = 18 +data5 = 17 +data6 = 16 +data7 = 15 +dc = 0 +wr = 47 +cs = -1 +freq = 20000000 + + +[I2C.Bus.i2c_bus] +host = 0 +scl = 5 +sda = 6 +freq = 100000 + + +[I2C.Device.indev_device] +bus = "i2c_bus" +dev_id = "ft6x36.I2C_ADDR" +reg_bits = "ft6x36.BITS" + + +[ST7796.display] +data_bus = "display_bus" +display_width = 320 +display_height = 480 +backlight_pin = 45 +color_byte_order = "st7796.BYTE_ORDER_BGR" +color_space = "lv.COLOR_FORMAT.RGB565" +rgb565_byte_swap = true + +[display.init] +params = [] + +[FT6x36.indev] +device = "indev_device" + +[display.set_color_inversion] +params = [true] + +[display.set_rotation] +params = ["lv.DISPLAY_ROTATION._90"] + +[display.set_backlight] +params = [100] + +[task_handler.TaskHandler] +params=[] diff --git a/display_configs/CYD-2432S024C.toml b/display_configs/CYD-2432S024C.toml new file mode 100644 index 00000000..a9071602 --- /dev/null +++ b/display_configs/CYD-2432S024C.toml @@ -0,0 +1,60 @@ +[MCU.esp32] +BOARD = "ESP32_GENERIC" +BOARD_VARIANT = "SPIRAM" +uart_repl_bitrate = 115200 + +[SPI.Bus.spi_bus] +host = 1 +mosi = 13 +miso = 12 +sck = 14 + +[SPIBus.display_bus] +spi_bus = "spi_bus" +freq = 40000000 +dc = 2 +cs = 15 + + +[I2C.Bus.i2c_bus] +host = 0 +scl = 32 +sda = 33 +freq = 400000 + + +[I2C.Device.indev_device] +bus = "i2c_bus" +dev_id = "cst820.I2C_ADDR" +reg_bits = "cst820.BITS" + + +[ILI9341.display] +data_bus = "display_bus" +display_width = 240 +display_height = 320 +backlight_pin = 27 +reset_pin = 17 +backlight_on_state = "st7789.STATE_PWM" +color_space = "lv.COLOR_FORMAT.RGB565" +color_byte_order = "ili9341.BYTE_ORDER_BGR" +rgb565_byte_swap = true + +[display._ORIENTATION_TABLE] +value = [0, 96, 192, 160] + + +[display.set_power] +params = [true] + +[display.init] +params = [1] + +[cst820.indev] +device = "indev_device" + +[display.set_backlight] +params = [100] + +[task_handler.TaskHandler] +params=[] diff --git a/display_configs/CYD-2432S028R.toml b/display_configs/CYD-2432S028R.toml new file mode 100644 index 00000000..7e0671b3 --- /dev/null +++ b/display_configs/CYD-2432S028R.toml @@ -0,0 +1,58 @@ +[MCU.esp32] +BOARD = "ESP32_GENERIC" +BOARD_VARIANT = "SPIRAM" +uart_repl_bitrate = 115200 + +[SPI.Bus.spi_bus] +host = 1 +mosi = 13 +miso = 12 +sck = 14 + +[SPIBus.display_bus] +spi_bus = "spi_bus" +freq = 24000000 +dc = 2 +cs = 15 + + +[SPI.Bus.indev_bus] +host = 2 +mosi= 32 +miso = 39 +sck = 25 + + +[SPI.Device.indev_device] +spi_bus = "indev_bus" +freq = 2000000 +cs = 33 + + +[ILI9341.display] +data_bus = "display_bus" +display_width = 320 +display_height = 240 +backlight_pin = 21 +backlight_on_state = "st7789.STATE_PWM" +color_space = "lv.COLOR_FORMAT.RGB565" +rgb565_byte_swap = true + +[display._ORIENTATION_TABLE] +value = [0, 96, 192, 160] + + +[display.set_power] +params = [true] + +[display.init] +params = [1] + +[xpt2046.indev] +device = "indev_device" + +[display.set_backlight] +params = [100] + +[task_handler.TaskHandler] +params=[] diff --git a/display_configs/CYD-2432S032C.toml b/display_configs/CYD-2432S032C.toml new file mode 100644 index 00000000..ee4f8046 --- /dev/null +++ b/display_configs/CYD-2432S032C.toml @@ -0,0 +1,66 @@ +[MCU.esp32] +BOARD = "ESP32_GENERIC" +BOARD_VARIANT = "SPIRAM" +uart_repl_bitrate = 115200 + +[SPI.Bus.spi_bus] +host = 1 +mosi = 13 +miso = 12 +sck = 14 + +[SPIBus.display_bus] +spi_bus = "spi_bus" +freq = 24000000 +dc = 2 +cs = 15 + + +[I2C.Bus.i2c_bus] +host = 0 +scl = 32 +sda = 33 +freq = 400000 + + +[I2C.Device.indev_device] +bus = "i2c_bus" +dev_id = "gt911.I2C_ADDR" +reg_bits = "gt911.BITS" + + +[ST7789.display] +data_bus = "display_bus" +display_width = 240 +display_height = 320 +backlight_pin = 27 +backlight_on_state = "st7789.STATE_PWM" +color_space = "lv.COLOR_FORMAT.RGB565" +color_byte_order = "st7789.BYTE_ORDER_BGR" +rgb565_byte_swap = true + +[display.set_power] +params = [true] + +[display.init] +params = [] + +[gt911.indev] +device = "indev_device" + +[indev.firmware_config.fw_config] + +[fw_config.width] +value=240 + +[fw_config.height] +value=320 + +[fw_config.save] +params=[] + +[display.set_backlight] +params = [100] + +[task_handler.TaskHandler] +params=[] diff --git a/display_configs/CYD-3248S035C.toml b/display_configs/CYD-3248S035C.toml new file mode 100644 index 00000000..7ebeb67f --- /dev/null +++ b/display_configs/CYD-3248S035C.toml @@ -0,0 +1,68 @@ +[MCU.esp32] +BOARD = "ESP32_GENERIC" +BOARD_VARIANT = "SPIRAM" +uart_repl_bitrate = 115200 + +[SPI.Bus.spi_bus] +host = 1 +mosi = 13 +miso = 12 +sck = 14 + +[SPIBus.display_bus] +spi_bus = "spi_bus" +freq = 24000000 +dc = 2 +cs = 15 + + +[I2C.Bus.i2c_bus] +host = 0 +scl = 32 +sda = 33 +freq = 400000 + + +[I2C.Device.indev_device] +bus = "i2c_bus" +dev_id = "gt911.I2C_ADDR" +reg_bits = "gt911.BITS" + + +[ST7796.display] +data_bus = "display_bus" +display_width = 320 +display_height = 480 +backlight_pin = 27 +backlight_on_state = "st7796.STATE_PWM" +reset_pin = 17 +reset_state = "st7796.STATE_LOW" +color_space = "lv.COLOR_FORMAT.RGB565" +color_byte_order = "st7796.BYTE_ORDER_BGR" +rgb565_byte_swap = true + +[display.set_power] +params = [true] + +[display.init] +params = [] + +[gt911.indev] +device = "indev_device" + +[indev.firmware_config.fw_config] + +[fw_config.width] +value=320 + +[fw_config.height] +value=480 + +[fw_config.save] +params=[] + +[display.set_backlight] +params = [100] + +[task_handler.TaskHandler] +params=[] diff --git a/display_configs/CYD-8048S043C.toml b/display_configs/CYD-8048S043C.toml new file mode 100644 index 00000000..2f2cdcd2 --- /dev/null +++ b/display_configs/CYD-8048S043C.toml @@ -0,0 +1,92 @@ +[MCU.esp32] +BOARD = "ESP32_GENERIC_S3" +BOARD_VARIANT = "SPIRAM_OCT" +flash_size = 8 +enable_jtag_repl = 'n' +enable_cdc_repl = 'n' +enable_uart_repl = 'y' +uart_repl_bitrate = 115200 + + +[RGBBus.display_bus] +data0 = 8 +data1 = 3 +data2 = 46 +data3 = 9 +data4 = 1 +data5 = 5 +data6 = 6 +data7 = 7 +data8 = 15 +data9 = 16 +data10 = 4 +data11 = 45 +data12 = 48 +data13 = 47 +data14 = 21 +data15 = 14 +hsync = 39 +vsync = 41 +de = 40 +pclk = 42 +freq = 12000000 +hsync_front_porch = 8 +hsync_back_porch = 8 +hsync_pulse_width = 4 +hsync_idle_low = true +vsync_front_porch = 8 +vsync_back_porch = 8 +vsync_pulse_width = 4 +vsync_idle_low = true +de_idle_high = false +pclk_idle_high = false +pclk_active_low = true + + +[I2C.Bus.i2c_bus] +host = 0 +scl = 20 +sda = 19 +freq = 400000 + + +[I2C.Device.indev_device] +bus = "i2c_bus" +dev_id = "ft6x36.I2C_ADDR" +reg_bits = "ft6x36.BITS" + + +[RGBDisplay.display] +data_bus = "display_bus" +display_width = 800 +display_height = 480 +backlight_pin = 2 +color_space = "lv.COLOR_FORMAT.RGB565" + + +[display.set_power] +params = [true] + + +[display.init] +params = [] + +[FT6x36.indev] +device = "indev_device" + +[indev.firmware_config.fw_config] + +[fw_config.width] +value=800 + +[fw_config.height] +value=480 + +[fw_config.save] +params=[] + +[display.set_backlight] +params = [100] + +[task_handler.TaskHandler] +params=[] diff --git a/display_configs/CYD-8048S050C_I.toml b/display_configs/CYD-8048S050C_I.toml new file mode 100644 index 00000000..2f2cdcd2 --- /dev/null +++ b/display_configs/CYD-8048S050C_I.toml @@ -0,0 +1,92 @@ +[MCU.esp32] +BOARD = "ESP32_GENERIC_S3" +BOARD_VARIANT = "SPIRAM_OCT" +flash_size = 8 +enable_jtag_repl = 'n' +enable_cdc_repl = 'n' +enable_uart_repl = 'y' +uart_repl_bitrate = 115200 + + +[RGBBus.display_bus] +data0 = 8 +data1 = 3 +data2 = 46 +data3 = 9 +data4 = 1 +data5 = 5 +data6 = 6 +data7 = 7 +data8 = 15 +data9 = 16 +data10 = 4 +data11 = 45 +data12 = 48 +data13 = 47 +data14 = 21 +data15 = 14 +hsync = 39 +vsync = 41 +de = 40 +pclk = 42 +freq = 12000000 +hsync_front_porch = 8 +hsync_back_porch = 8 +hsync_pulse_width = 4 +hsync_idle_low = true +vsync_front_porch = 8 +vsync_back_porch = 8 +vsync_pulse_width = 4 +vsync_idle_low = true +de_idle_high = false +pclk_idle_high = false +pclk_active_low = true + + +[I2C.Bus.i2c_bus] +host = 0 +scl = 20 +sda = 19 +freq = 400000 + + +[I2C.Device.indev_device] +bus = "i2c_bus" +dev_id = "ft6x36.I2C_ADDR" +reg_bits = "ft6x36.BITS" + + +[RGBDisplay.display] +data_bus = "display_bus" +display_width = 800 +display_height = 480 +backlight_pin = 2 +color_space = "lv.COLOR_FORMAT.RGB565" + + +[display.set_power] +params = [true] + + +[display.init] +params = [] + +[FT6x36.indev] +device = "indev_device" + +[indev.firmware_config.fw_config] + +[fw_config.width] +value=800 + +[fw_config.height] +value=480 + +[fw_config.save] +params=[] + +[display.set_backlight] +params = [100] + +[task_handler.TaskHandler] +params=[] diff --git a/display_configs/CYD-8048S070C.toml b/display_configs/CYD-8048S070C.toml new file mode 100644 index 00000000..33cca879 --- /dev/null +++ b/display_configs/CYD-8048S070C.toml @@ -0,0 +1,91 @@ +[MCU.esp32] +BOARD = "ESP32_GENERIC_S3" +BOARD_VARIANT = "SPIRAM_OCT" +flash_size = 8 +enable_jtag_repl = 'n' +enable_cdc_repl = 'n' +enable_uart_repl = 'y' +uart_repl_bitrate = 115200 + +[RGBBus.display_bus] +data0 = 15 +data1 = 7 +data2 = 6 +data3 = 5 +data4 = 4 +data5 = 9 +data6 = 46 +data7 = 3 +data8 = 8 +data9 = 16 +data10 = 1 +data11 = 14 +data12 = 21 +data13 = 47 +data14 = 48 +data15 = 45 +hsync = 39 +vsync = 40 +de = 41 +pclk = 42 +freq = 12000000 +hsync_front_porch = 210 +hsync_back_porch = 16 +hsync_pulse_width = 30 +hsync_idle_low = true +vsync_front_porch = 22 +vsync_back_porch = 10 +vsync_pulse_width = 13 +vsync_idle_low = true +de_idle_high = false +pclk_idle_high = false +pclk_active_low = true + + +[I2C.Bus.i2c_bus] +host = 0 +scl = 20 +sda = 19 +freq = 400000 + + +[I2C.Device.indev_device] +bus = "i2c_bus" +dev_id = "ft6x36.I2C_ADDR" +reg_bits = "ft6x36.BITS" + + +[RGBDisplay.display] +data_bus = "display_bus" +display_width = 800 +display_height = 480 +backlight_pin = 2 +color_space = "lv.COLOR_FORMAT.RGB565" + + +[display.set_power] +params = [true] + + +[display.init] +params = [] + +[FT6x36.indev] +device = "indev_device" + +[indev.firmware_config.fw_config] + +[fw_config.width] +value=800 + +[fw_config.height] +value=480 + +[fw_config.save] +params=[] + +[display.set_backlight] +params = [100] + +[task_handler.TaskHandler] +params=[] diff --git a/display_configs/ER-TFTMC050-3.toml b/display_configs/ER-TFTMC050-3.toml new file mode 100644 index 00000000..0c25d0d7 --- /dev/null +++ b/display_configs/ER-TFTMC050-3.toml @@ -0,0 +1,58 @@ +[MCU.esp32] +BOARD = "ESP32_GENERIC_S3" +BOARD_VARIANT = "SPIRAM_OCT" +flash_size = 16 +enable_jtag_repl = 'n' +enable_cdc_repl = 'n' +enable_uart_repl = 'y' +uart_repl_bitrate = 115200 + +[I2C.Bus.i2c_bus] +host = 0 +scl = 48 +sda = 47 +freq = 400000 + +[I80Bus.display_bus] +data0 = 11 +data1 = 12 +data2 = 13 +data3 = 14 +data4 = 15 +data5 = 16 +data6 = 17 +data7 = 18 +dc = 8 +wr = 6 +cs = -1 +freq = 80000000 + +[I2C.Device.indev_device] +bus = "i2c_bus" +dev_id = "gsl1680.I2C_ADDR" +reg_bits = "gsl1680.BITS" + +[LT7381.display] +data_bus = "display_bus" +display_width = 800 +display_height = 480 +backlight_pin = 4 +reset_pin = 21 +wait_pin = 9 +color_space = "lv.COLOR_FORMAT.RGB565" + +[display.set_power] +params = [true] + +[display.init] +params = ["lt7381.TYPE_ER_TFTMC050_3"] + +[GSL1680.indev] +device = "indev_device" +wake_pin = 10 + +[display.set_backlight] +params = [100] + +[task_handler.TaskHandler] +params=[] diff --git a/display_configs/ESP32-S3-Touch-LCD-4.3.toml b/display_configs/ESP32-S3-Touch-LCD-4.3.toml new file mode 100644 index 00000000..5bfa5bdf --- /dev/null +++ b/display_configs/ESP32-S3-Touch-LCD-4.3.toml @@ -0,0 +1,102 @@ +[MCU.esp32] +BOARD = "ESP32_GENERIC_S3" +BOARD_VARIANT = "SPIRAM_OCT" +flash_size = 8 +enable_jtag_repl = 'n' +enable_cdc_repl = 'n' +enable_uart_repl = 'y' +uart_repl_bitrate = 115200 +CONFIG_FREERTOS_HZ=1000 +CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240 = "y" +CONFIG_ESPTOOLPY_FLASHMODE_QIO = "y" +CONFIG_ESPTOOLPY_FLASHFREQ_120M = "y" +CONFIG_IDF_EXPERIMENTAL_FEATURES = "y" +CONFIG_SPIRAM_SPEED_120M = "y" +CONFIG_SPIRAM_FETCH_INSTRUCTIONS = "y" +CONFIG_SPIRAM_RODATA = "y" +CONFIG_ESP32S3_DATA_CACHE_LINE_64B = "y" +CONFIG_COMPILER_OPTIMIZATION_PERF = "y" + + +[RGBBus.display_bus] +data0 = 14 +data1 = 38 +data2 = 18 +data3 = 17 +data4 = 10 +data5 = 39 +data6 = 0 +data7 = 45 +data8 = 48 +data9 = 47 +data10 = 21 +data11 = 1 +data12 = 2 +data13 = 42 +data14 = 41 +data15 = 40 +hsync = 46 +vsync = 3 +de = 5 +pclk = 7 +freq = 13000000 +hsync_front_porch = 10 +hsync_back_porch = 10 +hsync_pulse_width = 10 +hsync_idle_low = false +vsync_front_porch = 20 +vsync_back_porch = 10 +vsync_pulse_width = 10 +vsync_idle_low = false +de_idle_high = false +pclk_idle_high = false +pclk_active_low = false + + +[I2C.Bus.i2c_bus] +host = 0 +scl = 9 +sda = 8 +freq = 400000 + + +[I2C.Device.indev_device] +bus = "i2c_bus" +dev_id = "ft6x36.I2C_ADDR" +reg_bits = "ft6x36.BITS" + + +[RGBDisplay.display] +data_bus = "display_bus" +display_width = 800 +display_height = 480 +backlight_pin = 2 +color_space = "lv.COLOR_FORMAT.RGB565" +rgb565_byte_swap = true + +[display.set_power] +params = [true] + + +[display.init] +params = [] + +[FT6x36.indev] +device = "indev_device" + +[indev.firmware_config.fw_config] + +[fw_config.width] +value=800 + +[fw_config.height] +value=480 + +[fw_config.save] +params=[] + +[display.set_backlight] +params = [100] + +[task_handler.TaskHandler] +params=[] diff --git a/display_configs/LilyGo-TDeck/LilyGo-TDeck.toml b/display_configs/LilyGo-TDeck/LilyGo-TDeck.toml new file mode 100644 index 00000000..c2b3b7c1 --- /dev/null +++ b/display_configs/LilyGo-TDeck/LilyGo-TDeck.toml @@ -0,0 +1,83 @@ +[MCU.esp32] +FROZEN_MANIFEST = "display_configs/LilyGo-TDeck/manifest.py" + +[SPI.Bus.spi_bus] +host = 1 +mosi = 41 +miso = 38 +sck = 40 + +[SPI.Device.lora_device] +spi_bus = "spi_bus" +freq = 20000000 +cs = 9 + +[SPIBus.display_bus] +spi_bus = "spi_bus" +freq = 40000000 +dc = 11 +cs = 12 + +[SDCard.sdcard] +spi_bus = "spi_bus" +freq = 10000000 +cs = 39 + +[I2C.Bus.i2c_bus] +host = 0 +scl = 8 +sda = 18 +freq = 100000 + +[I2C.Device.touch_device] +bus = "i2c_bus" +dev_id = "gt911.I2C_ADDR" +reg_bits = "gt911.BITS" + +[I2C.Device.keyboard_device] +bus = "i2c_bus" +dev_id = 85 +reg_bits = 8 + +[ST7789.display] +data_bus = "display_bus" +display_width = 320 +display_height = 240 +backlight_pin = 42 +backlight_on_state = "st7789.STATE_PWM" +color_space = "lv.COLOR_FORMAT.RGB565" +color_byte_order = "st7789.BYTE_ORDER_BGR" +rgb565_byte_swap = true + +[display.set_power] +params = [true] + +[display.init] +params = [] + +[gt911.touch] +device = "touch_device" + +[keyboard_s3.Keyboard.keyboard] +device = "keyboard_device" + +[trackball.TrackBall.tball] +up_pin = 3 +down_pin = 2 +left_pin = 15 +right_pin = 1 + +[power.Button.pwr_button] +pin = 10 + +[display.set_backlight] +params = [100] + +[sx1262.SX1262.lora] +spi_device = "lora_device" +gpio = 13 +irq = 45 +rst = 17 + +[task_handler.TaskHandler] +params=[] diff --git a/display_configs/LilyGo-TDeck/README.md b/display_configs/LilyGo-TDeck/README.md new file mode 100644 index 00000000..ce0fed56 --- /dev/null +++ b/display_configs/LilyGo-TDeck/README.md @@ -0,0 +1,4 @@ +To use this board all you need to do is run this build command... + + python3 make.py --custom-board-path=display_configs/LilyGo-TDeck + diff --git a/display_configs/LilyGo-TDeck/board.json b/display_configs/LilyGo-TDeck/board.json new file mode 100644 index 00000000..bc389865 --- /dev/null +++ b/display_configs/LilyGo-TDeck/board.json @@ -0,0 +1,6 @@ +{ + "mcu": "esp32s3", + "product": "Custom ESP32-S3 display board", + "url": "https://www.come_manufacturer.com/board.html", + "vendor": "Vendor name of board" +} diff --git a/display_configs/LilyGo-TDeck/keyboard_c3.py b/display_configs/LilyGo-TDeck/keyboard_c3.py new file mode 100644 index 00000000..dc545077 --- /dev/null +++ b/display_configs/LilyGo-TDeck/keyboard_c3.py @@ -0,0 +1,291 @@ +from micropython import const # NOQA +import machine + +from i2c import I2C + + +I2C_ADDR = const(0x55) +I2C_FREQ = const(100000) + +KEYBOARD_BL_PIN = const(9) +I2C_SDA = const(2) +I2C_SCL = const(10) + +KB_BRIGHTNESS_FREQ = const(1000) +KB_BRIGHTNESS_RES = const(16) # Resolution_bits +KB_BRIGHTNESS_BOOT_DUTY = const(0) +KB_BRIGHTNESS_DEFAULT_DUTY = const(32767) # Alt+B default duty , is duty is zero , use setting duty + +LILYGO_KB_BRIGHTNESS_CMD = const(0x01) +LILYGO_KB_ALT_B_BRIGHTNESS_CMD = const(0x02) + +rows = [0, 3, 19, 12, 18, 6, 7] +rowCount = len(rows) + +cols = [1, 4, 5, 11, 13] +colCount = len(cols) + +keys = [([False] * rowCount)[:]] * colCount + +lastValue = keys[:] +changedValue = keys[:] +keyboard = [([''] * rowCount)[:]] * colCount +keyboard_symbol = keyboard[:] + + +keyboard[0][0] = 'q' +keyboard[0][1] = 'w' +keyboard[0][2] = None # symbol +keyboard[0][3] = 'a' +keyboard[0][4] = None # ALT +keyboard[0][5] = ' ' +keyboard[0][6] = None # Mic + +keyboard[1][0] = 'e' +keyboard[1][1] = 's' +keyboard[1][2] = 'd' +keyboard[1][3] = 'p' +keyboard[1][4] = 'x' +keyboard[1][5] = 'z' +keyboard[1][6] = None # Left Shift + +keyboard[2][0] = 'r' +keyboard[2][1] = 'g' +keyboard[2][2] = 't' +keyboard[2][3] = None # Right Shift +keyboard[2][4] = 'v' +keyboard[2][5] = 'c' +keyboard[2][6] = 'f' + +keyboard[3][0] = 'u' +keyboard[3][1] = 'h' +keyboard[3][2] = 'y' +keyboard[3][3] = None # Enter +keyboard[3][4] = 'b' +keyboard[3][5] = 'n' +keyboard[3][6] = 'j' + +keyboard[4][0] = 'o' +keyboard[4][1] = 'l' +keyboard[4][2] = 'i' +keyboard[4][3] = None # Backspace +keyboard[4][4] = '$' +keyboard[4][5] = 'm' +keyboard[4][6] = 'k' + +keyboard_symbol[0][0] = '#' +keyboard_symbol[0][1] = '1' +keyboard_symbol[0][2] = None +keyboard_symbol[0][3] = '*' +keyboard_symbol[0][4] = None +keyboard_symbol[0][5] = None +keyboard_symbol[0][6] = '0' + +keyboard_symbol[1][0] = '2' +keyboard_symbol[1][1] = '4' +keyboard_symbol[1][2] = '5' +keyboard_symbol[1][3] = '@' +keyboard_symbol[1][4] = '8' +keyboard_symbol[1][5] = '7' +keyboard_symbol[1][6] = None + +keyboard_symbol[2][0] = '3' +keyboard_symbol[2][1] = '/' +keyboard_symbol[2][2] = '(' +keyboard_symbol[2][3] = None +keyboard_symbol[2][4] = '?' +keyboard_symbol[2][5] = '9' +keyboard_symbol[2][6] = '6' + +keyboard_symbol[3][0] = '_' +keyboard_symbol[3][1] = ':' +keyboard_symbol[3][2] = ')' +keyboard_symbol[3][3] = None +keyboard_symbol[3][4] = '!' +keyboard_symbol[3][5] = ',' +keyboard_symbol[3][6] = ';' + +keyboard_symbol[4][0] = '+' +keyboard_symbol[4][1] = '"' +keyboard_symbol[4][2] = '-' +keyboard_symbol[4][3] = None +keyboard_symbol[4][4] = None +keyboard_symbol[4][5] = '.' +keyboard_symbol[4][6] = '\'' + + +BL_state = False +comdata_flag = False +comdata = '' + +kb_brightness_duty = KB_BRIGHTNESS_BOOT_DUTY +kb_brightness_setting_duty = KB_BRIGHTNESS_DEFAULT_DUTY + +for y in range(rowCount): + print(rows[y], "as input") + + rows[y] = machine.Pin(rows[y], machine.Pin.IN) + + +for x in range(colCount): + print(cols[x], "as input-pullup") + cols[x] = (machine.Pin(cols[x], machine.Pin.IN, machine.Pin.PULL_UP)) + + +keyboard_BL_PIN = machine.Pin(KEYBOARD_BL_PIN, machine.Pin.OUT) +keyboard_BL_PIN = machine.PWM(keyboard_BL_PIN, freq=KB_BRIGHTNESS_FREQ, duty_u16=0) + + +i2c_bus = I2C.Bus( + host=0, + sda=_I2C_SDA, + scl=_I2C_SCL, + freq=_I2C_FREQ +) + + +i2c = I2C.Device( + bus=i2c_bus, + dev_id=_I2C_ADDR, + reg_bits=8 +) + + +data_out = bytearray(1) +data_mv = memoryview(data_out) + + +def i2c_send(val): + if isinstance(val, str): + val = ord(val) + + data_out[0] = val + + i2c.write(buf=data_mv) + + +def loop(): + global comdata + global comdata_flag + global BL_state + + readMatrix() + printMatrix() + + # key 3,3 is the enter key + if keyPressed(3, 3): + print('enter') + comdata = 0x0D + comdata_flag = True + + if keyPressed(4, 3): + print("backspace") + comdata = 0x08 + comdata_flag = True + + # Alt+B + if keyActive(0, 4) and keyPressed(3, 4): + print("Alt+B") + # If the software sets the duty cycle to 0, then the value set + # by the ATL+B register is used to ensure that ALT+B can normally light up the backlight. + if BL_state: + BL_state = False + keyboard_BL_PIN.duty_u16(0) # turn off + else: + BL_state = True + if kb_brightness_duty == 0: + print("User set bl duty is zero,use setting duty") + keyboard_BL_PIN.duty_u16(kb_brightness_setting_duty) + else: + print("Duty is not zero ,use user setting bl value") + + comdata_flag = False # Don't send char + + # Alt+C + if keyActive(0, 4) and keyPressed(2, 5): + print("Alt+C") + comdata = 0x0C + comdata_flag = True + + +def onRequest(): + global comdata + global comdata_flag + + if comdata_flag: + i2c_send(comdata) + comdata_flag = False + print("comdata :", comdata) + else: + i2c_send(0x00) + + +def readMatrix(): + # iterate the columns + for colIndex in range(colCount): + # col: set to output to low + + curCol = cols[colIndex] + curCol.init(machine.Pin.OUT) + curCol.value(0) + + # row: interate through the rows + for rowIndex in range(rowCount): + rowCol = rows[rowIndex] + rowCol.init(machine.Pin.IN, pull=machine.Pin.PULL_UP) + + time.sleep_ms(1) # arduino is not fast enought to switch input/output modes so wait 1 ms + + buttonPressed = bool(rowCol.value()) + + keys[colIndex][rowIndex] = buttonPressed + + if lastValue[colIndex][rowIndex] != buttonPressed: + changedValue[colIndex][rowIndex] = True + else: + changedValue[colIndex][rowIndex] = False + + lastValue[colIndex][rowIndex] = buttonPressed + rowCol.init(machine.Pin.IN, pull=machine.Pin.PULL_HOLD) + + # disable the column + curCol.init(machine.Pin.IN) + + +def keyPressed(colIndex, rowIndex): + return changedValue[colIndex][rowIndex] and keys[colIndex][rowIndex] is True + + +def keyActive(colIndex, rowIndex): + return keys[colIndex][rowIndex] is True + + +def isPrintableKey(colIndex, rowIndex): + return keyboard_symbol[colIndex][rowIndex] is not None or keyboard[colIndex][rowIndex] is not None + + +def printMatrix(): + global comdata + global comdata_flag + + for rowIndex in range(rowCount): + for colIndex in range(colCount): + # we only want to print if the key is pressed and it is a printable character + + if keyPressed(colIndex, rowIndex) and isPrintableKey(colIndex, rowIndex): + if keyActive(0, 2): + toPrint = keyboard_symbol[colIndex][rowIndex] + else: + toPrint = keyboard[colIndex][rowIndex] + + # keys 1,6 and 2,3 are Shift keys, so we want to upper case + + if keyActive(1, 6) or keyActive(2, 3): + toPrint = chr(ord(toPrint - 32)) + + print(toPrint) + + comdata = toPrint + comdata_flag = True + +''' \ No newline at end of file diff --git a/display_configs/LilyGo-TDeck/keyboard_s3.py b/display_configs/LilyGo-TDeck/keyboard_s3.py new file mode 100644 index 00000000..c573ce89 --- /dev/null +++ b/display_configs/LilyGo-TDeck/keyboard_s3.py @@ -0,0 +1,97 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + +import lvgl as lv # NOQA +import keypad_framework +from micropython import const # NOQA +import lcd_utils + +_LILYGO_KB_BRIGHTNESS_CMD = const(0x01) +_LILYGO_KB_ALT_B_BRIGHTNESS_CMD = const(0x02) + + +class Keyboard(keypad_framework.KeypadDriver): + def __init__(self, device, debug=False): # NOQA + self._device = device + self._debug = debug + self._brightness = 0 + self._brightness_default = 127 + + super().__init__() + + def set_default_brioghtness(self, value): + value = lcd_utils.remap(float(value), 0.0, 100.0, 30.0, 255.0) + value = int(round(value)) + + # clamp value at 29 - 255 + if value <= 30: + value = 0 + + if value > 255: + value = 255 + + self._brightness_default = value + + value = bytearray([value]) + self._device.write_mem(_LILYGO_KB_ALT_B_BRIGHTNESS_CMD, value) + + def get_brightness_default(self): + value = self._brightness_default + if value == 0: + value = 30 + + value = lcd_utils.remap(float(value), 30.0, 255.0, 0.0, 100.0) + return round(value, 1) + + def set_brightness(self, value): + value = lcd_utils.remap(float(value), 0.0, 100.0, 30.0, 255.0) + value = int(round(value)) + + # clamp value at 29 - 255 + if value <= 30: + value = 0 + + if value > 255: + value = 255 + + self._brightness = value + value = bytearray([value]) + self._device.write_mem(_LILYGO_KB_BRIGHTNESS_CMD, value) + + def get_brightness(self): + value = self._brightness + if value == 0: + value = 30 + + value = lcd_utils.remap(float(value), 30.0, 255.0, 0.0, 100.0) + return round(value, 1) + + def _get_key(self): + # lv.KEY.ESC = 0x1B + # lv.KEY.DEL = 0x7F + # lv.KEY.NEXT = 0x09 + # lv.KEY.PREV = 0x0B + # lv.KEY.HOME = 0x02 + # lv.KEY.END = 0x03 + key = bytearray(self._device.read_mem(0x00, num_bytes=1))[0] + if key == 0x00: # no key + return None + elif key == 0x08: # backspace + key = lv.KEY.BACKSPACE # 0x08 # NOQA + elif key == 0x0D: # enter + key = lv.KEY.ENTER # 0x0A # NOQA + elif key == 0x0C: # alt + c + return None + + if self._debug: + k = key + # check if key is in human readable ascii range and if it + # is then convert it form it's decimal value to the actual ascii + # key else convert to hex + if 127 > k >= 32: + k = chr(k) + else: + k = hex(k) + print('RAW KEY:', hex(k)) + + return self.PRESSED, key + diff --git a/display_configs/LilyGo-TDeck/manifest.py b/display_configs/LilyGo-TDeck/manifest.py new file mode 100644 index 00000000..fedd308f --- /dev/null +++ b/display_configs/LilyGo-TDeck/manifest.py @@ -0,0 +1,6 @@ +freeze('$(MPY_DIR)/../../display_configs/LilyGo-TDeck', 'keyboard_s3.py') +freeze('$(MPY_DIR)/../../display_configs/LilyGo-TDeck', 'sx1262.py') +freeze('$(MPY_DIR)/../../display_configs/LilyGo-TDeck', 'trackball.py') +freeze('$(MPY_DIR)/../../display_configs/LilyGo-TDeck', 'power.py') + + diff --git a/display_configs/LilyGo-TDeck/mpconfigboard.cmake b/display_configs/LilyGo-TDeck/mpconfigboard.cmake new file mode 100644 index 00000000..622abf77 --- /dev/null +++ b/display_configs/LilyGo-TDeck/mpconfigboard.cmake @@ -0,0 +1,17 @@ +set(IDF_TARGET esp32s3) + +set(SDKCONFIG_DEFAULTS + boards/sdkconfig.base + ${SDKCONFIG_IDF_VERSION_SPECIFIC} + boards/sdkconfig.usb + boards/sdkconfig.ble + boards/sdkconfig.spiram_sx + boards/sdkconfig.spiram_oct + boards/sdkconfig.240mhz + boards/LilyGo-TDeck/sdkconfig.board +) + +list(APPEND MICROPY_DEF_BOARD + MICROPY_HW_BOARD_NAME="LilyGo-TDeck" +) + diff --git a/display_configs/LilyGo-TDeck/mpconfigboard.h b/display_configs/LilyGo-TDeck/mpconfigboard.h new file mode 100644 index 00000000..4067bb29 --- /dev/null +++ b/display_configs/LilyGo-TDeck/mpconfigboard.h @@ -0,0 +1,13 @@ +#ifndef MICROPY_HW_BOARD_NAME +// Can be set by mpconfigboard.cmake. +#define MICROPY_HW_BOARD_NAME "LilyGo-TDeck" +#endif +#define MICROPY_HW_MCU_NAME "ESP32S3" + +// Enable UART REPL for modules that have an external USB-UART and don't use native USB. +#define MICROPY_HW_ENABLE_UART_REPL (0) +#define MICROPY_HW_USB_CDC (1) +#define MICROPY_HW_ESP_USB_SERIAL_JTAG (0) + +#define MICROPY_HW_I2C0_SCL (9) +#define MICROPY_HW_I2C0_SDA (8) diff --git a/display_configs/LilyGo-TDeck/partitions.csv b/display_configs/LilyGo-TDeck/partitions.csv new file mode 100644 index 00000000..d8a42d53 --- /dev/null +++ b/display_configs/LilyGo-TDeck/partitions.csv @@ -0,0 +1,5 @@ +# Name,Type,SubType,Offset,Size,Flags +nvs,data,nvs,0x9000,0x6000, +phy_init,data,phy,0xf000,0x1000, +factory,app,factory,0x10000,0x2F0000, +vfs,data,fat,0x300000,0xD00000, diff --git a/display_configs/LilyGo-TDeck/pins.py b/display_configs/LilyGo-TDeck/pins.py new file mode 100644 index 00000000..ccba693c --- /dev/null +++ b/display_configs/LilyGo-TDeck/pins.py @@ -0,0 +1,15 @@ +_C3_INT = const(46) + +_ES7210_DIN = const(14) +_ES2710_LRCK = const(21) +_ES2710_SCLK = const(47) +_ES2710_MCLK = const(48) + +_I2S_WS = const(5) +_I2S_DA = const(6) +_I2S_BCK = const(7) + +_GPIO0 = const(0) + +_UART0_RX = const(43) +_UART0_TX = const(44) diff --git a/display_configs/LilyGo-TDeck/power.py b/display_configs/LilyGo-TDeck/power.py new file mode 100644 index 00000000..e5503605 --- /dev/null +++ b/display_configs/LilyGo-TDeck/power.py @@ -0,0 +1,91 @@ +import machine # NOQA + +import lvgl as lv +import time + + +class Button: + + def __init__(self, pin): + self._pin = machine.Pin(pin, machine.Pin.IN) + + if not lv.is_initialized(): + lv.init() + + # press duration <= this number will call the sleep callback + self._sleep_time = 75 + self._sleep_callback = None + # press duration > sleep_time and <= this number will call the menu callback + self._menu_time = 150 + self._menu_callback = None + # press duration >= this number will call the power off callback + self._power_off_time = 3000 + self._power_off_callback = None + + self._timer = lv.timer_create_basic() + self._timer.pause() + self._timer.set_cb(self.__callback) + self._timer.set_period(33) + self._timer.set_repeat_count(-1) + self._timer.resume() + + def set_menu_time(self, val): + self._menu_time = val + + def get_menu_time(self): + return self._menu_time + + def set_menu_callback(self, cb): + self._menu_callback = cb + + def get_menu_callback(self): + return self._menu_callback + + def set_sleep_time(self, val): + self._sleep_time = val + + def get_sleep_time(self): + return self._sleep_time + + def set_sleep_callback(self, cb): + self._sleep_callback = cb + + def get_sleep_callback(self): + return self._sleep_callback + + def set_power_off_time(self, val): + self._power_off_time = val + + def get_power_off_time(self): + return self._power_off_time + + def set_power_off_callback(self, cb): + self._power_off_callback = cb + + def get_power_off_callback(self): + return self._power_off_callback + + def __callback(self, _): + value = self._pin.value() + + if value: + start_time = time.ticks_ms() # NOQA + + while value: + value = self._pin.value() + time.sleep_ms(1) # NOQA + + end_time = time.ticks_ms() # NOQA + diff = time.ticks_diff(end_time, start_time) # NOQA + + if diff <= self._sleep_time: + if self._sleep_callback is not None: + self._sleep_callback(self._pin) + + elif diff <= self._menu_time: + if self._menu_callback is not None: + self._menu_callback() + + elif diff >= self._power_off_time: + if self._power_off_callback is not None: + self._power_off_callback(self._pin) diff --git a/display_configs/LilyGo-TDeck/sdkconfig.board b/display_configs/LilyGo-TDeck/sdkconfig.board new file mode 100644 index 00000000..2d335377 --- /dev/null +++ b/display_configs/LilyGo-TDeck/sdkconfig.board @@ -0,0 +1,58 @@ + +CONFIG_FREERTOS_HZ=1000 +CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y +CONFIG_ESPTOOLPY_AFTER_NORESET=y + +CONFIG_ESPTOOLPY_FLASHSIZE_2MB=n +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=n +CONFIG_ESPTOOLPY_FLASHSIZE_8MB=n +CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y +CONFIG_ESPTOOLPY_FLASHSIZE_32MB=n +CONFIG_ESPTOOLPY_FLASHSIZE_64MB=n +CONFIG_ESPTOOLPY_FLASHSIZE_128MB=n + +CONFIG_ESPTOOLPY_FLASHMODE_OPI=n +CONFIG_ESPTOOLPY_FLASHMODE_QIO=y +CONFIG_ESPTOOLPY_FLASHMODE_QOUT=n +CONFIG_ESPTOOLPY_FLASHMODE_DIO=n +CONFIG_ESPTOOLPY_FLASHMODE_DOUT=n + +CONFIG_ESPTOOLPY_FLASHFREQ_15M=n +CONFIG_ESPTOOLPY_FLASHFREQ_16M=n +CONFIG_ESPTOOLPY_FLASHFREQ_20M=n +CONFIG_ESPTOOLPY_FLASHFREQ_24M=n +CONFIG_ESPTOOLPY_FLASHFREQ_26M=n +CONFIG_ESPTOOLPY_FLASHFREQ_30M=n +CONFIG_ESPTOOLPY_FLASHFREQ_32M=n +CONFIG_ESPTOOLPY_FLASHFREQ_40M=n +CONFIG_ESPTOOLPY_FLASHFREQ_48M=n +CONFIG_ESPTOOLPY_FLASHFREQ_60M=n +CONFIG_ESPTOOLPY_FLASHFREQ_64M=n +CONFIG_ESPTOOLPY_FLASHFREQ_80M=y +CONFIG_ESPTOOLPY_FLASHFREQ_120M=n + +CONFIG_SPIRAM_SPEED_20M=n +CONFIG_SPIRAM_SPEED_26M=n +CONFIG_SPIRAM_SPEED_40M=n +CONFIG_SPIRAM_SPEED_80M=y +CONFIG_SPIRAM_SPEED_120M=n + +CONFIG_SPIRAM_IGNORE_NOTFOUND=n +CONFIG_SPIRAM_RODATA=y +CONFIG_SPIRAM_FETCH_INSTRUCTIONS=y + +CONFIG_COMPILER_OPTIMIZATION_SIZE=n +CONFIG_COMPILER_OPTIMIZATION_PERF=y +CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT=y + +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="boards/LilyGo-TDeck/partitions.csv" + +CONFIG_LWIP_LOCAL_HOSTNAME="LilyGo-TDeck" + +CONFIG_TINYUSB_DESC_USE_ESPRESSIF_VID=n +CONFIG_TINYUSB_DESC_USE_DEFAULT_PID=n +CONFIG_TINYUSB_DESC_CUSTOM_VID=0x2341 +CONFIG_TINYUSB_DESC_CUSTOM_PID=0x056B +CONFIG_TINYUSB_DESC_MANUFACTURER_STRING="LilyGo" +CONFIG_TINYUSB_DESC_PRODUCT_STRING="TDeck" diff --git a/display_configs/LilyGo-TDeck/sx1262.py b/display_configs/LilyGo-TDeck/sx1262.py new file mode 100644 index 00000000..d90f0399 --- /dev/null +++ b/display_configs/LilyGo-TDeck/sx1262.py @@ -0,0 +1,2409 @@ +from micropython import const # NOQA +import machine +import time + + +def ASSERT(state): + assert state == _ERR_NONE, ERROR[state] + + +def yield_(): + time.sleep_ms(1) + + +_SX126X_FREQUENCY_STEP_SIZE = 0.9536743164 +_SX126X_MAX_PACKET_LENGTH = const(255) +_SX126X_CRYSTAL_FREQ = 32.0 +_SX126X_DIV_EXPONENT = const(25) +_SX126X_CMD_NOP = const(0x00) +_SX126X_CMD_SET_SLEEP = const(0x84) +_SX126X_CMD_SET_STANDBY = const(0x80) +_SX126X_CMD_SET_FS = const(0xC1) +_SX126X_CMD_SET_TX = const(0x83) +_SX126X_CMD_SET_RX = const(0x82) +_SX126X_CMD_STOP_TIMER_ON_PREAMBLE = const(0x9F) +_SX126X_CMD_SET_RX_DUTY_CYCLE = const(0x94) +_SX126X_CMD_SET_CAD = const(0xC5) +_SX126X_CMD_SET_TX_CONTINUOUS_WAVE = const(0xD1) +_SX126X_CMD_SET_TX_INFINITE_PREAMBLE = const(0xD2) +_SX126X_CMD_SET_REGULATOR_MODE = const(0x96) +_SX126X_CMD_CALIBRATE = const(0x89) +_SX126X_CMD_CALIBRATE_IMAGE = const(0x98) +_SX126X_CMD_SET_PA_CONFIG = const(0x95) +_SX126X_CMD_SET_RX_TX_FALLBACK_MODE = const(0x93) +_SX126X_CMD_WRITE_REGISTER = const(0x0D) +_SX126X_CMD_READ_REGISTER = const(0x1D) +_SX126X_CMD_WRITE_BUFFER = const(0x0E) +_SX126X_CMD_READ_BUFFER = const(0x1E) +_SX126X_CMD_SET_DIO_IRQ_PARAMS = const(0x08) +_SX126X_CMD_GET_IRQ_STATUS = const(0x12) +_SX126X_CMD_CLEAR_IRQ_STATUS = const(0x02) +_SX126X_CMD_SET_DIO2_AS_RF_SWITCH_CTRL = const(0x9D) +_SX126X_CMD_SET_DIO3_AS_TCXO_CTRL = const(0x97) +_SX126X_CMD_SET_RF_FREQUENCY = const(0x86) +_SX126X_CMD_SET_PACKET_TYPE = const(0x8A) +_SX126X_CMD_GET_PACKET_TYPE = const(0x11) +_SX126X_CMD_SET_TX_PARAMS = const(0x8E) +_SX126X_CMD_SET_MODULATION_PARAMS = const(0x8B) +_SX126X_CMD_SET_PACKET_PARAMS = const(0x8C) +_SX126X_CMD_SET_CAD_PARAMS = const(0x88) +_SX126X_CMD_SET_BUFFER_BASE_ADDRESS = const(0x8F) +_SX126X_CMD_SET_LORA_SYMB_NUM_TIMEOUT = const(0x0A) +_SX126X_CMD_GET_STATUS = const(0xC0) +_SX126X_CMD_GET_RSSI_INST = const(0x15) +_SX126X_CMD_GET_RX_BUFFER_STATUS = const(0x13) +_SX126X_CMD_GET_PACKET_STATUS = const(0x14) +_SX126X_CMD_GET_DEVICE_ERRORS = const(0x17) +_SX126X_CMD_CLEAR_DEVICE_ERRORS = const(0x07) +_SX126X_CMD_GET_STATS = const(0x10) +_SX126X_CMD_RESET_STATS = const(0x00) +_SX126X_REG_WHITENING_INITIAL_MSB = const(0x06B8) +_SX126X_REG_WHITENING_INITIAL_LSB = const(0x06B9) +_SX126X_REG_CRC_INITIAL_MSB = const(0x06BC) +_SX126X_REG_CRC_INITIAL_LSB = const(0x06BD) +_SX126X_REG_CRC_POLYNOMIAL_MSB = const(0x06BE) +_SX126X_REG_CRC_POLYNOMIAL_LSB = const(0x06BF) +_SX126X_REG_SYNC_WORD_0 = const(0x06C0) +_SX126X_REG_SYNC_WORD_1 = const(0x06C1) +_SX126X_REG_SYNC_WORD_2 = const(0x06C2) +_SX126X_REG_SYNC_WORD_3 = const(0x06C3) +_SX126X_REG_SYNC_WORD_4 = const(0x06C4) +_SX126X_REG_SYNC_WORD_5 = const(0x06C5) +_SX126X_REG_SYNC_WORD_6 = const(0x06C6) +_SX126X_REG_SYNC_WORD_7 = const(0x06C7) +_SX126X_REG_NODE_ADDRESS = const(0x06CD) +_SX126X_REG_BROADCAST_ADDRESS = const(0x06CE) +_SX126X_REG_LORA_SYNC_WORD_MSB = const(0x0740) +_SX126X_REG_LORA_SYNC_WORD_LSB = const(0x0741) +_SX126X_REG_RANDOM_NUMBER_0 = const(0x0819) +_SX126X_REG_RANDOM_NUMBER_1 = const(0x081A) +_SX126X_REG_RANDOM_NUMBER_2 = const(0x081B) +_SX126X_REG_RANDOM_NUMBER_3 = const(0x081C) +_SX126X_REG_RX_GAIN = const(0x08AC) +_SX126X_REG_OCP_CONFIGURATION = const(0x08E7) +_SX126X_REG_XTA_TRIM = const(0x0911) +_SX126X_REG_XTB_TRIM = const(0x0912) +_SX126X_REG_SENSITIVITY_CONFIG = const(0x0889) +_SX126X_REG_TX_CLAMP_CONFIG = const(0x08D8) +_SX126X_REG_RTC_STOP = const(0x0920) +_SX126X_REG_RTC_EVENT = const(0x0944) +_SX126X_REG_IQ_CONFIG = const(0x0736) +_SX126X_REG_RX_GAIN_RETENTION_0 = const(0x029F) +_SX126X_REG_RX_GAIN_RETENTION_1 = const(0x02A0) +_SX126X_REG_RX_GAIN_RETENTION_2 = const(0x02A1) +_SX126X_SLEEP_START_COLD = const(0b00000000) +_SX126X_SLEEP_START_WARM = const(0b00000100) +_SX126X_SLEEP_RTC_OFF = const(0b00000000) +_SX126X_SLEEP_RTC_ON = const(0b00000001) +_SX126X_STANDBY_RC = const(0x00) +_SX126X_STANDBY_XOSC = const(0x01) +_SX126X_RX_TIMEOUT_NONE = const(0x000000) +_SX126X_RX_TIMEOUT_INF = const(0xFFFFFF) +_SX126X_TX_TIMEOUT_NONE = const(0x000000) +_SX126X_STOP_ON_PREAMBLE_OFF = const(0x00) +_SX126X_STOP_ON_PREAMBLE_ON = const(0x01) +_SX126X_REGULATOR_LDO = const(0x00) +_SX126X_REGULATOR_DC_DC = const(0x01) +_SX126X_CALIBRATE_IMAGE_OFF = const(0b00000000) +_SX126X_CALIBRATE_IMAGE_ON = const(0b01000000) +_SX126X_CALIBRATE_ADC_BULK_P_OFF = const(0b00000000) +_SX126X_CALIBRATE_ADC_BULK_P_ON = const(0b00100000) +_SX126X_CALIBRATE_ADC_BULK_N_OFF = const(0b00000000) +_SX126X_CALIBRATE_ADC_BULK_N_ON = const(0b00010000) +_SX126X_CALIBRATE_ADC_PULSE_OFF = const(0b00000000) +_SX126X_CALIBRATE_ADC_PULSE_ON = const(0b00001000) +_SX126X_CALIBRATE_PLL_OFF = const(0b00000000) +_SX126X_CALIBRATE_PLL_ON = const(0b00000100) +_SX126X_CALIBRATE_RC13M_OFF = const(0b00000000) +_SX126X_CALIBRATE_RC13M_ON = const(0b00000010) +_SX126X_CALIBRATE_RC64K_OFF = const(0b00000000) +_SX126X_CALIBRATE_RC64K_ON = const(0b00000001) +_SX126X_CALIBRATE_ALL = const(0b01111111) +_SX126X_CAL_IMG_430_MHZ_1 = const(0x6B) +_SX126X_CAL_IMG_430_MHZ_2 = const(0x6F) +_SX126X_CAL_IMG_470_MHZ_1 = const(0x75) +_SX126X_CAL_IMG_470_MHZ_2 = const(0x81) +_SX126X_CAL_IMG_779_MHZ_1 = const(0xC1) +_SX126X_CAL_IMG_779_MHZ_2 = const(0xC5) +_SX126X_CAL_IMG_863_MHZ_1 = const(0xD7) +_SX126X_CAL_IMG_863_MHZ_2 = const(0xDB) +_SX126X_CAL_IMG_902_MHZ_1 = const(0xE1) +_SX126X_CAL_IMG_902_MHZ_2 = const(0xE9) +_SX126X_PA_CONFIG_HP_MAX = const(0x07) +_SX126X_PA_CONFIG_PA_LUT = const(0x01) +_SX126X_PA_CONFIG_SX1262_8 = const(0x00) +_SX126X_RX_TX_FALLBACK_MODE_FS = const(0x40) +_SX126X_RX_TX_FALLBACK_MODE_STDBY_XOSC = const(0x30) +_SX126X_RX_TX_FALLBACK_MODE_STDBY_RC = const(0x20) +_SX126X_IRQ_TIMEOUT = const(0b1000000000) +_SX126X_IRQ_CAD_DETECTED = const(0b0100000000) +_SX126X_IRQ_CAD_DONE = const(0b0010000000) +_SX126X_IRQ_CRC_ERR = const(0b0001000000) +_SX126X_IRQ_HEADER_ERR = const(0b0000100000) +_SX126X_IRQ_HEADER_VALID = const(0b0000010000) +_SX126X_IRQ_SYNC_WORD_VALID = const(0b0000001000) +_SX126X_IRQ_PREAMBLE_DETECTED = const(0b0000000100) +_SX126X_IRQ_RX_DONE = const(0b0000000010) +_SX126X_IRQ_TX_DONE = const(0b0000000001) +_SX126X_IRQ_ALL = const(0b1111111111) +_SX126X_IRQ_NONE = const(0b0000000000) +_SX126X_DIO2_AS_IRQ = const(0x00) +_SX126X_DIO2_AS_RF_SWITCH = const(0x01) +_SX126X_DIO3_OUTPUT_1_6 = const(0x00) +_SX126X_DIO3_OUTPUT_1_7 = const(0x01) +_SX126X_DIO3_OUTPUT_1_8 = const(0x02) +_SX126X_DIO3_OUTPUT_2_2 = const(0x03) +_SX126X_DIO3_OUTPUT_2_4 = const(0x04) +_SX126X_DIO3_OUTPUT_2_7 = const(0x05) +_SX126X_DIO3_OUTPUT_3_0 = const(0x06) +_SX126X_DIO3_OUTPUT_3_3 = const(0x07) +_SX126X_PACKET_TYPE_GFSK = const(0x00) +_SX126X_PACKET_TYPE_LORA = const(0x01) +_SX126X_PA_RAMP_10U = const(0x00) +_SX126X_PA_RAMP_20U = const(0x01) +_SX126X_PA_RAMP_40U = const(0x02) +_SX126X_PA_RAMP_80U = const(0x03) +_SX126X_PA_RAMP_200U = const(0x04) +_SX126X_PA_RAMP_800U = const(0x05) +_SX126X_PA_RAMP_1700U = const(0x06) +_SX126X_PA_RAMP_3400U = const(0x07) +_SX126X_GFSK_FILTER_NONE = const(0x00) +_SX126X_GFSK_FILTER_GAUSS_0_3 = const(0x08) +_SX126X_GFSK_FILTER_GAUSS_0_5 = const(0x09) +_SX126X_GFSK_FILTER_GAUSS_0_7 = const(0x0A) +_SX126X_GFSK_FILTER_GAUSS_1 = const(0x0B) +_SX126X_GFSK_RX_BW_4_8 = const(0x1F) +_SX126X_GFSK_RX_BW_5_8 = const(0x17) +_SX126X_GFSK_RX_BW_7_3 = const(0x0F) +_SX126X_GFSK_RX_BW_9_7 = const(0x1E) +_SX126X_GFSK_RX_BW_11_7 = const(0x16) +_SX126X_GFSK_RX_BW_14_6 = const(0x0E) +_SX126X_GFSK_RX_BW_19_5 = const(0x1D) +_SX126X_GFSK_RX_BW_23_4 = const(0x15) +_SX126X_GFSK_RX_BW_29_3 = const(0x0D) +_SX126X_GFSK_RX_BW_39_0 = const(0x1C) +_SX126X_GFSK_RX_BW_46_9 = const(0x14) +_SX126X_GFSK_RX_BW_58_6 = const(0x0C) +_SX126X_GFSK_RX_BW_78_2 = const(0x1B) +_SX126X_GFSK_RX_BW_93_8 = const(0x13) +_SX126X_GFSK_RX_BW_117_3 = const(0x0B) +_SX126X_GFSK_RX_BW_156_2 = const(0x1A) +_SX126X_GFSK_RX_BW_187_2 = const(0x12) +_SX126X_GFSK_RX_BW_234_3 = const(0x0A) +_SX126X_GFSK_RX_BW_312_0 = const(0x19) +_SX126X_GFSK_RX_BW_373_6 = const(0x11) +_SX126X_GFSK_RX_BW_467_0 = const(0x09) +_SX126X_LORA_BW_7_8 = const(0x00) +_SX126X_LORA_BW_10_4 = const(0x08) +_SX126X_LORA_BW_15_6 = const(0x01) +_SX126X_LORA_BW_20_8 = const(0x09) +_SX126X_LORA_BW_31_25 = const(0x02) +_SX126X_LORA_BW_41_7 = const(0x0A) +_SX126X_LORA_BW_62_5 = const(0x03) +_SX126X_LORA_BW_125_0 = const(0x04) +_SX126X_LORA_BW_250_0 = const(0x05) +_SX126X_LORA_BW_500_0 = const(0x06) +_SX126X_LORA_CR_4_5 = const(0x01) +_SX126X_LORA_CR_4_6 = const(0x02) +_SX126X_LORA_CR_4_7 = const(0x03) +_SX126X_LORA_CR_4_8 = const(0x04) +_SX126X_LORA_LOW_DATA_RATE_OPTIMIZE_OFF = const(0x00) +_SX126X_LORA_LOW_DATA_RATE_OPTIMIZE_ON = const(0x01) +_SX126X_GFSK_PREAMBLE_DETECT_OFF = const(0x00) +_SX126X_GFSK_PREAMBLE_DETECT_8 = const(0x04) +_SX126X_GFSK_PREAMBLE_DETECT_16 = const(0x05) +_SX126X_GFSK_PREAMBLE_DETECT_24 = const(0x06) +_SX126X_GFSK_PREAMBLE_DETECT_32 = const(0x07) +_SX126X_GFSK_ADDRESS_FILT_OFF = const(0x00) +_SX126X_GFSK_ADDRESS_FILT_NODE = const(0x01) +_SX126X_GFSK_ADDRESS_FILT_NODE_BROADCAST = const(0x02) +_SX126X_GFSK_PACKET_FIXED = const(0x00) +_SX126X_GFSK_PACKET_VARIABLE = const(0x01) +_SX126X_GFSK_CRC_OFF = const(0x01) +_SX126X_GFSK_CRC_1_BYTE = const(0x00) +_SX126X_GFSK_CRC_2_BYTE = const(0x02) +_SX126X_GFSK_CRC_1_BYTE_INV = const(0x04) +_SX126X_GFSK_CRC_2_BYTE_INV = const(0x06) +_SX126X_GFSK_WHITENING_OFF = const(0x00) +_SX126X_GFSK_WHITENING_ON = const(0x01) +_SX126X_LORA_HEADER_EXPLICIT = const(0x00) +_SX126X_LORA_HEADER_IMPLICIT = const(0x01) +_SX126X_LORA_CRC_OFF = const(0x00) +_SX126X_LORA_CRC_ON = const(0x01) +_SX126X_LORA_IQ_STANDARD = const(0x00) +_SX126X_LORA_IQ_INVERTED = const(0x01) +_SX126X_CAD_ON_1_SYMB = const(0x00) +_SX126X_CAD_ON_2_SYMB = const(0x01) +_SX126X_CAD_ON_4_SYMB = const(0x02) +_SX126X_CAD_ON_8_SYMB = const(0x03) +_SX126X_CAD_ON_16_SYMB = const(0x04) +_SX126X_CAD_GOTO_STDBY = const(0x00) +_SX126X_CAD_GOTO_RX = const(0x01) +_SX126X_STATUS_MODE_STDBY_RC = const(0b00100000) +_SX126X_STATUS_MODE_STDBY_XOSC = const(0b00110000) +_SX126X_STATUS_MODE_FS = const(0b01000000) +_SX126X_STATUS_MODE_RX = const(0b01010000) +_SX126X_STATUS_MODE_TX = const(0b01100000) +_SX126X_STATUS_DATA_AVAILABLE = const(0b00000100) +_SX126X_STATUS_CMD_TIMEOUT = const(0b00000110) +_SX126X_STATUS_CMD_INVALID = const(0b00001000) +_SX126X_STATUS_CMD_FAILED = const(0b00001010) +_SX126X_STATUS_TX_DONE = const(0b00001100) +_SX126X_STATUS_SPI_FAILED = const(0b11111111) +_SX126X_GFSK_RX_STATUS_PREAMBLE_ERR = const(0b10000000) +_SX126X_GFSK_RX_STATUS_SYNC_ERR = const(0b01000000) +_SX126X_GFSK_RX_STATUS_ADRS_ERR = const(0b00100000) +_SX126X_GFSK_RX_STATUS_CRC_ERR = const(0b00010000) +_SX126X_GFSK_RX_STATUS_LENGTH_ERR = const(0b00001000) +_SX126X_GFSK_RX_STATUS_ABORT_ERR = const(0b00000100) +_SX126X_GFSK_RX_STATUS_PACKET_RECEIVED = const(0b00000010) +_SX126X_GFSK_RX_STATUS_PACKET_SENT = const(0b00000001) +_SX126X_PA_RAMP_ERR = const(0b100000000) +_SX126X_PLL_LOCK_ERR = const(0b001000000) +_SX126X_XOSC_START_ERR = const(0b000100000) +_SX126X_IMG_CALIB_ERR = const(0b000010000) +_SX126X_ADC_CALIB_ERR = const(0b000001000) +_SX126X_PLL_CALIB_ERR = const(0b000000100) +_SX126X_RC13M_CALIB_ERR = const(0b000000010) +_SX126X_RC64K_CALIB_ERR = const(0b000000001) +_SX126X_SYNC_WORD_PUBLIC = const(0x34) +_SX126X_SYNC_WORD_PRIVATE = const(0x12) + +_ERR_NONE = const(0) +_ERR_UNKNOWN = const(-1) +_ERR_CHIP_NOT_FOUND = const(-2) +_ERR_MEMORY_ALLOCATION_FAILED = const(-3) +_ERR_PACKET_TOO_LONG = const(-4) +_ERR_TX_TIMEOUT = const(-5) +_ERR_RX_TIMEOUT = const(-6) +_ERR_CRC_MISMATCH = const(-7) +_ERR_INVALID_BANDWIDTH = const(-8) +_ERR_INVALID_SPREADING_FACTOR = const(-9) +_ERR_INVALID_CODING_RATE = const(-10) +_ERR_INVALID_BIT_RANGE = const(-11) +_ERR_INVALID_FREQUENCY = const(-12) +_ERR_INVALID_OUTPUT_POWER = const(-13) +_PREAMBLE_DETECTED = const(-14) +_CHANNEL_FREE = const(-15) +_ERR_SPI_WRITE_FAILED = const(-16) +_ERR_INVALID_CURRENT_LIMIT = const(-17) +_ERR_INVALID_PREAMBLE_LENGTH = const(-18) +_ERR_INVALID_GAIN = const(-19) +_ERR_WRONG_MODEM = const(-20) +_ERR_INVALID_NUM_SAMPLES = const(-21) +_ERR_INVALID_RSSI_OFFSET = const(-22) +_ERR_INVALID_ENCODING = const(-23) +_ERR_INVALID_BIT_RATE = const(-101) +_ERR_INVALID_FREQUENCY_DEVIATION = const(-102) +_ERR_INVALID_BIT_RATE_BW_RATIO = const(-103) +_ERR_INVALID_RX_BANDWIDTH = const(-104) +_ERR_INVALID_SYNC_WORD = const(-105) +_ERR_INVALID_DATA_SHAPING = const(-106) +_ERR_INVALID_MODULATION = const(-107) +_ERR_AT_FAILED = const(-201) +_ERR_URL_MALFORMED = const(-202) +_ERR_RESPONSE_MALFORMED_AT = const(-203) +_ERR_RESPONSE_MALFORMED = const(-204) +_ERR_MQTT_CONN_VERSION_REJECTED = const(-205) +_ERR_MQTT_CONN_ID_REJECTED = const(-206) +_ERR_MQTT_CONN_SERVER_UNAVAILABLE = const(-207) +_ERR_MQTT_CONN_BAD_USERNAME_PASSWORD = const(-208) +_ERR_MQTT_CONN_NOT_AUTHORIZED = const(-208) +_ERR_MQTT_UNEXPECTED_PACKET_ID = const(-209) +_ERR_MQTT_NO_NEW_PACKET_AVAILABLE = const(-210) +_ERR_CMD_MODE_FAILED = const(-301) +_ERR_FRAME_MALFORMED = const(-302) +_ERR_FRAME_INCORRECT_CHECKSUM = const(-303) +_ERR_FRAME_UNEXPECTED_ID = const(-304) +_ERR_FRAME_NO_RESPONSE = const(-305) +_ERR_INVALID_RTTY_SHIFT = const(-401) +_ERR_UNSUPPORTED_ENCODING = const(-402) +_ERR_INVALID_DATA_RATE = const(-501) +_ERR_INVALID_ADDRESS_WIDTH = const(-502) +_ERR_INVALID_PIPE_NUMBER = const(-503) +_ERR_ACK_NOT_RECEIVED = const(-504) +_ERR_INVALID_NUM_BROAD_ADDRS = const(-601) +_ERR_INVALID_CRC_CONFIGURATION = const(-701) +_LORA_DETECTED = const(-702) +_ERR_INVALID_TCXO_VOLTAGE = const(-703) +_ERR_INVALID_MODULATION_PARAMETERS = const(-704) +_ERR_SPI_CMD_TIMEOUT = const(-705) +_ERR_SPI_CMD_INVALID = const(-706) +_ERR_SPI_CMD_FAILED = const(-707) +_ERR_INVALID_SLEEP_PERIOD = const(-708) +_ERR_INVALID_RX_PERIOD = const(-709) +_ERR_INVALID_CALLSIGN = const(-801) +_ERR_INVALID_NUM_REPEATERS = const(-802) +_ERR_INVALID_REPEATER_CALLSIGN = const(-803) +_ERR_INVALID_PACKET_TYPE = const(-804) +_ERR_INVALID_PACKET_LENGTH = const(-805) + +ERROR = { + 0: 'ERR_NONE', + -1: 'ERR_UNKNOWN', + -2: 'ERR_CHIP_NOT_FOUND', + -3: 'ERR_MEMORY_ALLOCATION_FAILED', + -4: 'ERR_PACKET_TOO_LONG', + -5: 'ERR_TX_TIMEOUT', + -6: 'ERR_RX_TIMEOUT', + -7: 'ERR_CRC_MISMATCH', + -8: 'ERR_INVALID_BANDWIDTH', + -9: 'ERR_INVALID_SPREADING_FACTOR', + -10: 'ERR_INVALID_CODING_RATE', + -11: 'ERR_INVALID_BIT_RANGE', + -12: 'ERR_INVALID_FREQUENCY', + -13: 'ERR_INVALID_OUTPUT_POWER', + -14: 'PREAMBLE_DETECTED', + -15: 'CHANNEL_FREE', + -16: 'ERR_SPI_WRITE_FAILED', + -17: 'ERR_INVALID_CURRENT_LIMIT', + -18: 'ERR_INVALID_PREAMBLE_LENGTH', + -19: 'ERR_INVALID_GAIN', + -20: 'ERR_WRONG_MODEM', + -21: 'ERR_INVALID_NUM_SAMPLES', + -22: 'ERR_INVALID_RSSI_OFFSET', + -23: 'ERR_INVALID_ENCODING', + -101: 'ERR_INVALID_BIT_RATE', + -102: 'ERR_INVALID_FREQUENCY_DEVIATION', + -103: 'ERR_INVALID_BIT_RATE_BW_RATIO', + -104: 'ERR_INVALID_RX_BANDWIDTH', + -105: 'ERR_INVALID_SYNC_WORD', + -106: 'ERR_INVALID_DATA_SHAPING', + -107: 'ERR_INVALID_MODULATION', + -201: 'ERR_AT_FAILED', + -202: 'ERR_URL_MALFORMED', + -203: 'ERR_RESPONSE_MALFORMED_AT', + -204: 'ERR_RESPONSE_MALFORMED', + -205: 'ERR_MQTT_CONN_VERSION_REJECTED', + -206: 'ERR_MQTT_CONN_ID_REJECTED', + -207: 'ERR_MQTT_CONN_SERVER_UNAVAILABLE', + -208: 'ERR_MQTT_CONN_BAD_USERNAME_PASSWORD', + -208: 'ERR_MQTT_CONN_NOT_AUTHORIZED', + -209: 'ERR_MQTT_UNEXPECTED_PACKET_ID', + -210: 'ERR_MQTT_NO_NEW_PACKET_AVAILABLE', + -301: 'ERR_CMD_MODE_FAILED', + -302: 'ERR_FRAME_MALFORMED', + -303: 'ERR_FRAME_INCORRECT_CHECKSUM', + -304: 'ERR_FRAME_UNEXPECTED_ID', + -305: 'ERR_FRAME_NO_RESPONSE', + -401: 'ERR_INVALID_RTTY_SHIFT', + -402: 'ERR_UNSUPPORTED_ENCODING', + -501: 'ERR_INVALID_DATA_RATE', + -502: 'ERR_INVALID_ADDRESS_WIDTH', + -503: 'ERR_INVALID_PIPE_NUMBER', + -504: 'ERR_ACK_NOT_RECEIVED', + -601: 'ERR_INVALID_NUM_BROAD_ADDRS', + -701: 'ERR_INVALID_CRC_CONFIGURATION', + -702: 'LORA_DETECTED', + -703: 'ERR_INVALID_TCXO_VOLTAGE', + -704: 'ERR_INVALID_MODULATION_PARAMETERS', + -705: 'ERR_SPI_CMD_TIMEOUT', + -706: 'ERR_SPI_CMD_INVALID', + -707: 'ERR_SPI_CMD_FAILED', + -708: 'ERR_INVALID_SLEEP_PERIOD', + -709: 'ERR_INVALID_RX_PERIOD', + -801: 'ERR_INVALID_CALLSIGN', + -802: 'ERR_INVALID_NUM_REPEATERS', + -803: 'ERR_INVALID_REPEATER_CALLSIGN', + -804: 'ERR_INVALID_PACKET_TYPE', + -805: 'ERR_INVALID_PACKET_LENGTH' +} + +2000000 + + +class SX126X: + + def __init__(self, spi_device, irq, rst, gpio): + self._irq = irq + self.spi = spi_device + + self._rx_buf = bytearray(_SX126X_MAX_PACKET_LENGTH) + self._rx_mv = memoryview(self._rx_buf) + self._tx_buf = bytearray(_SX126X_MAX_PACKET_LENGTH) + self._tx_mv = memoryview(self._tx_buf) + + self.irq = machine.Pin(irq, mode=machine.Pin.IN) + self.rst = machine.Pin(rst, mode=machine.Pin.OUT) + self.gpio = machine.Pin(gpio, mode=machine.Pin.IN) + + self._bwKhz = 0 + self._sf = 0 + self._bw = 0 + self._cr = 0 + self._ldro = 0 + self._crcType = 0 + self._preambleLength = 0 + self._tcxoDelay = 0 + self._headerType = 0 + self._implicitLen = 0 + self._txIq = 0 + self._rxIq = 0 + self._invertIQ = 0 + self._ldroAuto = True + + self._br = 0 + self._freqDev = 0 + self._rxBw = 0 + self._rxBwKhz = 0 + self._pulseShape = 0 + self._crcTypeFSK = 0 + self._preambleLengthFSK = 0 + self._addrComp = 0 + self._syncWordLength = 0 + self._whitening = 0 + self._packetType = 0 + self._dataRate = 0 + self._packetLength = 0 + self._preambleDetectorLength = 0 + + def begin( + self, + bw, + sf, + cr, + syncWord, + currentLimit, + preambleLength, + tcxoVoltage, + useRegulatorLDO=False, + txIq=False, + rxIq=False + ): + self._bwKhz = bw + self._sf = sf + + self._bw = _SX126X_LORA_BW_125_0 + self._cr = _SX126X_LORA_CR_4_7 + self._ldro = 0x00 + self._crcType = _SX126X_LORA_CRC_ON + self._preambleLength = preambleLength + self._tcxoDelay = 0 + self._headerType = _SX126X_LORA_HEADER_EXPLICIT + self._implicitLen = 0xFF + + self._txIq = txIq + self._rxIq = rxIq + self._invertIQ = _SX126X_LORA_IQ_STANDARD + + state = self.reset() + ASSERT(state) + + state = self.standby() + ASSERT(state) + + if tcxoVoltage > 0.0: + state = self.setTCXO(tcxoVoltage) + ASSERT(state) + + state = self.config(_SX126X_PACKET_TYPE_LORA) + ASSERT(state) + + if useRegulatorLDO: + state = self.setRegulatorLDO() + else: + state = self.setRegulatorDCDC() + ASSERT(state) + + state = self.setSpreadingFactor(sf) + ASSERT(state) + + state = self.setBandwidth(bw) + ASSERT(state) + + state = self.setCodingRate(cr) + ASSERT(state) + + state = self.setSyncWord(syncWord) + ASSERT(state) + + state = self.setCurrentLimit(currentLimit) + ASSERT(state) + + state = self.setPreambleLength(preambleLength) + ASSERT(state) + + state = self.setDio2AsRfSwitch(True) + ASSERT(state) + + return state + + def beginFSK( + self, + br, + freqDev, + rxBw, + currentLimit, + preambleLength, + dataShaping, + preambleDetectorLength, + tcxoVoltage, + useRegulatorLDO=False + ): + self._br = 21333 + self._freqDev = 52428 + self._rxBw = _SX126X_GFSK_RX_BW_156_2 + self._rxBwKhz = 156.2 + self._pulseShape = _SX126X_GFSK_FILTER_GAUSS_0_5 + self._crcTypeFSK = _SX126X_GFSK_CRC_2_BYTE_INV + self._preambleLengthFSK = preambleLength + self._addrComp = _SX126X_GFSK_ADDRESS_FILT_OFF + self._preambleDetectorLength = preambleDetectorLength + + state = self.reset() + ASSERT(state) + + state = self.standby() + ASSERT(state) + + if tcxoVoltage > 0.0: + state = self.setTCXO(tcxoVoltage) + ASSERT(state) + + state = self.config(_SX126X_PACKET_TYPE_GFSK) + ASSERT(state) + + if useRegulatorLDO: + state = self.setRegulatorLDO() + else: + state = self.setRegulatorDCDC() + ASSERT(state) + + state = self.setBitRate(br) + ASSERT(state) + + state = self.setFrequencyDeviation(freqDev) + ASSERT(state) + + state = self.setRxBandwidth(rxBw) + ASSERT(state) + + state = self.setCurrentLimit(currentLimit) + ASSERT(state) + + state = self.setDataShaping(dataShaping) + ASSERT(state) + + state = self.setPreambleLength(preambleLength) + ASSERT(state) + + sync = [0x2D, 0x01] + state = self.setSyncWord(sync, 2) + ASSERT(state) + + state = self.setWhitening(True, 0x0100) + ASSERT(state) + + state = self.variablePacketLengthMode(_SX126X_MAX_PACKET_LENGTH) + ASSERT(state) + + state = self.setDio2AsRfSwitch(True) + ASSERT(state) + + return state + + def reset(self, verify=True): + self.rst.value(1) + time.sleep_us(150) + self.rst.value(0) + time.sleep_us(150) + self.rst.value(1) + time.sleep_us(150) + + if not verify: + return _ERR_NONE + + start = time.ticks_ms() + while True: + state = self.standby() + if state == _ERR_NONE: + return _ERR_NONE + if abs(time.ticks_diff(start, time.ticks_ms())) >= 3000: + return state + time.sleep_ms(10) + + def transmit(self, data, len_, addr=0): + state = self.standby() + ASSERT(state) + + if len_ > _SX126X_MAX_PACKET_LENGTH: + return _ERR_PACKET_TOO_LONG + + modem = self.getPacketType() + if modem == _SX126X_PACKET_TYPE_LORA: + timeout = int((self.getTimeOnAir(len_) * 3) / 2) + + elif modem == _SX126X_PACKET_TYPE_GFSK: + timeout = int(self.getTimeOnAir(len_) * 5) + + else: + return _ERR_UNKNOWN + + state = self.startTransmit(data, len_, addr) + ASSERT(state) + + start = time.ticks_us() + while not self.irq.value(): + yield_() + if abs(time.ticks_diff(start, time.ticks_us())) > timeout: + self.clearIrqStatus() + self.standby() + return _ERR_TX_TIMEOUT + + elapsed = abs(time.ticks_diff(start, time.ticks_us())) + + self._dataRate = (len_ * 8.0) / (float(elapsed) / 1000000.0) + + state = self.clearIrqStatus() + ASSERT(state) + + state = self.standby() + + return state + + def receive(self, data, len_, timeout_en, timeout_ms): + state = self.standby() + ASSERT(state) + + timeout = 0 + + modem = self.getPacketType() + if modem == _SX126X_PACKET_TYPE_LORA: + symbolLength = float(1 << self._sf) / float(self._bwKhz) + timeout = int(symbolLength * 100.0 * 1000.0) + elif modem == _SX126X_PACKET_TYPE_GFSK: + maxLen = len_ + if len_ == 0: + maxLen = 0xFF + brBps = (float(_SX126X_CRYSTAL_FREQ) * 1000000.0 * 32.0) / float( + self._br + ) + timeout = int(((maxLen * 8.0) / brBps) * 1000000.0 * 5.0) + else: + return _ERR_UNKNOWN + + if timeout_ms == 0: + pass + else: + timeout = timeout_ms * 1000 + + if timeout_en: + timeoutValue = int(float(timeout) / 15.625) + else: + timeoutValue = _SX126X_RX_TIMEOUT_NONE + + state = self.startReceive(timeoutValue) + ASSERT(state) + + start = time.ticks_us() + while not self.irq.value(): + yield_() + if timeout_en: + if abs(time.ticks_diff(start, time.ticks_us())) > timeout: + self.fixImplicitTimeout() + self.clearIrqStatus() + self.standby() + return _ERR_RX_TIMEOUT + + if self._headerType == _SX126X_LORA_HEADER_IMPLICIT and self.getPacketType() == _SX126X_PACKET_TYPE_LORA: + state = self.fixImplicitTimeout() + ASSERT(state) + + return self.readData(data, len_) + + def transmitDirect(self, frf=0): + state = _ERR_NONE + if frf != 0: + state = self.setRfFrequency(frf) + ASSERT(state) + + data = [_SX126X_CMD_NOP] + return self.SPIwriteCommand( + [_SX126X_CMD_SET_TX_CONTINUOUS_WAVE], + 1, + data, + 1 + ) + + def receiveDirect(self): + return _ERR_UNKNOWN + + def scanChannel(self): + if self.getPacketType() != _SX126X_PACKET_TYPE_LORA: + return _ERR_WRONG_MODEM + + state = self.standby() + ASSERT(state) + + state = self.setDioIrqParams( + _SX126X_IRQ_CAD_DETECTED | _SX126X_IRQ_CAD_DONE, + _SX126X_IRQ_CAD_DETECTED | _SX126X_IRQ_CAD_DONE + ) + ASSERT(state) + + state = self.clearIrqStatus() + ASSERT(state) + + state = self.setCad() + ASSERT(state) + + while not self.irq.value(): + yield_() + + cadResult = self.getIrqStatus() + if cadResult & _SX126X_IRQ_CAD_DETECTED: + self.clearIrqStatus() + return _LORA_DETECTED + elif cadResult & _SX126X_IRQ_CAD_DONE: + self.clearIrqStatus() + return _CHANNEL_FREE + + return _ERR_UNKNOWN + + def sleep(self, retainConfig=True): + sleepMode = [_SX126X_SLEEP_START_WARM | _SX126X_SLEEP_RTC_OFF] + if not retainConfig: + sleepMode = [_SX126X_SLEEP_START_COLD | _SX126X_SLEEP_RTC_OFF] + state = self.SPIwriteCommand( + [_SX126X_CMD_SET_SLEEP], + 1, + sleepMode, + 1, + False + ) + + time.sleep_us(500) + + return state + + def standby(self, mode=_SX126X_STANDBY_RC): + data = [mode] + return self.SPIwriteCommand([_SX126X_CMD_SET_STANDBY], 1, data, 1) + + def setDio1Action(self, func): + self.irq.irq( + trigger=machine.Pin.IRQ_RISING, + handler=func + ) # Generic variant uPy + + def clearDio1Action(self): + self.irq = machine.Pin(self._irq, mode=machine.Pin.IN) + + def startTransmit(self, data, len_, addr=0): + if len_ > _SX126X_MAX_PACKET_LENGTH: + return _ERR_PACKET_TOO_LONG + + if ( + self._addrComp != _SX126X_GFSK_ADDRESS_FILT_OFF and + len_ > _SX126X_MAX_PACKET_LENGTH - 1 + ): + return _ERR_PACKET_TOO_LONG + + modem = self.getPacketType() + if modem == _SX126X_PACKET_TYPE_LORA: + if self._txIq: + self._invertIQ = _SX126X_LORA_IQ_INVERTED + else: + self._invertIQ = _SX126X_LORA_IQ_STANDARD + + if self._headerType == _SX126X_LORA_HEADER_IMPLICIT: + if len_ != self._implicitLen: + return _ERR_INVALID_PACKET_LENGTH + + state = self.setPacketParams( + self._preambleLength, + self._crcType, + len_, + self._headerType, + self._invertIQ + ) + elif modem == _SX126X_PACKET_TYPE_GFSK: + if self._packetType == _SX126X_GFSK_PACKET_FIXED: + if len_ != self._packetLength: + return _ERR_INVALID_PACKET_LENGTH + + state = self.setPacketParamsFSK( + self._preambleLengthFSK, + self._crcTypeFSK, + self._syncWordLength, + self._addrComp, + self._whitening, + self._packetType, + len_, + self._preambleDetectorLength + ) + else: + return _ERR_UNKNOWN + ASSERT(state) + + state = self.setDioIrqParams( + _SX126X_IRQ_TX_DONE | _SX126X_IRQ_TIMEOUT, + _SX126X_IRQ_TX_DONE + ) + ASSERT(state) + + state = self.setBufferBaseAddress() + ASSERT(state) + + state = self.writeBuffer(data, len_) + ASSERT(state) + + state = self.clearIrqStatus() + ASSERT(state) + + state = self.fixSensitivity() + ASSERT(state) + + state = self.setTx(_SX126X_TX_TIMEOUT_NONE) + ASSERT(state) + + while self.gpio.value(): + yield_() + + return state + + def startReceive(self, timeout=_SX126X_RX_TIMEOUT_INF): + state = _ERR_NONE + modem = self.getPacketType() + if modem == _SX126X_PACKET_TYPE_LORA: + if self._rxIq: + self._invertIQ = _SX126X_LORA_IQ_INVERTED + else: + self._invertIQ = _SX126X_LORA_IQ_STANDARD + + state = self.setPacketParams( + self._preambleLength, + self._crcType, + self._implicitLen, + self._headerType, + self._invertIQ + ) + elif modem == _SX126X_PACKET_TYPE_GFSK: + state = self.setPacketParamsFSK( + self._preambleLengthFSK, + self._crcTypeFSK, + self._syncWordLength, + self._addrComp, + self._whitening, + self._packetType, + self._packetLength, + self._preambleDetectorLength + ) + else: + return _ERR_UNKNOWN + ASSERT(state) + + state = self.startReceiveCommon() + ASSERT(state) + + state = self.setRx(timeout) + + return state + + def startReceiveDutyCycle(self, rxPeriod, sleepPeriod): + transitionTime = int(self._tcxoDelay + 1000) + sleepPeriod -= transitionTime + + rxPeriodRaw = int((rxPeriod * 8) / 125) + sleepPeriodRaw = int((sleepPeriod * 8) / 125) + + if rxPeriodRaw & 0xFF000000 or rxPeriodRaw == 0: + return _ERR_INVALID_RX_PERIOD + + if sleepPeriodRaw & 0xFF000000 or sleepPeriodRaw == 0: + return _ERR_INVALID_SLEEP_PERIOD + + state = self.startReceiveCommon() + ASSERT(state) + + data = [ + int((rxPeriodRaw >> 16) & 0xFF), + int((rxPeriodRaw >> 8) & 0xFF), + int(rxPeriodRaw & 0xFF), + int((sleepPeriodRaw >> 16) & 0xFF), + int((sleepPeriodRaw >> 8) & 0xFF), + int(sleepPeriodRaw & 0xFF) + ] + return self.SPIwriteCommand([_SX126X_CMD_SET_RX_DUTY_CYCLE], 1, data, 6) + + def startReceiveDutyCycleAuto(self, senderPreambleLength=0, minSymbols=8): + if senderPreambleLength == 0: + senderPreambleLength = self._preambleLength + + sleepSymbols = int(senderPreambleLength - 2 * minSymbols) + + if 2 * minSymbols > senderPreambleLength: + return self.startReceive() + + symbolLength = int(((10 * 1000) << self._sf) / (10 * self._bwKhz)) + sleepPeriod = symbolLength * sleepSymbols + + wakePeriod = int(max( + (symbolLength * (senderPreambleLength + 1) - (sleepPeriod - 1000)) / 2, + symbolLength * (minSymbols + 1) + )) + + if sleepPeriod < (self._tcxoDelay + 1016): + return self.startReceive() + + return self.startReceiveDutyCycle(wakePeriod, sleepPeriod) + + def startReceiveCommon(self): + state = self.setDioIrqParams( + _SX126X_IRQ_RX_DONE | _SX126X_IRQ_TIMEOUT | _SX126X_IRQ_CRC_ERR | _SX126X_IRQ_HEADER_ERR, + _SX126X_IRQ_RX_DONE + ) + + ASSERT(state) + + state = self.setBufferBaseAddress() + ASSERT(state) + + state = self.clearIrqStatus() + + modem = self.getPacketType() + if modem == _SX126X_PACKET_TYPE_LORA: + state = self.setPacketParams( + self._preambleLength, + self._crcType, + self._implicitLen, + self._headerType, + self._invertIQ + ) + elif modem == _SX126X_PACKET_TYPE_GFSK: + state = self.setPacketParamsFSK( + self._preambleLengthFSK, + self._crcTypeFSK, + self._syncWordLength, + self._addrComp, + self._whitening, + self._packetType + ) + else: + return _ERR_UNKNOWN + + return state + + def readData(self, data, len_): + state = self.standby() + ASSERT(state) + + irq = self.getIrqStatus() + crcState = _ERR_NONE + if irq & _SX126X_IRQ_CRC_ERR or irq & _SX126X_IRQ_HEADER_ERR: + crcState = _ERR_CRC_MISMATCH + + length = len_ + if len_ == _SX126X_MAX_PACKET_LENGTH: + length = self.getPacketLength() + + state = self.readBuffer(data, length) + ASSERT(state) + + state = self.clearIrqStatus() + + ASSERT(crcState) + + return state + + def setBandwidth(self, bw): + if self.getPacketType() != _SX126X_PACKET_TYPE_LORA: + return _ERR_WRONG_MODEM + + if not 0 < bw < 510: + return _ERR_INVALID_BANDWIDTH + + bw_div2 = int(bw / 2 + 0.01) + switch = { + 3: _SX126X_LORA_BW_7_8, + 5: _SX126X_LORA_BW_10_4, + 7: _SX126X_LORA_BW_15_6, + 10: _SX126X_LORA_BW_20_8, + 15: _SX126X_LORA_BW_31_25, + 20: _SX126X_LORA_BW_41_7, + 31: _SX126X_LORA_BW_62_5, + 62: _SX126X_LORA_BW_125_0, + 125: _SX126X_LORA_BW_250_0, + 250: _SX126X_LORA_BW_500_0 + } + try: + self._bw = switch[bw_div2] + except: + return _ERR_INVALID_BANDWIDTH + + self._bwKhz = bw + return self.setModulationParams( + self._sf, + self._bw, + self._cr, + self._ldro + ) + + def setSpreadingFactor(self, sf): + if self.getPacketType() != _SX126X_PACKET_TYPE_LORA: + return _ERR_WRONG_MODEM + + if not ((sf >= 5) and (sf <= 12)): + return _ERR_INVALID_SPREADING_FACTOR + + self._sf = sf + return self.setModulationParams( + self._sf, + self._bw, + self._cr, + self._ldro + ) + + def setCodingRate(self, cr): + if self.getPacketType() != _SX126X_PACKET_TYPE_LORA: + return _ERR_WRONG_MODEM + + if not ((cr >= 5) and (cr <= 8)): + return _ERR_INVALID_CODING_RATE + + self._cr = cr - 4 + return self.setModulationParams( + self._sf, + self._bw, + self._cr, + self._ldro + ) + + def setSyncWord(self, syncWord, *args): + if self.getPacketType() == _SX126X_PACKET_TYPE_LORA: + if len(args) > 0: + controlBits = args[0] + else: + controlBits = 0x44 + data = [ + int((syncWord & 0xF0) | ((controlBits & 0xF0) >> 4)), + int(((syncWord & 0x0F) << 4) | (controlBits & 0x0F)) + ] + + return self.writeRegister(_SX126X_REG_LORA_SYNC_WORD_MSB, data, 2) + + elif self.getPacketType() == _SX126X_PACKET_TYPE_GFSK: + len_ = args[0] + if len_ > 8: + return _ERR_INVALID_SYNC_WORD + + state = self.writeRegister(_SX126X_REG_SYNC_WORD_0, syncWord, len_) + ASSERT(state) + + self._syncWordLength = len_ * 8 + state = self.setPacketParamsFSK( + self._preambleLengthFSK, + self._crcTypeFSK, + self._syncWordLength, + self._addrComp, + self._whitening, + self._packetType, + self._packetLength, + self._preambleDetectorLength + ) + + return state + + else: + return _ERR_WRONG_MODEM + + def setCurrentLimit(self, currentLimit): + if not ((currentLimit >= 0) and (currentLimit <= 140)): + return _ERR_INVALID_CURRENT_LIMIT + + rawLimit = [int(currentLimit / 2.5)] + + return self.writeRegister(_SX126X_REG_OCP_CONFIGURATION, rawLimit, 1) + + def getCurrentLimit(self): + ocp = bytearray(1) + ocp_mv = memoryview(ocp) + self.readRegister(_SX126X_REG_OCP_CONFIGURATION, ocp_mv, 1) + + return float(ocp[0]) * 2.5 + + def setPreambleLength(self, preambleLength): + modem = self.getPacketType() + if modem == _SX126X_PACKET_TYPE_LORA: + self._preambleLength = preambleLength + return self.setPacketParams( + self._preambleLength, + self._crcType, + self._implicitLen, + self._headerType, + self._invertIQ + ) + elif modem == _SX126X_PACKET_TYPE_GFSK: + self._preambleLengthFSK = preambleLength + return self.setPacketParamsFSK( + self._preambleLengthFSK, + self._crcTypeFSK, + self._syncWordLength, + self._addrComp, + self._whitening, + self._packetType, + self._packetLength, + self._preambleDetectorLength + ) + + return _ERR_UNKNOWN + + def setFrequencyDeviation(self, freqDev): + if self.getPacketType() != _SX126X_PACKET_TYPE_GFSK: + return _ERR_WRONG_MODEM + + if not (freqDev <= 200.0): + return _ERR_INVALID_FREQUENCY_DEVIATION + + freqDevRaw = int( + ((freqDev * 1000.0) * float(1 << 25)) / (_SX126X_CRYSTAL_FREQ * 1000000.0) + ) + + self._freqDev = freqDevRaw + return self.setModulationParamsFSK( + self._br, + self._pulseShape, + self._rxBw, + self._freqDev + ) + + def setBitRate(self, br): + if self.getPacketType() != _SX126X_PACKET_TYPE_GFSK: + return _ERR_WRONG_MODEM + + if not 0.6 <= br <= 300.0: + return _ERR_INVALID_BIT_RATE + + brRaw = int((_SX126X_CRYSTAL_FREQ * 1000000.0 * 32.0) / (br * 1000.0)) + + self._br = brRaw + + return self.setModulationParamsFSK( + self._br, + self._pulseShape, + self._rxBw, + self._freqDev + ) + + def setRxBandwidth(self, rxBw): + if self.getPacketType() != _SX126X_PACKET_TYPE_GFSK: + return _ERR_WRONG_MODEM + + self._rxBwKhz = rxBw + + if abs(rxBw - 4.8) <= 0.001: + self._rxBw = _SX126X_GFSK_RX_BW_4_8 + elif abs(rxBw - 5.8) <= 0.001: + self._rxBw = _SX126X_GFSK_RX_BW_5_8 + elif abs(rxBw - 7.3) <= 0.001: + self._rxBw = _SX126X_GFSK_RX_BW_7_3 + elif abs(rxBw - 9.7) <= 0.001: + self._rxBw = _SX126X_GFSK_RX_BW_9_7 + elif abs(rxBw - 11.7) <= 0.001: + self._rxBw = _SX126X_GFSK_RX_BW_11_7 + elif abs(rxBw - 14.6) <= 0.001: + self._rxBw = _SX126X_GFSK_RX_BW_14_6 + elif abs(rxBw - 19.5) <= 0.001: + self._rxBw = _SX126X_GFSK_RX_BW_19_5 + elif abs(rxBw - 23.4) <= 0.001: + self._rxBw = _SX126X_GFSK_RX_BW_23_4 + elif abs(rxBw - 29.3) <= 0.001: + self._rxBw = _SX126X_GFSK_RX_BW_29_3 + elif abs(rxBw - 39.0) <= 0.001: + self._rxBw = _SX126X_GFSK_RX_BW_39_0 + elif abs(rxBw - 46.9) <= 0.001: + self._rxBw = _SX126X_GFSK_RX_BW_46_9 + elif abs(rxBw - 58.6) <= 0.001: + self._rxBw = _SX126X_GFSK_RX_BW_58_6 + elif abs(rxBw - 78.2) <= 0.001: + self._rxBw = _SX126X_GFSK_RX_BW_78_2 + elif abs(rxBw - 93.8) <= 0.001: + self._rxBw = _SX126X_GFSK_RX_BW_93_8 + elif abs(rxBw - 117.3) <= 0.001: + self._rxBw = _SX126X_GFSK_RX_BW_117_3 + elif abs(rxBw - 156.2) <= 0.001: + self._rxBw = _SX126X_GFSK_RX_BW_156_2 + elif abs(rxBw - 187.2) <= 0.001: + self._rxBw = _SX126X_GFSK_RX_BW_187_2 + elif abs(rxBw - 234.3) <= 0.001: + self._rxBw = _SX126X_GFSK_RX_BW_234_3 + elif abs(rxBw - 312.0) <= 0.001: + self._rxBw = _SX126X_GFSK_RX_BW_312_0 + elif abs(rxBw - 373.6) <= 0.001: + self._rxBw = _SX126X_GFSK_RX_BW_373_6 + elif abs(rxBw - 467.0) <= 0.001: + self._rxBw = _SX126X_GFSK_RX_BW_467_0 + else: + return _ERR_INVALID_RX_BANDWIDTH + + return self.setModulationParamsFSK( + self._br, + self._pulseShape, + self._rxBw, + self._freqDev + ) + + def setDataShaping(self, sh): + if self.getPacketType() != _SX126X_PACKET_TYPE_GFSK: + return _ERR_WRONG_MODEM + + sh *= 10.0 + if abs(sh - 0.0) <= 0.001: + self._pulseShape = _SX126X_GFSK_FILTER_NONE + elif abs(sh - 3.0) <= 0.001: + self._pulseShape = _SX126X_GFSK_FILTER_GAUSS_0_3 + elif abs(sh - 5.0) <= 0.001: + self._pulseShape = _SX126X_GFSK_FILTER_GAUSS_0_5 + elif abs(sh - 7.0) <= 0.001: + self._pulseShape = _SX126X_GFSK_FILTER_GAUSS_0_7 + elif abs(sh - 10.0) <= 0.001: + self._pulseShape = _SX126X_GFSK_FILTER_GAUSS_1 + else: + return _ERR_INVALID_DATA_SHAPING + + return self.setModulationParamsFSK( + self._br, + self._pulseShape, + self._rxBw, + self._freqDev + ) + + def setSyncBits(self, syncWord, bitsLen): + if self.getPacketType() != _SX126X_PACKET_TYPE_GFSK: + return _ERR_WRONG_MODEM + + if bitsLen > 0x40: + return _ERR_INVALID_SYNC_WORD + + bytesLen = int(bitsLen / 8) + if (bitsLen % 8) != 0: + bytesLen += 1 + + state = self.writeRegister(_SX126X_REG_SYNC_WORD_0, syncWord, bytesLen) + ASSERT(state) + + self._syncWordLength = bitsLen + state = self.setPacketParamsFSK( + self._preambleLengthFSK, + self._crcTypeFSK, + self._syncWordLength, + self._addrComp, + self._whitening, + self._packetType, + self._packetLength, + self._preambleDetectorLength + ) + + return state + + def setNodeAddress(self, nodeAddr): + if self.getPacketType() != _SX126X_PACKET_TYPE_GFSK: + return _ERR_WRONG_MODEM + + self._addrComp = _SX126X_GFSK_ADDRESS_FILT_NODE + + state = self.setPacketParamsFSK( + self._preambleLengthFSK, + self._crcTypeFSK, + self._syncWordLength, + self._addrComp, + self._whitening, + self._packetType, + self._packetLength, + self._preambleDetectorLength + ) + ASSERT(state) + + state = self.writeRegister(_SX126X_REG_NODE_ADDRESS, [nodeAddr], 1) + + return state + + def setBroadcastAddress(self, broadAddr): + if self.getPacketType() != _SX126X_PACKET_TYPE_GFSK: + return _ERR_WRONG_MODEM + + self._addrComp = _SX126X_GFSK_ADDRESS_FILT_NODE_BROADCAST + state = self.setPacketParamsFSK( + self._preambleLengthFSK, + self._crcTypeFSK, + self._syncWordLength, + self._addrComp, + self._whitening, + self._packetType, + self._packetLength, + self._preambleDetectorLength + ) + ASSERT(state) + + state = self.writeRegister(_SX126X_REG_BROADCAST_ADDRESS, [broadAddr], 1) + + return state + + def disableAddressFiltering(self): + if self.getPacketType() != _SX126X_PACKET_TYPE_GFSK: + return _ERR_WRONG_MODEM + + self._addrComp = _SX126X_GFSK_ADDRESS_FILT_OFF + return self.setPacketParamsFSK( + self._preambleLengthFSK, + self._crcTypeFSK, + self._syncWordLength, + self._addrComp, + self._whitening, + self._packetType, + self._packetLength, + self._preambleDetectorLength + ) + + def setCRC(self, len_, initial=0x1D0F, polynomial=0x1021, inverted=True): + modem = self.getPacketType() + + if modem == _SX126X_PACKET_TYPE_GFSK: + if len_ == 0: + self._crcTypeFSK = _SX126X_GFSK_CRC_OFF + elif len_ == 1: + if inverted: + self._crcTypeFSK = _SX126X_GFSK_CRC_1_BYTE_INV + else: + self._crcTypeFSK = _SX126X_GFSK_CRC_1_BYTE + elif len_ == 2: + if inverted: + self._crcTypeFSK = _SX126X_GFSK_CRC_2_BYTE_INV + else: + self._crcTypeFSK = _SX126X_GFSK_CRC_2_BYTE + else: + return _ERR_INVALID_CRC_CONFIGURATION + + state = self.setPacketParamsFSK( + self._preambleLengthFSK, + self._crcTypeFSK, + self._syncWordLength, + self._addrComp, + self._whitening, + self._packetType, + self._packetLength, + self._preambleDetectorLength + ) + ASSERT(state) + + data = [int((initial >> 8) & 0xFF), int(initial & 0xFF)] + state = self.writeRegister(_SX126X_REG_CRC_INITIAL_MSB, data, 2) + ASSERT(state) + + data[0] = int((polynomial >> 8) & 0xFF) + data[1] = int(polynomial & 0xFF) + state = self.writeRegister(_SX126X_REG_CRC_POLYNOMIAL_MSB, data, 2) + + return state + + elif modem == _SX126X_PACKET_TYPE_LORA: + + if len_: + self._crcType = _SX126X_LORA_CRC_ON + else: + self._crcType = _SX126X_LORA_CRC_OFF + + return self.setPacketParams( + self._preambleLength, + self._crcType, + self._implicitLen, + self._headerType, + self._invertIQ + ) + + return _ERR_UNKNOWN + + def setWhitening(self, enabled, initial=0x0100): + if self.getPacketType() != _SX126X_PACKET_TYPE_GFSK: + return _ERR_WRONG_MODEM + + if enabled is not True: + self._whitening = _SX126X_GFSK_WHITENING_OFF + + state = self.setPacketParamsFSK( + self._preambleLengthFSK, + self._crcTypeFSK, + self._syncWordLength, + self._addrComp, + self._whitening, + self._packetType, + self._packetLength, + self._preambleDetectorLength + ) + ASSERT(state) + else: + self._whitening = _SX126X_GFSK_WHITENING_ON + + data = bytearray(1) + data_mv = memoryview(data) + state = self.readRegister( + _SX126X_REG_WHITENING_INITIAL_MSB, + data_mv, + 1 + ) + ASSERT(state) + data2 = [ + (data[0] & 0xFE) | int((initial >> 8) & 0x01), + int(initial & 0xFF) + ] + state = self.writeRegister( + _SX126X_REG_WHITENING_INITIAL_MSB, + data2, + 2 + ) + ASSERT(state) + + state = self.setPacketParamsFSK( + self._preambleLengthFSK, + self._crcTypeFSK, + self._syncWordLength, + self._addrComp, + self._whitening, + self._packetType, + self._packetLength, + self._preambleDetectorLength + ) + ASSERT(state) + return state + + def getDataRate(self): + return self._dataRate + + def getRSSI(self): + packetStatus = self.getPacketStatus() + rssiPkt = int(packetStatus & 0xFF) + return -1.0 * rssiPkt / 2.0 + + def getSNR(self): + if self.getPacketType() != _SX126X_PACKET_TYPE_LORA: + return _ERR_WRONG_MODEM + + packetStatus = self.getPacketStatus() + snrPkt = int((packetStatus >> 8) & 0xFF) + if snrPkt < 128: + return snrPkt / 4.0 + else: + return (snrPkt - 256) / 4.0 + + def getPacketLength(self, update=True): + rxBufStatus = bytearray(2) + rxBufStatus_mv = memoryview(rxBufStatus) + self.SPIreadCommand( + [_SX126X_CMD_GET_RX_BUFFER_STATUS], + 1, + rxBufStatus_mv, + 2 + ) + return rxBufStatus[0] + + def fixedPacketLengthMode(self, len_=_SX126X_MAX_PACKET_LENGTH): + return self.setPacketMode(_SX126X_GFSK_PACKET_FIXED, len_) + + def variablePacketLengthMode(self, maxLen=_SX126X_MAX_PACKET_LENGTH): + return self.setPacketMode(_SX126X_GFSK_PACKET_VARIABLE, maxLen) + + def getTimeOnAir(self, len_): + if self.getPacketType() == _SX126X_PACKET_TYPE_LORA: + symbolLength_us = int( + ((1000 * 10) << self._sf) / (self._bwKhz * 10) + ) + sfCoeff1_x4 = 17 + + sfCoeff2 = 8 + if self._sf == 5 or self._sf == 6: + sfCoeff1_x4 = 25 + sfCoeff2 = 0 + + sfDivisor = 4 * self._sf + if symbolLength_us >= 16000: + sfDivisor = 4 * (self._sf - 2) + + bitsPerCrc = 16 + N_symbol_header = 20 if self._headerType == _SX126X_LORA_HEADER_EXPLICIT else 0 + + bitCount = int( + 8 * len_ + self._crcType * bitsPerCrc - 4 * self._sf + sfCoeff2 + N_symbol_header + ) + if bitCount < 0: + bitCount = 0 + + nPreCodedSymbols = int((bitCount + (sfDivisor - 1)) / sfDivisor) + + nSymbol_x4 = int((self._preambleLength + 8) * 4 + sfCoeff1_x4 + nPreCodedSymbols * (self._cr + 4) * 4) + + return int((symbolLength_us * nSymbol_x4) / 4) + else: + return int((len_ * 8 * self._br) / (_SX126X_CRYSTAL_FREQ * 32)) + + def implicitHeader(self, len_): + return self.setHeaderType(_SX126X_LORA_HEADER_IMPLICIT, len_) + + def explicitHeader(self): + return self.setHeaderType(_SX126X_LORA_HEADER_EXPLICIT) + + def setRegulatorLDO(self): + return self.setRegulatorMode(_SX126X_REGULATOR_LDO) + + def setRegulatorDCDC(self): + return self.setRegulatorMode(_SX126X_REGULATOR_DC_DC) + + def setEncoding(self, encoding): + return self.setWhitening(encoding) + + def forceLDRO(self, enable): + if self.getPacketType() != _SX126X_PACKET_TYPE_LORA: + return _ERR_WRONG_MODEM + + self._ldroAuto = False + self._ldro = enable + return self.setModulationParams( + self._sf, + self._bw, + self._cr, + self._ldro + ) + + def autoLDRO(self): + if self.getPacketType() != _SX126X_PACKET_TYPE_LORA: + return _ERR_WRONG_MODEM + + self._ldroAuto = True + return self.setModulationParams( + self._sf, + self._bw, + self._cr, + self._ldro + ) + + def setTCXO(self, voltage, delay=5000): + self.standby() + + if self.getDeviceErrors() & _SX126X_XOSC_START_ERR: + self.clearDeviceErrors() + + if abs(voltage - 0.0) <= 0.001: + return self.reset() + + data = [0, 0, 0, 0] + if abs(voltage - 1.6) <= 0.001: + data[0] = _SX126X_DIO3_OUTPUT_1_6 + elif abs(voltage - 1.7) <= 0.001: + data[0] = _SX126X_DIO3_OUTPUT_1_7 + elif abs(voltage - 1.8) <= 0.001: + data[0] = _SX126X_DIO3_OUTPUT_1_8 + elif abs(voltage - 2.2) <= 0.001: + data[0] = _SX126X_DIO3_OUTPUT_2_2 + elif abs(voltage - 2.4) <= 0.001: + data[0] = _SX126X_DIO3_OUTPUT_2_4 + elif abs(voltage - 2.7) <= 0.001: + data[0] = _SX126X_DIO3_OUTPUT_2_7 + elif abs(voltage - 3.0) <= 0.001: + data[0] = _SX126X_DIO3_OUTPUT_3_0 + elif abs(voltage - 3.3) <= 0.001: + data[0] = _SX126X_DIO3_OUTPUT_3_3 + else: + return _ERR_INVALID_TCXO_VOLTAGE + + delayValue = int(float(delay) / 15.625) + data[1] = int((delayValue >> 16) & 0xFF) + data[2] = int((delayValue >> 8) & 0xFF) + data[3] = int(delayValue & 0xFF) + + self._tcxoDelay = delay + + return self.SPIwriteCommand( + [_SX126X_CMD_SET_DIO3_AS_TCXO_CTRL], + 1, + data, + 4 + ) + + def setDio2AsRfSwitch(self, enable=True): + data = [0] + if enable: + data = [_SX126X_DIO2_AS_RF_SWITCH] + else: + data = [_SX126X_DIO2_AS_IRQ] + return self.SPIwriteCommand( + [_SX126X_CMD_SET_DIO2_AS_RF_SWITCH_CTRL], + 1, + data, + 1 + ) + + def setTx(self, timeout=0): + data = [ + int((timeout >> 16) & 0xFF), + int((timeout >> 8) & 0xFF), + int(timeout & 0xFF) + ] + + return self.SPIwriteCommand([_SX126X_CMD_SET_TX], 1, data, 3) + + def setRx(self, timeout): + data = [ + int((timeout >> 16) & 0xFF), + int((timeout >> 8) & 0xFF), + int(timeout & 0xFF) + ] + + return self.SPIwriteCommand([_SX126X_CMD_SET_RX], 1, data, 3) + + def setCad(self): + return self.SPIwriteCommand([_SX126X_CMD_SET_CAD], 1, [], 0) + + def setPaConfig( + self, + paDutyCycle, + deviceSel, + hpMax=_SX126X_PA_CONFIG_HP_MAX, + paLut=_SX126X_PA_CONFIG_PA_LUT + ): + data = [paDutyCycle, hpMax, deviceSel, paLut] + return self.SPIwriteCommand([_SX126X_CMD_SET_PA_CONFIG], 1, data, 4) + + def writeRegister(self, addr, data, numBytes): + cmd = [ + _SX126X_CMD_WRITE_REGISTER, int((addr >> 8) & 0xFF), + int(addr & 0xFF) + ] + state = self.SPIwriteCommand(cmd, 3, data, numBytes) + return state + + def readRegister(self, addr, data, numBytes): + cmd = [ + _SX126X_CMD_READ_REGISTER, int((addr >> 8) & 0xFF), + int(addr & 0xFF) + ] + return self.SPItransfer(cmd, 3, False, [], data, numBytes, True) + + def writeBuffer(self, data, numBytes, offset=0x00): + cmd = [_SX126X_CMD_WRITE_BUFFER, offset] + state = self.SPIwriteCommand(cmd, 2, data, numBytes) + + return state + + def readBuffer(self, data, numBytes): + cmd = [_SX126X_CMD_READ_BUFFER, _SX126X_CMD_NOP] + state = self.SPIreadCommand(cmd, 2, data, numBytes) + + return state + + def setDioIrqParams( + self, + irqMask, + dio1Mask, + dio2Mask=_SX126X_IRQ_NONE, + dio3Mask=_SX126X_IRQ_NONE + ): + data = [ + (irqMask >> 8) & 0xFF, + irqMask & 0xFF, + (dio1Mask >> 8) & 0xFF, + dio1Mask & 0xFF, + (dio2Mask >> 8) & 0xFF, + dio2Mask & 0xFF, + (dio3Mask >> 8) & 0xFF, + dio3Mask & 0xFF + ] + return self.SPIwriteCommand([_SX126X_CMD_SET_DIO_IRQ_PARAMS], 1, data, 8) + + def getIrqStatus(self): + data = bytearray(2) + data_mv = memoryview(data) + self.SPIreadCommand([_SX126X_CMD_GET_IRQ_STATUS], 1, data_mv, 2) + return (data[0] << 8) | data[1] + + def clearIrqStatus(self, clearIrqParams=_SX126X_IRQ_ALL): + data = [ + (clearIrqParams >> 8) & 0xFF, + clearIrqParams & 0xFF + ] + return self.SPIwriteCommand([_SX126X_CMD_CLEAR_IRQ_STATUS], 1, data, 2) + + def setRfFrequency(self, frf): + data = [ + (frf >> 24) & 0xFF, + (frf >> 16) & 0xFF, + (frf >> 8) & 0xFF, + frf & 0xFF + ] + return self.SPIwriteCommand([_SX126X_CMD_SET_RF_FREQUENCY], 1, data, 4) + + def calibrateImage(self, data): + return self.SPIwriteCommand([_SX126X_CMD_CALIBRATE_IMAGE], 1, data, 2) + + def getPacketType(self): + data = bytearray([0xFF]) + data_mv = memoryview(data) + self.SPIreadCommand([_SX126X_CMD_GET_PACKET_TYPE], 1, data_mv, 1) + return data[0] + + def setTxParams(self, power, rampTime=_SX126X_PA_RAMP_200U): + if power < 0: + power += 256 + data = [power, rampTime] + return self.SPIwriteCommand([_SX126X_CMD_SET_TX_PARAMS], 1, data, 2) + + def setPacketMode(self, mode, len_): + if self.getPacketType() != _SX126X_PACKET_TYPE_GFSK: + return _ERR_WRONG_MODEM + + state = self.setPacketParamsFSK( + self._preambleLengthFSK, + self._crcTypeFSK, + self._syncWordLength, + self._addrComp, + self._whitening, + mode, + len_, + self._preambleDetectorLength + ) + ASSERT(state) + + self._packetType = mode + self._packetLength = len_ + return state + + def setHeaderType(self, headerType, len_=0xFF): + if self.getPacketType() != _SX126X_PACKET_TYPE_LORA: + return _ERR_WRONG_MODEM + + state = self.setPacketParams( + self._preambleLength, + self._crcType, + len_, + headerType, + self._invertIQ + ) + ASSERT(state) + + self._headerType = headerType + self._implicitLen = len_ + + return state + + def setModulationParams(self, sf, bw, cr, ldro): + if self._ldroAuto: + symbolLength = float((1 << self._sf)) / float(self._bwKhz) + if symbolLength >= 16.0: + self._ldro = _SX126X_LORA_LOW_DATA_RATE_OPTIMIZE_ON + else: + self._ldro = _SX126X_LORA_LOW_DATA_RATE_OPTIMIZE_OFF + else: + self._ldro = ldro + + data = [sf, bw, cr, self._ldro] + return self.SPIwriteCommand( + [_SX126X_CMD_SET_MODULATION_PARAMS], + 1, + data, + 4 + ) + + def setModulationParamsFSK(self, br, pulseShape, rxBw, freqDev): + data = [ + (br >> 16) & 0xFF, + (br >> 8) & 0xFF, + br & 0xFF, + pulseShape, + rxBw, + (freqDev >> 16) & 0xFF, + (freqDev >> 8) & 0xFF, + freqDev & 0xFF + ] + + return self.SPIwriteCommand( + [_SX126X_CMD_SET_MODULATION_PARAMS], + 1, + data, + 8 + ) + + def setPacketParams( + self, + preambleLength, + crcType, + payloadLength, + headerType, + invertIQ=_SX126X_LORA_IQ_STANDARD + ): + state = self.fixInvertedIQ(invertIQ) + ASSERT(state) + data = [ + (preambleLength >> 8) & 0xFF, + preambleLength & 0xFF, + headerType, + payloadLength, + crcType, + invertIQ + ] + + return self.SPIwriteCommand([_SX126X_CMD_SET_PACKET_PARAMS], 1, data, 6) + + def setPacketParamsFSK( + self, + preambleLength, + crcType, + syncWordLength, + addrComp, + whitening, + packetType=_SX126X_GFSK_PACKET_VARIABLE, + payloadLength=0xFF, + preambleDetectorLength=_SX126X_GFSK_PREAMBLE_DETECT_16 + ): + data = [ + (preambleLength >> 8) & 0xFF, + preambleLength & 0xFF, + preambleDetectorLength, + syncWordLength, + addrComp, + packetType, + payloadLength, + crcType, + whitening + ] + return self.SPIwriteCommand([_SX126X_CMD_SET_PACKET_PARAMS], 1, data, 9) + + def setBufferBaseAddress(self, txBaseAddress=0x00, rxBaseAddress=0x00): + data = [txBaseAddress, rxBaseAddress] + return self.SPIwriteCommand( + [_SX126X_CMD_SET_BUFFER_BASE_ADDRESS], + 1, + data, + 2 + ) + + def setRegulatorMode(self, mode): + data = [mode] + return self.SPIwriteCommand([_SX126X_CMD_SET_REGULATOR_MODE], 1, data, 1) + + def getStatus(self): + data = bytearray(1) + data_mv = memoryview(data) + self.SPIreadCommand([_SX126X_CMD_GET_STATUS], 1, data_mv, 1) + return data[0] + + def getPacketStatus(self): + data = bytearray(3) + data_mv = memoryview(data) + self.SPIreadCommand([_SX126X_CMD_GET_PACKET_STATUS], 1, data_mv, 3) + return (data[0] << 16) | (data[1] << 8) | data[2] + + def getDeviceErrors(self): + data = bytearray(2) + data_mv = memoryview(data) + self.SPIreadCommand([_SX126X_CMD_GET_DEVICE_ERRORS], 1, data_mv, 2) + opError = ((data[0] & 0xFF) << 8) & data[1] + return opError + + def clearDeviceErrors(self): + data = [_SX126X_CMD_NOP, _SX126X_CMD_NOP] + return self.SPIwriteCommand( + [_SX126X_CMD_CLEAR_DEVICE_ERRORS], + 1, + data, + 2 + ) + + def setFrequencyRaw(self, freq): + frf = int((freq * (1 << _SX126X_DIV_EXPONENT)) / _SX126X_CRYSTAL_FREQ) + return self.setRfFrequency(frf) + + def fixSensitivity(self): + sensitivityConfig = bytearray(1) + sensitivityConfig_mv = memoryview(sensitivityConfig) + state = self.readRegister( + _SX126X_REG_SENSITIVITY_CONFIG, + sensitivityConfig_mv, + 1 + ) + ASSERT(state) + + if self.getPacketType() == _SX126X_PACKET_TYPE_LORA and abs(self._bwKhz - 500.0) <= 0.001: + sensitivityConfig_mv[0] &= 0xFB + else: + sensitivityConfig_mv[0] |= 0x04 + return self.writeRegister( + _SX126X_REG_SENSITIVITY_CONFIG, + sensitivityConfig, + 1 + ) + + def fixPaClamping(self): + clampConfig = bytearray(1) + clampConfig_mv = memoryview(clampConfig) + state = self.readRegister(_SX126X_REG_TX_CLAMP_CONFIG, clampConfig_mv, 1) + ASSERT(state) + + clampConfig_mv[0] |= 0x1E + return self.writeRegister(_SX126X_REG_TX_CLAMP_CONFIG, clampConfig, 1) + + def fixImplicitTimeout(self): + if not ( + self._headerType == _SX126X_LORA_HEADER_IMPLICIT and + self.getPacketType() == _SX126X_PACKET_TYPE_LORA + ): + return _ERR_WRONG_MODEM + + rtcStop = [0x00] + state = self.writeRegister(_SX126X_REG_RTC_STOP, rtcStop, 1) + ASSERT(state) + + rtcEvent = bytearray(1) + rtcEvent_mv = memoryview(rtcEvent) + state = self.readRegister(_SX126X_REG_RTC_EVENT, rtcEvent_mv, 1) + ASSERT(state) + + rtcEvent_mv[0] |= 0x02 + return self.writeRegister(_SX126X_REG_RTC_EVENT, rtcEvent, 1) + + def fixInvertedIQ(self, iqConfig): + iqConfigCurrent = bytearray(1) + iqConfigCurrent_mv = memoryview(iqConfigCurrent) + state = self.readRegister(_SX126X_REG_IQ_CONFIG, iqConfigCurrent_mv, 1) + ASSERT(state) + + if iqConfig == _SX126X_LORA_IQ_STANDARD: + iqConfigCurrent_mv[0] &= 0xFB + else: + iqConfigCurrent_mv[0] |= 0x04 + + return self.writeRegister(_SX126X_REG_IQ_CONFIG, iqConfigCurrent, 1) + + def config(self, modem): + state = self.setBufferBaseAddress() + ASSERT(state) + + data = [0, 0, 0, 0, 0, 0, 0] + data[0] = modem + state = self.SPIwriteCommand([_SX126X_CMD_SET_PACKET_TYPE], 1, data, 1) + ASSERT(state) + + data[0] = _SX126X_RX_TX_FALLBACK_MODE_STDBY_RC + state = self.SPIwriteCommand( + [_SX126X_CMD_SET_RX_TX_FALLBACK_MODE], + 1, + data, + 1 + ) + ASSERT(state) + + data[0] = _SX126X_CAD_ON_8_SYMB + data[1] = self._sf + 13 + data[2] = 10 + data[3] = _SX126X_CAD_GOTO_STDBY + data[4] = 0x00 + data[5] = 0x00 + data[6] = 0x00 + state = self.SPIwriteCommand([_SX126X_CMD_SET_CAD_PARAMS], 1, data, 7) + ASSERT(state) + + state = self.clearIrqStatus() + state |= self.setDioIrqParams(_SX126X_IRQ_NONE, _SX126X_IRQ_NONE) + ASSERT(state) + + data[0] = _SX126X_CALIBRATE_ALL + state = self.SPIwriteCommand([_SX126X_CMD_CALIBRATE], 1, data, 1) + ASSERT(state) + + time.sleep_ms(5) + + while self.gpio.value(): + yield_() + + return _ERR_NONE + + def SPIwriteCommand(self, cmd, cmdLen, data, numBytes, waitForBusy=True): + return self.SPItransfer(cmd, cmdLen, True, data, [], numBytes, waitForBusy) + + def SPIreadCommand(self, cmd, cmdLen, data, numBytes, waitForBusy=True): + return self.SPItransfer(cmd, cmdLen, False, [], data, numBytes, waitForBusy) + + def SPItransfer( + self, + cmd, + cmdLen, + write, + dataOut, + dataIn, + numBytes, + waitForBusy, + timeout=5000 + ): + start = time.ticks_ms() + while self.gpio.value(): + yield_() + if time.ticks_diff(time.ticks_ms(), start) >= timeout: + self.cs.value(1) + return _ERR_SPI_CMD_TIMEOUT + + for i in range(cmdLen): + self.spi.write(bytes([cmd[i]])) + + status = 0 + + if write: + for i in range(numBytes): + try: + in_ = self.spi.read(1, dataOut[i]) + except: + in_ = self.spi.read(1, write=dataOut[i]) + + if ( + in_[0] & 0b00001110 == _SX126X_STATUS_CMD_TIMEOUT or + in_[0] & 0b00001110 == _SX126X_STATUS_CMD_INVALID or + in_[0] & 0b00001110 == _SX126X_STATUS_CMD_FAILED + ): + status = in_[0] & 0b00001110 + break + elif in_[0] == 0x00 or in_[0] == 0xFF: + status = _SX126X_STATUS_SPI_FAILED + break + else: + + try: + in_ = self.spi.read(1, _SX126X_CMD_NOP) + except: + in_ = self.spi.read(1, write=_SX126X_CMD_NOP) + + if ( + in_[0] & 0b00001110 == _SX126X_STATUS_CMD_TIMEOUT or + in_[0] & 0b00001110 == _SX126X_STATUS_CMD_INVALID or + in_[0] & 0b00001110 == _SX126X_STATUS_CMD_FAILED + ): + status = in_[0] & 0b00001110 + elif in_[0] == 0x00 or in_[0] == 0xFF: + status = _SX126X_STATUS_SPI_FAILED + else: + for i in range(numBytes): + try: + dataIn[i] = self.spi.read(1, _SX126X_CMD_NOP)[0] + except: + dataIn[i] = self.spi.read(1, write=_SX126X_CMD_NOP)[0] + + if waitForBusy: + time.sleep_us(1) + start = time.ticks_ms() + while self.gpio.value(): + yield_() + if time.ticks_diff(time.ticks_ms(), start) >= timeout: + status = _SX126X_STATUS_CMD_TIMEOUT + break + + switch = { + _SX126X_STATUS_CMD_TIMEOUT: _ERR_SPI_CMD_TIMEOUT, + _SX126X_STATUS_CMD_INVALID: _ERR_SPI_CMD_INVALID, + _SX126X_STATUS_CMD_FAILED: _ERR_SPI_CMD_FAILED, + _SX126X_STATUS_SPI_FAILED: _ERR_CHIP_NOT_FOUND + } + try: + return switch[status] + except: + return _ERR_NONE + + +_SX126X_PA_CONFIG_SX1262 = const(0x00) + + +class SX1262(SX126X): + TX_DONE = _SX126X_IRQ_TX_DONE + RX_DONE = _SX126X_IRQ_RX_DONE + ADDR_FILT_OFF = _SX126X_GFSK_ADDRESS_FILT_OFF + ADDR_FILT_NODE = _SX126X_GFSK_ADDRESS_FILT_NODE + ADDR_FILT_NODE_BROAD = _SX126X_GFSK_ADDRESS_FILT_NODE_BROADCAST + PREAMBLE_DETECT_OFF = _SX126X_GFSK_PREAMBLE_DETECT_OFF + PREAMBLE_DETECT_8 = _SX126X_GFSK_PREAMBLE_DETECT_8 + PREAMBLE_DETECT_16 = _SX126X_GFSK_PREAMBLE_DETECT_16 + PREAMBLE_DETECT_24 = _SX126X_GFSK_PREAMBLE_DETECT_24 + PREAMBLE_DETECT_32 = _SX126X_GFSK_PREAMBLE_DETECT_32 + STATUS = ERROR + + def __init__(self, spi_device, irq, rst, gpio): + super().__init__(spi_device, irq, rst, gpio) + self._callbackFunction = self._dummyFunction + + def begin( + self, + freq=434.0, + bw=125.0, + sf=9, + cr=7, + syncWord=_SX126X_SYNC_WORD_PRIVATE, + power=14, + currentLimit=60.0, + preambleLength=8, + implicit=False, + implicitLen=0xFF, + crcOn=True, + txIq=False, + rxIq=False, + tcxoVoltage=1.6, + useRegulatorLDO=False, + blocking=True + ): + state = super().begin(bw, sf, cr, syncWord, currentLimit, + preambleLength, tcxoVoltage, useRegulatorLDO, + txIq, rxIq) + ASSERT(state) + + if not implicit: + state = super().explicitHeader() + else: + state = super().implicitHeader(implicitLen) + ASSERT(state) + + state = super().setCRC(crcOn) + ASSERT(state) + + state = self.setFrequency(freq) + ASSERT(state) + + state = self.setOutputPower(power) + ASSERT(state) + + state = super().fixPaClamping() + ASSERT(state) + + state = self.setBlockingCallback(blocking) + + return state + + def beginFSK( + self, + freq=434.0, + br=48.0, + freqDev=50.0, + rxBw=156.2, + power=14, + currentLimit=60.0, + preambleLength=16, + dataShaping=0.5, + syncWord=[0x2D, 0x01], + syncBitsLength=16, + addrFilter=_SX126X_GFSK_ADDRESS_FILT_OFF, + addr=0x00, + crcLength=2, + crcInitial=0x1D0F, + crcPolynomial=0x1021, + crcInverted=True, + whiteningOn=True, + whiteningInitial=0x0100, + fixedPacketLength=False, + packetLength=0xFF, + preambleDetectorLength=_SX126X_GFSK_PREAMBLE_DETECT_16, + tcxoVoltage=1.6, + useRegulatorLDO=False, + blocking=True + ): + state = super().beginFSK(br, freqDev, rxBw, currentLimit, + preambleLength, dataShaping, + preambleDetectorLength, tcxoVoltage, + useRegulatorLDO) + ASSERT(state) + + state = super().setSyncBits(syncWord, syncBitsLength) + ASSERT(state) + + if addrFilter == _SX126X_GFSK_ADDRESS_FILT_OFF: + state = super().disableAddressFiltering() + elif addrFilter == _SX126X_GFSK_ADDRESS_FILT_NODE: + state = super().setNodeAddress(addr) + elif addrFilter == _SX126X_GFSK_ADDRESS_FILT_NODE_BROADCAST: + state = super().setBroadcastAddress(addr) + else: + state = _ERR_UNKNOWN + + ASSERT(state) + + state = super().setCRC(crcLength, crcInitial, + crcPolynomial, crcInverted) + ASSERT(state) + + state = super().setWhitening(whiteningOn, whiteningInitial) + ASSERT(state) + + if fixedPacketLength: + state = super().fixedPacketLengthMode(packetLength) + else: + state = super().variablePacketLengthMode(packetLength) + + ASSERT(state) + + state = self.setFrequency(freq) + ASSERT(state) + + state = self.setOutputPower(power) + ASSERT(state) + + state = super().fixPaClamping() + ASSERT(state) + + state = self.setBlockingCallback(blocking) + + return state + + def setFrequency(self, freq, calibrate=True): + if freq < 150.0 or freq > 960.0: + return _ERR_INVALID_FREQUENCY + + if calibrate: + data = self._tx_buf + if freq > 900.0: + data[0] = _SX126X_CAL_IMG_902_MHZ_1 + data[1] = _SX126X_CAL_IMG_902_MHZ_2 + elif freq > 850.0: + data[0] = _SX126X_CAL_IMG_863_MHZ_1 + data[1] = _SX126X_CAL_IMG_863_MHZ_2 + elif freq > 770.0: + data[0] = _SX126X_CAL_IMG_779_MHZ_1 + data[1] = _SX126X_CAL_IMG_779_MHZ_2 + elif freq > 460.0: + data[0] = _SX126X_CAL_IMG_470_MHZ_1 + data[1] = _SX126X_CAL_IMG_470_MHZ_2 + else: + data[0] = _SX126X_CAL_IMG_430_MHZ_1 + data[1] = _SX126X_CAL_IMG_430_MHZ_2 + + state = super().calibrateImage(self._tx_mv[:2]) + ASSERT(state) + + return super().setFrequencyRaw(freq) + + def setOutputPower(self, power): + if not (-9 <= power <= 22): + return _ERR_INVALID_OUTPUT_POWER + + ocp = bytearray(1) + ocp_mv = memoryview(ocp) + state = super().readRegister(_SX126X_REG_OCP_CONFIGURATION, ocp_mv, 1) + ASSERT(state) + + state = super().setPaConfig(0x04, _SX126X_PA_CONFIG_SX1262) + ASSERT(state) + + state = super().setTxParams(power) + ASSERT(state) + + return super().writeRegister(_SX126X_REG_OCP_CONFIGURATION, ocp, 1) + + def setTxIq(self, txIq): + self._txIq = txIq + + def setRxIq(self, rxIq): + self._rxIq = rxIq + if not self.blocking: + ASSERT(super().startReceive()) + + def setPreambleDetectorLength(self, preambleDetectorLength): + self._preambleDetectorLength = preambleDetectorLength + if not self.blocking: + ASSERT(super().startReceive()) + + def setBlockingCallback(self, blocking, callback=None): + self.blocking = blocking + if not self.blocking: + state = super().startReceive() + ASSERT(state) + + if callback is not None: + self._callbackFunction = callback + super().setDio1Action(self._onIRQ) + else: + self._callbackFunction = self._dummyFunction + super().clearDio1Action() + return state + else: + state = super().standby() + ASSERT(state) + self._callbackFunction = self._dummyFunction + super().clearDio1Action() + return state + + def recv(self, len=0, timeout_en=False, timeout_ms=0): + if not self.blocking: + return self._readData(len) + else: + return self._receive(len, timeout_en, timeout_ms) + + def send(self, data): + if not self.blocking: + return self._startTransmit(data) + else: + return self._transmit(data) + + def _events(self): + return super().getIrqStatus() + + def _receive(self, len_=0, timeout_en=False, timeout_ms=0): + length = len_ + + if len_ == 0: + length = _SX126X_MAX_PACKET_LENGTH + + data = bytearray(length) + data_mv = memoryview(data) + + try: + state = super().receive(data_mv, length, timeout_en, timeout_ms) + except AssertionError as e: + state = list(ERROR.keys())[list(ERROR.values()).index(str(e))] + + if state == _ERR_NONE or state == _ERR_CRC_MISMATCH: + if len_ == 0: + length = super().getPacketLength(False) + data = data[:length] + + else: + return b'', state + + return bytes(data), state + + def _transmit(self, data): + if isinstance(data, bytes) or isinstance(data, bytearray): + pass + else: + return 0, _ERR_INVALID_PACKET_TYPE + + state = super().transmit(data, len(data)) + return len(data), state + + def _readData(self, len_=0): + length = super().getPacketLength() + + if len_ < length and len_ != 0: + length = len_ + + data = bytearray(length) + data_mv = memoryview(data) + + try: + state = super().readData(data_mv, length) + except AssertionError as e: + state = list(ERROR.keys())[list(ERROR.values()).index(str(e))] + + ASSERT(super().startReceive()) + + if state == _ERR_NONE or state == _ERR_CRC_MISMATCH: + return bytes(data), state + + else: + return b'', state + + def _startTransmit(self, data): + if isinstance(data, bytes) or isinstance(data, bytearray): + pass + else: + return 0, _ERR_INVALID_PACKET_TYPE + + state = super().startTransmit(data, len(data)) + return len(data), state + + def _dummyFunction(self, *args): + pass + + def _onIRQ(self, callback): + events = self._events() + if events & _SX126X_IRQ_TX_DONE: + super().startReceive() + self._callbackFunction(events) diff --git a/display_configs/LilyGo-TDeck/trackball.py b/display_configs/LilyGo-TDeck/trackball.py new file mode 100644 index 00000000..e64778b7 --- /dev/null +++ b/display_configs/LilyGo-TDeck/trackball.py @@ -0,0 +1,70 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser +import lvgl as lv # NOQA +import keypad_framework +import machine +from micropython import const # NOQA + +_UP = 0x01 +_DOWN = 0x02 +_LEFT = 0x04 +_RIGHT = 0x08 + + +class TrackBall(keypad_framework.KeypadDriver): + + def __init__(self, up_pin, down_pin, left_pin, right_pin): # NOQA + + self._up_pin = machine.Pin(up_pin, machine.Pin.IN) + self._down_pin = machine.Pin(down_pin, machine.Pin.IN) + self._left_pin = machine.Pin(left_pin, machine.Pin.IN) + self._right_pin = machine.Pin(right_pin, machine.Pin.IN) + self._key = 0x00 + + super().__init__() + + self._indev_drv.set_mode(lv.INDEV_MODE.EVENT) # NOQA + self.__timer = lv.timer_create(self.__callback, 33, None) # NOQA + self.__timer.set_repeat_count(-1) # NOQA + + def __callback(self, _): + self.read() + last_state = self._current_state + + while self._current_state == self.PRESSED: + # this might be too fast so I may have to put a stall in here. + lv.refr_now(self._disp_drv) + self.read() + + if last_state == self.PRESSED: + lv.refr_now(self._disp_drv) + + def _get_key(self): + key = self._key + if key == 0x00: + if self._up_pin.value(): + key |= _UP + if self._down_pin.value(): + key |= _DOWN + if self._left_pin.value(): + key |= _LEFT + if self._right_pin.value(): + key |= _RIGHT + + if key & _UP: + key &= ~_UP + self._key = key + return lv.KEY.UP + elif key & _DOWN: + key &= ~_DOWN + self._key = key + return lv.KEY.DOWN + elif key & _LEFT: + key &= ~_LEFT + self._key = key + return lv.KEY.LEFT + elif key & _RIGHT: + key &= ~_RIGHT + self._key = key + return lv.KEY.RIGHT + else: + self._key = 0x00 diff --git a/display_driver_framework.pyi b/display_driver_framework.pyi index 2edf07e2..6c12027b 100644 --- a/display_driver_framework.pyi +++ b/display_driver_framework.pyi @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + from typing import Optional, Tuple, Union, ClassVar, Callable, List, Any from typing import TYPE_CHECKING diff --git a/encoder_framework.pyi b/encoder_framework.pyi index 3a8024a8..d9593c00 100644 --- a/encoder_framework.pyi +++ b/encoder_framework.pyi @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + from typing import Union, Optional, Tuple, ClassVar from typing import TYPE_CHECKING diff --git a/esp32_stubs/nvs.pyi b/esp32_stubs/nvs.pyi deleted file mode 100644 index 539a303e..00000000 --- a/esp32_stubs/nvs.pyi +++ /dev/null @@ -1,71 +0,0 @@ -from typing import Union, Final - - -TYPE_I8: Final[int] = 0x11 -TYPE_U8: Final[int] = 0x01 -TYPE_I16: Final[int] = 0x12 -TYPE_U16: Final[int] = 0x02 -TYPE_I32: Final[int] = 0x14 -TYPE_U32: Final[int] = 0x04 -TYPE_I64: Final[int] = 0x18 -TYPE_U64: Final[int] = 0x08 -TYPE_STR: Final[int] = 0x21 -TYPE_BLOB: Final[int] = 0x42 -TYPE_FLOAT: Final[int] = 0xFE - - -class NVS: - - def __init__(self, name: str, /): - """ - Constructor - - :param name: This is the name you give for a group of - data you want to store - """ - ... - - def set(self, type: int, key: str, value: Union[int, float, str, bytes, memoryview, bytearray]) -> None: - """ - Stores data. - - :param type: One of TYPE_* constants - :param key: The name of the data to set - :param value: The data - """ - ... - - def get(self, type: int, key: str) -> Union[int, float, str, bytes]: - """ - Gets stored data - - :param type: One of TYPE_* constants - :param key: The name of the data to get - """ - ... - - def erase(self, key: str) -> None: - """ - Erases a single entry supplied by `key`. - """ - ... - - def commit(self) -> None: - """ - Commits changes made. - """ - ... - - def close(self) -> None: - """ - Closes the connection to the NVS. - - This is automatically done if the NVS gets garbage collected. - """ - ... - - def reset(self) -> None: - """ - Erases all stored data and their keys. - """ - ... diff --git a/ext_mod/esp32_components.cmake b/ext_mod/esp32_components.cmake index e69de29b..33312ed5 100644 --- a/ext_mod/esp32_components.cmake +++ b/ext_mod/esp32_components.cmake @@ -0,0 +1 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser \ No newline at end of file diff --git a/ext_mod/lcd_bus/common_include/i2c_bus.h b/ext_mod/lcd_bus/common_include/i2c_bus.h index 8893c136..0cd7f51a 100644 --- a/ext_mod/lcd_bus/common_include/i2c_bus.h +++ b/ext_mod/lcd_bus/common_include/i2c_bus.h @@ -1,3 +1,5 @@ +// Copyright (c) 2024 - 2025 Kevin G. Schlosser + #ifndef _I2C_BUS_H_ #define _I2C_BUS_H_ diff --git a/ext_mod/lcd_bus/common_include/i80_bus.h b/ext_mod/lcd_bus/common_include/i80_bus.h index dc7e5f16..40819bbd 100644 --- a/ext_mod/lcd_bus/common_include/i80_bus.h +++ b/ext_mod/lcd_bus/common_include/i80_bus.h @@ -1,3 +1,5 @@ +// Copyright (c) 2024 - 2025 Kevin G. Schlosser + #ifndef _I80_BUS_H_ #define _I80_BUS_H_ diff --git a/ext_mod/lcd_bus/common_include/rgb_bus.h b/ext_mod/lcd_bus/common_include/rgb_bus.h index cf352568..a9bbacb2 100644 --- a/ext_mod/lcd_bus/common_include/rgb_bus.h +++ b/ext_mod/lcd_bus/common_include/rgb_bus.h @@ -1,3 +1,5 @@ +// Copyright (c) 2024 - 2025 Kevin G. Schlosser + #ifndef _RGB_BUS_H_ #define _RGB_BUS_H_ diff --git a/ext_mod/lcd_bus/common_include/spi_bus.h b/ext_mod/lcd_bus/common_include/spi_bus.h index 736e62d2..cde39087 100644 --- a/ext_mod/lcd_bus/common_include/spi_bus.h +++ b/ext_mod/lcd_bus/common_include/spi_bus.h @@ -1,3 +1,5 @@ +// Copyright (c) 2024 - 2025 Kevin G. Schlosser + #ifndef _SPI_BUS_H_ #define _SPI_BUS_H_ diff --git a/ext_mod/lcd_bus/common_src/i2c_bus.c b/ext_mod/lcd_bus/common_src/i2c_bus.c index e767f198..3fdc7d36 100644 --- a/ext_mod/lcd_bus/common_src/i2c_bus.c +++ b/ext_mod/lcd_bus/common_src/i2c_bus.c @@ -1,3 +1,5 @@ +// Copyright (c) 2024 - 2025 Kevin G. Schlosser + // local includes #include "lcd_types.h" #include "modlcd_bus.h" diff --git a/ext_mod/lcd_bus/common_src/i80_bus.c b/ext_mod/lcd_bus/common_src/i80_bus.c index 7b6e7988..2c97dfc2 100644 --- a/ext_mod/lcd_bus/common_src/i80_bus.c +++ b/ext_mod/lcd_bus/common_src/i80_bus.c @@ -1,3 +1,5 @@ +// Copyright (c) 2024 - 2025 Kevin G. Schlosser + /* includes */ // local includes #include "lcd_types.h" diff --git a/ext_mod/lcd_bus/common_src/rgb_bus.c b/ext_mod/lcd_bus/common_src/rgb_bus.c index 64f6df75..bcb511a5 100644 --- a/ext_mod/lcd_bus/common_src/rgb_bus.c +++ b/ext_mod/lcd_bus/common_src/rgb_bus.c @@ -1,3 +1,5 @@ +// Copyright (c) 2024 - 2025 Kevin G. Schlosser + // local includes #include "lcd_types.h" #include "modlcd_bus.h" diff --git a/ext_mod/lcd_bus/common_src/spi_bus.c b/ext_mod/lcd_bus/common_src/spi_bus.c index 28d33c0e..2de31f7c 100644 --- a/ext_mod/lcd_bus/common_src/spi_bus.c +++ b/ext_mod/lcd_bus/common_src/spi_bus.c @@ -1,3 +1,6 @@ +// Copyright (c) 2024 - 2025 Kevin G. Schlosser + + /* includes */ // local includes #include "lcd_types.h" diff --git a/ext_mod/lcd_bus/esp32_include/dsi_bus.h b/ext_mod/lcd_bus/esp32_include/dsi_bus.h index aa63d57e..44e63115 100644 --- a/ext_mod/lcd_bus/esp32_include/dsi_bus.h +++ b/ext_mod/lcd_bus/esp32_include/dsi_bus.h @@ -1,3 +1,6 @@ +// Copyright (c) 2024 - 2025 Kevin G. Schlosser + + #ifndef _ESP32_DSI_BUS_H_ #define _ESP32_DSI_BUS_H_ diff --git a/ext_mod/lcd_bus/esp32_include/i2c_bus.h b/ext_mod/lcd_bus/esp32_include/i2c_bus.h index 032bc687..b0d5f7af 100644 --- a/ext_mod/lcd_bus/esp32_include/i2c_bus.h +++ b/ext_mod/lcd_bus/esp32_include/i2c_bus.h @@ -1,3 +1,5 @@ +// Copyright (c) 2024 - 2025 Kevin G. Schlosser + #ifndef _ESP32_I2C_BUS_H_ #define _ESP32_I2C_BUS_H_ diff --git a/ext_mod/lcd_bus/esp32_include/i80_bus.h b/ext_mod/lcd_bus/esp32_include/i80_bus.h index 093a101d..47fe1bb5 100644 --- a/ext_mod/lcd_bus/esp32_include/i80_bus.h +++ b/ext_mod/lcd_bus/esp32_include/i80_bus.h @@ -1,3 +1,5 @@ +// Copyright (c) 2024 - 2025 Kevin G. Schlosser + #ifndef _ESP32_I80_BUS_H_ #define _ESP32_I80_BUS_H_ diff --git a/ext_mod/lcd_bus/esp32_include/led_bus.h b/ext_mod/lcd_bus/esp32_include/led_bus.h index f1c8e404..e18fe488 100644 --- a/ext_mod/lcd_bus/esp32_include/led_bus.h +++ b/ext_mod/lcd_bus/esp32_include/led_bus.h @@ -1,3 +1,5 @@ +// Copyright (c) 2024 - 2025 Kevin G. Schlosser + #ifndef _ESP32_LED_BUS_H_ #define _ESP32_LED_BUS_H_ diff --git a/ext_mod/lcd_bus/esp32_include/rgb565_dither.h b/ext_mod/lcd_bus/esp32_include/rgb565_dither.h new file mode 100644 index 00000000..292aba74 --- /dev/null +++ b/ext_mod/lcd_bus/esp32_include/rgb565_dither.h @@ -0,0 +1,22 @@ +#ifndef __RGB565_DITHER_H__ + #define __RGB565_DITHER_H__ + +#include +#include + + #define CALC_THRESHOLD(x, y) (uint8_t)(((y & 7) << 3) + (x & 7)) + + extern uint8_t *red_thresh; + extern uint8_t *green_thresh; + extern uint8_t *blue_thresh; + + bool rgb565_dither_init(void); + + static inline void rgb565_dither_pixel(uint8_t treshold_id, uint16_t *pixel) + { + *pixel = (((((*pixel >> 8) & 0xF8) + red_thresh[treshold_id]) << 8) | + ((((*pixel >> 3) & 0xFC) + green_thresh[treshold_id]) << 3) | + ((((*pixel & 0x1F) << 3) + blue_thresh[treshold_id]) >> 3)); + } + +#endif diff --git a/ext_mod/lcd_bus/esp32_include/rgb_bus.h b/ext_mod/lcd_bus/esp32_include/rgb_bus.h index 08e2c475..ab9dd4eb 100644 --- a/ext_mod/lcd_bus/esp32_include/rgb_bus.h +++ b/ext_mod/lcd_bus/esp32_include/rgb_bus.h @@ -1,3 +1,5 @@ +// Copyright (c) 2024 - 2025 Kevin G. Schlosser + #include "soc/soc_caps.h" #if SOC_LCD_RGB_SUPPORTED @@ -102,6 +104,7 @@ uint8_t rotation: 2; uint8_t bytes_per_pixel: 2; uint8_t last_update: 1; + uint8_t rgb565_dither: 1; rgb_bus_lock_t copy_lock; rgb_bus_event_t copy_task_exit; diff --git a/ext_mod/lcd_bus/esp32_include/spi_bus.h b/ext_mod/lcd_bus/esp32_include/spi_bus.h index 59b53461..aea784de 100644 --- a/ext_mod/lcd_bus/esp32_include/spi_bus.h +++ b/ext_mod/lcd_bus/esp32_include/spi_bus.h @@ -1,3 +1,5 @@ +// Copyright (c) 2024 - 2025 Kevin G. Schlosser + #ifndef _ESP32_SPI_BUS_H_ #define _ESP32_SPI_BUS_H_ diff --git a/ext_mod/lcd_bus/esp32_src/dsi_bus.c b/ext_mod/lcd_bus/esp32_src/dsi_bus.c index 323cd5fb..f826de6e 100644 --- a/ext_mod/lcd_bus/esp32_src/dsi_bus.c +++ b/ext_mod/lcd_bus/esp32_src/dsi_bus.c @@ -1,3 +1,5 @@ +// Copyright (c) 2024 - 2025 Kevin G. Schlosser + // local includes #include "lcd_types.h" #include "modlcd_bus.h" diff --git a/ext_mod/lcd_bus/esp32_src/i2c_bus.c b/ext_mod/lcd_bus/esp32_src/i2c_bus.c index e22c3940..a890200e 100644 --- a/ext_mod/lcd_bus/esp32_src/i2c_bus.c +++ b/ext_mod/lcd_bus/esp32_src/i2c_bus.c @@ -1,3 +1,4 @@ +// Copyright (c) 2024 - 2025 Kevin G. Schlosser // local includes #include "lcd_types.h" diff --git a/ext_mod/lcd_bus/esp32_src/i80_bus.c b/ext_mod/lcd_bus/esp32_src/i80_bus.c index 3fe7ca23..f8441281 100644 --- a/ext_mod/lcd_bus/esp32_src/i80_bus.c +++ b/ext_mod/lcd_bus/esp32_src/i80_bus.c @@ -1,3 +1,6 @@ +// Copyright (c) 2024 - 2025 Kevin G. Schlosser + + // local includes #include "lcd_types.h" #include "modlcd_bus.h" diff --git a/ext_mod/lcd_bus/esp32_src/led_bus.c b/ext_mod/lcd_bus/esp32_src/led_bus.c index c77b4fa1..b448d06d 100644 --- a/ext_mod/lcd_bus/esp32_src/led_bus.c +++ b/ext_mod/lcd_bus/esp32_src/led_bus.c @@ -1,3 +1,4 @@ +// Copyright (c) 2024 - 2025 Kevin G. Schlosser static bool led_rmt_bus_trans_done_cb(rmt_channel_handle_t tx_chan, const rmt_tx_done_event_data_t *edata, void *user_ctx) diff --git a/ext_mod/lcd_bus/esp32_src/rgb565_dither.c b/ext_mod/lcd_bus/esp32_src/rgb565_dither.c new file mode 100644 index 00000000..8c013b0c --- /dev/null +++ b/ext_mod/lcd_bus/esp32_src/rgb565_dither.c @@ -0,0 +1,66 @@ + +#include "rgb565_dither.h" +#include + +uint8_t* red_thresh = NULL; +uint8_t* green_thresh = NULL; +uint8_t* blue_thresh = NULL; + +bool rgb565_dither_init(void) +{ + if (red_thresh == NULL) { + red_thresh = (uint8_t *)malloc(64); + if (red_thresh != NULL) { + memcpy(red_thresh, + (uint8_t []){ + 1, 7, 3, 5, 0, 8, 2, 6, + 7, 1, 5, 3, 8, 0, 6, 2, + 3, 5, 0, 8, 2, 6, 1, 7, + 5, 3, 8, 0, 6, 2, 7, 1, + 0, 8, 2, 6, 1, 7, 3, 5, + 8, 0, 6, 2, 7, 1, 5, 3, + 2, 6, 1, 7, 3, 5, 0, 8, + 6, 2, 7, 1, 5, 3, 8, 0 + }, 64); + } + } + + if (green_thresh == NULL) { + green_thresh = (uint8_t *)malloc(64); + if (green_thresh != NULL) { + memcpy(green_thresh, + (uint8_t []){ + 1, 3, 2, 2, 3, 1, 2, 2, + 2, 2, 0, 4, 2, 2, 4, 0, + 3, 1, 2, 2, 1, 3, 2, 2, + 2, 2, 4, 0, 2, 2, 0, 4, + 1, 3, 2, 2, 3, 1, 2, 2, + 2, 2, 0, 4, 2, 2, 4, 0, + 3, 1, 2, 2, 1, 3, 2, 2, + 2, 2, 4, 0, 2, 2, 0, 4 + }, 64); + } + } + if (blue_thresh == NULL) { + blue_thresh = (uint8_t *)malloc(64); + if (blue_thresh != NULL) { + memcpy(blue_thresh, + (uint8_t []){ + 5, 3, 8, 0, 6, 2, 7, 1, + 3, 5, 0, 8, 2, 6, 1, 7, + 8, 0, 6, 2, 7, 1, 5, 3, + 0, 8, 2, 6, 1, 7, 3, 5, + 6, 2, 7, 1, 5, 3, 8, 0, + 2, 6, 1, 7, 3, 5, 0, 8, + 7, 1, 5, 3, 8, 0, 6, 2, + 1, 7, 3, 5, 0, 8, 2, 6 + }, 64); + } + } + + if (red_thresh == NULL || blue_thresh == NULL || green_thresh == NULL) return false; + else return true; +} + + + diff --git a/ext_mod/lcd_bus/esp32_src/rgb_bus.c b/ext_mod/lcd_bus/esp32_src/rgb_bus.c index e029ac92..07db7cf8 100644 --- a/ext_mod/lcd_bus/esp32_src/rgb_bus.c +++ b/ext_mod/lcd_bus/esp32_src/rgb_bus.c @@ -1,3 +1,6 @@ +// Copyright (c) 2024 - 2025 Kevin G. Schlosser + + #include "soc/soc_caps.h" #if SOC_LCD_RGB_SUPPORTED @@ -30,6 +33,8 @@ #include "py/objtype.h" #include "py/objexcept.h" + #include "rgb565_dither.h" + // stdlib includes #include @@ -98,6 +103,7 @@ ARG_pclk_idle_high, ARG_pclk_active_low, ARG_refresh_on_demand, + ARG_rgb565_dither }; const mp_arg_t allowed_args[] = { @@ -134,6 +140,7 @@ { MP_QSTR_pclk_idle_high, MP_ARG_BOOL | MP_ARG_KW_ONLY, { .u_bool = false } }, { MP_QSTR_pclk_active_low, MP_ARG_BOOL | MP_ARG_KW_ONLY, { .u_bool = false } }, { MP_QSTR_refresh_on_demand, MP_ARG_BOOL | MP_ARG_KW_ONLY, { .u_bool = false } }, + { MP_QSTR_rgb565_dither, MP_ARG_BOOL | MP_ARG_KW_ONLY, { .u_bool = false } }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; @@ -145,6 +152,8 @@ self->callback = mp_const_none; + self->rgb565_dither = (uint8_t)args[ARG_rgb565_dither].u_bool; + self->bus_config.pclk_hz = (uint32_t)args[ARG_freq].u_int; self->bus_config.hsync_pulse_width = (uint32_t)args[ARG_hsync_pulse_width].u_int; self->bus_config.hsync_back_porch = (uint32_t)args[ARG_hsync_back_porch].u_int; @@ -342,6 +351,8 @@ mp_lcd_rgb_bus_obj_t *self = (mp_lcd_rgb_bus_obj_t *)obj; + if (bpp != 16 && self->rgb565_dither) self->rgb565_dither = 0; + if (bpp == 16 && rgb565_byte_swap) { /* We change the pins aound when the bus width is 16 and wanting to diff --git a/ext_mod/lcd_bus/esp32_src/rgb_bus_rotation.c b/ext_mod/lcd_bus/esp32_src/rgb_bus_rotation.c index 5c282600..f1fd8666 100644 --- a/ext_mod/lcd_bus/esp32_src/rgb_bus_rotation.c +++ b/ext_mod/lcd_bus/esp32_src/rgb_bus_rotation.c @@ -1,3 +1,6 @@ +// Copyright (c) 2024 - 2025 Kevin G. Schlosser + + #include "soc/soc_caps.h" #if SOC_LCD_RGB_SUPPORTED @@ -19,6 +22,7 @@ #include "esp_lcd_panel_ops.h" #include "rgb_bus.h" + #include "rgb565_dither.h" #include @@ -119,7 +123,7 @@ static void rotate0(uint8_t *src, uint8_t *dst, uint32_t x_start, uint32_t y_start, uint32_t x_end, uint32_t y_end, uint32_t dst_width, uint32_t dst_height, - uint8_t bytes_per_pixel); + uint8_t bytes_per_pixel, uint8_t rgb565_dither); static void rotate_8bpp(uint8_t *src, uint8_t *dst, uint32_t x_start, uint32_t y_start, uint32_t x_end, uint32_t y_end, uint32_t dst_width, uint32_t dst_height, @@ -127,7 +131,7 @@ static void rotate_16bpp(uint16_t *src, uint16_t *dst, uint32_t x_start, uint32_t y_start, uint32_t x_end, uint32_t y_end, uint32_t dst_width, uint32_t dst_height, - uint8_t rotate); + uint8_t rotate, uint8_t rgb565_dither); static void rotate_24bpp(uint8_t *src, uint8_t *dst, uint32_t x_start, uint32_t y_start, uint32_t x_end, uint32_t y_end, uint32_t dst_width, uint32_t dst_height, @@ -140,7 +144,7 @@ static void copy_pixels(void *dst, void *src, uint32_t x_start, uint32_t y_start, uint32_t x_end, uint32_t y_end, uint32_t dst_width, uint32_t dst_height, - uint32_t bytes_per_pixel, uint8_t rotate); + uint32_t bytes_per_pixel, uint8_t rotate, uint8_t rgb565_dither); static bool rgb_bus_trans_done_cb(esp_lcd_panel_handle_t panel, @@ -230,7 +234,7 @@ self->x_start, self->y_start, self->x_end, self->y_end, self->width, self->height, - bytes_per_pixel, self->rotation); + bytes_per_pixel, self->rotation, self->rgb565_dither); rgb_bus_lock_release(&self->tx_color_lock); @@ -307,7 +311,6 @@ } - __attribute__((always_inline)) static inline void copy_8bpp(uint8_t *from, uint8_t *to) { @@ -336,12 +339,12 @@ void copy_pixels(void *dst, void *src, uint32_t x_start, uint32_t y_start, uint32_t x_end, uint32_t y_end, uint32_t dst_width, uint32_t dst_height, - uint32_t bytes_per_pixel, uint8_t rotate) + uint32_t bytes_per_pixel, uint8_t rotate, uint8_t rgb565_dither) { if (rotate == RGB_BUS_ROTATION_0) { rotate0(src, dst, MIN(x_start, dst_width), MIN(y_start, dst_height), MIN(x_end, dst_width), MIN(y_end, dst_height), - dst_width, dst_height, bytes_per_pixel); + dst_width, dst_height, bytes_per_pixel, rgb565_dither); } else { y_end += 1; if (rotate == RGB_BUS_ROTATION_90 || rotate == RGB_BUS_ROTATION_270) { @@ -359,7 +362,7 @@ if (bytes_per_pixel == 1) { rotate_8bpp(src, dst, x_start, y_start, x_end, y_end, dst_width, dst_height, rotate); } else if (bytes_per_pixel == 2) { - rotate_16bpp(src, dst, x_start, y_start, x_end, y_end, dst_width, dst_height, rotate); + rotate_16bpp(src, dst, x_start, y_start, x_end, y_end, dst_width, dst_height, rotate, rgb565_dither); } else if (bytes_per_pixel == 3) { rotate_24bpp(src, dst, x_start, y_start, x_end, y_end, dst_width, dst_height, rotate); } else if (bytes_per_pixel == 4) { @@ -371,20 +374,30 @@ void rotate0(uint8_t *src, uint8_t *dst, uint32_t x_start, uint32_t y_start, uint32_t x_end, uint32_t y_end, uint32_t dst_width, - uint32_t dst_height, uint8_t bytes_per_pixel) + uint32_t dst_height, uint8_t bytes_per_pixel, uint8_t rgb565_dither) { dst += ((y_start * dst_width + x_start) * bytes_per_pixel); - - if(x_start == 0 && x_end == (dst_width - 1)){ + if(x_start == 0 && x_end == (dst_width - 1) && !rgb565_dither) { memcpy(dst, src, dst_width * (y_end - y_start + 1) * bytes_per_pixel); } else { - uint32_t src_bytes_per_line = (x_end - x_start + 1) * bytes_per_pixel; + uint32_t src_bytes_per_line = (x_end - x_start) * bytes_per_pixel; uint32_t dst_bytes_per_line = dst_width * bytes_per_pixel; - for(uint32_t y = y_start; y < y_end; y++){ - memcpy(dst, src, src_bytes_per_line); - dst += dst_bytes_per_line; - src += src_bytes_per_line; + if (rgb565_dither) { + for(uint32_t y = y_start; y < y_end; y++) { + for (uint32_t x=0;x diff --git a/ext_mod/lcd_utils/include/binary_float.h b/ext_mod/lcd_utils/include/binary_float.h index 30225670..fd99ca17 100644 --- a/ext_mod/lcd_utils/include/binary_float.h +++ b/ext_mod/lcd_utils/include/binary_float.h @@ -1,3 +1,5 @@ +// Copyright (c) 2024 - 2025 Kevin G. Schlosser + #include "py/obj.h" #include "py/runtime.h" diff --git a/ext_mod/lcd_utils/include/remap.h b/ext_mod/lcd_utils/include/remap.h index 6fac54ac..e1378b56 100644 --- a/ext_mod/lcd_utils/include/remap.h +++ b/ext_mod/lcd_utils/include/remap.h @@ -1,3 +1,5 @@ +// Copyright (c) 2024 - 2025 Kevin G. Schlosser + #include "py/obj.h" #include "py/runtime.h" diff --git a/ext_mod/lcd_utils/micropython.cmake b/ext_mod/lcd_utils/micropython.cmake index 9fc47bea..9c1689ae 100644 --- a/ext_mod/lcd_utils/micropython.cmake +++ b/ext_mod/lcd_utils/micropython.cmake @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + # Create an INTERFACE library for our C module. add_library(usermod_lcd_utils INTERFACE) diff --git a/ext_mod/lcd_utils/micropython.mk b/ext_mod/lcd_utils/micropython.mk index fdf28601..7d8af5b6 100644 --- a/ext_mod/lcd_utils/micropython.mk +++ b/ext_mod/lcd_utils/micropython.mk @@ -1,3 +1,4 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser ################################################################################ # lcd_bus build rules diff --git a/ext_mod/lcd_utils/src/binary_float.c b/ext_mod/lcd_utils/src/binary_float.c index 3c33ccdf..e0003fcd 100644 --- a/ext_mod/lcd_utils/src/binary_float.c +++ b/ext_mod/lcd_utils/src/binary_float.c @@ -1,3 +1,5 @@ +// Copyright (c) 2024 - 2025 Kevin G. Schlosser + #include "../include/remap.h" #include "py/obj.h" diff --git a/ext_mod/lcd_utils/src/lcd_utils.c b/ext_mod/lcd_utils/src/lcd_utils.c index bcdd01a8..3cf80547 100644 --- a/ext_mod/lcd_utils/src/lcd_utils.c +++ b/ext_mod/lcd_utils/src/lcd_utils.c @@ -1,3 +1,5 @@ +// Copyright (c) 2024 - 2025 Kevin G. Schlosser + #include "../include/remap.h" #include "../include/binary_float.h" diff --git a/ext_mod/lcd_utils/src/remap.c b/ext_mod/lcd_utils/src/remap.c index 726ff571..7ccf48cb 100644 --- a/ext_mod/lcd_utils/src/remap.c +++ b/ext_mod/lcd_utils/src/remap.c @@ -1,3 +1,5 @@ +// Copyright (c) 2024 - 2025 Kevin G. Schlosser + #include "../include/remap.h" #include "py/obj.h" diff --git a/ext_mod/lvgl/micropython.cmake b/ext_mod/lvgl/micropython.cmake index 94c8da02..659be9aa 100644 --- a/ext_mod/lvgl/micropython.cmake +++ b/ext_mod/lvgl/micropython.cmake @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + # This file is to be given as "make USER_C_MODULES=..." when building Micropython port find_package(Python3 REQUIRED COMPONENTS Interpreter) diff --git a/ext_mod/lvgl/micropython.mk b/ext_mod/lvgl/micropython.mk index b1c0c1a5..a2055018 100644 --- a/ext_mod/lvgl/micropython.mk +++ b/ext_mod/lvgl/micropython.mk @@ -1,3 +1,4 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser ################################################################################ # LVGL build rules diff --git a/ext_mod/micropython.cmake b/ext_mod/micropython.cmake index 1e02132f..396403c7 100644 --- a/ext_mod/micropython.cmake +++ b/ext_mod/micropython.cmake @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + if(ESP_PLATFORM) include(${CMAKE_CURRENT_LIST_DIR}/esp32_components.cmake) include(${CMAKE_CURRENT_LIST_DIR}/spi3wire/micropython.cmake) diff --git a/ext_mod/spi3wire/include/esp_lcd_panel_io_additions.h b/ext_mod/spi3wire/include/esp_lcd_panel_io_additions.h index 48911a08..1e44fe33 100644 --- a/ext_mod/spi3wire/include/esp_lcd_panel_io_additions.h +++ b/ext_mod/spi3wire/include/esp_lcd_panel_io_additions.h @@ -4,6 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +// Copyright (c) 2024 - 2025 Kevin G. Schlosser + #pragma once #include diff --git a/ext_mod/spi3wire/include/spi3wire.h b/ext_mod/spi3wire/include/spi3wire.h index 28790883..0ff23de9 100644 --- a/ext_mod/spi3wire/include/spi3wire.h +++ b/ext_mod/spi3wire/include/spi3wire.h @@ -1,4 +1,4 @@ - +// Copyright (c) 2024 - 2025 Kevin G. Schlosser #ifndef __SPI3WIRE_H__ #define __SPI3WIRE_H__ diff --git a/ext_mod/spi3wire/micropython.cmake b/ext_mod/spi3wire/micropython.cmake index f6c18792..85661e29 100644 --- a/ext_mod/spi3wire/micropython.cmake +++ b/ext_mod/spi3wire/micropython.cmake @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + # Create an INTERFACE library for our C module. add_library(usermod_spi3wire INTERFACE) diff --git a/ext_mod/spi3wire/src/esp_lcd_panel_io_3wire_spi.c b/ext_mod/spi3wire/src/esp_lcd_panel_io_3wire_spi.c index f93b051d..e5568a01 100644 --- a/ext_mod/spi3wire/src/esp_lcd_panel_io_3wire_spi.c +++ b/ext_mod/spi3wire/src/esp_lcd_panel_io_3wire_spi.c @@ -4,6 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +// Copyright (c) 2024 - 2025 Kevin G. Schlosser + #include #include "driver/gpio.h" diff --git a/ext_mod/spi3wire/src/spi3wire.c b/ext_mod/spi3wire/src/spi3wire.c index 35c25951..ea948040 100644 --- a/ext_mod/spi3wire/src/spi3wire.c +++ b/ext_mod/spi3wire/src/spi3wire.c @@ -1,3 +1,5 @@ +// Copyright (c) 2024 - 2025 Kevin G. Schlosser + #include "py/obj.h" #include "py/runtime.h" #include "esp_lcd_panel_io_additions.h" diff --git a/gen/fixed_gen_json.py b/gen/fixed_gen_json.py index ab153822..ab9b0324 100644 --- a/gen/fixed_gen_json.py +++ b/gen/fixed_gen_json.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import os import sys import shutil diff --git a/gen/lvgl_api_gen_mpy.py b/gen/lvgl_api_gen_mpy.py index 0319f3df..6fb91fe7 100644 --- a/gen/lvgl_api_gen_mpy.py +++ b/gen/lvgl_api_gen_mpy.py @@ -1,3 +1,6 @@ +# MIT license; Copyright (c) 2021 Amir Gonnen +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + # TODO # - Array conversion improvements: # - return custom iterable object instead of Blob when converting to array diff --git a/gen/python_api_gen_mpy.py b/gen/python_api_gen_mpy.py index 5c57ef39..f5b17127 100644 --- a/gen/python_api_gen_mpy.py +++ b/gen/python_api_gen_mpy.py @@ -1,3 +1,6 @@ +# MIT license; Copyright (c) 2021 Amir Gonnen +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + # TODO # - Array conversion improvements: # - return custom iterable object instead of Blob when converting to array diff --git a/gen/stub_gen.py b/gen/stub_gen.py index 6da737d9..1268ce0f 100644 --- a/gen/stub_gen.py +++ b/gen/stub_gen.py @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + import sys import json import os diff --git a/i2c.pyi b/i2c.pyi index d14dedc4..460a3ac7 100644 --- a/i2c.pyi +++ b/i2c.pyi @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + from typing import Optional, Union from typing import TYPE_CHECKING diff --git a/io_expander_framework.pyi b/io_expander_framework.pyi index 1c32f930..ba4ae08a 100644 --- a/io_expander_framework.pyi +++ b/io_expander_framework.pyi @@ -1,33 +1,101 @@ -from typing import Union, Optional, ClassVar +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + +from typing import Union, ClassVar, Callable, Final, TYPE_CHECKING + +if TYPE_CHECKING: + import machine + import i2c + + +EXIO0: Final[int] = ... + +EXIO1: Final[int] = ... +EXIO2: Final[int] = ... +EXIO3: Final[int] = ... +EXIO4: Final[int] = ... +EXIO5: Final[int] = ... +EXIO6: Final[int] = ... +EXIO7: Final[int] = ... +EXIO8: Final[int] = ... + +EXIO9: Final[int] = ... +EXIO10: Final[int] = ... +EXIO11: Final[int] = ... +EXIO12: Final[int] = ... +EXIO13: Final[int] = ... +EXIO14: Final[int] = ... +EXIO15: Final[int] = ... +EXIO16: Final[int] = ... + +EXIO17: Final[int] = ... +EXIO18: Final[int] = ... +EXIO19: Final[int] = ... +EXIO20: Final[int] = ... +EXIO21: Final[int] = ... +EXIO22: Final[int] = ... +EXIO23: Final[int] = ... +EXIO24: Final[int] = ... + +EXIO25: Final[int] = ... +EXIO26: Final[int] = ... +EXIO27: Final[int] = ... +EXIO28: Final[int] = ... +EXIO29: Final[int] = ... +EXIO30: Final[int] = ... +EXIO31: Final[int] = ... +EXIO32: Final[int] = ... + -EXIO1: int = ... -EXIO2: int = ... -EXIO3: int = ... -EXIO4: int = ... -EXIO5: int = ... -EXIO6: int = ... -EXIO7: int = ... -EXIO8: int = ... class Pin(object): IN: ClassVar[int] = ... OUT: ClassVar[int] = ... + OPEN_DRAIN: ClassVar[int] = ... + + IRQ_RISING: ClassVar[int] = ... + IRQ_FALLING: ClassVar[int] = ... + + PULL_UP: ClassVar[int] = ... + PULL_DOWN: ClassVar[int] = ... _id: int = ... _mode: int = ... _buf: bytearray = ... _mv: memoryview = ... + _adc: Union["ADC", None] = ... + _pwm: Union["PWM", None] = ... + _irq: Union[Callable[["Pin"], None], None] = ... + _int_pin: ClassVar[machine.Pin | None] = ... + _reg_int_pins: ClassVar[list["Pin"]] = ... + _device: ClassVar[i2c.I2C.Device | machine.SPI.Device | None] = ... + _irq_input_state: int = 0 + + def __init__(self, id: int, mode: int = -1, pull: int | None = -1, value: int | float = -1): + ... + + @classmethod + def _int_cb(cls, pin: machine.Pin) -> None: + ... - def __init__(self, id: int, mode: int = -1, value: Optional[int] = None): + def _interrupt_cb(self) -> None: ... - def init(self, mode: int = -1, value: Optional[int] = None): + @classmethod + def set_int_pin(cls, pin_num: int, pull: int = -1): ... - def value(self, x: Optional[int] = None) -> Optional[int]: + @classmethod + def set_device(cls, device: i2c.I2C.Device | machine.SPI.Device): ... - def __call__(self, x: Optional[int] = None) -> Optional[int]: + + def init(self, mode: int = -1, pull: int | None = -1, value: int = -1) -> None: + ... + + def value(self, x: int | float = -1) -> int | float | None: + ... + + def __call__(self, x: int | float = -1) -> int | float | None: ... def on(self) -> None: @@ -42,14 +110,99 @@ class Pin(object): def high(self) -> None: ... - def mode(self, mode: Optional[int] = None) -> Optional[int]: + def mode(self, mode: int = -1) -> int | None: + ... + + def irq(self, handler: Union[Callable[["Pin"], None], None], trigger: int = RISING | FALLING) -> None: + ... + + def _set_irq(self, handler: Union[Callable[["Pin"], None], None], trigger: int) -> None: + ... + + def _set_pull(self, pull: int | None) -> None: + ... + + def _set_dir(self, direction: int) -> None: + ... + + def _set_level(self, level: int | float) -> None: + ... + + def _get_level(self) -> int | float | None: + ... + + +class PWM: + _pin: Pin = ... + + def __init__(self, pin: Pin, freq: int = -1, duty: int = -1): + ... + + def init(self, freq: int = -1, duty: int = -1) -> None: + ... + + def deinit(self) -> None: + ... + + def freq(self, freq: int = -1) -> int | None: + ... + + def duty(self, duty: int = -1) -> int | None: + ... + + +class ADC: + # 511 + WIDTH_9BIT: ClassVar[int] = ... + # 1023 + WIDTH_10BIT: ClassVar[int] = ... + # 2047 + WIDTH_11BIT: ClassVar[int] = ... + # 4095 + WIDTH_12BIT: ClassVar[int] = ... + # 8191 + WIDTH_13BIT: ClassVar[int] = ... + + # 1.1V + ATTN_0DB: ClassVar[int] = ... + # 1.5V + ATTN_2_5DB: ClassVar[int] = ... + # 2.2V + ATTN_6DB: ClassVar[int] = ... + # 3.9V + ATTN_11DB: ClassVar[int] = ... + + _pin: Pin = ... + _attn: int = ... + _width: int = ... + + _min_read: ClassVar[int] = ... + _max_read: ClassVar[int] = ... + + + def __init__(self, pin: Pin, atten: int = -1): + ... + + def init(self, atten: int = -1) -> None: + ... + + def deinit(self) -> None: + ... + + def read_uv(self) -> float: + ... + + def atten(self, atten: int = -1) -> None: + ... + + def width(self, width: int) -> None: ... - def _set_dir(self, direction: int): + def read(self) -> int: ... - def _set_level(self, level: Union[int, float]): + def _read(self) -> int: ... - def _get_level(self) -> Optional[Union[int, float]]: + def _init(self, atten) -> None: ... diff --git a/keypad_framework.pyi b/keypad_framework.pyi index 08f78e9a..1f7ea676 100644 --- a/keypad_framework.pyi +++ b/keypad_framework.pyi @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + from typing import Optional, Tuple import _indev_base diff --git a/lcd_bus.pyi b/lcd_bus.pyi index c6eafdba..04008e7a 100644 --- a/lcd_bus.pyi +++ b/lcd_bus.pyi @@ -1,6 +1,8 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + from typing import Any, Callable, Optional, Union, ClassVar, Final import array -import spi as _spi +import machine _BufferType = Union[bytearray, memoryview, bytes, array.array] @@ -21,14 +23,14 @@ class I2CBus: sda: int, scl: int, addr: int, - host: Optional[int] = 0, - control_phase_bytes: Optional[int] = 1, - dc_bit_offset: Optional[int] = 6, - freq: Optional[int] = 10000000, - dc_low_on_data: Optional[bool] = False, - sda_pullup: Optional[bool] = True, - scl_pullup: Optional[bool] = True, - disable_control_phase: Optional[bool] = False + host: int = 0, + control_phase_bytes: int = 1, + dc_bit_offset: int = 6, + freq: int = 10000000, + dc_low_on_data: bool = False, + sda_pullup: bool = True, + scl_pullup: bool = True, + disable_control_phase: bool = False ): ... @@ -68,15 +70,17 @@ class SPIBus: def __init__( self, *, - spi_bus: _spi.SPI.Bus, - freq: int, + spi_bus: machine.SPI.Bus, dc: int, - cs: Optional[int] = -1, - polarity: int = 0, - phase: int = 0, - firstbit: int = _spi.SPI.MSB, - cs_high_active: bool = False, + freq: int, + cs: int = -1, dc_low_on_data: bool = False, + lsb_first: bool = False, + cs_high_active: bool = False, + spi_mode: int = 0, + dual: bool = False, + quad: bool = False, + octal: bool = False ): ... @@ -228,28 +232,29 @@ class RGBBus: data5: int, data6: int, data7: int, - data8: Optional[int] = -1, - data9: Optional[int] = -1, - data10: Optional[int] = -1, - data11: Optional[int] = -1, - data12: Optional[int] = -1, - data13: Optional[int] = -1, - data14: Optional[int] = -1, - data15: Optional[int] = -1, - freq: Optional[int] = 8000000, - hsync_front_porch: Optional[int] = 0, - hsync_back_porch: Optional[int] = 0, - hsync_pulse_width: Optional[int] = 1, - hsync_idle_low: Optional[bool] = False, - vsync_front_porch: Optional[int] = 0, - vsync_back_porch: Optional[int] = 0, - vsync_pulse_width: Optional[int] = 1, - vsync_idle_low: Optional[bool] = False, - de_idle_high: Optional[bool] = False, - pclk_idle_high: Optional[bool] = False, - pclk_active_low: Optional[bool] = False, - disp_active_low: Optional[bool] = False, - refresh_on_demand: Optional[bool] = False + data8: int = -1, + data9: int = -1, + data10: int = -1, + data11: int = -1, + data12: int = -1, + data13: int = -1, + data14: int = -1, + data15: int = -1, + freq: int = 8000000, + hsync_front_porch: int = 0, + hsync_back_porch: int = 0, + hsync_pulse_width: int = 1, + hsync_idle_low: bool = False, + vsync_front_porch: int = 0, + vsync_back_porch: int = 0, + vsync_pulse_width: int = 1, + vsync_idle_low: bool = False, + de_idle_high: bool = False, + pclk_idle_high: bool = False, + pclk_active_low: bool = False, + disp_active_low: bool = False, + refresh_on_demand: bool = False, + rgb565_dither: bool = False ): ... @@ -299,25 +304,25 @@ class I80Bus: data5: int, data6: int, data7: int, - data8: Optional[int] = -1, - data9: Optional[int] = -1, - data10: Optional[int] = -1, - data11: Optional[int] = -1, - data12: Optional[int] = -1, - data13: Optional[int] = -1, - data14: Optional[int] = -1, - data15: Optional[int] = -1, - cs: Optional[int] = -1, - freq: Optional[int] = 10000000, - dc_idle_high: Optional[bool] = False, - dc_cmd_high: Optional[bool] = False, - dc_dummy_high: Optional[bool] = False, - dc_data_high: Optional[bool] = True, - cs_active_high: Optional[bool] = False, - reverse_color_bits: Optional[bool] = False, - swap_color_bytes: Optional[bool] = False, - pclk_active_low: Optional[bool] = False, - pclk_idle_low: Optional[bool] = False, + data8: int = -1, + data9: int = -1, + data10: int = -1, + data11: int = -1, + data12: int = -1, + data13: int = -1, + data14: int = -1, + data15: int = -1, + cs: int = -1, + freq: int = 10000000, + dc_idle_high: bool = False, + dc_cmd_high: bool = False, + dc_dummy_high: bool = False, + dc_data_high: bool = True, + cs_active_high: bool = False, + reverse_color_bits: bool = False, + swap_color_bytes: bool = False, + pclk_active_low: bool = False, + pclk_idle_low: bool = False, ): ... diff --git a/lcd_utils.pyi b/lcd_utils.pyi index f0b7c4e8..2abfb2b0 100644 --- a/lcd_utils.pyi +++ b/lcd_utils.pyi @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + from typing import Union def remap( diff --git a/lib/lv_conf.h b/lib/lv_conf.h index 69d71dd2..4f97f728 100644 --- a/lib/lv_conf.h +++ b/lib/lv_conf.h @@ -1,7 +1,4 @@ -/** - * @file lv_conf.h - * Configuration file for v9.1.1-dev - */ +// Copyright (c) 2024 - 2025 Kevin G. Schlosser #ifndef __MICROPY_CONFIG__ #define __MICROPY_CONFIG__ diff --git a/make.py b/make.py index bec02e05..d57bef44 100644 --- a/make.py +++ b/make.py @@ -1,8 +1,10 @@ #!/usr/bin/env python3 +# Copyright (c) 2024 - 2025 Kevin G. Schlosser import os import sys import builder +import shutil from argparse import ArgumentParser @@ -12,6 +14,59 @@ SCRIPT_DIR = os.path.abspath(os.path.dirname(sys.argv[0])) MPY_DIR = os.path.join(SCRIPT_DIR, 'micropython') + +argParser = ArgumentParser(prefix_chars='-') +argParser.add_argument( + '--custom-board-path', + dest='custom_board_path', + default=None, + action='store' +) +args, extra_args = argParser.parse_known_args(sys.argv[1:]) + +custom_board_path = args.custom_board_path + +if custom_board_path is not None: + if not os.path.exists(custom_board_path): + raise RuntimeError( + 'Supplied custom board path does not exist.' + ) + + for file in os.listdir(custom_board_path): + if file.endswith('.toml'): + extra_args.insert(0, f'--toml={os.path.join(custom_board_path, file)}') + break + + +argParser = ArgumentParser(prefix_chars='-') +argParser.add_argument( + '--toml', + dest='toml', + help='use a toml file to setup the build.', + action='store', + default=None +) +args, extra_args = argParser.parse_known_args(extra_args) + + +if args.toml is not None: + toml_path = args.toml + build_path = os.path.join(SCRIPT_DIR, 'build') + if not os.path.exists(build_path): + os.mkdir(build_path) + + driver_out_path = os.path.join(build_path, 'display.py') + + from builder import toml_reader + + build_command = toml_reader.run(toml_path, driver_out_path) + + for arg in extra_args: + if arg not in build_command: + build_command.append(arg) + + extra_args = build_command + argParser = ArgumentParser(prefix_chars='-') argParser.add_argument( 'target', @@ -25,10 +80,11 @@ ) -args1, extra_args = argParser.parse_known_args(sys.argv[1:]) +args1, extra_args = argParser.parse_known_args(extra_args) target = args1.target[0] -argParser = ArgumentParser(prefix_chars='mscLBFDIVE') + +argParser = ArgumentParser(prefix_chars='-mscLBFDIVE') argParser.add_argument( 'clean', @@ -106,6 +162,14 @@ default=[] ) +argParser.add_argument( + '--no-scrub', + dest='no_scrub', + default=False, + action='store_true' +) + + args2, extra_args = argParser.parse_known_args(extra_args) lv_cflags = args2.lv_cflags @@ -115,6 +179,13 @@ displays = args2.displays indevs = args2.indevs expanders = args2.expanders +builder.DO_NOT_SCRUB_BUILD_FOLDER = args2.no_scrub + + +if frozen_manifest is not None: + frozen_manifest = os.path.abspath(frozen_manifest) + if not os.path.exists(frozen_manifest): + raise RuntimeError('Frozen manifest does not exist.') if lv_cflags is None: @@ -134,10 +205,12 @@ def get_submodules(): os.path.join(SCRIPT_DIR, 'lib/micropython/mpy-cross') ): builder.get_micropython() + if not os.path.exists( os.path.join(SCRIPT_DIR, 'lib/lvgl/lvgl.h') ): builder.get_lvgl() + if not os.path.exists(os.path.join( SCRIPT_DIR, 'lib/pycparser/pycparser') ): @@ -190,6 +263,22 @@ def create_lvgl_header(): get_submodules() + if custom_board_path is not None: + if custom_board_path.endswith('/') or custom_board_path.endswith('\\'): + custom_board_path = custom_board_path[:-1] + + board_name = os.path.split(custom_board_path)[-1] + dst_path = f'lib/micropython/ports/{target}/boards/{board_name}' + if os.path.exists(dst_path): + shutil.rmtree(dst_path) + + shutil.copytree(custom_board_path, dst_path) + + if board is None or board != board_name: + board = board_name + + mod.custom_board_path = custom_board_path + extra_args, lv_cflags, board = mod.parse_args(extra_args, lv_cflags, board) extra_args = mod.build_commands( target, extra_args, SCRIPT_DIR, lv_cflags, board) diff --git a/micropy_updates/common/mp_spi_common.h b/micropy_updates/common/mp_spi_common.h index 3c199ff3..e10c209d 100644 --- a/micropy_updates/common/mp_spi_common.h +++ b/micropy_updates/common/mp_spi_common.h @@ -1,3 +1,5 @@ +// Copyright (c) 2024 - 2025 Kevin G. Schlosser + #include #include "py/obj.h" diff --git a/micropy_updates/esp32/machine_hw_spi.c b/micropy_updates/esp32/machine_hw_spi.c index bae7fe84..3839ac09 100644 --- a/micropy_updates/esp32/machine_hw_spi.c +++ b/micropy_updates/esp32/machine_hw_spi.c @@ -1,29 +1,5 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2017 "Eric Poulsen" - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * 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. - */ +// Copyright (c) 2017 "Eric Poulsen" +// Copyright (c) 2024 - 2025 Kevin G. Schlosser #include #include @@ -343,13 +319,12 @@ static void machine_hw_spi_device_transfer(mp_obj_base_t *self_in, size_t len, c transaction.flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_USE_RXDATA; transaction.length = bits_to_send; - if (self->dual) { - transaction.flags |= SPI_TRANS_MODE_DIO; + transaction.flags |= SPI_TRANS_MODE_DIO | SPI_TRANS_MULTILINE_ADDR; } else if (self->quad) { - transaction.flags |= SPI_TRANS_MODE_QIO; + transaction.flags |= SPI_TRANS_MODE_QIO | SPI_TRANS_MULTILINE_ADDR; } else if (self->octal) { - transaction.flags |= SPI_TRANS_MODE_OCT; + transaction.flags |= SPI_TRANS_MODE_OCT | SPI_TRANS_MULTILINE_ADDR; } spi_device_transmit(spi_device, &transaction); @@ -387,11 +362,11 @@ static void machine_hw_spi_device_transfer(mp_obj_base_t *self_in, size_t len, c } if (self->dual) { - transaction->flags |= SPI_TRANS_MODE_DIO; + transaction->flags |= SPI_TRANS_MODE_DIO | SPI_TRANS_MULTILINE_ADDR; } else if (self->quad) { - transaction->flags |= SPI_TRANS_MODE_QIO; + transaction->flags |= SPI_TRANS_MODE_QIO | SPI_TRANS_MULTILINE_ADDR; } else if (self->octal) { - transaction->flags |= SPI_TRANS_MODE_OCT; + transaction->flags |= SPI_TRANS_MODE_OCT | SPI_TRANS_MULTILINE_ADDR; } spi_device_queue_trans(spi_device, transaction, portMAX_DELAY); @@ -582,13 +557,13 @@ void mp_machine_hw_spi_bus_initilize(mp_machine_hw_spi_bus_obj_t *bus) .data5_io_num = (int)mp_obj_get_int(bus->data5), .data6_io_num = (int)mp_obj_get_int(bus->data6), .data7_io_num = (int)mp_obj_get_int(bus->data7), - .flags = flags, + .flags = SPICOMMON_BUSFLAG_MASTER, .max_transfer_sz = SPI_LL_DMA_MAX_BIT_LEN / 8 }; esp_err_t ret; -#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 +#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 ret = spi_bus_initialize((spi_host_device_t)bus->host, &buscfg, SPI_DMA_CH_AUTO); #else if (bus->host == SPI2_HOST) { @@ -663,12 +638,18 @@ mp_obj_t machine_hw_spi_device_make_new(const mp_obj_type_t *type, size_t n_args self->quad = quad; self->octal = octal; + uint8_t flags = 0; + + if (self->firstbit == MICROPY_PY_MACHINE_SPI_LSB) flags |= SPI_DEVICE_TXBIT_LSBFIRST | SPI_DEVICE_RXBIT_LSBFIRST; + + if (dual || quad || octal) flags |= SPI_DEVICE_HALFDUPLEX; + spi_device_interface_config_t devcfg = { .clock_speed_hz = (uint32_t)spi_get_actual_clock(APB_CLK_FREQ, args[ARG_freq].u_int, 0), .mode = self->phase | (self->polarity << 1), .spics_io_num = cs, .queue_size = 2, - .flags = self->firstbit == MICROPY_PY_MACHINE_SPI_LSB ? SPI_DEVICE_TXBIT_LSBFIRST | SPI_DEVICE_RXBIT_LSBFIRST : 0, + .flags = flags, .pre_cb = NULL }; @@ -749,4 +730,4 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_QSTR_SPI, MP_TYPE_FLAG_NONE, locals_dict, &machine_spi_locals_dict -); \ No newline at end of file +); diff --git a/micropy_updates/esp32/machine_sdcard.c b/micropy_updates/esp32/machine_sdcard.c index 2137866a..f65e1752 100644 --- a/micropy_updates/esp32/machine_sdcard.c +++ b/micropy_updates/esp32/machine_sdcard.c @@ -1,28 +1,5 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2019 Nicko van Someren - * - * 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. - */ +// Copyright (c) 2019 Nicko van Someren +// Copyright (c) 2024 - 2025 Kevin G. Schlosser #include @@ -139,21 +116,28 @@ static mp_obj_t machine_sdcard_make_new(const mp_obj_type_t *type, size_t n_args ARG_width, ARG_cd, ARG_wp, + ARG_cmd, + ARG_clk, + ARG_data_pins, ARG_spi_bus, ARG_cs, ARG_freq, }; static const mp_arg_t make_new_args[] = { - { MP_QSTR_slot, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} }, - { MP_QSTR_width, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} }, - { MP_QSTR_cd, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, - { MP_QSTR_wp, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_slot, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} }, + { MP_QSTR_width, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} }, + { MP_QSTR_cd, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_wp, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + // Added so a user can set their own custom data pins + { MP_QSTR_cmd, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_clk, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_data_pins, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, // These are only needed if using SPI mode - { MP_QSTR_spi_bus, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_cs, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_spi_bus, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_cs, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, // freq is valid for both SPI and SDMMC interfaces - { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 20000000} }, + { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 20000000} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(make_new_args)]; @@ -234,7 +218,34 @@ static mp_obj_t machine_sdcard_make_new(const mp_obj_type_t *type, size_t n_args slot_config.gpio_cd = (int)args[ARG_cd].u_int; slot_config.gpio_wp = (int)args[ARG_wp].u_int; - int width = args[ARG_width].u_int; + int clk = (int)args[ARG_clk].u_int; + int cmd = (int)args[ARG_cmd].u_int; + int width = (int)args[ARG_width].u_int; + + if (clk != -1) slot_config.clk = clk; + if (cmd != -1) slot_config.cmd = cmd; + + if (args[ARG_data_pins].u_obj != mp_const_none) { + mp_obj_tuple_t *t = MP_OBJ_TO_PTR(args[ARG_data_pins].u_obj); + if ((int)t->len != width) { + mp_raise_ValueError(MP_ERROR_TEXT("width does not match the number of data pins provided")); + } + + slot_config.d0 = (int)mp_obj_get_int(t->items[0]); + + if (width >= 4) { + slot_config.d1 = (int)mp_obj_get_int(t->items[1]); + slot_config.d2 = (int)mp_obj_get_int(t->items[2]); + slot_config.d3 = (int)mp_obj_get_int(t->items[3]); + } + if (width == 8) { + slot_config.d4 = (int)mp_obj_get_int(t->items[4]); + slot_config.d5 = (int)mp_obj_get_int(t->items[5]); + slot_config.d6 = (int)mp_obj_get_int(t->items[6]); + slot_config.d7 = (int)mp_obj_get_int(t->items[7]); + } + } + if (width == 1 || width == 4 || (width == 8 && slot_num == 0)) { slot_config.width = width; } else { diff --git a/micropy_updates/rp2/machine_spi.c b/micropy_updates/rp2/machine_spi.c index 726c3b7e..1c5e6f2f 100644 --- a/micropy_updates/rp2/machine_spi.c +++ b/micropy_updates/rp2/machine_spi.c @@ -1,28 +1,6 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2020-2021 Damien P. George - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ +// Copyright (c) 2020-2021 Damien P. George +// Copyright (c) 2024 - 2025 Kevin G. Schlosser + #include "py/runtime.h" #include "py/mphal.h" diff --git a/micropy_updates/stm32/machine_spi.c b/micropy_updates/stm32/machine_spi.c index 220c6802..8b04784e 100644 --- a/micropy_updates/stm32/machine_spi.c +++ b/micropy_updates/stm32/machine_spi.c @@ -1,28 +1,6 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2013-2018 Damien P. George - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ +// Copyright (c) 2013-2018 Damien P. George +// Copyright (c) 2024 - 2025 Kevin G. Schlosser + #include "../../../../micropy_updates/common/mp_spi_common.h" #include "py/runtime.h" diff --git a/micropy_updates/unix/machine_sdl.c b/micropy_updates/unix/machine_sdl.c index 72062c42..f649daa9 100644 --- a/micropy_updates/unix/machine_sdl.c +++ b/micropy_updates/unix/machine_sdl.c @@ -1,3 +1,5 @@ +// Copyright (c) 2024 - 2025 Kevin G. Schlosser + #include "machine_sdl.h" #include "SDL.h" diff --git a/micropy_updates/unix/machine_sdl.h b/micropy_updates/unix/machine_sdl.h index 34443a38..c8260cdf 100644 --- a/micropy_updates/unix/machine_sdl.h +++ b/micropy_updates/unix/machine_sdl.h @@ -1,3 +1,4 @@ +// Copyright (c) 2024 - 2025 Kevin G. Schlosser #ifndef __MACHINE_SDL_H__ #define __MACHINE_SDL_H__ diff --git a/micropy_updates/unix/machine_timer.c b/micropy_updates/unix/machine_timer.c index 475ff1f1..4aee543c 100644 --- a/micropy_updates/unix/machine_timer.c +++ b/micropy_updates/unix/machine_timer.c @@ -1,4 +1,4 @@ - +// Copyright (c) 2024 - 2025 Kevin G. Schlosser #include "py/obj.h" #include "py/runtime.h" diff --git a/micropy_updates/unix/machine_timer.h b/micropy_updates/unix/machine_timer.h index ccf11ae4..3dbc1b54 100644 --- a/micropy_updates/unix/machine_timer.h +++ b/micropy_updates/unix/machine_timer.h @@ -1,3 +1,5 @@ +// Copyright (c) 2024 - 2025 Kevin G. Schlosser + #include "py/obj.h" #include "py/runtime.h" diff --git a/pointer_framework.pyi b/pointer_framework.pyi index dd8642c3..96482f2c 100644 --- a/pointer_framework.pyi +++ b/pointer_framework.pyi @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + from typing import Optional, Tuple, TYPE_CHECKING import _indev_base import lcd_utils as _lcd_utils diff --git a/spi.pyi b/spi.pyi deleted file mode 100644 index 7a28346b..00000000 --- a/spi.pyi +++ /dev/null @@ -1,52 +0,0 @@ -from typing import Optional, Any, Callable, Union, ClassVar -from array import array - - -class SPI(object): - MSB: ClassVar[int] = ... - LSB: ClassVar[int] = ... - - def __init__( - self, - id: int, - baudrate: int, - /, - *, - polarity: int=0, - phase: int=0, - bits: int=8, - firstbit: int=MSB, - sck: Union[str, int]=None, - mosi: Union[str, int]=None, - miso: Union[str, int]=None, - cs: Union[str, int]=None, - ): - ... - - def deinit(self) -> None: - ... - - def read(self, nbytes: int, write: int=0x00, /) -> bytes: - ... - - def readinto(self, buf: Union[memoryview, bytes, bytearray, array], write: int=0x00, /) -> None: - ... - - def write(self, buf: Union[memoryview, bytes, bytearray, array], /) -> None: - ... - - def write_readinto( - self, - write_buf: Union[memoryview, bytes, bytearray, array], - read_buf: Union[memoryview, bytes, bytearray, array], - / - ) -> None: - ... - - -del ClassVar -del Callable -del Union -del Any -del Optional -del array diff --git a/spi3wire.pyi b/spi3wire.pyi index 10a449fb..dc65332e 100644 --- a/spi3wire.pyi +++ b/spi3wire.pyi @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + from typing import Optional class Spi3Wire: diff --git a/task_handler.pyi b/task_handler.pyi index 69c35425..348b4318 100644 --- a/task_handler.pyi +++ b/task_handler.pyi @@ -1,34 +1,6 @@ -############################################################################## -# Event Loop module: advancing tick count and scheduling lvgl task handler. -# Import after lvgl module. -# This should be imported and used by display driver. -# Display driver should first check if an event loop is already running. -# -# Usage example with SDL: -# -# SDL.init(auto_refresh=False) -# # Register SDL display driver. -# # Register SDL mouse driver -# event_loop = lv_utils.event_loop() -# -# -# uasyncio example with SDL: -# -# SDL.init(auto_refresh=False) -# # Register SDL display driver. -# # Register SDL mouse driver -# event_loop = lv_utils.event_loop(asynchronous=True) -# uasyncio.Loop.run_forever() -# -# uasyncio example with ili9341: -# -# event_loop = lv_utils.event_loop(asynchronous=True) # Optional! -# self.disp = ili9341(asynchronous=True) -# uasyncio.Loop.run_forever() -# # MIT license; Copyright (c) 2021 Amir Gonnen -# -############################################################################## +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + from typing import Callable, ClassVar, Optional from machine import Timer diff --git a/touch_cal_data.pyi b/touch_cal_data.pyi index 9527eb49..ef798b22 100644 --- a/touch_cal_data.pyi +++ b/touch_cal_data.pyi @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + from typing import Optional # this class is used as a template for writing the mechanism that is diff --git a/touch_calibrate.pyi b/touch_calibrate.pyi index 062a73da..ae6b44aa 100644 --- a/touch_calibrate.pyi +++ b/touch_calibrate.pyi @@ -1,3 +1,5 @@ +# Copyright (c) 2024 - 2025 Kevin G. Schlosser + from typing import Tuple import lvgl as lv