From b878c700bfdeceafb389f7049a8f94de3844229a Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Mon, 30 Jan 2023 14:06:17 -0800 Subject: [PATCH] Initial working version --- .../adafruit_circuitpython_pr.md | 13 + .github/workflows/build.yml | 14 + .github/workflows/failure-help-text.yml | 19 + .github/workflows/release_gh.yml | 18 + .github/workflows/release_pypi.yml | 19 + .gitignore | 48 +++ .pre-commit-config.yaml | 42 ++ .pylintrc | 399 ++++++++++++++++++ .readthedocs.yaml | 19 + CODE_OF_CONDUCT.md | 141 +++++++ LICENSE | 21 + LICENSES/CC-BY-4.0.txt | 324 ++++++++++++++ LICENSES/MIT.txt | 19 + LICENSES/Unlicense.txt | 20 + README.rst | 114 +++++ README.rst.license | 3 + adafruit_acep7in.py | 88 ++++ docs/_static/favicon.ico | Bin 0 -> 4414 bytes docs/_static/favicon.ico.license | 3 + docs/api.rst | 8 + docs/api.rst.license | 4 + docs/conf.py | 197 +++++++++ docs/examples.rst | 8 + docs/examples.rst.license | 4 + docs/index.rst | 53 +++ docs/index.rst.license | 4 + docs/requirements.txt | 5 + examples/acep7in_simpletest.py | 46 ++ examples/display-ruler-720p.bmp | Bin 0 -> 921926 bytes examples/display-ruler-720p.bmp.license | 2 + optional_requirements.txt | 3 + pyproject.toml | 49 +++ requirements.txt | 7 + 33 files changed, 1714 insertions(+) create mode 100644 .github/PULL_REQUEST_TEMPLATE/adafruit_circuitpython_pr.md create mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/failure-help-text.yml create mode 100644 .github/workflows/release_gh.yml create mode 100644 .github/workflows/release_pypi.yml create mode 100644 .gitignore create mode 100644 .pre-commit-config.yaml create mode 100644 .pylintrc create mode 100644 .readthedocs.yaml create mode 100644 CODE_OF_CONDUCT.md create mode 100644 LICENSE create mode 100644 LICENSES/CC-BY-4.0.txt create mode 100644 LICENSES/MIT.txt create mode 100644 LICENSES/Unlicense.txt create mode 100644 README.rst create mode 100644 README.rst.license create mode 100644 adafruit_acep7in.py create mode 100644 docs/_static/favicon.ico create mode 100644 docs/_static/favicon.ico.license create mode 100644 docs/api.rst create mode 100644 docs/api.rst.license create mode 100644 docs/conf.py create mode 100644 docs/examples.rst create mode 100644 docs/examples.rst.license create mode 100644 docs/index.rst create mode 100644 docs/index.rst.license create mode 100644 docs/requirements.txt create mode 100644 examples/acep7in_simpletest.py create mode 100644 examples/display-ruler-720p.bmp create mode 100644 examples/display-ruler-720p.bmp.license create mode 100644 optional_requirements.txt create mode 100644 pyproject.toml create mode 100644 requirements.txt diff --git a/.github/PULL_REQUEST_TEMPLATE/adafruit_circuitpython_pr.md b/.github/PULL_REQUEST_TEMPLATE/adafruit_circuitpython_pr.md new file mode 100644 index 0000000..8de294e --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/adafruit_circuitpython_pr.md @@ -0,0 +1,13 @@ +# SPDX-FileCopyrightText: 2021 Adafruit Industries +# +# SPDX-License-Identifier: MIT + +Thank you for contributing! Before you submit a pull request, please read the following. + +Make sure any changes you're submitting are in line with the CircuitPython Design Guide, available here: https://docs.circuitpython.org/en/latest/docs/design_guide.html + +If your changes are to documentation, please verify that the documentation builds locally by following the steps found here: https://adafru.it/build-docs + +Before submitting the pull request, make sure you've run Pylint and Black locally on your code. You can do this manually or using pre-commit. Instructions are available here: https://adafru.it/check-your-code + +Please remove all of this text before submitting. Include an explanation or list of changes included in your PR, as well as, if applicable, a link to any related issues. diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..041a337 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,14 @@ +# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries +# +# SPDX-License-Identifier: MIT + +name: Build CI + +on: [pull_request, push] + +jobs: + test: + runs-on: ubuntu-latest + steps: + - name: Run Build CI workflow + uses: adafruit/workflows-circuitpython-libs/build@main diff --git a/.github/workflows/failure-help-text.yml b/.github/workflows/failure-help-text.yml new file mode 100644 index 0000000..0b1194f --- /dev/null +++ b/.github/workflows/failure-help-text.yml @@ -0,0 +1,19 @@ +# SPDX-FileCopyrightText: 2021 Scott Shawcroft for Adafruit Industries +# +# SPDX-License-Identifier: MIT + +name: Failure help text + +on: + workflow_run: + workflows: ["Build CI"] + types: + - completed + +jobs: + post-help: + runs-on: ubuntu-latest + if: ${{ github.event.workflow_run.conclusion == 'failure' && github.event.workflow_run.event == 'pull_request' }} + steps: + - name: Post comment to help + uses: adafruit/circuitpython-action-library-ci-failed@v1 diff --git a/.github/workflows/release_gh.yml b/.github/workflows/release_gh.yml new file mode 100644 index 0000000..b8aa8d6 --- /dev/null +++ b/.github/workflows/release_gh.yml @@ -0,0 +1,18 @@ +# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries +# +# SPDX-License-Identifier: MIT + +name: GitHub Release Actions + +on: + release: + types: [published] + +jobs: + upload-release-assets: + runs-on: ubuntu-latest + steps: + - name: Run GitHub Release CI workflow + uses: adafruit/workflows-circuitpython-libs/release-gh@main + with: + github-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release_pypi.yml b/.github/workflows/release_pypi.yml new file mode 100644 index 0000000..c16b495 --- /dev/null +++ b/.github/workflows/release_pypi.yml @@ -0,0 +1,19 @@ +# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries +# +# SPDX-License-Identifier: MIT + +name: PyPI Release Actions + +on: + release: + types: [published] + +jobs: + upload-release-assets: + runs-on: ubuntu-latest + steps: + - name: Run PyPI Release CI workflow + uses: adafruit/workflows-circuitpython-libs/release-pypi@main + with: + pypi-username: ${{ secrets.pypi_username }} + pypi-password: ${{ secrets.pypi_password }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..db3d538 --- /dev/null +++ b/.gitignore @@ -0,0 +1,48 @@ +# SPDX-FileCopyrightText: 2022 Kattni Rembor, written for Adafruit Industries +# +# SPDX-License-Identifier: MIT + +# Do not include files and directories created by your personal work environment, such as the IDE +# you use, except for those already listed here. Pull requests including changes to this file will +# not be accepted. + +# This .gitignore file contains rules for files generated by working with CircuitPython libraries, +# including building Sphinx, testing with pip, and creating a virual environment, as well as the +# MacOS and IDE-specific files generated by using MacOS in general, or the PyCharm or VSCode IDEs. + +# If you find that there are files being generated on your machine that should not be included in +# your git commit, you should create a .gitignore_global file on your computer to include the +# files created by your personal setup. To do so, follow the two steps below. + +# First, create a file called .gitignore_global somewhere convenient for you, and add rules for +# the files you want to exclude from git commits. + +# Second, configure Git to use the exclude file for all Git repositories by running the +# following via commandline, replacing "path/to/your/" with the actual path to your newly created +# .gitignore_global file: +# git config --global core.excludesfile path/to/your/.gitignore_global + +# CircuitPython-specific files +*.mpy + +# Python-specific files +__pycache__ +*.pyc + +# Sphinx build-specific files +_build + +# This file results from running `pip -e install .` in a local repository +*.egg-info + +# Virtual environment-specific files +.env +.venv + +# MacOS-specific files +*.DS_Store + +# IDE-specific files +.idea +.vscode +*~ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..0e5fccc --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,42 @@ +# SPDX-FileCopyrightText: 2020 Diego Elio Pettenò +# +# SPDX-License-Identifier: Unlicense + +repos: + - repo: https://github.com/python/black + rev: 22.3.0 + hooks: + - id: black + - repo: https://github.com/fsfe/reuse-tool + rev: v0.14.0 + hooks: + - id: reuse + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.2.0 + hooks: + - id: check-yaml + - id: end-of-file-fixer + - id: trailing-whitespace + - repo: https://github.com/pycqa/pylint + rev: v2.15.5 + hooks: + - id: pylint + name: pylint (library code) + types: [python] + args: + - --disable=consider-using-f-string + exclude: "^(docs/|examples/|tests/|setup.py$)" + - id: pylint + name: pylint (example code) + description: Run pylint rules on "examples/*.py" files + types: [python] + files: "^examples/" + args: + - --disable=missing-docstring,invalid-name,consider-using-f-string,duplicate-code + - id: pylint + name: pylint (test code) + description: Run pylint rules on "tests/*.py" files + types: [python] + files: "^tests/" + args: + - --disable=missing-docstring,consider-using-f-string,duplicate-code diff --git a/.pylintrc b/.pylintrc new file mode 100644 index 0000000..40208c3 --- /dev/null +++ b/.pylintrc @@ -0,0 +1,399 @@ +# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries +# +# SPDX-License-Identifier: Unlicense + +[MASTER] + +# A comma-separated list of package or module names from where C extensions may +# be loaded. Extensions are loading into the active Python interpreter and may +# run arbitrary code +extension-pkg-whitelist= + +# Add files or directories to the ignore-list. They should be base names, not +# paths. +ignore=CVS + +# Add files or directories matching the regex patterns to the ignore-list. The +# regex matches against base names, not paths. +ignore-patterns= + +# Python code to execute, usually for sys.path manipulation such as +# pygtk.require(). +#init-hook= + +# Use multiple processes to speed up Pylint. +jobs=1 + +# List of plugins (as comma separated values of python modules names) to load, +# usually to register additional checkers. +load-plugins=pylint.extensions.no_self_use + +# Pickle collected data for later comparisons. +persistent=yes + +# Specify a configuration file. +#rcfile= + +# Allow loading of arbitrary C extensions. Extensions are imported into the +# active Python interpreter and may run arbitrary code. +unsafe-load-any-extension=no + + +[MESSAGES CONTROL] + +# Only show warnings with the listed confidence levels. Leave empty to show +# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED +confidence= + +# Disable the message, report, category or checker with the given id(s). You +# can either give multiple identifiers separated by comma (,) or put this +# option multiple times (only on the command line, not in the configuration +# file where it should appear only once).You can also use "--disable=all" to +# disable everything first and then reenable specific checks. For example, if +# you want to run only the similarities checker, you can use "--disable=all +# --enable=similarities". If you want to run only the classes checker, but have +# no Warning level messages displayed, use"--disable=all --enable=classes +# --disable=W" +# disable=import-error,raw-checker-failed,bad-inline-option,locally-disabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,deprecated-str-translate-call +disable=raw-checker-failed,bad-inline-option,locally-disabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,import-error,pointless-string-statement,unspecified-encoding + +# Enable the message, report, category or checker with the given id(s). You can +# either give multiple identifier separated by comma (,) or put this option +# multiple time (only on the command line, not in the configuration file where +# it should appear only once). See also the "--disable" option for examples. +enable= + + +[REPORTS] + +# Python expression which should return a note less than 10 (10 is the highest +# note). You have access to the variables errors warning, statement which +# respectively contain the number of errors / warnings messages and the total +# number of statements analyzed. This is used by the global evaluation report +# (RP0004). +evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) + +# Template used to display messages. This is a python new-style format string +# used to format the message information. See doc for all details +#msg-template= + +# Set the output format. Available formats are text, parseable, colorized, json +# and msvs (visual studio).You can also give a reporter class, eg +# mypackage.mymodule.MyReporterClass. +output-format=text + +# Tells whether to display a full report or only the messages +reports=no + +# Activate the evaluation score. +score=yes + + +[REFACTORING] + +# Maximum number of nested blocks for function / method body +max-nested-blocks=5 + + +[LOGGING] + +# Logging modules to check that the string format arguments are in logging +# function parameter format +logging-modules=logging + + +[SPELLING] + +# Spelling dictionary name. Available dictionaries: none. To make it working +# install python-enchant package. +spelling-dict= + +# List of comma separated words that should not be checked. +spelling-ignore-words= + +# A path to a file that contains private dictionary; one word per line. +spelling-private-dict-file= + +# Tells whether to store unknown words to indicated private dictionary in +# --spelling-private-dict-file option instead of raising a message. +spelling-store-unknown-words=no + + +[MISCELLANEOUS] + +# List of note tags to take in consideration, separated by a comma. +# notes=FIXME,XXX,TODO +notes=FIXME,XXX + + +[TYPECHECK] + +# List of decorators that produce context managers, such as +# contextlib.contextmanager. Add to this list to register other decorators that +# produce valid context managers. +contextmanager-decorators=contextlib.contextmanager + +# List of members which are set dynamically and missed by pylint inference +# system, and so shouldn't trigger E1101 when accessed. Python regular +# expressions are accepted. +generated-members= + +# Tells whether missing members accessed in mixin class should be ignored. A +# mixin class is detected if its name ends with "mixin" (case insensitive). +ignore-mixin-members=yes + +# This flag controls whether pylint should warn about no-member and similar +# checks whenever an opaque object is returned when inferring. The inference +# can return multiple potential results while evaluating a Python object, but +# some branches might not be evaluated, which results in partial inference. In +# that case, it might be useful to still emit no-member and other checks for +# the rest of the inferred objects. +ignore-on-opaque-inference=yes + +# List of class names for which member attributes should not be checked (useful +# for classes with dynamically set attributes). This supports the use of +# qualified names. +ignored-classes=optparse.Values,thread._local,_thread._local + +# List of module names for which member attributes should not be checked +# (useful for modules/projects where namespaces are manipulated during runtime +# and thus existing member attributes cannot be deduced by static analysis. It +# supports qualified module names, as well as Unix pattern matching. +ignored-modules=board + +# Show a hint with possible names when a member name was not found. The aspect +# of finding the hint is based on edit distance. +missing-member-hint=yes + +# The minimum edit distance a name should have in order to be considered a +# similar match for a missing member name. +missing-member-hint-distance=1 + +# The total number of similar names that should be taken in consideration when +# showing a hint for a missing member. +missing-member-max-choices=1 + + +[VARIABLES] + +# List of additional names supposed to be defined in builtins. Remember that +# you should avoid to define new builtins when possible. +additional-builtins= + +# Tells whether unused global variables should be treated as a violation. +allow-global-unused-variables=yes + +# List of strings which can identify a callback function by name. A callback +# name must start or end with one of those strings. +callbacks=cb_,_cb + +# A regular expression matching the name of dummy variables (i.e. expectedly +# not used). +dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_ + +# Argument names that match this expression will be ignored. Default to name +# with leading underscore +ignored-argument-names=_.*|^ignored_|^unused_ + +# Tells whether we should check for unused import in __init__ files. +init-import=no + +# List of qualified module names which can have objects that can redefine +# builtins. +redefining-builtins-modules=six.moves,future.builtins + + +[FORMAT] + +# Expected format of line ending, e.g. empty (any line ending), LF or CRLF. +# expected-line-ending-format= +expected-line-ending-format=LF + +# Regexp for a line that is allowed to be longer than the limit. +ignore-long-lines=^\s*(# )??$ + +# Number of spaces of indent required inside a hanging or continued line. +indent-after-paren=4 + +# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 +# tab). +indent-string=' ' + +# Maximum number of characters on a single line. +max-line-length=100 + +# Maximum number of lines in a module +max-module-lines=1000 + +# Allow the body of a class to be on the same line as the declaration if body +# contains single statement. +single-line-class-stmt=no + +# Allow the body of an if to be on the same line as the test if there is no +# else. +single-line-if-stmt=no + + +[SIMILARITIES] + +# Ignore comments when computing similarities. +ignore-comments=yes + +# Ignore docstrings when computing similarities. +ignore-docstrings=yes + +# Ignore imports when computing similarities. +ignore-imports=yes + +# Minimum lines number of a similarity. +min-similarity-lines=12 + + +[BASIC] + +# Regular expression matching correct argument names +argument-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ + +# Regular expression matching correct attribute names +attr-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ + +# Bad variable names which should always be refused, separated by a comma +bad-names=foo,bar,baz,toto,tutu,tata + +# Regular expression matching correct class attribute names +class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ + +# Regular expression matching correct class names +# class-rgx=[A-Z_][a-zA-Z0-9]+$ +class-rgx=[A-Z_][a-zA-Z0-9_]+$ + +# Regular expression matching correct constant names +const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ + +# Minimum line length for functions/classes that require docstrings, shorter +# ones are exempt. +docstring-min-length=-1 + +# Regular expression matching correct function names +function-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ + +# Good variable names which should always be accepted, separated by a comma +# good-names=i,j,k,ex,Run,_ +good-names=r,g,b,w,i,j,k,n,x,y,z,ex,ok,Run,_ + +# Include a hint for the correct naming format with invalid-name +include-naming-hint=no + +# Regular expression matching correct inline iteration names +inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ + +# Regular expression matching correct method names +method-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ + +# Regular expression matching correct module names +module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ + +# Colon-delimited sets of names that determine each other's naming style when +# the name regexes allow several styles. +name-group= + +# Regular expression which should only match function or class names that do +# not require a docstring. +no-docstring-rgx=^_ + +# List of decorators that produce properties, such as abc.abstractproperty. Add +# to this list to register other decorators that produce valid properties. +property-classes=abc.abstractproperty + +# Regular expression matching correct variable names +variable-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ + + +[IMPORTS] + +# Allow wildcard imports from modules that define __all__. +allow-wildcard-with-all=no + +# Analyse import fallback blocks. This can be used to support both Python 2 and +# 3 compatible code, which means that the block might have code that exists +# only in one or another interpreter, leading to false positives when analysed. +analyse-fallback-blocks=no + +# Deprecated modules which should not be used, separated by a comma +deprecated-modules=optparse,tkinter.tix + +# Create a graph of external dependencies in the given file (report RP0402 must +# not be disabled) +ext-import-graph= + +# Create a graph of every (i.e. internal and external) dependencies in the +# given file (report RP0402 must not be disabled) +import-graph= + +# Create a graph of internal dependencies in the given file (report RP0402 must +# not be disabled) +int-import-graph= + +# Force import order to recognize a module as part of the standard +# compatibility libraries. +known-standard-library= + +# Force import order to recognize a module as part of a third party library. +known-third-party=enchant + + +[CLASSES] + +# List of method names used to declare (i.e. assign) instance attributes. +defining-attr-methods=__init__,__new__,setUp + +# List of member names, which should be excluded from the protected access +# warning. +exclude-protected=_asdict,_fields,_replace,_source,_make + +# List of valid names for the first argument in a class method. +valid-classmethod-first-arg=cls + +# List of valid names for the first argument in a metaclass class method. +valid-metaclass-classmethod-first-arg=mcs + + +[DESIGN] + +# Maximum number of arguments for function / method +max-args=5 + +# Maximum number of attributes for a class (see R0902). +# max-attributes=7 +max-attributes=11 + +# Maximum number of boolean expressions in a if statement +max-bool-expr=5 + +# Maximum number of branch for function / method body +max-branches=12 + +# Maximum number of locals for function / method body +max-locals=15 + +# Maximum number of parents for a class (see R0901). +max-parents=7 + +# Maximum number of public methods for a class (see R0904). +max-public-methods=20 + +# Maximum number of return / yield for function / method body +max-returns=6 + +# Maximum number of statements in function / method body +max-statements=50 + +# Minimum number of public methods for a class (see R0903). +min-public-methods=1 + + +[EXCEPTIONS] + +# Exceptions that will emit a warning when being caught. Defaults to +# "Exception" +overgeneral-exceptions=Exception diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 0000000..b79ec5b --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,19 @@ +# SPDX-FileCopyrightText: 2021 Melissa LeBlanc-Williams for Adafruit Industries +# +# SPDX-License-Identifier: Unlicense + +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +build: + os: ubuntu-20.04 + tools: + python: "3" + +python: + install: + - requirements: docs/requirements.txt + - requirements: requirements.txt diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..01a7515 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,141 @@ + +# Adafruit Community Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and leaders pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, gender identity and expression, level or type of +experience, education, socio-economic status, nationality, personal appearance, +race, religion, or sexual identity and orientation. + +## Our Standards + +We are committed to providing a friendly, safe and welcoming environment for +all. + +Examples of behavior that contributes to creating a positive environment +include: + +* Be kind and courteous to others +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Collaborating with other community members +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and sexual attention or advances +* The use of inappropriate images, including in a community member's avatar +* The use of inappropriate language, including in a community member's nickname +* Any spamming, flaming, baiting or other attention-stealing behavior +* Excessive or unwelcome helping; answering outside the scope of the question + asked +* Discussion or promotion of activities or projects that intend or pose a risk of + significant harm +* Trolling, insulting/derogatory comments, and personal or political attacks +* Promoting or spreading disinformation, lies, or conspiracy theories against + a person, group, organisation, project, or community +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate + +The goal of the standards and moderation guidelines outlined here is to build +and maintain a respectful community. We ask that you don’t just aim to be +"technically unimpeachable", but rather try to be your best self. + +We value many things beyond technical expertise, including collaboration and +supporting others within our community. Providing a positive experience for +other community members can have a much more significant impact than simply +providing the correct answer. + +## Our Responsibilities + +Project leaders are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project leaders have the right and responsibility to remove, edit, or +reject messages, comments, commits, code, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any community member for other behaviors that they deem +inappropriate, threatening, offensive, or harmful. + +## Moderation + +Instances of behaviors that violate the Adafruit Community Code of Conduct +may be reported by any member of the community. Community members are +encouraged to report these situations, including situations they witness +involving other community members. + +You may report in the following ways: + +In any situation, you may email . + +On the Adafruit Discord, you may send an open message from any channel +to all Community Moderators by tagging @community moderators. You may +also send an open message from any channel, or a direct message to +any Community Moderator. + +Email and direct message reports will be kept confidential. + +In situations on Discord where the issue is particularly offensive, possibly +illegal, requires immediate action, or violates the Discord terms of service, +you should also report the message directly to [Discord](https://discord.com/safety). + +These are the steps for upholding our community’s standards of conduct. + +1. Any member of the community may report any situation that violates the + CircuitPython Community Code of Conduct. All reports will be reviewed and + investigated. +2. If the behavior is a severe violation, the community member who + committed the violation may be banned immediately, without warning. +3. Otherwise, moderators will first respond to such behavior with a warning. +4. Moderators follow a soft "three strikes" policy - the community member may + be given another chance, if they are receptive to the warning and change their + behavior. +5. If the community member is unreceptive or unreasonable when warned by a + moderator, or the warning goes unheeded, they may be banned for a first or + second offense. Repeated offenses will result in the community member being + banned. +6. Disciplinary actions (warnings, bans, etc) for Code of Conduct violations apply + to the platform where the violation occurred. However, depending on the severity + of the violation, the disciplinary action may be applied across Adafruit's other + community platforms. For example, a severe violation on the Adafruit Discord + server may result in a ban on not only the Adafruit Discord server, but also on + the Adafruit GitHub organisation, Adafruit Forums, Adafruit Twitter, etc. + +## Scope + +This Code of Conduct and the enforcement policies listed above apply to all +Adafruit Community venues. This includes but is not limited to any community +spaces (both public and private), the entire Adafruit Discord server, and +Adafruit GitHub repositories. Examples of Adafruit Community spaces include +but are not limited to meet-ups, audio chats on the Adafruit Discord, or +interaction at a conference. + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. As a community +member, you are representing our community, and are expected to behave +accordingly. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org/), +version 1.4, available on [contributor-covenant.org](https://www.contributor-covenant.org/version/1/4/code-of-conduct.html), +and the [Rust Code of Conduct](https://www.rust-lang.org/en-US/conduct.html). + +For other projects adopting the Adafruit Community Code of +Conduct, please contact the maintainers of those projects for enforcement. +If you wish to use this code of conduct for your own project, consider +explicitly mentioning your moderation policy or making a copy with your +own moderation policy so as to avoid confusion. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..dfb5d22 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2023 Scott Shawcroft for Adafruit Industries + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/LICENSES/CC-BY-4.0.txt b/LICENSES/CC-BY-4.0.txt new file mode 100644 index 0000000..3f92dfc --- /dev/null +++ b/LICENSES/CC-BY-4.0.txt @@ -0,0 +1,324 @@ +Creative Commons Attribution 4.0 International Creative Commons Corporation +("Creative Commons") is not a law firm and does not provide legal services +or legal advice. Distribution of Creative Commons public licenses does not +create a lawyer-client or other relationship. Creative Commons makes its licenses +and related information available on an "as-is" basis. Creative Commons gives +no warranties regarding its licenses, any material licensed under their terms +and conditions, or any related information. Creative Commons disclaims all +liability for damages resulting from their use to the fullest extent possible. + +Using Creative Commons Public Licenses + +Creative Commons public licenses provide a standard set of terms and conditions +that creators and other rights holders may use to share original works of +authorship and other material subject to copyright and certain other rights +specified in the public license below. The following considerations are for +informational purposes only, are not exhaustive, and do not form part of our +licenses. + +Considerations for licensors: Our public licenses are intended for use by +those authorized to give the public permission to use material in ways otherwise +restricted by copyright and certain other rights. Our licenses are irrevocable. +Licensors should read and understand the terms and conditions of the license +they choose before applying it. Licensors should also secure all rights necessary +before applying our licenses so that the public can reuse the material as +expected. Licensors should clearly mark any material not subject to the license. +This includes other CC-licensed material, or material used under an exception +or limitation to copyright. More considerations for licensors : wiki.creativecommons.org/Considerations_for_licensors + +Considerations for the public: By using one of our public licenses, a licensor +grants the public permission to use the licensed material under specified +terms and conditions. If the licensor's permission is not necessary for any +reason–for example, because of any applicable exception or limitation to copyright–then +that use is not regulated by the license. Our licenses grant only permissions +under copyright and certain other rights that a licensor has authority to +grant. Use of the licensed material may still be restricted for other reasons, +including because others have copyright or other rights in the material. A +licensor may make special requests, such as asking that all changes be marked +or described. Although not required by our licenses, you are encouraged to +respect those requests where reasonable. More considerations for the public +: wiki.creativecommons.org/Considerations_for_licensees Creative Commons Attribution +4.0 International Public License + +By exercising the Licensed Rights (defined below), You accept and agree to +be bound by the terms and conditions of this Creative Commons Attribution +4.0 International Public License ("Public License"). To the extent this Public +License may be interpreted as a contract, You are granted the Licensed Rights +in consideration of Your acceptance of these terms and conditions, and the +Licensor grants You such rights in consideration of benefits the Licensor +receives from making the Licensed Material available under these terms and +conditions. + +Section 1 – Definitions. + +a. Adapted Material means material subject to Copyright and Similar Rights +that is derived from or based upon the Licensed Material and in which the +Licensed Material is translated, altered, arranged, transformed, or otherwise +modified in a manner requiring permission under the Copyright and Similar +Rights held by the Licensor. For purposes of this Public License, where the +Licensed Material is a musical work, performance, or sound recording, Adapted +Material is always produced where the Licensed Material is synched in timed +relation with a moving image. + +b. Adapter's License means the license You apply to Your Copyright and Similar +Rights in Your contributions to Adapted Material in accordance with the terms +and conditions of this Public License. + +c. Copyright and Similar Rights means copyright and/or similar rights closely +related to copyright including, without limitation, performance, broadcast, +sound recording, and Sui Generis Database Rights, without regard to how the +rights are labeled or categorized. For purposes of this Public License, the +rights specified in Section 2(b)(1)-(2) are not Copyright and Similar Rights. + +d. Effective Technological Measures means those measures that, in the absence +of proper authority, may not be circumvented under laws fulfilling obligations +under Article 11 of the WIPO Copyright Treaty adopted on December 20, 1996, +and/or similar international agreements. + +e. Exceptions and Limitations means fair use, fair dealing, and/or any other +exception or limitation to Copyright and Similar Rights that applies to Your +use of the Licensed Material. + +f. Licensed Material means the artistic or literary work, database, or other +material to which the Licensor applied this Public License. + +g. Licensed Rights means the rights granted to You subject to the terms and +conditions of this Public License, which are limited to all Copyright and +Similar Rights that apply to Your use of the Licensed Material and that the +Licensor has authority to license. + +h. Licensor means the individual(s) or entity(ies) granting rights under this +Public License. + +i. Share means to provide material to the public by any means or process that +requires permission under the Licensed Rights, such as reproduction, public +display, public performance, distribution, dissemination, communication, or +importation, and to make material available to the public including in ways +that members of the public may access the material from a place and at a time +individually chosen by them. + +j. Sui Generis Database Rights means rights other than copyright resulting +from Directive 96/9/EC of the European Parliament and of the Council of 11 +March 1996 on the legal protection of databases, as amended and/or succeeded, +as well as other essentially equivalent rights anywhere in the world. + +k. You means the individual or entity exercising the Licensed Rights under +this Public License. Your has a corresponding meaning. + +Section 2 – Scope. + + a. License grant. + +1. Subject to the terms and conditions of this Public License, the Licensor +hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive, +irrevocable license to exercise the Licensed Rights in the Licensed Material +to: + + A. reproduce and Share the Licensed Material, in whole or in part; and + + B. produce, reproduce, and Share Adapted Material. + +2. Exceptions and Limitations. For the avoidance of doubt, where Exceptions +and Limitations apply to Your use, this Public License does not apply, and +You do not need to comply with its terms and conditions. + + 3. Term. The term of this Public License is specified in Section 6(a). + +4. Media and formats; technical modifications allowed. The Licensor authorizes +You to exercise the Licensed Rights in all media and formats whether now known +or hereafter created, and to make technical modifications necessary to do +so. The Licensor waives and/or agrees not to assert any right or authority +to forbid You from making technical modifications necessary to exercise the +Licensed Rights, including technical modifications necessary to circumvent +Effective Technological Measures. For purposes of this Public License, simply +making modifications authorized by this Section 2(a)(4) never produces Adapted +Material. + + 5. Downstream recipients. + +A. Offer from the Licensor – Licensed Material. Every recipient of the Licensed +Material automatically receives an offer from the Licensor to exercise the +Licensed Rights under the terms and conditions of this Public License. + +B. No downstream restrictions. You may not offer or impose any additional +or different terms or conditions on, or apply any Effective Technological +Measures to, the Licensed Material if doing so restricts exercise of the Licensed +Rights by any recipient of the Licensed Material. + +6. No endorsement. Nothing in this Public License constitutes or may be construed +as permission to assert or imply that You are, or that Your use of the Licensed +Material is, connected with, or sponsored, endorsed, or granted official status +by, the Licensor or others designated to receive attribution as provided in +Section 3(a)(1)(A)(i). + + b. Other rights. + +1. Moral rights, such as the right of integrity, are not licensed under this +Public License, nor are publicity, privacy, and/or other similar personality +rights; however, to the extent possible, the Licensor waives and/or agrees +not to assert any such rights held by the Licensor to the limited extent necessary +to allow You to exercise the Licensed Rights, but not otherwise. + +2. Patent and trademark rights are not licensed under this Public License. + +3. To the extent possible, the Licensor waives any right to collect royalties +from You for the exercise of the Licensed Rights, whether directly or through +a collecting society under any voluntary or waivable statutory or compulsory +licensing scheme. In all other cases the Licensor expressly reserves any right +to collect such royalties. + +Section 3 – License Conditions. + +Your exercise of the Licensed Rights is expressly made subject to the following +conditions. + + a. Attribution. + +1. If You Share the Licensed Material (including in modified form), You must: + +A. retain the following if it is supplied by the Licensor with the Licensed +Material: + +i. identification of the creator(s) of the Licensed Material and any others +designated to receive attribution, in any reasonable manner requested by the +Licensor (including by pseudonym if designated); + + ii. a copyright notice; + + iii. a notice that refers to this Public License; + + iv. a notice that refers to the disclaimer of warranties; + +v. a URI or hyperlink to the Licensed Material to the extent reasonably practicable; + +B. indicate if You modified the Licensed Material and retain an indication +of any previous modifications; and + +C. indicate the Licensed Material is licensed under this Public License, and +include the text of, or the URI or hyperlink to, this Public License. + +2. You may satisfy the conditions in Section 3(a)(1) in any reasonable manner +based on the medium, means, and context in which You Share the Licensed Material. +For example, it may be reasonable to satisfy the conditions by providing a +URI or hyperlink to a resource that includes the required information. + +3. If requested by the Licensor, You must remove any of the information required +by Section 3(a)(1)(A) to the extent reasonably practicable. + +4. If You Share Adapted Material You produce, the Adapter's License You apply +must not prevent recipients of the Adapted Material from complying with this +Public License. + +Section 4 – Sui Generis Database Rights. + +Where the Licensed Rights include Sui Generis Database Rights that apply to +Your use of the Licensed Material: + +a. for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, +reuse, reproduce, and Share all or a substantial portion of the contents of +the database; + +b. if You include all or a substantial portion of the database contents in +a database in which You have Sui Generis Database Rights, then the database +in which You have Sui Generis Database Rights (but not its individual contents) +is Adapted Material; and + +c. You must comply with the conditions in Section 3(a) if You Share all or +a substantial portion of the contents of the database. + +For the avoidance of doubt, this Section 4 supplements and does not replace +Your obligations under this Public License where the Licensed Rights include +other Copyright and Similar Rights. + +Section 5 – Disclaimer of Warranties and Limitation of Liability. + +a. Unless otherwise separately undertaken by the Licensor, to the extent possible, +the Licensor offers the Licensed Material as-is and as-available, and makes +no representations or warranties of any kind concerning the Licensed Material, +whether express, implied, statutory, or other. This includes, without limitation, +warranties of title, merchantability, fitness for a particular purpose, non-infringement, +absence of latent or other defects, accuracy, or the presence or absence of +errors, whether or not known or discoverable. Where disclaimers of warranties +are not allowed in full or in part, this disclaimer may not apply to You. + +b. To the extent possible, in no event will the Licensor be liable to You +on any legal theory (including, without limitation, negligence) or otherwise +for any direct, special, indirect, incidental, consequential, punitive, exemplary, +or other losses, costs, expenses, or damages arising out of this Public License +or use of the Licensed Material, even if the Licensor has been advised of +the possibility of such losses, costs, expenses, or damages. Where a limitation +of liability is not allowed in full or in part, this limitation may not apply +to You. + +c. The disclaimer of warranties and limitation of liability provided above +shall be interpreted in a manner that, to the extent possible, most closely +approximates an absolute disclaimer and waiver of all liability. + +Section 6 – Term and Termination. + +a. This Public License applies for the term of the Copyright and Similar Rights +licensed here. However, if You fail to comply with this Public License, then +Your rights under this Public License terminate automatically. + +b. Where Your right to use the Licensed Material has terminated under Section +6(a), it reinstates: + +1. automatically as of the date the violation is cured, provided it is cured +within 30 days of Your discovery of the violation; or + + 2. upon express reinstatement by the Licensor. + +c. For the avoidance of doubt, this Section 6(b) does not affect any right +the Licensor may have to seek remedies for Your violations of this Public +License. + +d. For the avoidance of doubt, the Licensor may also offer the Licensed Material +under separate terms or conditions or stop distributing the Licensed Material +at any time; however, doing so will not terminate this Public License. + + e. Sections 1, 5, 6, 7, and 8 survive termination of this Public License. + +Section 7 – Other Terms and Conditions. + +a. The Licensor shall not be bound by any additional or different terms or +conditions communicated by You unless expressly agreed. + +b. Any arrangements, understandings, or agreements regarding the Licensed +Material not stated herein are separate from and independent of the terms +and conditions of this Public License. + +Section 8 – Interpretation. + +a. For the avoidance of doubt, this Public License does not, and shall not +be interpreted to, reduce, limit, restrict, or impose conditions on any use +of the Licensed Material that could lawfully be made without permission under +this Public License. + +b. To the extent possible, if any provision of this Public License is deemed +unenforceable, it shall be automatically reformed to the minimum extent necessary +to make it enforceable. If the provision cannot be reformed, it shall be severed +from this Public License without affecting the enforceability of the remaining +terms and conditions. + +c. No term or condition of this Public License will be waived and no failure +to comply consented to unless expressly agreed to by the Licensor. + +d. Nothing in this Public License constitutes or may be interpreted as a limitation +upon, or waiver of, any privileges and immunities that apply to the Licensor +or You, including from the legal processes of any jurisdiction or authority. + +Creative Commons is not a party to its public licenses. Notwithstanding, Creative +Commons may elect to apply one of its public licenses to material it publishes +and in those instances will be considered the "Licensor." The text of the +Creative Commons public licenses is dedicated to the public domain under the +CC0 Public Domain Dedication. Except for the limited purpose of indicating +that material is shared under a Creative Commons public license or as otherwise +permitted by the Creative Commons policies published at creativecommons.org/policies, +Creative Commons does not authorize the use of the trademark "Creative Commons" +or any other trademark or logo of Creative Commons without its prior written +consent including, without limitation, in connection with any unauthorized +modifications to any of its public licenses or any other arrangements, understandings, +or agreements concerning use of licensed material. For the avoidance of doubt, +this paragraph does not form part of the public licenses. + +Creative Commons may be contacted at creativecommons.org. diff --git a/LICENSES/MIT.txt b/LICENSES/MIT.txt new file mode 100644 index 0000000..204b93d --- /dev/null +++ b/LICENSES/MIT.txt @@ -0,0 +1,19 @@ +MIT License Copyright (c) + +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. diff --git a/LICENSES/Unlicense.txt b/LICENSES/Unlicense.txt new file mode 100644 index 0000000..24a8f90 --- /dev/null +++ b/LICENSES/Unlicense.txt @@ -0,0 +1,20 @@ +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. For more information, +please refer to diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..cadfadb --- /dev/null +++ b/README.rst @@ -0,0 +1,114 @@ +Introduction +============ + + +.. image:: https://readthedocs.org/projects/adafruit-circuitpython-acep7in/badge/?version=latest + :target: https://docs.circuitpython.org/projects/acep7in/en/latest/ + :alt: Documentation Status + + +.. image:: https://raw.githubusercontent.com/adafruit/Adafruit_CircuitPython_Bundle/main/badges/adafruit_discord.svg + :target: https://adafru.it/discord + :alt: Discord + + +.. image:: https://github.com/adafruit/Adafruit_CircuitPython_ACeP7In/workflows/Build%20CI/badge.svg + :target: https://github.com/adafruit/Adafruit_CircuitPython_ACeP7In/actions + :alt: Build Status + + +.. image:: https://img.shields.io/badge/code%20style-black-000000.svg + :target: https://github.com/psf/black + :alt: Code Style: Black + +Driver for 7.3" 7-color (aka ACeP) epaper display + + +Dependencies +============= +This driver depends on: + +* `Adafruit CircuitPython `_ + +Please ensure all dependencies are available on the CircuitPython filesystem. +This is easily achieved by downloading +`the Adafruit library and driver bundle `_ +or individual libraries can be installed using +`circup `_. + +.. todo:: Describe the Adafruit product this library works with. For PCBs, you can also add the +image from the assets folder in the PCB's GitHub repo. + +`Purchase one from the Adafruit shop `_ +Installing from PyPI +===================== +.. note:: This library is not available on PyPI yet. Install documentation is included + as a standard element. Stay tuned for PyPI availability! + +.. todo:: Remove the above note if PyPI version is/will be available at time of release. + +On supported GNU/Linux systems like the Raspberry Pi, you can install the driver locally `from +PyPI `_. +To install for current user: + +.. code-block:: shell + + pip3 install adafruit-circuitpython-acep7in + +To install system-wide (this may be required in some cases): + +.. code-block:: shell + + sudo pip3 install adafruit-circuitpython-acep7in + +To install in a virtual environment in your current project: + +.. code-block:: shell + + mkdir project-name && cd project-name + python3 -m venv .venv + source .env/bin/activate + pip3 install adafruit-circuitpython-acep7in + +Installing to a Connected CircuitPython Device with Circup +========================================================== + +Make sure that you have ``circup`` installed in your Python environment. +Install it with the following command if necessary: + +.. code-block:: shell + + pip3 install circup + +With ``circup`` installed and your CircuitPython device connected use the +following command to install: + +.. code-block:: shell + + circup install adafruit_acep7in + +Or the following command to update an existing version: + +.. code-block:: shell + + circup update + +Usage Example +============= + +.. todo:: Add a quick, simple example. It and other examples should live in the +examples folder and be included in docs/examples.rst. + +Documentation +============= +API documentation for this library can be found on `Read the Docs `_. + +For information on building library documentation, please check out +`this guide `_. + +Contributing +============ + +Contributions are welcome! Please read our `Code of Conduct +`_ +before contributing to help this project stay welcoming. diff --git a/README.rst.license b/README.rst.license new file mode 100644 index 0000000..bb3baba --- /dev/null +++ b/README.rst.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries +SPDX-FileCopyrightText: Copyright (c) 2023 Scott Shawcroft for Adafruit Industries +SPDX-License-Identifier: MIT diff --git a/adafruit_acep7in.py b/adafruit_acep7in.py new file mode 100644 index 0000000..f24539b --- /dev/null +++ b/adafruit_acep7in.py @@ -0,0 +1,88 @@ +# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries +# SPDX-FileCopyrightText: Copyright (c) 2023 Scott Shawcroft for Adafruit Industries +# +# SPDX-License-Identifier: MIT +""" +`adafruit_acep7in` +================================================================================ + +Driver for 7.3" 7-color (aka ACeP) epaper display + + +* Author(s): Scott Shawcroft + +Implementation Notes +-------------------- + +**Software and Dependencies:** + +* Adafruit CircuitPython firmware for the supported boards: + https://circuitpython.org/downloads + +""" + +import displayio + +__version__ = "0.0.0+auto.0" +__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_ACeP7In.git" + +_START_SEQUENCE = ( + b"\xaa\x06\x49\x55\x20\x08\x09\x18" # CMDH + b"\x01\x06\x3F\x00\x32\x2A\x0E\x2A" # power setting PWRR + b"\x00\x02\x5f\x69" # panel setting (PSR) + b"\x03\x04\x00\x54\x00\x44" # POFS + b"\x05\x04\x40\x1F\x1F\x2C" # booster BTST1 + b"\x06\x04\x6F\x1F\x16\x25" # booster BTST2 + b"\x08\x04\x6F\x1F\x1F\x22" # booster BTST3 + b"\x13\x02\x00\x04" # IPC + b"\x30\x01\x02" # PLL setting + b"\x41\x01\x00" # TSE + b"\x50\x01\x3F" # vcom and data interval setting + b"\x60\x02\x02\x00" # tcon setting + b"\x61\x04\x03\x20\x01\xe0" # tres + b"\x82\x01\x1e" # vdcs + b"\x84\x01\x00" # t_vdcs + b"\x86\x01\x00" # agid + b"\xe3\x01\x2f" # PWS + b"\xe0\x01\x00" # ccset + b"\xe6\x01\x00" # tsset + b"\x04\x80\xc8" # power on and wait 10 ms +) + +_STOP_SEQUENCE = b"\x02\x01\x00" # Power off only +# pylint: disable=too-few-public-methods +class ACeP7In(displayio.EPaperDisplay): + r"""Display driver for 7" ACeP epaper display. Driver IC name is unknown. + + :param bus: The data bus the display is on + :param \**kwargs: + See below + + :Keyword Arguments: + * *width* (``int``) -- + Display width + * *height* (``int``) -- + Display height + * *rotation* (``int``) -- + Display rotation + """ + + def __init__(self, bus, **kwargs): + width = kwargs["width"] + height = kwargs["height"] + if "rotation" in kwargs and kwargs["rotation"] % 180 != 0: + width, height = height, width + + super().__init__( + bus, + _START_SEQUENCE, + _STOP_SEQUENCE, + **kwargs, + ram_width=800, + ram_height=480, + start_up_time=1, + busy_state=False, + write_black_ram_command=0x10, + refresh_display_command=b"\x12\x01\x00", + acep=True + ) diff --git a/docs/_static/favicon.ico b/docs/_static/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..5aca98376a1f7e593ebd9cf41a808512c2135635 GIT binary patch literal 4414 zcmd^BX;4#F6n=SG-XmlONeGrD5E6J{RVh+e928U#MG!$jWvO+UsvWh`x&VqGNx*en zx=qox7Dqv{kPwo%fZC$dDwVpRtz{HzTkSs8QhG0)%Y=-3@Kt!4ag|JcIo?$-F|?bXVS9UDUyev>MVZQ(H8K4#;BQW-t2CPorj8^KJrMX}QK zp+e<;4ldpXz~=)2GxNy811&)gt-}Q*yVQpsxr@VMoA##{)$1~=bZ1MmjeFw?uT(`8 z^g=09<=zW%r%buwN%iHtuKSg|+r7HkT0PYN*_u9k1;^Ss-Z!RBfJ?Un4w(awqp2b3 z%+myoFis_lTlCrGx2z$0BQdh+7?!JK#9K9@Z!VrG zNj6gK5r(b4?YDOLw|DPRoN7bdP{(>GEG41YcN~4r_SUHU2hgVtUwZG@s%edC;k7Sn zC)RvEnlq~raE2mY2ko64^m1KQL}3riixh?#J{o)IT+K-RdHae2eRX91-+g!y`8^># z-zI0ir>P%Xon)!@xp-BK2bDYUB9k613NRrY6%lVjbFcQc*pRqiK~8xtkNPLxt}e?&QsTB}^!39t_%Qb)~Ukn0O%iC;zt z<&A-y;3h++)>c1br`5VFM~5(83!HKx$L+my8sW_c#@x*|*vB1yU)_dt3vH;2hqPWx zAl^6@?ipx&U7pf`a*>Yq6C85nb+B=Fnn+(id$W#WB^uHAcZVG`qg;rWB}ubvi(Y>D z$ei>REw$#xp0SHAd^|1hq&9HJ=jKK8^zTH~nk)G?yUcmTh9vUM6Y0LMw4(gYVY$D$ zGl&WY&H<)BbJ&3sYbKjx1j^=3-0Q#f^}(aP1?8^`&FUWMp|rmtpK)bLQ1Zo?^s4jqK=Lfg*9&geMGVQ z#^-*!V`fG@;H&{M9S8%+;|h&Qrxym0Ar>WT4BCVLR8cGXF=JmEYN(sNT(9vl+S|%g z8r7nXQ(95i^`=+XHo|){$vf2$?=`F$^&wFlYXyXg$B{a>$-Fp+V}+D;9k=~Xl~?C4 zAB-;RKXdUzBJE{V&d&%R>aEfFe;vxqI$0@hwVM}gFeQR@j}a>DDxR+n+-*6|_)k%% z*mSpDV|=5I9!&VC&9tD%fcVygWZV!iIo2qFtm#!*(s|@ZT33*Ad;+<|3^+yrp*;oH zBSYLV(H1zTU?2WjrCQoQW)Z>J2a=dTriuvezBmu16`tM2fm7Q@d4^iqII-xFpwHGI zn9CL}QE*1vdj2PX{PIuqOe5dracsciH6OlAZATvE8rj6ykqdIjal2 z0S0S~PwHb-5?OQ-tU-^KTG@XNrEVSvo|HIP?H;7ZhYeZkhSqh-{reE!5di;1zk$#Y zCe7rOnlzFYJ6Z#Hm$GoidKB=2HBCwm`BbZVeZY4ukmG%1uz7p2URs6c9j-Gjj^oQV zsdDb3@k2e`C$1I5ML5U0Qs0C1GAp^?!*`=|Nm(vWz3j*j*8ucum2;r0^-6Aca=Gv) zc%}&;!+_*S2tlnnJnz0EKeRmw-Y!@9ob!XQBwiv}^u9MkaXHvM=!<3YX;+2#5Cj5pp?FEK750S3BgeSDtaE^ zXUM@xoV6yBFKfzvY20V&Lr0yC + Download Library Bundle + CircuitPython Reference Documentation + CircuitPython Support Forum + Discord Chat + Adafruit Learning System + Adafruit Blog + Adafruit Store + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/docs/index.rst.license b/docs/index.rst.license new file mode 100644 index 0000000..31e43fb --- /dev/null +++ b/docs/index.rst.license @@ -0,0 +1,4 @@ +SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries +SPDX-FileCopyrightText: Copyright (c) 2023 Scott Shawcroft for Adafruit Industries + +SPDX-License-Identifier: MIT diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 0000000..88e6733 --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1,5 @@ +# SPDX-FileCopyrightText: 2021 Kattni Rembor for Adafruit Industries +# +# SPDX-License-Identifier: Unlicense + +sphinx>=4.0.0 diff --git a/examples/acep7in_simpletest.py b/examples/acep7in_simpletest.py new file mode 100644 index 0000000..5fdb982 --- /dev/null +++ b/examples/acep7in_simpletest.py @@ -0,0 +1,46 @@ +# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries +# SPDX-FileCopyrightText: Copyright (c) 2023 Scott Shawcroft for Adafruit Industries +# SPDX-FileCopyrightText: Copyright (c) 2021 Melissa LeBlanc-Williams for Adafruit Industries +# +# SPDX-License-Identifier: Unlicense + +"""Simple test script for 5.6" 600x448 7-color ACeP display. + """ +# pylint: disable=no-member + +import time +import board +import displayio +import adafruit_acep7in + +displayio.release_displays() + +# This pinout works on a Feather RP2040 and may need to be altered for other boards. +spi = board.SPI() # Uses SCK and MOSI +epd_cs = board.D9 +epd_dc = board.D10 +epd_reset = board.D11 +epd_busy = board.D12 + +display_bus = displayio.FourWire( + spi, command=epd_dc, chip_select=epd_cs, reset=epd_reset, baudrate=1000000 +) + +display = adafruit_acep7in.ACeP7In( + display_bus, width=800, height=480, busy_pin=epd_busy +) + +g = displayio.Group() + +fn = "/display-ruler-720p.bmp" + +with open(fn, "rb") as f: + pic = displayio.OnDiskBitmap(f) + t = displayio.TileGrid(pic, pixel_shader=pic.pixel_shader) + g.append(t) + + display.show(g) + + display.refresh() + + time.sleep(120) diff --git a/examples/display-ruler-720p.bmp b/examples/display-ruler-720p.bmp new file mode 100644 index 0000000000000000000000000000000000000000..f73b1c3c26e5530aa8af9eabb4411826e6d78615 GIT binary patch literal 921926 zcmeI*NtP=~p(bF_UwV=zX)k?q;gV4UHo$p@^J-L+I)^Q=ff_KW0YkRH7T5w47Qmo3 zz!um-mNnj(t8q7lB$MR+Df3F+m|OF?;tz8vBJ^MX>%Twv$}Zmi`xCp}|BVZu+3o({ zCwIF~?B2w+-R^5&+5PNgm;U{aup0mEb|3fur?vn3pa1*+q=hr?LK6qKQ0wl44?YOB z|9$XA{?6oYD<|JL32a;-&-Wri zO2Y1b<0yttfWRgM@?DS`IH-S)lzQ0W~Y9&B`z{3fo;0wL#|5C!k zbx?;05Fl_P0r__$Sk)3B@c05D0Mnm|>FyuD!+J=70D&tB#QZD%yHc&HAwYn@69}YN z{=yWnn+QHZk9Cm%0Rq<%=->J1UkSWUt!g1afWTu5q@RB5fAYo8zdZKI(mMhKE*J3m zAD0`dfdByl1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAaF|ozvp&KU3C*6K!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXr7x4KXmm8{q009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlya7zK7|8YxQbrT>!fB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t7A>2%rDqBS0=^R09D51PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAVA<|0zUua zX0$3MK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXFTt&c#e_Vx8B?Jf%AV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+0D+qc`23HX(W;mL0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNA}6#<|BaTP|D5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1a2k}KL5jw009D<6u4Qis+hpj z3+#4JKLi7)76{(}LfP`Z`cMT4tWZGyt?;Ct8d3_sm-7BpN!tmmOdx;PPtX251IS+o zD;uTZ%m|dp=j_iw*|j=>{`o#W_Dic9ssWu4$Y(rG`FG)4V7zxDupNQ?#Lv(B@D&gS z?kiwBXFr_nbPW*CeE;8;MsKWJ7Z~#|ej&uK2Kl$8=R`i+@mUb_FHHfrG<;*-vOo^I z{KQWV@v9+!MQoX6OJmPxJD+!Fe@kcHSofd%Is5WfIvWw_z6YjhzsdhbPP$=6f%3b4 zxlCu}0zUs^$9Z1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7e?B?3PG;}Si` z5+Fc;009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1a2=7KL5jw009D<6u5oDYJmU&0*@~cz5#?zmiLd}XFVi9fWQ?5Quw`;_gAP?6$A(n zcoKn~{Cko!rJDo@Tw5UIUzh;)_t&mneFO*)cuax#{!hxjn1AWN$LyzG5g|FbHBX)n0?hN0t5(LQy^adrg>iszO;DF+SNsX0D%V+ z@cADPc0zQA009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyuqWX6-1b1M5+Fc;009E85{SP=??!+Cfh`Kizb&41V0zw$Z{;W4@CXnX1g7~H zFM#6(vH9NsWPt#I)e3ZBH_ZRy3^4y&?T`(O009C?AkXx2=9SBM2oNB!c7ZbU#uUt3 z*FN@@jL+wPtmH%*Mtgz$YF|#i?i0hj{MY_8XpsN`0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RmeP@bl_hILpRJfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&=vq1R#4<7;Y%qLLa2@oJa zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5;&)eHFi zkJX=I10+Cz009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1fE>Lhkrcz3DkW81PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV6UC0zUs^^{3bX2@oJafB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5;&Cl~PfA5VS)b)NtM0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5LmrH`1}ty0t5(bQegD~Z-4{{ z5U3N_y}X2P1EFlbuRBO70t5)GKw$Th!mqnu!GH{b009CO0_pl+{#8gRLV&>91iG1D zyaW!HzwzFU009CU5y;6G)35t)BjYwq0t5*3sTU@HF$&H9JS7Ma*pNU@zLbNme>ZgA z4V3_aAdu#LapLFaUpyZO5Lml_&;MBa88$uw1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAVA>R1^k}dv!6lzCqRGz0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7)-K@lKh}PRjgJ5U0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5O{V0pa1df zXHfqM5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB=ED3xv=A@DU(uKgq^NfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&=wSdq6cBPj%KQ5(HP#|G z*3!n6$W=ptz_|il_Qm{5|DAjMiSld7rWWHkL1;4p0=E~4xfiE^`Tk1nwaAUNv~eYJ z)eskDy_RfhF^-dnb`T(NQ-Sg)U-I&Gnro38YiZ*;;%Xs4phlp@ z=YOmvn_7&c=A0=*fWY$zw8)LMwDCM=RZj^Js1aC8HnkW>ji)jM2t1EKi`-aC8_#oA z^^^dC8iBQBQ;Tubcq&7H!1D;S$c?qM@jPc$PYDpH5m-w$wHQZ@r!oWxJdZ$&+*nH+ z&vRDwlmLMmfwg2)i*eL=Dno$4^9Z!ajkUD#JZDu;2|T~RHGj|Tl*U@Jsl_->8QM;O zz;g<;$c?qM@tkK^uL%%1C9sxkYB7#ehPD$R@SFlIa$_xRJm(qKYXSsL39KcXT8!hA zq3r|+Jf}d5+&Ht1w{Krw-hLD~!(;XB%r>g)RgeII^$N7ejWgPK`_YHP?QIOg+S?gz z)K;k+0Rk%*XptM0ZM=PXJ7iy8c>D5EZ3I@fvGTKNcmxQXBhVr@D%&{BzYpKazjIEe zvIGd6B~Y17XVtl1xVDX9`uF~QKM|CF`L61eJY*Jf;0 zWeO1>unB<{xl!51`;>d{-i7>o7nb9{kb!U0TfvLxqOy&}dK4f)U^@aWa-*t^w_*DC z{@sV~-@bkS;k&o*(!a1C@~`SGkg7Jeb6Sm*0D%gD7P(Q=MvA}pZ{zImZ9n^a_daA{ z2*iqEgpY-HBS3(_c>*nRqo$3Ve;AW$K&oJ|##EEK6|BfiM@;fF8ziZ{&!<6T_;Nd7JG+D(AKD+MaD>6JB) zhgGx@^KbZxmm&Y+A3z8@{Qk#iX^8-V>j_k3)5VQdv=Og=#~*nf12D#4#jAhey`qbI zsR9B7wkFUbH>%n=nST|({1HxCRU2D7xyDO?z^p)v+^A|JRZR*JAn*tR;qyOk{t+N8a-*t^@LRrP0QT>O#5X_W-y=L1^?|?| z1*)>?!hu({5w3H`4?hpnzV!PbAB7;SYrLwBx~h~SKwu*REpnr(jrdvT`HvvPzj)gH zK1le}SMqNo&qTu{&|aV_n=b5DRU0Y)@-G2@7?Utg0N=)6{-|rbs*Sp;lp;W2BLXdQ zqpFSgXI{E@J;LjNG5^w!zR16gJP{3(z#RmtvgyKp)wa=H^yctO6TtXGF?EgCwozA` zQUnNWL7+u$)V2{{_6t7(lP-S4Qn&)H`qR(pG}X4Tg>!0*1PIg#w8)L>Hu4)F;o3Jw z;7j<^FLgir5=UCyMjeY%1PE+Epha#}w~;;tB){nqFMm@CR-S|EHY)2=i~xc43$)0M z>Neu#ZwS5gfp6hHUJuuvf$BDDD^!jEfx8N9=kq^0<`jS7ZQ$@$aJcxb`Ph%){K&t7 z!U6#Tl>#ktqqdFk2VmkWfbp_7Y;_w75+JZHffgZA*+xjd5Pk7& zkMr~INZ1|Ow60TUGz17-C{USA7qwE^Mtrp|T>9ou{75hVRkj*mCkSn%X3}d0ajCM= z$|e*eKwyOeEn?z~HsT+9j+4OnYrpls`Wxaev=N)h|N5mBo-acpK;U`;F)D6-JFkuS z`drq?N*+eSD4t8FZ0-jILkVmREL+h}cT z$`K&28i5uuac&#&=U?i7@-NT!hWv|XCMDu(PLY8SAaEmrbF=9+-8i?6aP1p@{H6ML z-%{G8`ChsN4n35AuQ^SQA+R}tbF=9+K(A;cy#4#?{L3l$ibh{EHpdVka2tV}fA~k} zc8i#JMH^uXSbxhe`Q^dn7yi8bSFfief$a*sBAd>}I=_vx;xF~*{5H-Wh64x?SeZbJ z+*nH+D?9auLtyg)Yssb- z(BiikTI9xB+Gu#{HAR3x1A(<RzR0r__}nF9!H zUZ6#8tfh_3KUn|}Sed|DvZ=*5R(9$Qhrs3qTI9xB+SvS)1ptAS39KcXT8v|5r`~V~ zY+j&6Zmgw^%|BTH5LlVOTC%CdI97J*4Tr$y1zP0BTH4tBlLY{Ql?kjRn_7%xWvAY7 z2y9-UMQ*I6jm5I+CI?STXuo_b9YAg~gF`^^7#Et*})88Qq44=s>pK`$@i zA#^j}KXiX5oof+9hi%Be$w{z6;E4s&*LMoPmwf+3V>!&G>vw)ves6d>q3e67k-(}1 z`mgEmg&xM$B2uo#*P^p|V%*t0ozT^&RYYK=0^y4~ev!wCj{G|~$KBO#PQHA9P{sxV z1fEtP&iuyzo@f{`j&6M$@-MzP+PzwO>o(O-fIt(0VO|rzy7NS^NxN5Rq-p-e9%rqq z^j#$c2;5y@$iFlLbp3m9LWcQY+#~-Ed~6`_%mU?4zWDiSSctdyv6<Yh#5+mdLHlP%X z{aW1AZ|`@f$GCm}cDQA~#IQa+db&0gI<{~|8^;c}jR1kw2=q}DQ(;){77n+BQYQ*! zkhHV6IazYp(U%+^m$PX&_VmI~+wq0vHjW=>D**!Q5-36>46Im7i-%k8oqy9FzB_tb znhMIlbv=iThQKQY$~XyC1ax7)qjt981%)W)>5H39^lT%e1M{ZVu=GVI-b5dO=B;?f5pxW+C0a-HXQ znbdJuvaB^1?e7<|Y3ylSIv#)T-pRk7(<1=_{roFL#snj$Nq--9rNvyNTP(Kpdy7qn zg^Has)lEuGyEIulSV;$lcT;lR^6vo11_A^Q1afY4>Cx{kH-_b~InB$$tS{WUIbAtZ zD`$H-NXsqhsD4J6R}SZeM{3PQ`}=7?_gja@)a4k&DF9F8pX=Yj%K`xc-AruAyDYNH zX*b-5ttp;{4e?UAh_HUS*nb#jW%)7;rzIz)Cg*1%|I!?EygMF%d$Zh0{c&Zfje`Sh zAVA=m1%~MB7UEcrZA-y423#l}UALd69>+JF`y!kO1avWfnf%0!cYK6e&1-kqjANJ=@lQ0Qf z)4)o8MVxh>hjBJ3Q^ee~KwupLDRELBom$!( z=QOa=&LYmb!iOQ5o9K2IF*hxFSX1BnVm77p>q{R#?oSI3ON1%pv5mG7Ah2G6apreo zDGvREc*_ReVtVM_5iU0!7Am&v)e-khkL}j-A(Q*XYzn=f{psf2^s;zTdAG9I#<7EJ zBS7GJ1@gpf<~|N>fA`^*BQG2lFC|XOFTMU3XNL!#i`gXq4$N#IKwv@O)U2=Ho(|8m zz45-Aw~ZU(%&uIE%f*&raoC>wl@9857o`q5U6X%(mv_7HSHBK!=6?sMHW1jnz|q(J zLKJn|v(Gf!;o<(N+uR!r$uxvhzom$?ep7sm2M+5)nY<@$&oy_8 z2#iywIH2y`hanUzLg8d;o!oIs?(_i*-5AGkIQ{Ei3H0}`PO;lgV5I{2i+_G_!z+NX zSPZ^=UmbxbQ!DL=ck}JXR&%ND;YjhC{L6iev+u!*6S4UiJBCvUZAppBe;Ni`W zAp&QKPNr7ck&|t; z>wnEomWBvCjX)W4q0`-bFL%G(7cXV+Hz@gcKYJ|`Sgk-2adC{}`1|I#nOy^(+SJ%d^&@L&Sd>0Q4TJJ~M}kN56*P5#9>V7l$i|GGbb z;P-#;eG;`#;E@E%Szoanx>&3YAM<k8PZ(*4JJy2)m z-vgZtT_Lanfn%@orEUG|e-AW9`S(C4LstkqzrfzCFRbpr?Ds%ptjoXdulA2uywfGu zzYlaqb%nrP1tzcY#d+Vs`@VPW-n8+m{0oO1dH-X~K>0UCwMJmO0(AaH+y;`P6-GsBh~g!k{_(1V)%i`ggt1~Ll-HZKr<_U#;l z=>+hcBX3-`BLDKmZw$cctZ!U1|GV*7QaypE7I^CXiU(cJ<=)F7Xptb@T~b4ldrqIjEOg0l7El)eA6QW4<#@J;6wFlasJnb zUwoXV-nb_J9_pOx41os}=mYSfy0(;mW&Fv%hdOmSL*S_dasWP7m*wAMoe#Ysuv&o> zfR8o0rTmM3_IbFCSG<#@aA7<2oPAmK#Oc@(Z>4E zlo1jjaBYDW+0>$qYrCkA0D<)jw8*9wZLI%H86g1z*A{4zO)c8Ewu|}*5LmxJi)?Dq z#`@2c5fUJ9ZGjfq)S``RyQq%#A9;f4bJ!z3mE!x-{ zmQ?}-2rLS;$fg!;EDlrw0t5)`3AD(j7H#Ye%PIi^1QrEaWK)Ya76+;T0RjZ}1X^TM zi#GO#Wt9K{0*eAIvZ+NIivv}F009Df0xhzsMH_p=vPysefklB9+0>$q#eph7fB=C# zffm`+qK&;_StUS#z@k8lY--WQ;y@K3K;UWu(+|L~c5i{JomdqSAn-f_i@`HLlooTd z7H!Or(p~}tZY2;RC{$hE->Ri)y*c_m_+XblSF^j{3!6S3r$>%!d&S2cS6ph*#udA( zDgp$~5lHbD4%nrSdTjFL9&;_kUJAW<7aO16a`H{L9j@&kby(u^EiKx(yq9VqK;TsZ z@e4fv>z7_tP5nVJ`-bTI;NYW(Q}o4jT&}UA$Z{nMC0ewx&;`2*5V(~BAZ&YQI5$n0RjyL;umY11M7hN)j@adHc> zm)BE?JV%UCI4Lw)nb|cdcgaeNHZJL(V+jzrKp=jBhkqew^8E!>Ego82`cBK{DPO-W zy(N+YFkUL3PN36!`kF3(Y|+N$y;K7M00{EhZ=BujWm=l# zg{{MpIRIn$&At#g9xxnv^@SE~T)opOBtW1}Abo-7%got}&AQs=O66q&!W8$ze6Y*E6h6bo;pl$hjBJvBJ(@=X1O|aTKTG$M8D7{D z*7M%@7#CxK?jdc7t6iD2E3X$@it=G5HI2V?ftzwJU+u>GKI(?~VBByz0WV;x~UIo)FZofzCC{$ljWzY|h66CiK}f&N{MP*r-5BRr%xKGJ%8mm@Bu zEz|8`N7#_!ZQL6Rhg(-NKjcDrM|w3cLv?3#9iq;+r0OO?P?L{XWR@{7(Mu0a_(M;4FcdMImX5`!pr% zqp07W>dX_jxR^HQ`~0~fXSJDX7~bt24(+dhV`tKB*mGh*{+)oanE-(rffynEU%t=F zdD@kurQDLYk9)_X@={G}MVa07Wwc27Jo_8>^z|-3mdE6oU%w^hUq2U|t*1X=rcn9|3f*+_;9>vz`&c~{Z5%ty zHUb2mKp=)ff5n@Y$J85_atMr3Fs{Eo|Ax0WVh7T#d+6T%sIVJ5bh5DgJ4s^)fo%$u zzmgUNhWty*UFxN5iFf_Kyp+N6w*EdJpZA<|ALBOM`a}AK>giwVT7UG3NBMUG#%2Np zLa3zx$~iPF$E=GhIpMmQTHc$@%97>wOGLZ;OYi>nSvX%`MJf3=PiQXz0#RTLlW}P( zb87pv)T`IJ>O-8?CTc~8vtS8IMzmqg}5Fqd{0)58TPyf!&zcAK(b=}?j`Im<| z`#M5k+X7ww#kW8DC|m-mC|At?y4s2alz&UY_7fn`LZHvG6i<~6_Q%W=AM1gwSR_E;ZUVQ?zajLB1^IWk)2(3wcM}K^aJRNk zG(2>u@>hRTHN!zCDh->*>)#^x`bGJ78qOX91eysHQC2K2G+$9t{w)~VO@P3?1ZqB{w*QePk_Lk1&Smq7MD6zQMAmzR9*ktUwriX z-;%KX1PI(-ph&V}ar!5s4|`D-J=~kN6#3VcC<0Laolvux0D*=AMUoYZ;d9Vu`%o4= zQE<$^P$2)^!!ZEoYtJ=Sv~i+on+XsgP$5u;OtHL_PesvFjSTr03WWH36F<*=2*9QK zW2F^s#A0p)2oQLkz$9eGm8EtVI5e7M2JQctC;EIW`}Fr;i&3Ipp71c9{N|{|!tQ2oSiJz?e;; z2SY05oSN&? zTgtw8V&vc2pPt4?;Q9hZwme4u^+}eKFAlgO+Nuhf|6Tv-qecR25%@y*ov?3w;~U@k z&Ub$L)1Q9y(MP}e&2N77t6%;6=Rg194}bWhAN}YjKl#bee)h9p{Nfki``-7y`OR;B z@rz&l#3w%SsZV|CGoSg)=Rg1XuYUEbU-`;czVxLpec=lidh{2%A&$okT&%MqB<0_t zq5=dqEASxsw>Ouo2)1~}DvHU!%|5jaoWP>M!{lH1h2Orj<5Iun#N%+piTz=-{5x%9 z4}q-0E!SJt^|9R!TVn1da$iQvMz3-ux!{H}7LF0RpoE@^6->>NUoN8tf)O z;6VlC-@=Khm}4%~U^f8*4=N!47EX-(TL7|~!1D^kFYoa0@W<}DEoo%Ma(s)TzbNdE zz2D$t2NrJL|6KsGo50ot`p>}#_LoLcV6hX{;Ice}M{yhRJp2q zZ42aA^74y)In_Fk@#Vj8fjq`sF5lgUqIZpl7LB)PW7|(bqbES%H3BWNsYM&F8M|W$ z5V%<2&9471&gq`)i@im6TeNZUSyTZ500a|{6juM;RH zdSmp(m-${--QA9A(cczr+zn8}1hy{FT>yvld-LYWELvn!i#DE&U3UqrM0T8r+UU=Be0=V4j3c%8^(NNo&v{b(-gcGbZ-a;u7-DAbGJ zvd?>MB&QSIxnOfYg4Eg#+Q{GE@>ufy1)ZHabTW>aaa{7uiIa2KAZ>3*pDnhUY!v5l~Fi(5Z}JPE&k3$fdi zHm=`9s`1usG#W=d-|^qgo>xuAktP_o8%G*Lp_E&??h`Av5zoUd&qr<}HgY?wG>pmJ z<+H!eB|b~L|0WGwZKbb0J$6`Et2|ZIx%cC^MH}(#PX4>@2x4vdjFzoDXB%-SQ?2Wd zBVygUjrcSw&qiFo=IyZl*xGe(xxW3DZqdeVtqyt|&VQW!T{Z*EE-|*lQhY*P{npD5 zZQP=f(CdB#X&g6cBY!0f&Na^FNYMoGgUfMOx|b-1~kE7u9#<;Ij6#9Ph4tYtcsNa{exn z&vMMCtKV{+_3SrR%p*KBI0hj=sZV z;>D$Lt>1sXe(=J-L00|-6FJ7y`Yu9(IUu$XO*w}0%K;VV~>9XQ> z^{*wHjHCWJ!irVBKz+%ZJg?#_zSR|<|JHDI)dPbz28zW6R*OVK0agRW;=+ckLO|7D z^lr#y?>QpJ_dsS=S