Repository: pimoroni/st7789-python Branch: main Commit: 2e0df2861ef6 Files: 32 Total size: 59.2 KB Directory structure: gitextract_u_1k7z4_/ ├── .coveragerc ├── .github/ │ ├── ISSUE_TEMPLATE.md │ ├── PULL_REQUEST_TEMPLATE.md │ └── workflows/ │ ├── build.yml │ ├── qa.yml │ └── test.yml ├── .gitignore ├── .stickler.yml ├── CHANGELOG.md ├── LICENSE ├── Makefile ├── README.md ├── ST7789.py ├── check.sh ├── examples/ │ ├── 320x240.py │ ├── LICENSE.txt │ ├── framerate.py │ ├── gif.py │ ├── image.py │ ├── round.py │ ├── scrolling-text.py │ └── shapes.py ├── install.sh ├── pyproject.toml ├── requirements-dev.txt ├── st7789/ │ └── __init__.py ├── tests/ │ ├── conftest.py │ ├── test_dimensions.py │ ├── test_display.py │ └── test_setup.py ├── tox.ini └── uninstall.sh ================================================ FILE CONTENTS ================================================ ================================================ FILE: .coveragerc ================================================ [run] source = st7789 omit = .tox/* ================================================ FILE: .github/ISSUE_TEMPLATE.md ================================================ Thank you for opening an issue on an Pimoroni Python library repository. To improve the speed of resolution please review the following guidelines and common troubleshooting steps below before creating the issue: - **Do not use GitHub issues for troubleshooting projects and issues.** Instead use the forums at http://forums.pimoroni.com to ask questions and troubleshoot why something isn't working as expected. In many cases the problem is a common issue that you will more quickly receive help from the forum community. GitHub issues are meant for known defects in the code. If you don't know if there is a defect in the code then start with troubleshooting on the forum first. - **If following a tutorial or guide be sure you didn't miss a step.** Carefully check all of the steps and commands to run have been followed. Consult the forum if you're unsure or have questions about steps in a guide/tutorial. - **For Python/Raspberry Pi projects check these very common issues to ensure they don't apply**: - If you are receiving an **ImportError: No module named...** error then a library the code depends on is not installed. Check the tutorial/guide or README to ensure you have installed the necessary libraries. Usually the missing library can be installed with the `pip` tool, but check the tutorial/guide for the exact command. - **Be sure you are supplying adequate power to the board.** Check the specs of your board and power in an external power supply. In many cases just plugging a board into your computer is not enough to power it and other peripherals. - **Double check all soldering joints and connections.** Flakey connections cause many mysterious problems. See the [guide to excellent soldering](https://learn.adafruit.com/adafruit-guide-excellent-soldering/tools) for examples of good solder joints. If you're sure this issue is a defect in the code and checked the steps above please fill in the following fields to provide enough troubleshooting information. You may delete the guideline and text above to just leave the following details: - Platform/operating system (i.e. Raspberry Pi with Raspbian operating system, Windows 32-bit, Windows 64-bit, Mac OSX 64-bit, etc.): **INSERT PLATFORM/OPERATING SYSTEM HERE** - Python version (run `python -version` or `python3 -version`): **INSERT PYTHON VERSION HERE** - Error message you are receiving, including any Python exception traces: **INSERT ERROR MESAGE/EXCEPTION TRACES HERE*** - List the steps to reproduce the problem below (if possible attach code or commands to run): **LIST REPRO STEPS BELOW** ================================================ FILE: .github/PULL_REQUEST_TEMPLATE.md ================================================ Thank you for creating a pull request to contribute to Pimoroni's GitHub code! Before you open the request please review the following guidelines and tips to help it be more easily integrated: - **Describe the scope of your change--i.e. what the change does and what parts of the code were modified.** This will help us understand any risks of integrating the code. - **Describe any known limitations with your change.** For example if the change doesn't apply to a supported platform of the library please mention it. - **Please run any tests or examples that can exercise your modified code.** We strive to not break users of the code and running tests/examples helps with this process. You should install tox (`pip install tox`) and run it in the `library` folder to execute the tests and run Python linting. Thank you again for contributing! We will try to test and integrate the change as soon as we can, but be aware we have many GitHub repositories to manage and can't immediately respond to every request. There is no need to bump or check in on a pull request (it will clutter the discussion of the request). Also don't be worried if the request is closed or not integrated--sometimes the priorities of Pimoroni's GitHub code (education, ease of use) might not match the priorities of the pull request. Don't fret, the open source community thrives on forks and GitHub makes it easy to keep your changes in a forked repo. After reviewing the guidelines above you can delete this text from the pull request. ================================================ FILE: .github/workflows/build.yml ================================================ name: Build on: pull_request: push: branches: - main jobs: test: name: Python ${{ matrix.python }} runs-on: ubuntu-latest strategy: matrix: python: ['3.9', '3.10', '3.11'] env: RELEASE_FILE: ${{ github.event.repository.name }}-${{ github.event.release.tag_name || github.sha }}-py${{ matrix.python }} steps: - name: Checkout Code uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python }} uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} - name: Install Dependencies run: | make dev-deps - name: Build Packages run: | make build - name: Upload Packages uses: actions/upload-artifact@v4 with: name: ${{ env.RELEASE_FILE }} path: dist/ ================================================ FILE: .github/workflows/qa.yml ================================================ name: QA on: pull_request: push: branches: - main jobs: test: name: linting & spelling runs-on: ubuntu-latest env: TERM: xterm-256color steps: - name: Checkout Code uses: actions/checkout@v4 - name: Set up Python '3,11' uses: actions/setup-python@v5 with: python-version: '3.11' - name: Install Dependencies run: | make dev-deps - name: Run Quality Assurance run: | make qa - name: Run Code Checks run: | make check - name: Run Bash Code Checks run: | make shellcheck ================================================ FILE: .github/workflows/test.yml ================================================ name: Tests on: pull_request: push: branches: - main jobs: test: name: Python ${{ matrix.python }} runs-on: ubuntu-latest strategy: matrix: python: ['3.9', '3.10', '3.11'] steps: - name: Checkout Code uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python }} uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} - name: Install Dependencies run: | make dev-deps - name: Run Tests run: | make pytest - name: Coverage if: ${{ matrix.python == '3.9' }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | python -m pip install coveralls coveralls --service=github ================================================ FILE: .gitignore ================================================ build/ _build/ *.o *.so *.a *.py[cod] *.egg-info dist/ __pycache__ .DS_Store *.deb *.dsc *.build *.changes *.orig.* packaging/*tar.xz library/debian/ .coverage .pytest_cache .tox ================================================ FILE: .stickler.yml ================================================ --- linters: flake8: python: 3 max-line-length: 160 ================================================ FILE: CHANGELOG.md ================================================ 1.0.1 ----- * Add spidev and numpy dependencies. 1.0.0 ----- * Repackage to hatch/pyproject.toml * Port to gpiod/gpiodevice 0.0.4 ----- * Add support for 320x240 2.0" LCD (Display HAT Mini) * Add support for 240x135 1.14" LCD (@slabua) * Rework numpy RGB888 to RGB565 * Support displaying numpy arrays (@zecktos) 0.0.3 ----- * Add support for RLCD * Brought back `offset_left` and `offset_top` parameters 0.0.2 ----- * Fix for image retention * Drop defunct parameters 0.0.1 ----- * Initial Release ================================================ FILE: LICENSE ================================================ The MIT License (MIT) Copyright (c) 2014 Adafruit Industries Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: Makefile ================================================ LIBRARY_NAME := $(shell hatch project metadata name 2> /dev/null) LIBRARY_VERSION := $(shell hatch version 2> /dev/null) .PHONY: usage install uninstall check pytest qa build-deps check tag wheel sdist clean dist testdeploy deploy usage: ifdef LIBRARY_NAME @echo "Library: ${LIBRARY_NAME}" @echo "Version: ${LIBRARY_VERSION}\n" else @echo "WARNING: You should 'make dev-deps'\n" endif @echo "Usage: make , where target is one of:\n" @echo "install: install the library locally from source" @echo "uninstall: uninstall the local library" @echo "dev-deps: install Python dev dependencies" @echo "check: perform basic integrity checks on the codebase" @echo "qa: run linting and package QA" @echo "pytest: run Python test fixtures" @echo "clean: clean Python build and dist directories" @echo "build: build Python distribution files" @echo "testdeploy: build and upload to test PyPi" @echo "deploy: build and upload to PyPi" @echo "tag: tag the repository with the current version\n" version: @hatch version install: ./install.sh --unstable uninstall: ./uninstall.sh dev-deps: python3 -m pip install -r requirements-dev.txt sudo apt install dos2unix shellcheck check: @bash check.sh shellcheck: shellcheck *.sh qa: tox -e qa pytest: tox -e py nopost: @bash check.sh --nopost tag: version git tag -a "v${LIBRARY_VERSION}" -m "Version ${LIBRARY_VERSION}" build: check @hatch build clean: -rm -r dist testdeploy: build twine upload --repository testpypi dist/* deploy: nopost build twine upload dist/* ================================================ FILE: README.md ================================================ # Python ST7789 [![Build Status](https://img.shields.io/github/actions/workflow/status/pimoroni/st7789-python/test.yml?branch=main)](https://github.com/pimoroni/st7789-python/actions/workflows/test.yml) [![Coverage Status](https://coveralls.io/repos/github/pimoroni/st7789-python/badge.svg?branch=main)](https://coveralls.io/github/pimoroni/st7789-python?branch=main) [![PyPi Package](https://img.shields.io/pypi/v/st7789.svg)](https://pypi.python.org/pypi/st7789) [![Python Versions](https://img.shields.io/pypi/pyversions/st7789.svg)](https://pypi.python.org/pypi/st7789) Python library to control an ST7789 TFT LCD display Designed specifically to work with a ST7789 based 240x240 pixel TFT SPI display. (Specifically the [1.3" SPI LCD from Pimoroni](https://shop.pimoroni.com/products/1-3-spi-colour-lcd-240x240-breakout)). ![Animated GIF showing the ST7789 SPI LCD displaying Deploy/Rainbows in alternating frames](https://raw.githubusercontent.com/pimoroni/st7789-python/master/square-lcd-breakout-1.gif) # Installation Make sure you have the following dependencies: ```` sudo apt-get update sudo apt-get install python-rpi.gpio python-spidev python-pip python-pil python-numpy ```` Install this library by running: ```` sudo pip install st7789 ```` You might also need to enable I2C and SPI in raspi-config. See example of usage in the examples folder. # Licensing & History This library is a modification of a modification of code originally written by Tony DiCola for Adafruit Industries, and modified to work with the ST7735 by Clement Skau. To create this ST7789 driver, it has been hard-forked from st7735-python which was originally modified by Pimoroni to include support for their 160x80 SPI LCD breakout. ## Modifications include: * PIL/Pillow has been removed from the underlying display driver to separate concerns- you should create your own PIL image and display it using `display(image)` * `width`, `height`, `rotation`, `invert`, `offset_left` and `offset_top` parameters can be passed into `__init__` for alternate displays * `Adafruit_GPIO` has been replaced with `RPi.GPIO` and `spidev` to closely align with our other software (IE: Raspberry Pi only) * Test fixtures have been added to keep this library stable Pimoroni invests time and resources forking and modifying this open source code, please support Pimoroni and open-source software by purchasing products from us, too! Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! Modified from 'Modified from 'Adafruit Python ILI9341' written by Tony DiCola for Adafruit Industries.' written by Clement Skau. MIT license, all text above must be included in any redistribution ================================================ FILE: ST7789.py ================================================ from warnings import warn from st7789 import * # noqa F403 warn( 'Using "import ST7789" is deprecated. Please "import st7789" (all lowercase)!', DeprecationWarning, stacklevel=2, ) ================================================ FILE: check.sh ================================================ #!/bin/bash # This script handles some basic QA checks on the source NOPOST=$1 LIBRARY_NAME=$(hatch project metadata name) LIBRARY_VERSION=$(hatch version | awk -F "." '{print $1"."$2"."$3}') POST_VERSION=$(hatch version | awk -F "." '{print substr($4,0,length($4))}') TERM=${TERM:="xterm-256color"} success() { echo -e "$(tput setaf 2)$1$(tput sgr0)" } inform() { echo -e "$(tput setaf 6)$1$(tput sgr0)" } warning() { echo -e "$(tput setaf 1)$1$(tput sgr0)" } while [[ $# -gt 0 ]]; do K="$1" case $K in -p|--nopost) NOPOST=true shift ;; *) if [[ $1 == -* ]]; then printf "Unrecognised option: %s\n" "$1"; exit 1 fi POSITIONAL_ARGS+=("$1") shift esac done inform "Checking $LIBRARY_NAME $LIBRARY_VERSION\n" inform "Checking for trailing whitespace..." if grep -IUrn --color "[[:blank:]]$" --exclude-dir=dist --exclude-dir=.tox --exclude-dir=.git --exclude=PKG-INFO; then warning "Trailing whitespace found!" exit 1 else success "No trailing whitespace found." fi printf "\n" inform "Checking for DOS line-endings..." if grep -lIUrn --color $'\r' --exclude-dir=dist --exclude-dir=.tox --exclude-dir=.git --exclude=Makefile; then warning "DOS line-endings found!" exit 1 else success "No DOS line-endings found." fi printf "\n" inform "Checking CHANGELOG.md..." if ! grep "^${LIBRARY_VERSION}" CHANGELOG.md > /dev/null 2>&1; then warning "Changes missing for version ${LIBRARY_VERSION}! Please update CHANGELOG.md." exit 1 else success "Changes found for version ${LIBRARY_VERSION}." fi printf "\n" inform "Checking for git tag ${LIBRARY_VERSION}..." if ! git tag -l | grep -E "${LIBRARY_VERSION}$"; then warning "Missing git tag for version ${LIBRARY_VERSION}" fi printf "\n" if [[ $NOPOST ]]; then inform "Checking for .postN on library version..." if [[ "$POST_VERSION" != "" ]]; then warning "Found .$POST_VERSION on library version." inform "Please only use these for testpypi releases." exit 1 else success "OK" fi fi ================================================ FILE: examples/320x240.py ================================================ #!/usr/bin/env python3 import time from PIL import Image, ImageDraw from st7789 import ST7789 # Buttons BUTTON_A = 5 BUTTON_B = 6 BUTTON_X = 16 BUTTON_Y = 24 # Onboard RGB LED LED_R = 17 LED_G = 27 LED_B = 22 # General SPI_PORT = 0 SPI_CS = 1 SPI_DC = 9 BACKLIGHT = 13 # Screen dimensions WIDTH = 320 HEIGHT = 240 buffer = Image.new("RGB", (WIDTH, HEIGHT)) draw = ImageDraw.Draw(buffer) draw.rectangle((0, 0, 50, 50), (255, 0, 0)) draw.rectangle((320 - 50, 0, 320, 50), (0, 255, 0)) draw.rectangle((0, 240 - 50, 50, 240), (0, 0, 255)) draw.rectangle((320 - 50, 240 - 50, 320, 240), (255, 255, 0)) display = ST7789( port=SPI_PORT, cs=SPI_CS, dc=SPI_DC, backlight=BACKLIGHT, width=WIDTH, height=HEIGHT, rotation=180, spi_speed_hz=60 * 1000 * 1000, ) while True: display.display(buffer) time.sleep(1.0 / 60) ================================================ FILE: examples/LICENSE.txt ================================================ Examples originally modified from Adafruit_Python_ILI9341 https://github.com/adafruit/Adafruit_Python_ILI9341 Copyright (c 2014 Adafruit Industries Author: Tony DiCola 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. ================================================ FILE: examples/framerate.py ================================================ #!/usr/bin/env python3 import math import sys import time from PIL import Image, ImageDraw import st7789 # Higher SPI bus speed = higher framerate try: SPI_SPEED_MHZ = int(sys.argv[1]) except ValueError: sys.exit(1) except IndexError: SPI_SPEED_MHZ = 80 try: display_type = sys.argv[2] except IndexError: display_type = "square" print( f""" framerate.py - Test LCD framerate. If you're using Breakout Garden, plug the 1.3" LCD (SPI) breakout into the front slot. Usage: {sys.argv[0]} Where is one of: * square - 240x240 1.3" Square LCD * round - 240x240 1.3" Round LCD (applies an offset) * rect - 240x135 1.14" Rectangular LCD (applies an offset) * dhmini - 320x240 2.0" Rectangular LCD Running at: {SPI_SPEED_MHZ}MHz on a {display_type} display. """ ) try: width, height, rotation, backlight, offset_left, offset_top = { "square": (240, 240, 90, 19, 0, 0), "round": (240, 240, 90, 19, 40, 0), "rect": (240, 135, 0, 19, 40, 53), "dhmini": (320, 240, 180, 13, 0, 0), }[display_type] except IndexError: raise RuntimeError(f"Unsupported display type: {display_type}") # Create ST7789 LCD display class. disp = st7789.ST7789( width=width, height=height, rotation=rotation, port=0, cs=st7789.BG_SPI_CS_FRONT, # BG_SPI_CS_BACK or BG_SPI_CS_FRONT dc=9, backlight=19, # Breakout Garden: 18 for back slot, 19 for front slot. # NOTE: Change this to 13 for Pirate Audio boards spi_speed_hz=SPI_SPEED_MHZ * 1000000, offset_left=offset_left, offset_top=offset_top, ) WIDTH = disp.width HEIGHT = disp.height STEPS = WIDTH * 2 images = [] for step in range(STEPS): image = Image.new("RGB", (WIDTH, HEIGHT), (0, 0, 128)) draw = ImageDraw.Draw(image) if step % 2 == 0: draw.rectangle((WIDTH / 2, int(HEIGHT / 2), WIDTH, HEIGHT), (0, 128, 0)) else: draw.rectangle((0, 0, WIDTH / 2 - 1, int(HEIGHT / 2) - 1), (0, 128, 0)) f = math.sin((float(step) / STEPS) * math.pi) offset_left = int(f * WIDTH) draw.ellipse((offset_left, 35, offset_left + 10, 45), (255, 0, 0)) images.append(image) count = 0 time_start = time.time() while True: disp.display(images[count % len(images)]) count += 1 time_current = time.time() - time_start if count % 120 == 0: print( f"Time: {time_current:8.3f}, Frames: {count:6d}, FPS: {count / time_current:8.3f}" ) ================================================ FILE: examples/gif.py ================================================ #!/usr/bin/env python3 import sys import time from PIL import Image import st7789 print( """ gif.py - Display a gif on the LCD. If you're using Breakout Garden, plug the 1.3" LCD (SPI) breakout into the front slot. """ ) if len(sys.argv) < 2: print( f"""Usage: {sys.argv[0]} Where is a .gif file. Hint: {sys.argv[0]} deployrainbows.gif And is one of: * square - 240x240 1.3" Square LCD * round - 240x240 1.3" Round LCD (applies an offset) * rect - 240x135 1.14" Rectangular LCD (applies an offset) * dhmini - 320x240 2.0" Display HAT Mini """ ) sys.exit(1) image_file = sys.argv[1] try: display_type = sys.argv[2] except IndexError: display_type = "square" # Create ST7789 LCD display class. if display_type in ("square", "rect", "round"): disp = st7789.ST7789( height=135 if display_type == "rect" else 240, rotation=0 if display_type == "rect" else 90, port=0, cs=st7789.BG_SPI_CS_FRONT, # BG_SPI_CS_BACK or BG_SPI_CS_FRONT dc=9, backlight=19, # Breakout Garden: 18 for back slot, 19 for front slot. # NOTE: Change this to 13 for Pirate Audio boards spi_speed_hz=80 * 1000 * 1000, offset_left=0 if display_type == "square" else 40, offset_top=53 if display_type == "rect" else 0, ) elif display_type == "dhmini": disp = st7789.ST7789( height=240, width=320, rotation=180, port=0, cs=1, dc=9, backlight=13, spi_speed_hz=60 * 1000 * 1000, offset_left=0, offset_top=0, ) else: print("Invalid display type!") # Initialize display. disp.begin() width = disp.width height = disp.height # Load an image. print(f"Loading gif: {image_file}...") image = Image.open(image_file) print("Drawing gif, press Ctrl+C to exit!") frame = 0 while True: try: image.seek(frame) disp.display(image.resize((width, height))) frame += 1 time.sleep(0.05) except EOFError: frame = 0 ================================================ FILE: examples/image.py ================================================ #!/usr/bin/env python3 import sys from PIL import Image import st7789 print( """ image.py - Display an image on the LCD. If you're using Breakout Garden, plug the 1.3" LCD (SPI) breakout into the front slot. """ ) if len(sys.argv) < 2: print( f"""Usage: {sys.argv[0]} Where is one of: * square - 240x240 1.3" Square LCD * round - 240x240 1.3" Round LCD (applies an offset) * rect - 240x135 1.14" Rectangular LCD (applies an offset) * dhmini - 320x240 2.0" Display HAT Mini """ ) sys.exit(1) image_file = sys.argv[1] try: display_type = sys.argv[2] except IndexError: display_type = "square" # Create ST7789 LCD display class. if display_type in ("square", "rect", "round"): disp = st7789.ST7789( height=135 if display_type == "rect" else 240, rotation=0 if display_type == "rect" else 90, port=0, cs=st7789.BG_SPI_CS_FRONT, # BG_SPI_CS_BACK or BG_SPI_CS_FRONT dc=9, backlight=19, # Breakout Garden: 18 for back slot, 19 for front slot. # NOTE: Change this to 13 for Pirate Audio boards spi_speed_hz=80 * 1000 * 1000, offset_left=0 if display_type == "square" else 40, offset_top=53 if display_type == "rect" else 0, ) elif display_type == "dhmini": disp = st7789.ST7789( height=240, width=320, rotation=180, port=0, cs=1, dc=9, backlight=13, spi_speed_hz=60 * 1000 * 1000, offset_left=0, offset_top=0, ) else: print("Invalid display type!") WIDTH = disp.width HEIGHT = disp.height # Initialize display. disp.begin() # Load an image. print(f"Loading image: {image_file}...") image = Image.open(image_file) # Resize the image image = image.resize((WIDTH, HEIGHT)) # Draw the image on the display hardware. print("Drawing image") disp.display(image) ================================================ FILE: examples/round.py ================================================ #!/usr/bin/env python3 import colorsys import math import sys import time from PIL import Image, ImageDraw import st7789 print( f""" round.py - Shiny shiny round LCD! If you're using Breakout Garden, plug a 1.3" ROUND LCD (SPI) breakout into the front slot. Usage: {sys.argv[0]}