Compare commits

..

No commits in common. "master" and "dm-blinka" have entirely different histories.

26 changed files with 559 additions and 2410 deletions

View file

@ -1,57 +0,0 @@
name: Build CI
on: [pull_request, push]
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Dump GitHub context
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT"
- name: Translate Repo Name For Build Tools filename_prefix
id: repo-name
run: |
echo ::set-output name=repo-name::$(
echo ${{ github.repository }} |
awk -F '\/' '{ print tolower($2) }' |
tr '_' '-'
)
- name: Set up Python 3.6
uses: actions/setup-python@v1
with:
python-version: 3.6
- name: Versions
run: |
python3 --version
- name: Checkout Current Repo
uses: actions/checkout@v1
with:
submodules: true
- name: Checkout tools repo
uses: actions/checkout@v2
with:
repository: adafruit/actions-ci-circuitpython-libs
path: actions-ci
- name: Install dependencies
# (e.g. - apt-get: gettext, etc; pip: circuitpython-build-tools, requirements.txt; etc.)
run: |
source actions-ci/install.sh
- name: Pip install pylint, black, & Sphinx
run: |
pip install --force-reinstall pylint black==19.10b0 Sphinx sphinx-rtd-theme
- name: Library version
run: git describe --dirty --always --tags
- name: Check formatting
run: |
black --check --target-version=py35 .
- name: PyLint
run: |
pylint $( find . -path './adafruit*.py' )
([[ ! -d "examples" ]] || pylint --disable=missing-docstring,invalid-name,bad-whitespace $( find . -path "./examples/*.py" ))
- name: Build assets
run: circuitpython-build-bundles --filename_prefix ${{ steps.repo-name.outputs.repo-name }} --library_location .
- name: Build docs
working-directory: docs
run: sphinx-build -E -W -b html . _build/html

View file

@ -1,81 +0,0 @@
name: Release Actions
on:
release:
types: [published]
jobs:
upload-release-assets:
runs-on: ubuntu-latest
steps:
- name: Dump GitHub context
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT"
- name: Translate Repo Name For Build Tools filename_prefix
id: repo-name
run: |
echo ::set-output name=repo-name::$(
echo ${{ github.repository }} |
awk -F '\/' '{ print tolower($2) }' |
tr '_' '-'
)
- name: Set up Python 3.6
uses: actions/setup-python@v1
with:
python-version: 3.6
- name: Versions
run: |
python3 --version
- name: Checkout Current Repo
uses: actions/checkout@v1
with:
submodules: true
- name: Checkout tools repo
uses: actions/checkout@v2
with:
repository: adafruit/actions-ci-circuitpython-libs
path: actions-ci
- name: Install deps
run: |
source actions-ci/install.sh
- name: Build assets
run: circuitpython-build-bundles --filename_prefix ${{ steps.repo-name.outputs.repo-name }} --library_location .
- name: Upload Release Assets
# the 'official' actions version does not yet support dynamically
# supplying asset names to upload. @csexton's version chosen based on
# discussion in the issue below, as its the simplest to implement and
# allows for selecting files with a pattern.
# https://github.com/actions/upload-release-asset/issues/4
#uses: actions/upload-release-asset@v1.0.1
uses: csexton/release-asset-action@master
with:
pattern: "bundles/*"
github-token: ${{ secrets.GITHUB_TOKEN }}
upload-pypi:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Check For setup.py
id: need-pypi
run: |
echo ::set-output name=setup-py::$( find . -wholename './setup.py' )
- name: Set up Python
if: contains(steps.need-pypi.outputs.setup-py, 'setup.py')
uses: actions/setup-python@v1
with:
python-version: '3.x'
- name: Install dependencies
if: contains(steps.need-pypi.outputs.setup-py, 'setup.py')
run: |
python -m pip install --upgrade pip
pip install setuptools wheel twine
- name: Build and publish
if: contains(steps.need-pypi.outputs.setup-py, 'setup.py')
env:
TWINE_USERNAME: ${{ secrets.pypi_username }}
TWINE_PASSWORD: ${{ secrets.pypi_password }}
run: |
python setup.py sdist
twine upload dist/*

1
.gitignore vendored
View file

@ -4,6 +4,7 @@ __pycache__
_build _build
*.pyc *.pyc
.env .env
build*
bundles bundles
*.DS_Store *.DS_Store
.eggs .eggs

View file

@ -52,7 +52,7 @@ confidence=
# no Warning level messages displayed, use"--disable=all --enable=classes # no Warning level messages displayed, use"--disable=all --enable=classes
# --disable=W" # --disable=W"
# disable=import-error,print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call # disable=import-error,print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call
disable=print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call,import-error,bad-continuation disable=print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call,import-error
# Enable the message, report, category or checker with the given id(s). You can # 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 # either give multiple identifier separated by comma (,) or put this option
@ -156,7 +156,7 @@ ignored-classes=optparse.Values,thread._local,_thread._local
# (useful for modules/projects where namespaces are manipulated during runtime # (useful for modules/projects where namespaces are manipulated during runtime
# and thus existing member attributes cannot be deduced by static analysis. It # and thus existing member attributes cannot be deduced by static analysis. It
# supports qualified module names, as well as Unix pattern matching. # supports qualified module names, as well as Unix pattern matching.
ignored-modules=board ignored-modules=
# Show a hint with possible names when a member name was not found. The aspect # Show a hint with possible names when a member name was not found. The aspect
# of finding the hint is based on edit distance. # of finding the hint is based on edit distance.

33
.travis.yml Normal file
View file

@ -0,0 +1,33 @@
dist: trusty
sudo: false
language: python
python:
- '3.6'
cache:
pip: true
deploy:
- provider: releases
api_key: "$GITHUB_TOKEN"
file_glob: true
file: "$TRAVIS_BUILD_DIR/bundles/*"
skip_cleanup: true
overwrite: true
on:
tags: true
- provider: pypi
user: adafruit-travis
on:
tags: true
password:
secure: qcc4jJ7uVD270sLdbvyiBdsVS7JOLDO02XsWXsSL4HPuiIlAddBD1/NWUBC7e9APPFojQZnK6lHx6HFIduRG3clZRYawePPsclCQ7KxgDaXDRUKW2CcpvdrBBvHpoaCsbzdB9QDFH3JIrZPksKRiCMRSxdbFmdzucoBIdQ1ERgcRSB1ncnBywVqzSj1kiMXUtGLFqN6wo5x4kF2z8/bZ7FACyzzOGTpqq3wQLb/CropSpZ8bmoW0Q8fJmoaUR39kRfEHu1g3KW8Nvd6Sv0RbUbe5SkW2fdrHoRT2/FN00HElL7Lc3ShiD+aHujvzdmm4FAic2iMrrAKI74fr5b6dlNcLHwEtOiq6zxtkedydk1dN3NWMdyKCaYYKRwxSXEa9DkCC2w+DCx1ExJWO8r3oz+AaLUNhCrzww9GR8JBUP+siAtus3GaBB3B8njymM59NkOfd8rdKaN4E7x0eOqRV/gDjAoz1JqBNXR/BKM/np5UJ5UMRbY7sy8mB6hdF+wvnEOJfjYX4C3Ao/ZT8IVieNAYRojHHmKi4bh6aqK9noJ33belGgPewyeg3NXZE7uprL1XGnC9lCi0P4lWTskdPlhtysXOKOos3vuIpRHxZC6uiP/zE3Y7PO9WPs9fSMdQKBCExqu9OwZEFMKiJiOyM3quInQuxKSBYrlh3bXe69lA=
install:
- pip install -r requirements.txt
- pip install pylint circuitpython-build-tools Sphinx sphinx-rtd-theme
- pip install --force-reinstall pylint==1.9.2
script:
- pylint adafruit_epd
- ([[ ! -d "examples" ]] || pylint --disable=missing-docstring,invalid-name,bad-whitespace
examples/*.py)
- circuitpython-build-bundles --filename_prefix adafruit-circuitpython-epd --library_location
.
- cd docs && sphinx-build -E -W -b html . _build/html && cd ..

View file

@ -34,8 +34,6 @@ Examples of unacceptable behavior by participants include:
* Excessive or unwelcome helping; answering outside the scope of the question * Excessive or unwelcome helping; answering outside the scope of the question
asked asked
* Trolling, insulting/derogatory comments, and personal or political attacks * 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 * Public or private harassment
* Publishing others' private information, such as a physical or electronic * Publishing others' private information, such as a physical or electronic
address, without explicit permission address, without explicit permission
@ -74,10 +72,10 @@ You may report in the following ways:
In any situation, you may send an email to <support@adafruit.com>. In any situation, you may send an email to <support@adafruit.com>.
On the Adafruit Discord, you may send an open message from any channel On the Adafruit Discord, you may send an open message from any channel
to all Community Moderators by tagging @community moderators. You may to all Community Helpers by tagging @community helpers. You may also send an
also send an open message from any channel, or a direct message to open message from any channel, or a direct message to @kattni#1507,
@kattni#1507, @tannewt#4653, @Dan Halbert#1614, @cater#2442, @tannewt#4653, @Dan Halbert#1614, @cater#2442, @sommersoft#0222, or
@sommersoft#0222, @Mr. Certainly#0472 or @Andon#8175. @Andon#8175.
Email and direct message reports will be kept confidential. Email and direct message reports will be kept confidential.

View file

@ -6,11 +6,11 @@ Introduction
:alt: Documentation Status :alt: Documentation Status
.. image:: https://img.shields.io/discord/327254708534116352.svg .. image:: https://img.shields.io/discord/327254708534116352.svg
:target: https://adafru.it/discord :target: https://discord.gg/nBQh6qu
:alt: Discord :alt: Discord
.. image:: https://github.com/adafruit/Adafruit_CircuitPython_EPD/workflows/Build%20CI/badge.svg .. image:: https://travis-ci.org/adafruit/Adafruit_CircuitPython_EPD.svg?branch=master
:target: https://github.com/adafruit/Adafruit_CircuitPython_EPD/actions/ :target: https://travis-ci.org/adafruit/Adafruit_CircuitPython_EPD
:alt: Build Status :alt: Build Status
This library is for using CircuitPython with e-ink displays with built in SRAM. This library is for using CircuitPython with e-ink displays with built in SRAM.
@ -21,37 +21,11 @@ This driver depends on:
* `Adafruit CircuitPython <https://github.com/adafruit/circuitpython>`_ * `Adafruit CircuitPython <https://github.com/adafruit/circuitpython>`_
* `Bus Device <https://github.com/adafruit/Adafruit_CircuitPython_BusDevice>`_ * `Bus Device <https://github.com/adafruit/Adafruit_CircuitPython_BusDevice>`_
* `font5x8.bin found in the examples bundle <https://github.com/adafruit/Adafruit_CircuitPython_Bundle>`_
Please ensure all dependencies are available on the CircuitPython filesystem. Please ensure all dependencies are available on the CircuitPython filesystem.
This is easily achieved by downloading This is easily achieved by downloading
`the Adafruit library and driver bundle <https://github.com/adafruit/Adafruit_CircuitPython_Bundle>`_. `the Adafruit library and driver bundle <https://github.com/adafruit/Adafruit_CircuitPython_Bundle>`_.
Installing from PyPI
====================
On supported GNU/Linux systems like the Raspberry Pi, you can install the driver locally `from
PyPI <https://pypi.org/project/adafruit-circuitpython-epd/>`_. To install for current user:
.. code-block:: shell
pip3 install adafruit-circuitpython-epd
To install system-wide (this may be required in some cases):
.. code-block:: shell
sudo pip3 install adafruit-circuitpython-epd
To install in a virtual environment in your current project:
.. code-block:: shell
mkdir project-name && cd project-name
python3 -m venv .env
source .env/bin/activate
pip3 install adafruit-circuitpython-epd
Usage Example Usage Example
============= =============
@ -65,35 +39,31 @@ Usage Example
# create the spi device and pins we will need # create the spi device and pins we will need
spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO) spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)
ecs = digitalio.DigitalInOut(board.D12) ecs = digitalio.DigitalInOut(board.D10)
dc = digitalio.DigitalInOut(board.D11) dc = digitalio.DigitalInOut(board.D9)
srcs = digitalio.DigitalInOut(board.D10) # can be None to use internal memory srcs = digitalio.DigitalInOut(board.D8)
rst = digitalio.DigitalInOut(board.D9) # can be None to not use this pin rst = digitalio.DigitalInOut(board.D7)
busy = digitalio.DigitalInOut(board.D5) # can be None to not use this pin busy = digitalio.DigitalInOut(board.D6)
# give them all to our driver # give them all to our driver
print("Creating display") display = Adafruit_IL0373(152, 152, rst, dc, busy, srcs, ecs, spi)
display = Adafruit_IL0373(104, 212, spi, # 2.13" Tri-color display
cs_pin=ecs, dc_pin=dc, sramcs_pin=srcs,
rst_pin=rst, busy_pin=busy)
display.rotation = 1
# clear the buffer # clear the buffer
print("Clear buffer") display.clear_buffer()
display.fill(Adafruit_EPD.WHITE)
display.pixel(10, 100, Adafruit_EPD.BLACK)
print("Draw Rectangles") r_width = 5
display.fill_rect(5, 5, 10, 10, Adafruit_EPD.RED) r_pos = display.height
display.rect(0, 0, 20, 30, Adafruit_EPD.BLACK)
print("Draw lines") #draw some rectangles!
display.line(0, 0, display.width-1, display.height-1, Adafruit_EPD.BLACK) color = Adafruit_EPD.BLACK
display.line(0, display.height-1, display.width-1, 0, Adafruit_EPD.RED) while r_pos > display.height/2:
if r_pos < display.height - 50:
color = Adafruit_EPD.RED
display.rect(display.width - r_pos, display.height - r_pos,
display.width - 2*(display.width - r_pos),
display.height - 2*(display.height - r_pos), color)
r_pos = r_pos - r_width
print("Draw text")
display.text('hello world', 25, 10, Adafruit_EPD.BLACK)
display.display() display.display()
@ -104,7 +74,52 @@ Contributions are welcome! Please read our `Code of Conduct
<https://github.com/adafruit/Adafruit_CircuitPython_EPD/blob/master/CODE_OF_CONDUCT.md>`_ <https://github.com/adafruit/Adafruit_CircuitPython_EPD/blob/master/CODE_OF_CONDUCT.md>`_
before contributing to help this project stay welcoming. before contributing to help this project stay welcoming.
Documentation Building locally
============= ================
For information on building library documentation, please check out `this guide <https://learn.adafruit.com/creating-and-sharing-a-circuitpython-library/sharing-our-docs-on-readthedocs#sphinx-5-1>`_. Zip release files
-----------------
To build this library locally you'll need to install the
`circuitpython-build-tools <https://github.com/adafruit/circuitpython-build-tools>`_ package.
.. code-block:: shell
python3 -m venv .env
source .env/bin/activate
pip install circuitpython-build-tools
Once installed, make sure you are in the virtual environment:
.. code-block:: shell
source .env/bin/activate
Then run the build:
.. code-block:: shell
circuitpython-build-bundles --filename_prefix adafruit-circuitpython-epd --library_location .
Sphinx documentation
-----------------------
Sphinx is used to build the documentation based on rST files and comments in the code. First,
install dependencies (feel free to reuse the virtual environment from above):
.. code-block:: shell
python3 -m venv .env
source .env/bin/activate
pip install Sphinx sphinx-rtd-theme
Now, once you have the virtual environment activated:
.. code-block:: shell
cd docs
sphinx-build -E -W -b html . _build/html
This will output the documentation to ``docs/_build/html``. Open the index.html in your browser to
view them. It will also (due to -W) error out on any warning like Travis will. This is a good way to
locally verify it will pass.

View file

@ -27,318 +27,120 @@ CircuitPython driver for Adafruit ePaper display breakouts
""" """
import time import time
from micropython import const import digitalio
from digitalio import Direction
from adafruit_epd import mcp_sram from adafruit_epd import mcp_sram
__version__ = "0.0.0-auto.0" class Adafruit_EPD:
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_EPD.git"
class Adafruit_EPD: # pylint: disable=too-many-instance-attributes, too-many-public-methods
"""Base class for EPD displays """Base class for EPD displays
""" """
BLACK = 0
WHITE = 1
INVERSE = 2
RED = 3
DARK = 4
LIGHT = 5
BLACK = const(0) # pylint: disable=too-many-arguments
WHITE = const(1) def __init__(self, width, height, rst_pin, dc_pin, busy_pin, srcs_pin, cs_pin, spi):
INVERSE = const(2) self.width = width
RED = const(3) self.height = height
DARK = const(4)
LIGHT = const(5)
def __init__( # Setup reset pin.
self, width, height, spi, cs_pin, dc_pin, sramcs_pin, rst_pin, busy_pin
): # pylint: disable=too-many-arguments
self._width = width
self._height = height
# Setup reset pin, if we have one
self._rst = rst_pin self._rst = rst_pin
if rst_pin: self._rst.direction = digitalio.Direction.OUTPUT
self._rst.direction = Direction.OUTPUT
# Setup busy pin, if we have one # Setup busy pin.
self._busy = busy_pin self._busy = busy_pin
if busy_pin: self._busy.direction = digitalio.Direction.INPUT
self._busy.direction = Direction.INPUT
# Setup dc pin (required) # Setup dc pin.
self._dc = dc_pin self._dc = dc_pin
self._dc.direction = Direction.OUTPUT self._dc.direction = digitalio.Direction.OUTPUT
# Setup cs pin.
self._cs = cs_pin
self._cs.direction = digitalio.Direction.OUTPUT
self.spi_device = spi
self.sram = mcp_sram.Adafruit_MCP_SRAM(srcs_pin, spi)
# pylint: enable=too-many-arguments
def begin(self, reset=True):
"""Begin display and reset if desired."""
self._cs.value = True
self._dc.value = False self._dc.value = False
# Setup cs pin (required) if reset:
self._cs = cs_pin
self._cs.direction = Direction.OUTPUT
self._cs.value = True
# SPI interface (required)
self.spi_device = spi
while not self.spi_device.try_lock():
time.sleep(0.01)
self.spi_device.configure(baudrate=1000000) # 1 Mhz
self.spi_device.unlock()
self._spibuf = bytearray(1)
self._single_byte_tx = False
self.sram = None
if sramcs_pin:
self.sram = mcp_sram.Adafruit_MCP_SRAM(sramcs_pin, spi)
self._buf = bytearray(3)
self._buffer1_size = self._buffer2_size = 0
self._buffer1 = self._buffer2 = None
self._framebuf1 = self._framebuf2 = None
self._colorframebuf = self._blackframebuf = None
self._black_inverted = self._color_inverted = True
self.hardware_reset()
def display(self): # pylint: disable=too-many-branches
"""show the contents of the display buffer"""
self.power_up()
self.set_ram_address(0, 0)
if self.sram:
while not self.spi_device.try_lock():
time.sleep(0.01)
self.sram.cs_pin.value = False
# send read command
self._buf[0] = mcp_sram.Adafruit_MCP_SRAM.SRAM_READ
# send start address
self._buf[1] = 0
self._buf[2] = 0
self.spi_device.write(self._buf, end=3)
self.spi_device.unlock()
# first data byte from SRAM will be transfered in at the
# same time as the EPD command is transferred out
databyte = self.write_ram(0)
while not self.spi_device.try_lock():
time.sleep(0.01)
self._dc.value = True
if self.sram:
for _ in range(self._buffer1_size):
databyte = self._spi_transfer(databyte)
self.sram.cs_pin.value = True
else:
for databyte in self._buffer1:
self._spi_transfer(databyte)
self._cs.value = True
self.spi_device.unlock()
time.sleep(0.002)
if self.sram:
while not self.spi_device.try_lock():
time.sleep(0.01)
self.sram.cs_pin.value = False
# send read command
self._buf[0] = mcp_sram.Adafruit_MCP_SRAM.SRAM_READ
# send start address
self._buf[1] = (self._buffer1_size >> 8) & 0xFF
self._buf[2] = self._buffer1_size & 0xFF
self.spi_device.write(self._buf, end=3)
self.spi_device.unlock()
if self._buffer2_size != 0:
# first data byte from SRAM will be transfered in at the
# same time as the EPD command is transferred out
databyte = self.write_ram(1)
while not self.spi_device.try_lock():
time.sleep(0.01)
self._dc.value = True
if self.sram:
for _ in range(self._buffer2_size):
databyte = self._spi_transfer(databyte)
self.sram.cs_pin.value = True
else:
for databyte in self._buffer2:
self._spi_transfer(databyte)
self._cs.value = True
self.spi_device.unlock()
else:
if self.sram:
self.sram.cs_pin.value = True
self.update()
def hardware_reset(self):
"""If we have a reset pin, do a hardware reset by toggling it"""
if self._rst:
self._rst.value = False self._rst.value = False
time.sleep(0.1) time.sleep(.1)
self._rst.value = True self._rst.value = True
time.sleep(0.1) time.sleep(.1)
def command(self, cmd, data=None, end=True): def command(self, cmd, data=None, end=True):
"""Send command byte to display.""" """Send command byte to display."""
self._cs.value = True self._cs.value = True
self._dc.value = False self._dc.value = False
self._cs.value = False self._cs.value = False
outbuf = bytearray(1)
while not self.spi_device.try_lock(): while not self.spi_device.try_lock():
time.sleep(0.01) pass
ret = self._spi_transfer(cmd) self.spi_device.write_readinto(bytearray([cmd]), outbuf)
if data is not None: if data is not None:
self._dc.value = True self.data(data)
for b in data: else:
self._spi_transfer(b) self.spi_device.unlock()
if end: if end:
self._cs.value = True self._cs.value = True
return outbuf[0]
def data(self, dat):
"""Send data to display."""
self._dc.value = True
self.spi_device.write(dat)
self._cs.value = True
self.spi_device.unlock() self.spi_device.unlock()
return ret def draw_pixel(self, x, y, color):
"""This should be overridden in the subclass"""
def _spi_transfer(self, databyte): pass
"""Transfer one byte, toggling the cs pin if required by the EPD chipset"""
self._spibuf[0] = databyte
if self._single_byte_tx:
self._cs.value = False
self.spi_device.write_readinto(self._spibuf, self._spibuf)
if self._single_byte_tx:
self._cs.value = True
return self._spibuf[0]
def power_up(self):
"""Power up the display in preparation for writing RAM and updating.
must be implemented in subclass"""
raise NotImplementedError()
def power_down(self):
"""Power down the display, must be implemented in subclass"""
raise NotImplementedError()
def update(self):
"""Update the display from internal memory, must be implemented in subclass"""
raise NotImplementedError()
def write_ram(self, index):
"""Send the one byte command for starting the RAM write process. Returns
the byte read at the same time over SPI. index is the RAM buffer, can be
0 or 1 for tri-color displays. must be implemented in subclass"""
raise NotImplementedError()
def set_ram_address(self, x, y):
"""Set the RAM address location, must be implemented in subclass"""
raise NotImplementedError()
def set_black_buffer(self, index, inverted):
"""Set the index for the black buffer data (0 or 1) and whether its inverted"""
if index == 0:
self._blackframebuf = self._framebuf1
elif index == 1:
self._blackframebuf = self._framebuf2
else:
raise RuntimeError("Buffer index must be 0 or 1")
self._black_inverted = inverted
def set_color_buffer(self, index, inverted):
"""Set the index for the color buffer data (0 or 1) and whether its inverted"""
if index == 0:
self._colorframebuf = self._framebuf1
elif index == 1:
self._colorframebuf = self._framebuf2
else:
raise RuntimeError("Buffer index must be 0 or 1")
self._color_inverted = inverted
def _color_dup(self, func, args, color):
black = getattr(self._blackframebuf, func)
red = getattr(self._colorframebuf, func)
if self._blackframebuf is self._colorframebuf: # monochrome
black(*args, color=(color != Adafruit_EPD.WHITE) != self._black_inverted)
else:
black(*args, color=(color == Adafruit_EPD.BLACK) != self._black_inverted)
red(*args, color=(color == Adafruit_EPD.RED) != self._color_inverted)
def pixel(self, x, y, color):
"""draw a single pixel in the display buffer"""
self._color_dup("pixel", (x, y), color)
#framebuf methods
def fill(self, color): def fill(self, color):
"""fill the screen with the passed color""" """fill the screen with the passed color"""
red_fill = ((color == Adafruit_EPD.RED) != self._color_inverted) * 0xFF self.fill_rect(0, 0, self.width, self.height, color)
black_fill = ((color == Adafruit_EPD.BLACK) != self._black_inverted) * 0xFF
if self.sram: # pylint: disable=too-many-arguments
self.sram.erase(0x00, self._buffer1_size, black_fill) def fill_rect(self, x, y, width, height, color):
self.sram.erase(self._buffer1_size, self._buffer2_size, red_fill)
else:
self._blackframebuf.fill(black_fill)
self._colorframebuf.fill(red_fill)
def rect(self, x, y, width, height, color): # pylint: disable=too-many-arguments
"""draw a rectangle"""
self._color_dup("rect", (x, y, width, height), color)
def fill_rect(
self, x, y, width, height, color
): # pylint: disable=too-many-arguments
"""fill a rectangle with the passed color""" """fill a rectangle with the passed color"""
self._color_dup("fill_rect", (x, y, width, height), color) if width < 1 or height < 1 or (x+width) <= 0:
return
if (y+height) <= 0 or y >= self.height or x >= self.width:
return
xend = min(self.width, x+width)
yend = min(self.height, y+height)
x = max(x, 0)
y = max(y, 0)
for _x in range(xend - x):
for _y in range(yend - y):
self.draw_pixel(x + _x, y + _y, color)
return
def line(self, x_0, y_0, x_1, y_1, color): # pylint: disable=too-many-arguments def pixel(self, x, y, color=None):
"""Draw a line from (x_0, y_0) to (x_1, y_1) in passed color""" """draw a pixel"""
self._color_dup("line", (x_0, y_0, x_1, y_1), color) if x < 0 or x >= self.width or y < 0 or y >= self.height:
return None
#TODO: figure this out when we know what framebuffer we
# will actually use
#if color is None:
# return self.get_pixel(self, x, y)
def text(self, string, x, y, color, *, font_name="font5x8.bin"): self.draw_pixel(x, y, color)
"""Write text string at location (x, y) in given color, using font file""" return None
if self._blackframebuf is self._colorframebuf: # monochrome
self._blackframebuf.text(
string,
x,
y,
font_name=font_name,
color=(color != Adafruit_EPD.WHITE) != self._black_inverted,
)
else:
self._blackframebuf.text(
string,
x,
y,
font_name=font_name,
color=(color == Adafruit_EPD.BLACK) != self._black_inverted,
)
self._colorframebuf.text(
string,
x,
y,
font_name=font_name,
color=(color == Adafruit_EPD.RED) != self._color_inverted,
)
@property
def width(self):
"""The width of the display, accounting for rotation"""
if self.rotation in (0, 2):
return self._width
return self._height
@property
def height(self):
"""The height of the display, accounting for rotation"""
if self.rotation in (0, 2):
return self._height
return self._width
@property
def rotation(self):
"""The rotation of the display, can be one of (0, 1, 2, 3)"""
return self._framebuf1.rotation
@rotation.setter
def rotation(self, val):
self._framebuf1.rotation = val
if self._framebuf2:
self._framebuf2.rotation = val
def hline(self, x, y, width, color): def hline(self, x, y, width, color):
"""draw a horizontal line""" """draw a horizontal line"""
@ -348,39 +150,9 @@ class Adafruit_EPD: # pylint: disable=too-many-instance-attributes, too-many-pu
"""draw a vertical line""" """draw a vertical line"""
self.fill_rect(x, y, 1, height, color) self.fill_rect(x, y, 1, height, color)
def image(self, image): def rect(self, x, y, width, height, color):
"""Set buffer to value of Python Imaging Library image. The image should """draw a rectangle"""
be in RGB mode and a size equal to the display size. self.fill_rect(x, y, width, 1, color)
""" self.fill_rect(x, y+height, width, 1, color)
imwidth, imheight = image.size self.fill_rect(x, y, 1, height, color)
if imwidth != self.width or imheight != self.height: self.fill_rect(x+width, y, 1, height, color)
raise ValueError(
"Image must be same dimensions as display ({0}x{1}).".format(
self.width, self.height
)
)
if self.sram:
raise RuntimeError("PIL image is not for use with SRAM assist")
# Grab all the pixels from the image, faster than getpixel.
pix = image.load()
# clear out any display buffers
self.fill(Adafruit_EPD.WHITE)
if image.mode == "RGB": # RGB Mode
for y in range(image.size[1]):
for x in range(image.size[0]):
pixel = pix[x, y]
if (pixel[1] < 0x80 <= pixel[0]) and (pixel[2] < 0x80):
# reddish
self.pixel(x, y, Adafruit_EPD.RED)
elif (pixel[0] < 0x80) and (pixel[1] < 0x80) and (pixel[2] < 0x80):
# dark
self.pixel(x, y, Adafruit_EPD.BLACK)
elif image.mode == "L": # Grayscale
for y in range(image.size[1]):
for x in range(image.size[0]):
pixel = pix[x, y]
if pixel < 0x80:
self.pixel(x, y, Adafruit_EPD.BLACK)
else:
raise ValueError("Image must be in mode RGB or mode L.")

View file

@ -28,132 +28,205 @@ CircuitPython driver for Adafruit il0373 display breakouts
import time import time
from micropython import const from micropython import const
import adafruit_framebuf
from adafruit_epd.epd import Adafruit_EPD from adafruit_epd.epd import Adafruit_EPD
from adafruit_epd.mcp_sram import Adafruit_MCP_SRAM
__version__ = "0.0.0-auto.0" IL0373_PANEL_SETTING = const(0x00)
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_EPD.git" IL0373_POWER_SETTING = const(0x01)
IL0373_POWER_OFF = const(0x02)
_IL0373_PANEL_SETTING = const(0x00) IL0373_POWER_OFF_SEQUENCE = const(0x03)
_IL0373_POWER_SETTING = const(0x01) IL0373_POWER_ON = const(0x04)
_IL0373_POWER_OFF = const(0x02) IL0373_POWER_ON_MEASURE = const(0x05)
_IL0373_POWER_OFF_SEQUENCE = const(0x03) IL0373_BOOSTER_SOFT_START = const(0x06)
_IL0373_POWER_ON = const(0x04) IL0373_DEEP_SLEEP = const(0x07)
_IL0373_POWER_ON_MEASURE = const(0x05) IL0373_DTM1 = const(0x10)
_IL0373_BOOSTER_SOFT_START = const(0x06) IL0373_DATA_STOP = const(0x11)
_IL0373_DEEP_SLEEP = const(0x07) IL0373_DISPLAY_REFRESH = const(0x12)
_IL0373_DTM1 = const(0x10) IL0373_DTM2 = const(0x13)
_IL0373_DATA_STOP = const(0x11) IL0373_PDTM1 = const(0x14)
_IL0373_DISPLAY_REFRESH = const(0x12) IL0373_PDTM2 = const(0x15)
_IL0373_DTM2 = const(0x13) IL0373_PDRF = const(0x16)
_IL0373_PDTM1 = const(0x14) IL0373_LUT1 = const(0x20)
_IL0373_PDTM2 = const(0x15) IL0373_LUTWW = const(0x21)
_IL0373_PDRF = const(0x16) IL0373_LUTBW = const(0x22)
_IL0373_LUT1 = const(0x20) IL0373_LUTWB = const(0x23)
_IL0373_LUTWW = const(0x21) IL0373_LUTBB = const(0x24)
_IL0373_LUTBW = const(0x22) IL0373_PLL = const(0x30)
_IL0373_LUTWB = const(0x23) IL0373_CDI = const(0x50)
_IL0373_LUTBB = const(0x24) IL0373_RESOLUTION = const(0x61)
_IL0373_PLL = const(0x30) IL0373_VCM_DC_SETTING = const(0x82)
_IL0373_CDI = const(0x50)
_IL0373_RESOLUTION = const(0x61)
_IL0373_VCM_DC_SETTING = const(0x82)
class Adafruit_IL0373(Adafruit_EPD): class Adafruit_IL0373(Adafruit_EPD):
"""driver class for Adafruit IL0373 ePaper display breakouts""" """driver class for Adafruit IL0373 ePaper display breakouts"""
# pylint: disable=too-many-arguments # pylint: disable=too-many-arguments
def __init__( def __init__(self, width, height, rst_pin, dc_pin, busy_pin, srcs_pin, cs_pin, spi):
self, width, height, spi, *, cs_pin, dc_pin, sramcs_pin, rst_pin, busy_pin super(Adafruit_IL0373, self).__init__(width, height, rst_pin, dc_pin, busy_pin,
): srcs_pin, cs_pin, spi)
super(Adafruit_IL0373, self).__init__(
width, height, spi, cs_pin, dc_pin, sramcs_pin, rst_pin, busy_pin
)
self._buffer1_size = int(width * height / 8) self.bw_bufsize = int(width * height / 8)
self._buffer2_size = int(width * height / 8) self.red_bufsize = int(width * height / 8)
if sramcs_pin: self.begin()
self._buffer1 = self.sram.get_view(0)
self._buffer2 = self.sram.get_view(self._buffer1_size)
else:
self._buffer1 = bytearray((width * height) // 8)
self._buffer2 = bytearray((width * height) // 8)
# since we have *two* framebuffers - one for red and one for black
# we dont subclass but manage manually
self._framebuf1 = adafruit_framebuf.FrameBuffer(
self._buffer1, width, height, buf_format=adafruit_framebuf.MHMSB
)
self._framebuf2 = adafruit_framebuf.FrameBuffer(
self._buffer2, width, height, buf_format=adafruit_framebuf.MHMSB
)
self.set_black_buffer(0, True)
self.set_color_buffer(1, True)
# pylint: enable=too-many-arguments # pylint: enable=too-many-arguments
def begin(self, reset=True): def begin(self, reset=True):
"""Begin communication with the display and set basic settings""" """Begin communication with the display and set basic settings"""
if reset: super(Adafruit_IL0373, self).begin(reset)
self.hardware_reset()
self.power_down()
def busy_wait(self): while self._busy.value is False:
"""Wait for display to be done with current task, either by polling the pass
busy pin, or pausing"""
if self._busy:
while not self._busy.value:
time.sleep(0.01)
else:
time.sleep(0.5)
def power_up(self): self.command(IL0373_POWER_SETTING, bytearray([0x03, 0x00, 0x2b, 0x2b, 0x09]))
"""Power up the display in preparation for writing RAM and updating""" self.command(IL0373_BOOSTER_SOFT_START, bytearray([0x17, 0x17, 0x17]))
self.hardware_reset()
self.busy_wait()
self.command(_IL0373_POWER_SETTING, bytearray([0x03, 0x00, 0x2B, 0x2B, 0x09]))
self.command(_IL0373_BOOSTER_SOFT_START, bytearray([0x17, 0x17, 0x17]))
self.command(_IL0373_POWER_ON)
self.busy_wait()
time.sleep(0.2)
self.command(_IL0373_PANEL_SETTING, bytearray([0xCF]))
self.command(_IL0373_CDI, bytearray([0x37]))
self.command(_IL0373_PLL, bytearray([0x29]))
_b1 = self._width & 0xFF
_b2 = (self._height >> 8) & 0xFF
_b3 = self._height & 0xFF
self.command(_IL0373_RESOLUTION, bytearray([_b1, _b2, _b3]))
self.command(_IL0373_VCM_DC_SETTING, bytearray([0x0A]))
time.sleep(0.05)
def power_down(self):
"""Power down the display - required when not actively displaying!"""
self.command(_IL0373_CDI, bytearray([0x17]))
self.command(_IL0373_VCM_DC_SETTING, bytearray([0x00]))
self.command(_IL0373_POWER_OFF)
def update(self): def update(self):
"""Update the display from internal memory""" """update the display"""
self.command(_IL0373_DISPLAY_REFRESH) self.command(IL0373_DISPLAY_REFRESH)
time.sleep(0.1)
self.busy_wait()
if not self._busy:
time.sleep(15) # wait 15 seconds
def write_ram(self, index): while self._busy.value is False:
"""Send the one byte command for starting the RAM write process. Returns pass
the byte read at the same time over SPI. index is the RAM buffer, can be
0 or 1 for tri-color displays."""
if index == 0:
return self.command(_IL0373_DTM1, end=False)
if index == 1:
return self.command(_IL0373_DTM2, end=False)
raise RuntimeError("RAM index must be 0 or 1")
def set_ram_address(self, x, y): # pylint: disable=unused-argument, no-self-use self.command(IL0373_CDI, bytearray([0x17]))
"""Set the RAM address location, not used on this chipset but required by self.command(IL0373_VCM_DC_SETTING, bytearray([0x00]))
the superclass""" self.command(IL0373_POWER_OFF)
return # on this chip it does nothing time.sleep(2)
def power_up(self):
"""power up the display"""
self.command(IL0373_POWER_ON)
while self._busy.value is False:
pass
time.sleep(.2)
self.command(IL0373_PANEL_SETTING, bytearray([0xCF]))
self.command(IL0373_CDI, bytearray([0x37]))
self.command(IL0373_PLL, bytearray([0x29]))
_b1 = self.height & 0xFF
_b2 = (self.height >> 8) & 0xFF
_b3 = self.width & 0xFF
_b4 = (self.width >> 8) & 0xFF
self.command(IL0373_RESOLUTION, bytearray([_b1, _b2, _b3, _b4]))
self.command(IL0373_VCM_DC_SETTING, bytearray([0x0A]))
def display(self):
"""show the contents of the display buffer"""
self.power_up()
while not self.spi_device.try_lock():
pass
self.sram.cs_pin.value = False
#send read command
self.spi_device.write(bytearray([Adafruit_MCP_SRAM.SRAM_READ]))
#send start address
self.spi_device.write(bytearray([0x00, 0x00]))
self.spi_device.unlock()
#first data byte from SRAM will be transfered in at the
#same time as the EPD command is transferred out
cmd = self.command(IL0373_DTM1, end=False)
while not self.spi_device.try_lock():
pass
self._dc.value = True
xfer = bytearray([cmd])
outbuf = bytearray(1)
for _ in range(self.bw_bufsize):
outbuf[0] = xfer[0]
self.spi_device.write_readinto(outbuf, xfer)
self._cs.value = True
self.sram.cs_pin.value = True
time.sleep(.002)
self.sram.cs_pin.value = False
#send read command
self.spi_device.write(bytearray([Adafruit_MCP_SRAM.SRAM_READ]))
#send start address
self.spi_device.write(bytearray([(self.bw_bufsize >> 8), (self.bw_bufsize & 0xFF)]))
self.spi_device.unlock()
#first data byte from SRAM will be transfered in at the
#same time as the EPD command is transferred out
cmd = self.command(IL0373_DTM2, end=False)
while not self.spi_device.try_lock():
pass
self._dc.value = True
xfer = bytearray([cmd])
outbuf = bytearray(1)
for _ in range(self.bw_bufsize):
outbuf[0] = xfer[0]
self.spi_device.write_readinto(outbuf, xfer)
self._cs.value = True
self.sram.cs_pin.value = True
self.spi_device.unlock()
self.update()
def image(self, image):
"""Set buffer to value of Python Imaging Library image. The image should
be in RGB mode and a size equal to the display size.
"""
if image.mode != 'RGB':
raise ValueError('Image must be in mode RGB.')
imwidth, imheight = image.size
if imwidth != self.width or imheight != self.height:
raise ValueError('Image must be same dimensions as display ({0}x{1}).' \
.format(self.width, self.height))
# Grab all the pixels from the image, faster than getpixel.
pix = image.load()
for y in iter(range(image.size[1])):
for x in iter(range(image.size[0])):
if x == 0:
x = 1
pixel = pix[x, y]
addr = int(((self.width - x) * self.height + y)/8)
if pixel == (0xFF, 0, 0):
addr = addr + self.bw_bufsize
current = self.sram.read8(addr)
if pixel in ((0xFF, 0, 0), (0, 0, 0)):
current = current & ~(1 << (7 - y%8))
else:
current = current | (1 << (7 - y%8))
self.sram.write8(addr, current)
def draw_pixel(self, x, y, color):
"""draw a single pixel in the display buffer"""
if (x < 0) or (x >= self.width) or (y < 0) or (y >= self.height):
return
if x == 0:
x = 1
addr = int(((self.width - x) * self.height + y)/8)
if color == Adafruit_EPD.RED:
addr = addr + self.bw_bufsize
current = self.sram.read8(addr)
if color == Adafruit_EPD.WHITE:
current = current | (1 << (7 - y%8))
elif color in (Adafruit_EPD.RED, Adafruit_EPD.BLACK):
current = current & ~(1 << (7 - y%8))
elif color == Adafruit_EPD.INVERSE:
current = current ^ (1 << (7 - y%8))
self.sram.write8(addr, current)
return
def clear_buffer(self):
"""clear the display buffer"""
self.sram.erase(0x00, self.bw_bufsize, 0xFF)
self.sram.erase(self.bw_bufsize, self.red_bufsize, 0xFF)
def clear_display(self):
"""clear the entire display"""
self.clear_buffer()
self.display()

View file

@ -1,159 +0,0 @@
# The MIT License (MIT)
#
# Copyright (c) 2018 Dean Miller 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.
"""
`adafruit_epd.il0398` - Adafruit IL0398 - ePaper display driver
====================================================================================
CircuitPython driver for Adafruit IL0398 display breakouts
* Author(s): Dean Miller, ladyada
"""
import time
from micropython import const
import adafruit_framebuf
from adafruit_epd.epd import Adafruit_EPD
__version__ = "0.0.0-auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_EPD.git"
_IL0398_PANEL_SETTING = const(0x00)
_IL0398_POWER_SETTING = const(0x01)
_IL0398_POWER_OFF = const(0x02)
_IL0398_POWER_OFF_SEQUENCE = const(0x03)
_IL0398_POWER_ON = const(0x04)
_IL0398_POWER_ON_MEASURE = const(0x05)
_IL0398_BOOSTER_SOFT_START = const(0x06)
_IL0398_DEEP_SLEEP = const(0x07)
_IL0398_DTM1 = const(0x10)
_IL0398_DATA_STOP = const(0x11)
_IL0398_DISPLAY_REFRESH = const(0x12)
_IL0398_DTM2 = const(0x13)
_IL0398_PDTM1 = const(0x14)
_IL0398_PDTM2 = const(0x15)
_IL0398_PDRF = const(0x16)
_IL0398_LUT1 = const(0x20)
_IL0398_LUTWW = const(0x21)
_IL0398_LUTBW = const(0x22)
_IL0398_LUTWB = const(0x23)
_IL0398_LUTBB = const(0x24)
_IL0398_PLL = const(0x30)
_IL0398_CDI = const(0x50)
_IL0398_RESOLUTION = const(0x61)
_IL0398_GETSTATUS = const(0x71)
_IL0398_VCM_DC_SETTING = const(0x82)
class Adafruit_IL0398(Adafruit_EPD):
"""driver class for Adafruit IL0373 ePaper display breakouts"""
# pylint: disable=too-many-arguments
def __init__(
self, width, height, spi, *, cs_pin, dc_pin, sramcs_pin, rst_pin, busy_pin
):
super(Adafruit_IL0398, self).__init__(
width, height, spi, cs_pin, dc_pin, sramcs_pin, rst_pin, busy_pin
)
self._buffer1_size = int(width * height / 8)
self._buffer2_size = int(width * height / 8)
if sramcs_pin:
self._buffer1 = self.sram.get_view(0)
self._buffer2 = self.sram.get_view(self._buffer1_size)
else:
self._buffer1 = bytearray((width * height) // 8)
self._buffer2 = bytearray((width * height) // 8)
# since we have *two* framebuffers - one for red and one for black
# we dont subclass but manage manually
self._framebuf1 = adafruit_framebuf.FrameBuffer(
self._buffer1, width, height, buf_format=adafruit_framebuf.MHMSB
)
self._framebuf2 = adafruit_framebuf.FrameBuffer(
self._buffer2, width, height, buf_format=adafruit_framebuf.MHMSB
)
self.set_black_buffer(0, True)
self.set_color_buffer(1, True)
# pylint: enable=too-many-arguments
def begin(self, reset=True):
"""Begin communication with the display and set basic settings"""
if reset:
self.hardware_reset()
self.power_down()
def busy_wait(self):
"""Wait for display to be done with current task, either by polling the
busy pin, or pausing"""
if self._busy:
while not self._busy.value:
# self.command(_IL0398_GETSTATUS)
time.sleep(0.01)
else:
time.sleep(0.5)
def power_up(self):
"""Power up the display in preparation for writing RAM and updating"""
self.hardware_reset()
self.busy_wait()
self.command(_IL0398_BOOSTER_SOFT_START, bytearray([0x17, 0x17, 0x17]))
self.command(_IL0398_POWER_ON)
self.busy_wait()
time.sleep(0.2)
self.command(_IL0398_PANEL_SETTING, bytearray([0x0F]))
_b0 = (self._width >> 8) & 0xFF
_b1 = self._width & 0xFF
_b2 = (self._height >> 8) & 0xFF
_b3 = self._height & 0xFF
self.command(_IL0398_RESOLUTION, bytearray([_b0, _b1, _b2, _b3]))
time.sleep(0.05)
def power_down(self):
"""Power down the display - required when not actively displaying!"""
self.command(_IL0398_CDI, bytearray([0xF7]))
self.command(_IL0398_POWER_OFF)
self.busy_wait()
self.command(_IL0398_DEEP_SLEEP, bytearray([0xA5]))
def update(self):
"""Update the display from internal memory"""
self.command(_IL0398_DISPLAY_REFRESH)
time.sleep(0.1)
self.busy_wait()
if not self._busy:
time.sleep(15) # wait 15 seconds
def write_ram(self, index):
"""Send the one byte command for starting the RAM write process. Returns
the byte read at the same time over SPI. index is the RAM buffer, can be
0 or 1 for tri-color displays."""
if index == 0:
return self.command(_IL0398_DTM1, end=False)
if index == 1:
return self.command(_IL0398_DTM2, end=False)
raise RuntimeError("RAM index must be 0 or 1")
def set_ram_address(self, x, y): # pylint: disable=unused-argument, no-self-use
"""Set the RAM address location, not used on this chipset but required by
the superclass"""
return # on this chip it does nothing

View file

@ -1,182 +0,0 @@
# The MIT License (MIT)
#
# Copyright (c) 2018 Dean Miller 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.
"""
`adafruit_epd.il91874` - Adafruit IL91874 - ePaper display driver
====================================================================================
CircuitPython driver for Adafruit IL91874 display breakouts
* Author(s): Dean Miller, Ladyada
"""
import time
from micropython import const
import adafruit_framebuf
from adafruit_epd.epd import Adafruit_EPD
__version__ = "0.0.0-auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_EPD.git"
_IL91874_PANEL_SETTING = const(0x00)
_IL91874_POWER_SETTING = const(0x01)
_IL91874_POWER_OFF = const(0x02)
_IL91874_POWER_OFF_SEQUENCE = const(0x03)
_IL91874_POWER_ON = const(0x04)
_IL91874_POWER_ON_MEASURE = const(0x05)
_IL91874_BOOSTER_SOFT_START = const(0x06)
_IL91874_DEEP_SLEEP = const(0x07)
_IL91874_DTM1 = const(0x10)
_IL91874_DATA_STOP = const(0x11)
_IL91874_DISPLAY_REFRESH = const(0x12)
_IL91874_DTM2 = const(0x13)
_IL91874_PDTM1 = const(0x14)
_IL91874_PDTM2 = const(0x15)
_IL91874_PDRF = const(0x16)
_IL91874_LUT1 = const(0x20)
_IL91874_LUTWW = const(0x21)
_IL91874_LUTBW = const(0x22)
_IL91874_LUTWB = const(0x23)
_IL91874_LUTBB = const(0x24)
_IL91874_PLL = const(0x30)
_IL91874_CDI = const(0x50)
_IL91874_RESOLUTION = const(0x61)
_IL91874_VCM_DC_SETTING = const(0x82)
# pylint: disable=line-too-long
_LUT_VCOMDC = b"\x00\x00\x00\x1a\x1a\x00\x00\x01\x00\n\n\x00\x00\x08\x00\x0e\x01\x0e\x01\x10\x00\n\n\x00\x00\x08\x00\x04\x10\x00\x00\x05\x00\x03\x0e\x00\x00\n\x00#\x00\x00\x00\x01"
_LUT_WW = b"\x90\x1a\x1a\x00\x00\x01@\n\n\x00\x00\x08\x84\x0e\x01\x0e\x01\x10\x80\n\n\x00\x00\x08\x00\x04\x10\x00\x00\x05\x00\x03\x0e\x00\x00\n\x00#\x00\x00\x00\x01"
_LUT_BW = b"\xa0\x1a\x1a\x00\x00\x01\x00\n\n\x00\x00\x08\x84\x0e\x01\x0e\x01\x10\x90\n\n\x00\x00\x08\xb0\x04\x10\x00\x00\x05\xb0\x03\x0e\x00\x00\n\xc0#\x00\x00\x00\x01"
_LUT_BB = b"\x90\x1a\x1a\x00\x00\x01@\n\n\x00\x00\x08\x84\x0e\x01\x0e\x01\x10\x80\n\n\x00\x00\x08\x00\x04\x10\x00\x00\x05\x00\x03\x0e\x00\x00\n\x00#\x00\x00\x00\x01"
_LUT_WB = b"\x90\x1a\x1a\x00\x00\x01 \n\n\x00\x00\x08\x84\x0e\x01\x0e\x01\x10\x10\n\n\x00\x00\x08\x00\x04\x10\x00\x00\x05\x00\x03\x0e\x00\x00\n\x00#\x00\x00\x00\x01"
# pylint: enable=line-too-long
class Adafruit_IL91874(Adafruit_EPD):
"""driver class for Adafruit IL91874 ePaper display breakouts"""
# pylint: disable=too-many-arguments
def __init__(
self, width, height, spi, *, cs_pin, dc_pin, sramcs_pin, rst_pin, busy_pin
):
super(Adafruit_IL91874, self).__init__(
width, height, spi, cs_pin, dc_pin, sramcs_pin, rst_pin, busy_pin
)
self._buffer1_size = int(width * height / 8)
self._buffer2_size = int(width * height / 8)
if sramcs_pin:
self._buffer1 = self.sram.get_view(0)
self._buffer2 = self.sram.get_view(self._buffer1_size)
else:
self._buffer1 = bytearray((width * height) // 8)
self._buffer2 = bytearray((width * height) // 8)
# since we have *two* framebuffers - one for red and one for black
# we dont subclass but manage manually
self._framebuf1 = adafruit_framebuf.FrameBuffer(
self._buffer1, width, height, buf_format=adafruit_framebuf.MHMSB
)
self._framebuf2 = adafruit_framebuf.FrameBuffer(
self._buffer2, width, height, buf_format=adafruit_framebuf.MHMSB
)
self.set_black_buffer(0, True)
self.set_color_buffer(1, False)
self._single_byte_tx = True
def begin(self, reset=True):
"""Begin communication with the display and set basic settings"""
if reset:
self.hardware_reset()
self.power_down()
def busy_wait(self):
"""Wait for display to be done with current task, either by polling the
busy pin, or pausing"""
if self._busy:
while not self._busy.value:
time.sleep(0.01)
else:
time.sleep(0.5)
def power_up(self):
"""Power up the display in preparation for writing RAM and updating"""
self.hardware_reset()
time.sleep(0.2)
self.command(_IL91874_POWER_ON)
self.busy_wait()
self.command(_IL91874_PANEL_SETTING, bytearray([0xAF]))
self.command(_IL91874_PLL, bytearray([0x3A]))
self.command(_IL91874_POWER_SETTING, bytearray([0x03, 0x00, 0x2B, 0x2B, 0x09]))
self.command(_IL91874_BOOSTER_SOFT_START, bytearray([0x07, 0x07, 0x17]))
self.command(0xF8, bytearray([0x60, 0xA5])) # mystery command in example code
self.command(0xF8, bytearray([0x89, 0xA5])) # mystery command in example code
self.command(0xF8, bytearray([0x90, 0x00])) # mystery command in example code
self.command(0xF8, bytearray([0x93, 0xA2])) # mystery command in example code
self.command(0xF8, bytearray([0x73, 0x41])) # mystery command in example code
self.command(_IL91874_VCM_DC_SETTING, bytearray([0x12]))
self.command(_IL91874_CDI, bytearray([0x87]))
# Look Up Tables
self.command(_IL91874_LUT1, _LUT_VCOMDC)
self.command(_IL91874_LUTWW, _LUT_WW)
self.command(_IL91874_LUTBW, _LUT_BW)
self.command(_IL91874_LUTWB, _LUT_WB)
self.command(_IL91874_LUTBB, _LUT_BB)
_b0 = (self._width >> 8) & 0xFF
_b1 = self._width & 0xFF
_b2 = (self._height >> 8) & 0xFF
_b3 = self._height & 0xFF
self.command(_IL91874_RESOLUTION, bytearray([_b0, _b1, _b2, _b3]))
self.command(_IL91874_PDRF, bytearray([0x00]))
def power_down(self):
"""Power down the display - required when not actively displaying!"""
self.command(_IL91874_POWER_OFF, bytearray([0x17]))
self.busy_wait()
if self._rst: # Only deep sleep if we can get out of it
self.command(_IL91874_DEEP_SLEEP, bytearray([0xA5]))
def update(self):
"""Update the display from internal memory"""
self.command(_IL91874_DISPLAY_REFRESH)
self.busy_wait()
if not self._busy:
time.sleep(16) # wait 16 seconds
def write_ram(self, index):
"""Send the one byte command for starting the RAM write process. Returns
the byte read at the same time over SPI. index is the RAM buffer, can be
0 or 1 for tri-color displays."""
if index == 0:
return self.command(_IL91874_DTM1, end=False)
if index == 1:
return self.command(_IL91874_DTM2, end=False)
raise RuntimeError("RAM index must be 0 or 1")
def set_ram_address(self, x, y): # pylint: disable=unused-argument, no-self-use
"""Set the RAM address location, not used on this chipset but required by
the superclass"""
return # on this chip it does nothing

View file

@ -27,34 +27,13 @@ CircuitPython driver for Microchip SRAM chips
""" """
from micropython import const from micropython import const
from adafruit_bus_device import spi_device import digitalio
__version__ = "0.0.0-auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_EPD.git"
SRAM_SEQUENTIAL_MODE = const(1 << 6) SRAM_SEQUENTIAL_MODE = const(1 << 6)
class Adafruit_MCP_SRAM_View:
"""A interface class that turns an SRAM chip into something like a memoryview"""
def __init__(self, sram, offset):
self._sram = sram
self._offset = offset
self._buf = [0]
def __getitem__(self, i):
return self._sram.read(self._offset + i, 1)[0]
def __setitem__(self, i, val):
self._buf[0] = val
self._sram.write(self._offset + i, self._buf)
class Adafruit_MCP_SRAM: class Adafruit_MCP_SRAM:
"""supporting class for communicating with """supporting class for communicating with
Microchip SRAM chips""" Microchip SRAM chips"""
SRAM_READ = 0x03 SRAM_READ = 0x03
SRAM_WRITE = 0x02 SRAM_WRITE = 0x02
SRAM_RDSR = 0x05 SRAM_RDSR = 0x05
@ -62,39 +41,40 @@ class Adafruit_MCP_SRAM:
def __init__(self, cs_pin, spi): def __init__(self, cs_pin, spi):
# Handle hardware SPI # Handle hardware SPI
self._spi = spi_device.SPIDevice(spi, cs_pin, baudrate=8000000)
self.spi_device = spi self.spi_device = spi
self.cs_pin = cs_pin self.cs_pin = cs_pin
self._buf = bytearray(3)
self._buf[0] = Adafruit_MCP_SRAM.SRAM_WRSR
self._buf[1] = 0x43
with self._spi as spidev:
spidev.write(self._buf, end=2) # pylint: disable=no-member
def get_view(self, offset): self.cs_pin.direction = digitalio.Direction.OUTPUT
"""Create an object that can be used as a memoryview, with a given offset""" while not self.spi_device.try_lock():
return Adafruit_MCP_SRAM_View(self, offset) pass
self.cs_pin.value = False
self.spi_device.write(bytearray([Adafruit_MCP_SRAM.SRAM_WRSR, 0x43]))
self.cs_pin.value = True
self.spi_device.unlock()
def write(self, addr, buf, reg=SRAM_WRITE): def write(self, addr, buf, reg=SRAM_WRITE):
"""write the passed buffer to the passed address""" """write the passed buffer to the passed address"""
self._buf[0] = reg cmd = bytearray([reg, (addr >> 8) & 0xFF, addr & 0xFF] + buf)
self._buf[1] = (addr >> 8) & 0xFF
self._buf[2] = addr & 0xFF
with self._spi as spi: while not self.spi_device.try_lock():
spi.write(self._buf, end=3) # pylint: disable=no-member pass
spi.write(bytearray(buf)) # pylint: disable=no-member self.cs_pin.value = False
self.spi_device.write(cmd)
self.cs_pin.value = True
self.spi_device.unlock()
def read(self, addr, length, reg=SRAM_READ): def read(self, addr, length, reg=SRAM_READ):
"""read passed number of bytes at the passed address""" """read passed number of bytes at the passed address"""
self._buf[0] = reg cmd = bytearray([reg, (addr >> 8) & 0xFF, addr & 0xFF])
self._buf[1] = (addr >> 8) & 0xFF
self._buf[2] = addr & 0xFF
buf = bytearray(length) buf = bytearray(length)
with self._spi as spi: while not self.spi_device.try_lock():
spi.write(self._buf, end=3) # pylint: disable=no-member pass
spi.readinto(buf) # pylint: disable=no-member self.cs_pin.value = False
self.spi_device.write(cmd)
self.spi_device.readinto(buf)
self.cs_pin.value = True
self.spi_device.unlock()
return buf return buf
def read8(self, addr, reg=SRAM_READ): def read8(self, addr, reg=SRAM_READ):
@ -116,11 +96,13 @@ class Adafruit_MCP_SRAM:
def erase(self, addr, length, value): def erase(self, addr, length, value):
"""erase the passed number of bytes starting at the passed address""" """erase the passed number of bytes starting at the passed address"""
self._buf[0] = Adafruit_MCP_SRAM.SRAM_WRITE cmd = bytearray([Adafruit_MCP_SRAM.SRAM_WRITE, (addr >> 8) & 0xFF, addr & 0xFF])
self._buf[1] = (addr >> 8) & 0xFF
self._buf[2] = addr & 0xFF while not self.spi_device.try_lock():
fill = bytearray([value]) pass
with self._spi as spi: self.cs_pin.value = False
spi.write(self._buf, end=3) # pylint: disable=no-member self.spi_device.write(cmd)
for _ in range(length): for _ in range(length):
spi.write(fill) # pylint: disable=no-member self.spi_device.write(bytearray([value]))
self.cs_pin.value = True
self.spi_device.unlock()

View file

@ -1,172 +0,0 @@
# The MIT License (MIT)
#
# Copyright (c) 2018 Dean Miller 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.
"""
`adafruit_epd.ssd1608` - Adafruit SSD1608 - ePaper display driver
====================================================================================
CircuitPython driver for Adafruit SSD1608 display breakouts
* Author(s): Dean Miller, Ladyada
"""
import time
from micropython import const
import adafruit_framebuf
from adafruit_epd.epd import Adafruit_EPD
__version__ = "0.0.0-auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_EPD.git"
_SSD1608_DRIVER_CONTROL = const(0x01)
_SSD1608_GATE_VOLTAGE = const(0x03)
_SSD1608_SOURCE_VOLTAGE = const(0x04)
_SSD1608_DISPLAY_CONTROL = const(0x07)
_SSD1608_NON_OVERLAP = const(0x0B)
_SSD1608_BOOSTER_SOFT_START = const(0x0C)
_SSD1608_GATE_SCAN_START = const(0x0F)
_SSD1608_DEEP_SLEEP = const(0x10)
_SSD1608_DATA_MODE = const(0x11)
_SSD1608_SW_RESET = const(0x12)
_SSD1608_TEMP_WRITE = const(0x1A)
_SSD1608_TEMP_READ = const(0x1B)
_SSD1608_TEMP_CONTROL = const(0x1C)
_SSD1608_TEMP_LOAD = const(0x1D)
_SSD1608_MASTER_ACTIVATE = const(0x20)
_SSD1608_DISP_CTRL1 = const(0x21)
_SSD1608_DISP_CTRL2 = const(0x22)
_SSD1608_WRITE_RAM = const(0x24)
_SSD1608_READ_RAM = const(0x25)
_SSD1608_VCOM_SENSE = const(0x28)
_SSD1608_VCOM_DURATION = const(0x29)
_SSD1608_WRITE_VCOM = const(0x2C)
_SSD1608_READ_OTP = const(0x2D)
_SSD1608_WRITE_LUT = const(0x32)
_SSD1608_WRITE_DUMMY = const(0x3A)
_SSD1608_WRITE_GATELINE = const(0x3B)
_SSD1608_WRITE_BORDER = const(0x3C)
_SSD1608_SET_RAMXPOS = const(0x44)
_SSD1608_SET_RAMYPOS = const(0x45)
_SSD1608_SET_RAMXCOUNT = const(0x4E)
_SSD1608_SET_RAMYCOUNT = const(0x4F)
_SSD1608_NOP = const(0xFF)
_LUT_DATA = b'\x02\x02\x01\x11\x12\x12""fiiYX\x99\x99\x88\x00\x00\x00\x00\xf8\xb4\x13Q5QQ\x19\x01\x00' # pylint: disable=line-too-long
class Adafruit_SSD1608(Adafruit_EPD):
"""driver class for Adafruit SSD1608 ePaper display breakouts"""
# pylint: disable=too-many-arguments
def __init__(
self, width, height, spi, *, cs_pin, dc_pin, sramcs_pin, rst_pin, busy_pin
):
super(Adafruit_SSD1608, self).__init__(
width, height, spi, cs_pin, dc_pin, sramcs_pin, rst_pin, busy_pin
)
if height % 8 != 0:
height += 8 - height % 8
self._height = height
self._buffer1_size = int(width * height / 8)
if sramcs_pin:
self._buffer1 = self.sram.get_view(0)
else:
self._buffer1 = bytearray((width * height) // 8)
self._framebuf1 = adafruit_framebuf.FrameBuffer(
self._buffer1, width, height, buf_format=adafruit_framebuf.MHMSB
)
self.set_black_buffer(0, True)
self.set_color_buffer(0, True)
# pylint: enable=too-many-arguments
def begin(self, reset=True):
"""Begin communication with the display and set basic settings"""
if reset:
self.hardware_reset()
self.power_down()
def busy_wait(self):
"""Wait for display to be done with current task, either by polling the
busy pin, or pausing"""
if self._busy:
while self._busy.value:
time.sleep(0.01)
else:
time.sleep(0.5)
def power_up(self):
"""Power up the display in preparation for writing RAM and updating"""
self.hardware_reset()
self.busy_wait()
self.command(_SSD1608_SW_RESET)
self.busy_wait()
# driver output control
self.command(
_SSD1608_DRIVER_CONTROL,
bytearray([self._width - 1, (self._width - 1) >> 8, 0x00]),
)
# Set dummy line period
self.command(_SSD1608_WRITE_DUMMY, bytearray([0x1B]))
# Set gate line width
self.command(_SSD1608_WRITE_GATELINE, bytearray([0x0B]))
# Data entry sequence
self.command(_SSD1608_DATA_MODE, bytearray([0x03]))
# Set ram X start/end postion
self.command(_SSD1608_SET_RAMXPOS, bytearray([0x00, self._height // 8 - 1]))
# Set ram Y start/end postion
self.command(
_SSD1608_SET_RAMYPOS,
bytearray([0, 0, self._height - 1, (self._height - 1) >> 8]),
)
# Vcom Voltage
self.command(_SSD1608_WRITE_VCOM, bytearray([0x70]))
# LUT
self.command(_SSD1608_WRITE_LUT, _LUT_DATA)
self.busy_wait()
def power_down(self):
"""Power down the display - required when not actively displaying!"""
self.command(_SSD1608_DEEP_SLEEP, bytearray([0x01]))
time.sleep(0.1)
def update(self):
"""Update the display from internal memory"""
self.command(_SSD1608_DISP_CTRL2, bytearray([0xC7]))
self.command(_SSD1608_MASTER_ACTIVATE)
self.busy_wait()
if not self._busy:
time.sleep(3) # wait 3 seconds
def write_ram(self, index):
"""Send the one byte command for starting the RAM write process. Returns
the byte read at the same time over SPI. index is the RAM buffer, can be
0 or 1 for tri-color displays."""
if index == 0:
return self.command(_SSD1608_WRITE_RAM, end=False)
raise RuntimeError("RAM index must be 0")
def set_ram_address(self, x, y): # pylint: disable=unused-argument, no-self-use
"""Set the RAM address location, not used on this chipset but required by
the superclass"""
# Set RAM X address counter
self.command(_SSD1608_SET_RAMXCOUNT, bytearray([x]))
# Set RAM Y address counter
self.command(_SSD1608_SET_RAMYCOUNT, bytearray([y >> 8, y]))

View file

@ -1,194 +0,0 @@
# The MIT License (MIT)
#
# Copyright (c) 2018 Dean Miller 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.
"""
`adafruit_epd.ssd1675` - Adafruit SSD1675 - ePaper display driver
====================================================================================
CircuitPython driver for Adafruit SSD1675 display breakouts
* Author(s): Dean Miller, Ladyada
"""
import time
from micropython import const
import adafruit_framebuf
from adafruit_epd.epd import Adafruit_EPD
__version__ = "0.0.0-auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_EPD.git"
_SSD1675_DRIVER_CONTROL = const(0x01)
_SSD1675_GATE_VOLTAGE = const(0x03)
_SSD1675_SOURCE_VOLTAGE = const(0x04)
_SSD1675_DEEP_SLEEP = const(0x10)
_SSD1675_DATA_MODE = const(0x11)
_SSD1675_SW_RESET = const(0x12)
_SSD1675_HV_READY = const(0x14)
_SSD1675_VCI_READY = const(0x15)
_SSD1675_TEMP_WRITE = const(0x1A)
_SSD1675_MASTER_ACTIVATE = const(0x20)
_SSD1675_DISP_CTRL1 = const(0x21)
_SSD1675_DISP_CTRL2 = const(0x22)
_SSD1675_WRITE_RAM1 = const(0x24)
_SSD1675_WRITE_RAM2 = const(0x26)
_SSD1675_WRITE_VCOM = const(0x2C)
_SSD1675_READ_OTP = const(0x2D)
_SSD1675_WRITE_LUT = const(0x32)
_SSD1675_WRITE_DUMMY = const(0x3A)
_SSD1675_WRITE_GATELINE = const(0x3B)
_SSD1675_WRITE_BORDER = const(0x3C)
_SSD1675_SET_RAMXPOS = const(0x44)
_SSD1675_SET_RAMYPOS = const(0x45)
_SSD1675_SET_RAMXCOUNT = const(0x4E)
_SSD1675_SET_RAMYCOUNT = const(0x4F)
_SSD1675_SET_ANALOGBLOCK = const(0x74)
_SSD1675_SET_DIGITALBLOCK = const(0x7E)
_LUT_DATA = b"\x80`@\x00\x00\x00\x00\x10` \x00\x00\x00\x00\x80`@\x00\x00\x00\x00\x10` \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x03\x00\x00\x02\t\t\x00\x00\x02\x03\x03\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x15A\xa820\n" # pylint: disable=line-too-long
class Adafruit_SSD1675(Adafruit_EPD):
"""driver class for Adafruit SSD1675 ePaper display breakouts"""
# pylint: disable=too-many-arguments
def __init__(
self, width, height, spi, *, cs_pin, dc_pin, sramcs_pin, rst_pin, busy_pin
):
super(Adafruit_SSD1675, self).__init__(
width, height, spi, cs_pin, dc_pin, sramcs_pin, rst_pin, busy_pin
)
stride = width
if stride % 8 != 0:
stride += 8 - stride % 8
self._buffer1_size = int(stride * height / 8)
self._buffer2_size = self._buffer1_size
if sramcs_pin:
self._buffer1 = self.sram.get_view(0)
self._buffer2 = self.sram.get_view(self._buffer1_size)
else:
self._buffer1 = bytearray(self._buffer1_size)
self._buffer2 = bytearray(self._buffer2_size)
# since we have *two* framebuffers - one for red and one for black
# we dont subclass but manage manually
self._framebuf1 = adafruit_framebuf.FrameBuffer(
self._buffer1,
width,
height,
stride=stride,
buf_format=adafruit_framebuf.MHMSB,
)
self._framebuf2 = adafruit_framebuf.FrameBuffer(
self._buffer2,
width,
height,
stride=stride,
buf_format=adafruit_framebuf.MHMSB,
)
self.set_black_buffer(0, True)
self.set_color_buffer(0, True)
# pylint: enable=too-many-arguments
def begin(self, reset=True):
"""Begin communication with the display and set basic settings"""
if reset:
self.hardware_reset()
self.power_down()
def busy_wait(self):
"""Wait for display to be done with current task, either by polling the
busy pin, or pausing"""
if self._busy:
while self._busy.value:
time.sleep(0.01)
else:
time.sleep(0.5)
def power_up(self):
"""Power up the display in preparation for writing RAM and updating"""
self.hardware_reset()
time.sleep(0.1)
self.busy_wait()
self.command(_SSD1675_SW_RESET)
self.busy_wait()
# set analog block control
self.command(_SSD1675_SET_ANALOGBLOCK, bytearray([0x54]))
# set digital block control
self.command(_SSD1675_SET_DIGITALBLOCK, bytearray([0x3B]))
# driver output control
self.command(_SSD1675_DRIVER_CONTROL, bytearray([0xFA, 0x01, 0x00]))
# Data entry sequence
self.command(_SSD1675_DATA_MODE, bytearray([0x03]))
# Set ram X start/end postion
self.command(_SSD1675_SET_RAMXPOS, bytearray([0x00, 0x0F]))
# Set ram Y start/end postion
self.command(_SSD1675_SET_RAMYPOS, bytearray([0, 0, 0xF9, 0]))
# Border color
self.command(_SSD1675_WRITE_BORDER, bytearray([0x03]))
# Vcom Voltage
self.command(_SSD1675_WRITE_VCOM, bytearray([0x70]))
# Set gate voltage
self.command(_SSD1675_GATE_VOLTAGE, _LUT_DATA[70:71])
# Set gate voltage
self.command(_SSD1675_SOURCE_VOLTAGE, _LUT_DATA[71:74])
# Set dummy line period
self.command(_SSD1675_WRITE_DUMMY, _LUT_DATA[74:75])
# Set gate line width
self.command(_SSD1675_WRITE_GATELINE, _LUT_DATA[75:76])
# LUT
self.command(_SSD1675_WRITE_LUT, _LUT_DATA[0:70])
self.command(_SSD1675_SET_RAMXCOUNT, bytearray([0]))
# Set RAM Y address counter
self.command(_SSD1675_SET_RAMYCOUNT, bytearray([0xF9, 0]))
self.busy_wait()
def power_down(self):
"""Power down the display - required when not actively displaying!"""
self.command(_SSD1675_DEEP_SLEEP, bytearray([0x01]))
time.sleep(0.1)
def update(self):
"""Update the display from internal memory"""
self.command(_SSD1675_DISP_CTRL2, bytearray([0xC7]))
self.command(_SSD1675_MASTER_ACTIVATE)
self.busy_wait()
if not self._busy:
time.sleep(3) # wait 3 seconds
def write_ram(self, index):
"""Send the one byte command for starting the RAM write process. Returns
the byte read at the same time over SPI. index is the RAM buffer, can be
0 or 1 for tri-color displays."""
if index == 0:
return self.command(_SSD1675_WRITE_RAM1, end=False)
if index == 1:
return self.command(_SSD1675_WRITE_RAM2, end=False)
raise RuntimeError("RAM index must be 0 or 1")
def set_ram_address(self, x, y): # pylint: disable=unused-argument, no-self-use
"""Set the RAM address location, not used on this chipset but required by
the superclass"""
self.command(_SSD1675_SET_RAMXCOUNT, bytearray([x]))
self.command(_SSD1675_SET_RAMYCOUNT, bytearray([y, y >> 8]))

View file

@ -1,236 +0,0 @@
# The MIT License (MIT)
#
# Copyright (c) 2018 Dean Miller 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.
"""
`adafruit_epd.ssd1675b` - Adafruit SSD1675 - ePaper display driver
====================================================================================
CircuitPython driver for Adafruit SSD1675 display breakouts
* Author(s): Dean Miller, Ladyada
"""
import time
from micropython import const
import adafruit_framebuf
from adafruit_epd.epd import Adafruit_EPD
__version__ = "0.0.0-auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_EPD.git"
_SSD1675B_DRIVER_CONTROL = const(0x01)
_SSD1675B_GATE_VOLTAGE = const(0x03)
_SSD1675B_SOURCE_VOLTAGE = const(0x04)
_SSD1675B_INIT_SETTING = const(0x08)
_SSD1675B_INIT_WRITE_REG = const(0x09)
_SSD1675B_INIT_READ_REG = const(0x0A)
_SSD1675B_BOOSTER_SOFT_START = const(0x0C)
_SSD1675B_GATESCAN_START = const(0x0F)
_SSD1675B_DEEP_SLEEP = const(0x10)
_SSD1675B_DATA_MODE = const(0x11)
_SSD1675B_SW_RESET = const(0x12)
_SSD1675B_HV_READY = const(0x14)
_SSD1675B_VCI_READY = const(0x15)
_SSD1675B_TEMP_CONTROL = const(0x18)
_SSD1675B_TEMP_WRITE = const(0x1A)
_SSD1675B_TEMP_READ = const(0x1B)
_SSD1675B_EXTTEMP_WRITE = const(0x1C)
_SSD1675B_MASTER_ACTIVATE = const(0x20)
_SSD1675B_DISP_CTRL1 = const(0x21)
_SSD1675B_DISP_CTRL2 = const(0x22)
_SSD1675B_WRITE_RAM1 = const(0x24)
_SSD1675B_WRITE_RAM2 = const(0x26)
_SSD1675B_READ_RAM = const(0x27)
_SSD1675B_VCOM_SENSE = const(0x28)
_SSD1675B_VCOM_DURATION = const(0x29)
_SSD1675B_WRITE_VCOM_OTP = const(0x2A)
_SSD1675B_WRITE_VCOM_CTRL = const(0x2B)
_SSD1675B_WRITE_VCOM_REG = const(0x2C)
_SSD1675B_READ_OTP = const(0x2D)
_SSD1675B_READ_USERID = const(0x2E)
_SSD1675B_READ_STATUS = const(0x2F)
_SSD1675B_WRITE_WS_OTP = const(0x30)
_SSD1675B_LOAD_WS_OTP = const(0x31)
_SSD1675B_WRITE_LUT = const(0x32)
_SSD1675B_CRC_CALC = const(0x34)
_SSD1675B_CRC_READ = const(0x35)
_SSD1675B_PROG_OTP = const(0x36)
_SSD1675B_WRITE_DISPLAY_OPT = const(0x37)
_SSD1675B_WRITE_USERID = const(0x38)
_SSD1675B_OTP_PROGMODE = const(0x39)
_SSD1675B_WRITE_DUMMY = const(0x3A)
_SSD1675B_WRITE_GATELINE = const(0x3B)
_SSD1675B_WRITE_BORDER = const(0x3C)
_SSD1675B_SET_RAMXPOS = const(0x44)
_SSD1675B_SET_RAMYPOS = const(0x45)
_SSD1675B_AUTOWRITE_RED = const(0x46)
_SSD1675B_AUTOWRITE_BW = const(0x47)
_SSD1675B_SET_RAMXCOUNT = const(0x4E)
_SSD1675B_SET_RAMYCOUNT = const(0x4F)
_SSD1675B_SET_ANALOGBLOCK = const(0x74)
_SSD1675B_SET_DIGITALBLOCK = const(0x7E)
_SSD1675B_NOP = const(0xFF)
_LUT_DATA = b"\xa0\x90P\x00\x00\x00\x00\x00\x00\x00P\x90\xa0\x00\x00\x00\x00\x00\x00\x00\xa0\x90P\x00\x00\x00\x00\x00\x00\x00P\x90\xa0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x0f\x00\x00\x00\x0f\x0f\x00\x00\x03\x0f\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x15A\xa82P,\x0b" # pylint: disable=line-too-long
class Adafruit_SSD1675B(Adafruit_EPD):
"""driver class for Adafruit SSD1675B ePaper display breakouts"""
# pylint: disable=too-many-arguments
def __init__(
self, width, height, spi, *, cs_pin, dc_pin, sramcs_pin, rst_pin, busy_pin
):
super(Adafruit_SSD1675B, self).__init__(
width, height, spi, cs_pin, dc_pin, sramcs_pin, rst_pin, busy_pin
)
stride = width
if stride % 8 != 0:
stride += 8 - stride % 8
self._buffer1_size = int(stride * height / 8)
self._buffer2_size = self._buffer1_size
if sramcs_pin:
self._buffer1 = self.sram.get_view(0)
self._buffer2 = self.sram.get_view(self._buffer1_size)
else:
self._buffer1 = bytearray(self._buffer1_size)
self._buffer2 = bytearray(self._buffer2_size)
# since we have *two* framebuffers - one for red and one for black
# we dont subclass but manage manually
self._framebuf1 = adafruit_framebuf.FrameBuffer(
self._buffer1,
width,
height,
stride=stride,
buf_format=adafruit_framebuf.MHMSB,
)
self._framebuf2 = adafruit_framebuf.FrameBuffer(
self._buffer2,
width,
height,
stride=stride,
buf_format=adafruit_framebuf.MHMSB,
)
self.set_black_buffer(0, True)
self.set_color_buffer(0, True)
# pylint: enable=too-many-arguments
def begin(self, reset=True):
"""Begin communication with the display and set basic settings"""
if reset:
self.hardware_reset()
self.power_down()
def busy_wait(self):
"""Wait for display to be done with current task, either by polling the
busy pin, or pausing"""
if self._busy:
while self._busy.value:
time.sleep(0.01)
else:
time.sleep(0.5)
def power_up(self):
"""Power up the display in preparation for writing RAM and updating"""
self.hardware_reset()
time.sleep(0.1)
self.busy_wait()
self.command(_SSD1675B_SW_RESET)
self.busy_wait()
# set analog block control
self.command(_SSD1675B_SET_ANALOGBLOCK, bytearray([0x54]))
# set digital block control
self.command(_SSD1675B_SET_DIGITALBLOCK, bytearray([0x3B]))
self.command(
_SSD1675B_DRIVER_CONTROL,
bytearray([self._height - 1, (self._height - 1) >> 8, 0x00]),
)
# Data entry sequence
self.command(_SSD1675B_DATA_MODE, bytearray([0x03]))
# Set ram X start/end postion
self.command(_SSD1675B_SET_RAMXPOS, bytearray([0x00, self._width // 8]))
# Set ram Y start/end postion
self.command(
_SSD1675B_SET_RAMYPOS,
bytearray([0x0, 0x0, self._height - 1, (self._height - 1) >> 8]),
)
# Border color
self.command(_SSD1675B_WRITE_BORDER, bytearray([0x03]))
# Vcom Voltage
self.command(_SSD1675B_WRITE_VCOM_REG, bytearray([0x50]))
# Set gate voltage
self.command(_SSD1675B_GATE_VOLTAGE, _LUT_DATA[100:101])
# Set source voltage
self.command(_SSD1675B_SOURCE_VOLTAGE, _LUT_DATA[101:104])
# Set dummy line period
self.command(_SSD1675B_WRITE_DUMMY, _LUT_DATA[105:106])
# Set gate line width
self.command(_SSD1675B_WRITE_GATELINE, _LUT_DATA[106:107])
# LUT
self.command(_SSD1675B_WRITE_LUT, _LUT_DATA[0:100])
# Set temperature control
# self.command(_SSD1675B_TEMP_CONTROL, bytearray([0x80]))
# Set RAM X address counter
self.command(_SSD1675B_SET_RAMXCOUNT, bytearray([0]))
# Set RAM Y address counter
self.command(
_SSD1675B_SET_RAMYCOUNT,
bytearray([self._height - 1, (self._height - 1) >> 8]),
)
self.busy_wait()
def power_down(self):
"""Power down the display - required when not actively displaying!"""
self.command(_SSD1675B_DEEP_SLEEP, bytearray([0x01]))
time.sleep(0.1)
def update(self):
"""Update the display from internal memory"""
self.command(_SSD1675B_DISP_CTRL2, bytearray([0xC7]))
self.command(_SSD1675B_MASTER_ACTIVATE)
self.busy_wait()
if not self._busy:
time.sleep(3) # wait 3 seconds
def write_ram(self, index):
"""Send the one byte command for starting the RAM write process. Returns
the byte read at the same time over SPI. index is the RAM buffer, can be
0 or 1 for tri-color displays."""
if index == 0:
return self.command(_SSD1675B_WRITE_RAM1, end=False)
if index == 1:
return self.command(_SSD1675B_WRITE_RAM2, end=False)
raise RuntimeError("RAM index must be 0 or 1")
def set_ram_address(self, x, y): # pylint: disable=unused-argument, no-self-use
"""Set the RAM address location, not used on this chipset but required by
the superclass"""
self.command(_SSD1675B_SET_RAMXCOUNT, bytearray([x]))
self.command(_SSD1675B_SET_RAMYCOUNT, bytearray([y, y >> 8]))

View file

@ -1,186 +0,0 @@
# The MIT License (MIT)
#
# Copyright (c) 2018 Dean Miller 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.
"""
`adafruit_epd.ssd1681` - Adafruit SSD1681 - ePaper display driver
====================================================================================
CircuitPython driver for Adafruit SSD1681 display breakouts
* Author(s): Dean Miller, Ladyada
"""
import time
from micropython import const
import adafruit_framebuf
from adafruit_epd.epd import Adafruit_EPD
__version__ = "0.0.0-auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_EPD.git"
_SSD1681_DRIVER_CONTROL = const(0x01)
_SSD1681_GATE_VOLTAGE = const(0x03)
_SSD1681_SOURCE_VOLTAGE = const(0x04)
_SSD1681_INIT_SETTING = const(0x08)
_SSD1681_INIT_WRITE_REG = const(0x09)
_SSD1681_INIT_READ_REG = const(0x0A)
_SSD1681_BOOSTER_SOFT_START = const(0x0C)
_SSD1681_DEEP_SLEEP = const(0x10)
_SSD1681_DATA_MODE = const(0x11)
_SSD1681_SW_RESET = const(0x12)
_SSD1681_HV_DETECT = const(0x14)
_SSD1681_VCI_DETECT = const(0x15)
_SSD1681_TEMP_CONTROL = const(0x18)
_SSD1681_TEMP_WRITE = const(0x1A)
_SSD1681_TEMP_READ = const(0x1B)
_SSD1681_EXTTEMP_WRITE = const(0x1C)
_SSD1681_MASTER_ACTIVATE = const(0x20)
_SSD1681_DISP_CTRL1 = const(0x21)
_SSD1681_DISP_CTRL2 = const(0x22)
_SSD1681_WRITE_BWRAM = const(0x24)
_SSD1681_WRITE_REDRAM = const(0x26)
_SSD1681_READ_RAM = const(0x27)
_SSD1681_VCOM_SENSE = const(0x28)
_SSD1681_VCOM_DURATION = const(0x29)
_SSD1681_WRITE_VCOM_OTP = const(0x2A)
_SSD1681_WRITE_VCOM_CTRL = const(0x2B)
_SSD1681_WRITE_VCOM_REG = const(0x2C)
_SSD1681_READ_OTP = const(0x2D)
_SSD1681_READ_USERID = const(0x2E)
_SSD1681_READ_STATUS = const(0x2F)
_SSD1681_WRITE_WS_OTP = const(0x30)
_SSD1681_LOAD_WS_OTP = const(0x31)
_SSD1681_WRITE_LUT = const(0x32)
_SSD1681_CRC_CALC = const(0x34)
_SSD1681_CRC_READ = const(0x35)
_SSD1681_PROG_OTP = const(0x36)
_SSD1681_WRITE_DISPLAY_OPT = const(0x37)
_SSD1681_WRITE_USERID = const(0x38)
_SSD1681_OTP_PROGMODE = const(0x39)
_SSD1681_WRITE_BORDER = const(0x3C)
_SSD1681_END_OPTION = const(0x3F)
_SSD1681_SET_RAMXPOS = const(0x44)
_SSD1681_SET_RAMYPOS = const(0x45)
_SSD1681_AUTOWRITE_RED = const(0x46)
_SSD1681_AUTOWRITE_BW = const(0x47)
_SSD1681_SET_RAMXCOUNT = const(0x4E)
_SSD1681_SET_RAMYCOUNT = const(0x4F)
_SSD1681_NOP = const(0xFF)
_LUT_DATA = b'\x02\x02\x01\x11\x12\x12""fiiYX\x99\x99\x88\x00\x00\x00\x00\xf8\xb4\x13Q5QQ\x19\x01\x00' # pylint: disable=line-too-long
class Adafruit_SSD1681(Adafruit_EPD):
"""driver class for Adafruit SSD1681 ePaper display breakouts"""
# pylint: disable=too-many-arguments
def __init__(
self, width, height, spi, *, cs_pin, dc_pin, sramcs_pin, rst_pin, busy_pin
):
super(Adafruit_SSD1681, self).__init__(
width, height, spi, cs_pin, dc_pin, sramcs_pin, rst_pin, busy_pin
)
if height % 8 != 0:
height += 8 - height % 8
self._height = height
self._buffer1_size = int(width * height / 8)
if sramcs_pin:
self._buffer1 = self.sram.get_view(0)
else:
self._buffer1 = bytearray((width * height) // 8)
self._framebuf1 = adafruit_framebuf.FrameBuffer(
self._buffer1, width, height, buf_format=adafruit_framebuf.MHMSB
)
self.set_black_buffer(0, True)
self.set_color_buffer(0, True)
# pylint: enable=too-many-arguments
def begin(self, reset=True):
"""Begin communication with the display and set basic settings"""
if reset:
self.hardware_reset()
self.power_down()
def busy_wait(self):
"""Wait for display to be done with current task, either by polling the
busy pin, or pausing"""
if self._busy:
while self._busy.value:
time.sleep(0.01)
else:
time.sleep(0.5)
def power_up(self):
"""Power up the display in preparation for writing RAM and updating"""
self.hardware_reset()
self.busy_wait()
self.command(_SSD1681_SW_RESET)
self.busy_wait()
# driver output control
self.command(
_SSD1681_DRIVER_CONTROL,
bytearray([self._width - 1, (self._width - 1) >> 8, 0x00]),
)
# data entry mode
self.command(_SSD1681_DATA_MODE, bytearray([0x03]))
# Set ram X start/end postion
self.command(_SSD1681_SET_RAMXPOS, bytearray([0x00, self._height // 8 - 1]))
# Set ram Y start/end postion
self.command(
_SSD1681_SET_RAMYPOS,
bytearray([0, 0, self._height - 1, (self._height - 1) >> 8]),
)
# Set border waveform
self.command(_SSD1681_WRITE_BORDER, bytearray([0x05]))
# Set temperature control
self.command(_SSD1681_TEMP_CONTROL, bytearray([0x80]))
self.busy_wait()
def power_down(self):
"""Power down the display - required when not actively displaying!"""
self.command(_SSD1681_DEEP_SLEEP, bytearray([0x01]))
time.sleep(0.1)
def update(self):
"""Update the display from internal memory"""
self.command(_SSD1681_DISP_CTRL2, bytearray([0xF7]))
self.command(_SSD1681_MASTER_ACTIVATE)
self.busy_wait()
if not self._busy:
time.sleep(3) # wait 3 seconds
def write_ram(self, index):
"""Send the one byte command for starting the RAM write process. Returns
the byte read at the same time over SPI. index is the RAM buffer, can be
0 or 1 for tri-color displays."""
if index == 0:
return self.command(_SSD1681_WRITE_BWRAM, end=False)
raise RuntimeError("RAM index must be 0")
def set_ram_address(self, x, y): # pylint: disable=unused-argument, no-self-use
"""Set the RAM address location, not used on this chipset but required by
the superclass"""
# Set RAM X address counter
self.command(_SSD1681_SET_RAMXCOUNT, bytearray([x]))
# Set RAM Y address counter
self.command(_SSD1681_SET_RAMYCOUNT, bytearray([y >> 8, y]))

View file

@ -2,8 +2,7 @@
import os import os
import sys import sys
sys.path.insert(0, os.path.abspath('..'))
sys.path.insert(0, os.path.abspath(".."))
# -- General configuration ------------------------------------------------ # -- General configuration ------------------------------------------------
@ -11,10 +10,10 @@ sys.path.insert(0, os.path.abspath(".."))
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones. # ones.
extensions = [ extensions = [
"sphinx.ext.autodoc", 'sphinx.ext.autodoc',
"sphinx.ext.intersphinx", 'sphinx.ext.intersphinx',
"sphinx.ext.napoleon", 'sphinx.ext.napoleon',
"sphinx.ext.todo", 'sphinx.ext.todo',
] ]
# Uncomment the below if you use native CircuitPython modules such as # Uncomment the below if you use native CircuitPython modules such as
@ -23,40 +22,29 @@ extensions = [
# autodoc_mock_imports = ["digitalio", "busio", "micropython"] # autodoc_mock_imports = ["digitalio", "busio", "micropython"]
intersphinx_mapping = { intersphinx_mapping = {'python': ('https://docs.python.org/3.4', None),'BusDevice': ('https://circuitpython.readthedocs.io/projects/busdevice/en/latest/', None),'Register': ('https://circuitpython.readthedocs.io/projects/register/en/latest/', None),'CircuitPython': ('https://circuitpython.readthedocs.io/en/latest/', None)}
"python": ("https://docs.python.org/3.4", None),
"BusDevice": (
"https://circuitpython.readthedocs.io/projects/busdevice/en/latest/",
None,
),
"Register": (
"https://circuitpython.readthedocs.io/projects/register/en/latest/",
None,
),
"CircuitPython": ("https://circuitpython.readthedocs.io/en/latest/", None),
}
# Add any paths that contain templates here, relative to this directory. # Add any paths that contain templates here, relative to this directory.
templates_path = ["_templates"] templates_path = ['_templates']
source_suffix = ".rst" source_suffix = '.rst'
# The master toctree document. # The master toctree document.
master_doc = "index" master_doc = 'index'
# General information about the project. # General information about the project.
project = "Adafruit EPD Library" project = u'Adafruit EPD Library'
copyright = "2018 Dean Miller" copyright = u'2018 Dean Miller'
author = "Dean Miller" author = u'Dean Miller'
# The version info for the project you're documenting, acts as replacement for # The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the # |version| and |release|, also used in various other places throughout the
# built documents. # built documents.
# #
# The short X.Y version. # The short X.Y version.
version = "1.0" version = u'1.0'
# The full version, including alpha/beta/rc tags. # The full version, including alpha/beta/rc tags.
release = "1.0" release = u'1.0'
# The language for content autogenerated by Sphinx. Refer to documentation # The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages. # for a list of supported languages.
@ -68,7 +56,7 @@ language = None
# List of patterns, relative to source directory, that match files and # List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files. # directories to ignore when looking for source files.
# This patterns also effect to html_static_path and html_extra_path # This patterns also effect to html_static_path and html_extra_path
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store", ".env", "CODE_OF_CONDUCT.md"] exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store', '.env', 'CODE_OF_CONDUCT.md']
# The reST default role (used for this markup: `text`) to use for all # The reST default role (used for this markup: `text`) to use for all
# documents. # documents.
@ -80,7 +68,7 @@ default_role = "any"
add_function_parentheses = True add_function_parentheses = True
# The name of the Pygments (syntax highlighting) style to use. # The name of the Pygments (syntax highlighting) style to use.
pygments_style = "sphinx" pygments_style = 'sphinx'
# If true, `todo` and `todoList` produce output, else they produce nothing. # If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = False todo_include_todos = False
@ -95,62 +83,59 @@ napoleon_numpy_docstring = False
# The theme to use for HTML and HTML Help pages. See the documentation for # The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes. # a list of builtin themes.
# #
on_rtd = os.environ.get("READTHEDOCS", None) == "True" on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
if not on_rtd: # only import and set the theme if we're building docs locally if not on_rtd: # only import and set the theme if we're building docs locally
try: try:
import sphinx_rtd_theme import sphinx_rtd_theme
html_theme = 'sphinx_rtd_theme'
html_theme = "sphinx_rtd_theme" html_theme_path = [sphinx_rtd_theme.get_html_theme_path(), '.']
html_theme_path = [sphinx_rtd_theme.get_html_theme_path(), "."]
except: except:
html_theme = "default" html_theme = 'default'
html_theme_path = ["."] html_theme_path = ['.']
else: else:
html_theme_path = ["."] html_theme_path = ['.']
# Add any paths that contain custom static files (such as style sheets) here, # Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files, # relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css". # so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ["_static"] html_static_path = ['_static']
# The name of an image file (relative to this directory) to use as a favicon of # The name of an image file (relative to this directory) to use as a favicon of
# the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large. # pixels large.
# #
html_favicon = "_static/favicon.ico" html_favicon = '_static/favicon.ico'
# Output file base name for HTML help builder. # Output file base name for HTML help builder.
htmlhelp_basename = "AdafruitEpdLibrarydoc" htmlhelp_basename = 'AdafruitEpdLibrarydoc'
# -- Options for LaTeX output --------------------------------------------- # -- Options for LaTeX output ---------------------------------------------
latex_elements = { latex_elements = {
# The paper size ('letterpaper' or 'a4paper'). # The paper size ('letterpaper' or 'a4paper').
# #
# 'papersize': 'letterpaper', # 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
# # The font size ('10pt', '11pt' or '12pt').
# 'pointsize': '10pt', #
# Additional stuff for the LaTeX preamble. # 'pointsize': '10pt',
#
# 'preamble': '', # Additional stuff for the LaTeX preamble.
# Latex figure (float) alignment #
# # 'preamble': '',
# 'figure_align': 'htbp',
# Latex figure (float) alignment
#
# 'figure_align': 'htbp',
} }
# Grouping the document tree into LaTeX files. List of tuples # Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, # (source start file, target name, title,
# author, documentclass [howto, manual, or own class]). # author, documentclass [howto, manual, or own class]).
latex_documents = [ latex_documents = [
( (master_doc, 'AdafruitEPDLibrary.tex', u'AdafruitEPD Library Documentation',
master_doc, author, 'manual'),
"AdafruitEPDLibrary.tex",
"AdafruitEPD Library Documentation",
author,
"manual",
),
] ]
# -- Options for manual page output --------------------------------------- # -- Options for manual page output ---------------------------------------
@ -158,13 +143,8 @@ latex_documents = [
# One entry per manual page. List of tuples # One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section). # (source start file, name, description, authors, manual section).
man_pages = [ man_pages = [
( (master_doc, 'AdafruitEPDlibrary', u'Adafruit EPD Library Documentation',
master_doc, [author], 1)
"AdafruitEPDlibrary",
"Adafruit EPD Library Documentation",
[author],
1,
)
] ]
# -- Options for Texinfo output ------------------------------------------- # -- Options for Texinfo output -------------------------------------------
@ -173,13 +153,7 @@ man_pages = [
# (source start file, target name, title, author, # (source start file, target name, title, author,
# dir menu entry, description, category) # dir menu entry, description, category)
texinfo_documents = [ texinfo_documents = [
( (master_doc, 'AdafruitEPDLibrary', u'Adafruit EPD Library Documentation',
master_doc, author, 'AdafruitEPDLibrary', 'One line description of project.',
"AdafruitEPDLibrary", 'Miscellaneous'),
"Adafruit EPD Library Documentation",
author,
"AdafruitEPDLibrary",
"One line description of project.",
"Miscellaneous",
),
] ]

View file

@ -3,47 +3,22 @@ import busio
import board import board
from adafruit_epd.epd import Adafruit_EPD from adafruit_epd.epd import Adafruit_EPD
from adafruit_epd.il0373 import Adafruit_IL0373 from adafruit_epd.il0373 import Adafruit_IL0373
from adafruit_epd.il91874 import Adafruit_IL91874 # pylint: disable=unused-import
from adafruit_epd.il0398 import Adafruit_IL0398 # pylint: disable=unused-import
from adafruit_epd.ssd1608 import Adafruit_SSD1608 # pylint: disable=unused-import
from adafruit_epd.ssd1675 import Adafruit_SSD1675 # pylint: disable=unused-import
# create the spi device and pins we will need # create the spi device and pins we will need
spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO) spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)
ecs = digitalio.DigitalInOut(board.D10) ecs = digitalio.DigitalInOut(board.D10)
dc = digitalio.DigitalInOut(board.D9) dc = digitalio.DigitalInOut(board.D9)
srcs = digitalio.DigitalInOut(board.D7) # can be None to use internal memory srcs = digitalio.DigitalInOut(board.D8)
rst = digitalio.DigitalInOut(board.D11) # can be None to not use this pin rst = digitalio.DigitalInOut(board.D7)
busy = digitalio.DigitalInOut(board.D12) # can be None to not use this pin busy = digitalio.DigitalInOut(board.D6)
# give them all to our driver # give them all to our driver
print("Creating display") display = Adafruit_IL0373(152, 152, rst, dc, busy, srcs, ecs, spi)
# display = Adafruit_SSD1608(200, 200, spi, # 1.54" HD mono display
# display = Adafruit_SSD1675(122, 250, spi, # 2.13" HD mono display
# display = Adafruit_IL91874(176, 264, spi, # 2.7" Tri-color display
# display = Adafruit_IL0373(152, 152, spi, # 1.54" Tri-color display
# display = Adafruit_IL0373(128, 296, spi, # 2.9" Tri-color display
# display = Adafruit_IL0398(400, 300, spi, # 4.2" Tri-color display
display = Adafruit_IL0373(
104,
212,
spi, # 2.13" Tri-color display
cs_pin=ecs,
dc_pin=dc,
sramcs_pin=srcs,
rst_pin=rst,
busy_pin=busy,
)
# IF YOU HAVE A FLEXIBLE DISPLAY (2.13" or 2.9") uncomment these lines! FILENAME = "blinka.bmp"
# display.set_black_buffer(1, False)
# display.set_color_buffer(1, False)
display.rotation = 0
FILENAME = "blinka154mono.bmp"
# clear the buffer
display.clear_buffer()
def read_le(s): def read_le(s):
# as of this writting, int.from_bytes does not have LE support, DIY! # as of this writting, int.from_bytes does not have LE support, DIY!
@ -54,21 +29,14 @@ def read_le(s):
shift += 8 shift += 8
return result return result
class BMPError(Exception): class BMPError(Exception):
pass pass
def display_bitmap(epd, filename): # pylint: disable=too-many-locals, too-many-branches try:
try: with open("/" + FILENAME, "rb") as f:
f = open("/" + filename, "rb") print("File opened")
except OSError: if f.read(2) != b'BM': # check signature
print("Couldn't open file")
return
print("File opened")
try:
if f.read(2) != b"BM": # check signature
raise BMPError("Not BitMap file") raise BMPError("Not BitMap file")
bmpFileSize = read_le(f.read(4)) bmpFileSize = read_le(f.read(4))
@ -80,10 +48,8 @@ def display_bitmap(epd, filename): # pylint: disable=too-many-locals, too-many-
bmpHeight = read_le(f.read(4)) bmpHeight = read_le(f.read(4))
flip = True flip = True
print( print("Size: %d\nImage offset: %d\nHeader size: %d" %
"Size: %d\nImage offset: %d\nHeader size: %d" (bmpFileSize, bmpImageoffset, headerSize))
% (bmpFileSize, bmpImageoffset, headerSize)
)
print("Width: %d\nHeight: %d" % (bmpWidth, bmpHeight)) print("Width: %d\nHeight: %d" % (bmpWidth, bmpHeight))
if read_le(f.read(2)) != 1: if read_le(f.read(2)) != 1:
@ -107,25 +73,22 @@ def display_bitmap(epd, filename): # pylint: disable=too-many-locals, too-many-
# print ("seek to %d" % pos) # print ("seek to %d" % pos)
f.seek(pos) f.seek(pos)
rowdata = f.read(3 * bmpWidth)
for col in range(bmpWidth): for col in range(bmpWidth):
b, g, r = rowdata[3 * col : 3 * col + 3] # BMP files store RGB in BGR b, g, r = bytearray(f.read(3)) # BMP files store RGB in BGR
if r < 0x80 and g < 0x80 and b < 0x80: if r < 0x80 and g < 0x80 and b < 0x80:
epd.pixel(col, row, Adafruit_EPD.BLACK) display.draw_pixel(row, col, Adafruit_EPD.BLACK)
elif r >= 0x80 and g >= 0x80 and b >= 0x80: elif r >= 0x80 and g >= 0x80 and b >= 0x80:
pass # epd.pixel(row, col, Adafruit_EPD.WHITE) display.draw_pixel(row, col, Adafruit_EPD.WHITE)
elif r >= 0x80: elif r >= 0x80:
epd.pixel(col, row, Adafruit_EPD.RED) display.draw_pixel(row, col, Adafruit_EPD.RED)
except OSError:
print("Couldn't read file") except OSError as e:
except BMPError as e: if e.args[0] == 28:
print("Failed to parse BMP: " + e.args[0]) raise OSError("OS Error 28 0.25")
finally: else:
f.close() raise OSError("OS Error 0.5")
print("Finished drawing") except BMPError as e:
print("Failed to parse BMP: " + e.args[0])
# clear the buffer
display.fill(Adafruit_EPD.WHITE)
display_bitmap(display, FILENAME)
display.display() display.display()

View file

@ -5,107 +5,76 @@ import board
from PIL import Image from PIL import Image
from PIL import ImageDraw from PIL import ImageDraw
from PIL import ImageFont from PIL import ImageFont
from adafruit_epd.epd import Adafruit_EPD from adafruit_epd.il0373 import Adafruit_IL0373
from adafruit_epd.il0373 import Adafruit_IL0373 # pylint: disable=unused-import
from adafruit_epd.il91874 import Adafruit_IL91874 # pylint: disable=unused-import
from adafruit_epd.il0398 import Adafruit_IL0398 # pylint: disable=unused-import
from adafruit_epd.ssd1608 import Adafruit_SSD1608 # pylint: disable=unused-import
from adafruit_epd.ssd1675 import Adafruit_SSD1675 # pylint: disable=unused-import
from adafruit_epd.ssd1675b import Adafruit_SSD1675B # pylint: disable=unused-import
from adafruit_epd.ssd1681 import Adafruit_SSD1681 # pylint: disable=unused-import
# create the spi device and pins we will need # create the spi device and pins we will need
spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO) spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)
while not spi.try_lock():
pass
spi.configure(baudrate=16000000)
spi.unlock()
# create the spi device and pins we will need ecs = digitalio.DigitalInOut(board.D22)
spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO) dc = digitalio.DigitalInOut(board.D13)
ecs = digitalio.DigitalInOut(board.D4) srcs = digitalio.DigitalInOut(board.D6)
dc = digitalio.DigitalInOut(board.D5) rst = digitalio.DigitalInOut(board.D19)
srcs = None busy = digitalio.DigitalInOut(board.D26)
rst = digitalio.DigitalInOut(board.D6) # can be None to not use this pin
busy = digitalio.DigitalInOut(board.D7) # can be None to not use this pin
# give them all to our driver # give them all to our driver
print("Creating display") display = Adafruit_IL0373(152, 152, rst, dc, busy, srcs, ecs, spi)
# display = Adafruit_SSD1608(200, 200, spi, # 1.54" HD mono display
# display = Adafruit_SSD1681(200, 200, spi, # 1.54" HD mono display (alt)
# display = Adafruit_SSD1675(122, 250, spi, # 2.13" HD mono display
# display = Adafruit_IL91874(176, 264, spi, # 2.7" Tri-color display
# display = Adafruit_IL0373(152, 152, spi, # 1.54" Tri-color display
# display = Adafruit_IL0373(128, 296, spi, # 2.9" Tri-color display
# display = Adafruit_IL0398(400, 300, spi, # 4.2" Tri-color display
# display = Adafruit_IL0373(104, 212, spi, # 2.13" Tri-color display
display = Adafruit_SSD1675B(
122,
250,
spi, # 2.13" HD mono display (rev B)
cs_pin=ecs,
dc_pin=dc,
sramcs_pin=srcs,
rst_pin=rst,
busy_pin=busy,
)
display.rotation = 3
# Create blank image for drawing. # Create blank image for drawing.
# Make sure to create image with mode '1' for 1-bit color. # Make sure to create image with mode '1' for 1-bit color.
width = display.width width = display.width
height = display.height height = display.height
image = Image.new("RGB", (width, height)) image = Image.new('RGB', (width, height))
WHITE = (0xFF, 0xFF, 0xFF) WHITE = (0xFF, 0xFF, 0xFF)
RED = (0xFF, 0x00, 0x00) RED = (0xFF, 0x00, 0x00)
BLACK = (0x00, 0x00, 0x00) BLACK = (0x00, 0x00, 0x00)
# clear the buffer # clear the buffer
display.fill(Adafruit_EPD.WHITE) display.clear_buffer()
# Get drawing object to draw on image. # Get drawing object to draw on image.
draw = ImageDraw.Draw(image) draw = ImageDraw.Draw(image)
# empty it
draw.rectangle((0, 0, width, height), fill=WHITE)
# Draw an outline box # Draw a white filled box to clear the image.
draw.rectangle((1, 1, width - 2, height - 2), outline=BLACK, fill=WHITE) draw.rectangle((0,0,width,height), outline=BLACK, fill=WHITE)
# Draw some shapes. # Draw some shapes.
# First define some constants to allow easy resizing of shapes. # First define some constants to allow easy resizing of shapes.
padding = 5 padding = 2
shape_width = 30 shape_width = 30
top = padding top = padding
bottom = height - padding bottom = height-padding
# Move left to right keeping track of the current x position for drawing shapes. # Move left to right keeping track of the current x position for drawing shapes.
x = padding x = padding
# Draw an ellipse. # Draw an ellipse.
draw.ellipse((x, top, x + shape_width, bottom), outline=RED, fill=WHITE) draw.ellipse((x, top , x+shape_width, bottom), outline=RED, fill=WHITE)
x += shape_width + padding x += shape_width+padding
# Draw a rectangle. # Draw a rectangle.
draw.rectangle((x, top, x + shape_width, bottom), outline=RED, fill=BLACK) draw.rectangle((x, top, x+shape_width, bottom), outline=RED, fill=BLACK)
x += shape_width + padding x += shape_width+padding
# Draw a triangle. # Draw a triangle.
draw.polygon( draw.polygon([(x, bottom), (x+shape_width/2, top), (x+shape_width, bottom)],
[(x, bottom), (x + shape_width / 2, top), (x + shape_width, bottom)], outline=BLACK, fill=RED)
outline=BLACK, x += shape_width+padding
fill=RED,
)
x += shape_width + padding
# Draw an X. # Draw an X.
draw.line((x, bottom, x + shape_width, top), fill=RED) draw.line((x, bottom, x+shape_width, top), fill=RED)
draw.line((x, top, x + shape_width, bottom), fill=RED) draw.line((x, top, x+shape_width, bottom), fill=RED)
x += shape_width + padding x += shape_width+padding
# Load default font. # Load default font.
font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 20) font = ImageFont.load_default()
# Alternatively load a TTF font. Make sure the .ttf font # Alternatively load a TTF font. Make sure the .ttf font
# file is in the same directory as the python script! # file is in the same directory as the python script!
# Some other nice fonts to try: http://www.dafont.com/bitmap.php # Some other nice fonts to try: http://www.dafont.com/bitmap.php
# font = ImageFont.truetype('Minecraftia.ttf', 8) #font = ImageFont.truetype('Minecraftia.ttf', 8)
# Write two lines of text. # Write two lines of text.
draw.text((x, top), "Hello", font=font, fill=RED) draw.text((x, top), 'Hello', font=font, fill=RED)
draw.text((x, top + 20), "World!", font=font, fill=RED) draw.text((x, top+20), 'World!', font=font, fill=RED)
# Display image. # Display image.
display.image(image) display.image(image)

View file

@ -1,110 +0,0 @@
import time
import busio
import board
from digitalio import DigitalInOut, Direction
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont
from adafruit_epd.epd import Adafruit_EPD
from adafruit_epd.ssd1675b import Adafruit_SSD1675B # pylint: disable=unused-import
# create two buttons
switch1 = DigitalInOut(board.D6)
switch2 = DigitalInOut(board.D5)
switch1.direction = Direction.INPUT
switch2.direction = Direction.INPUT
# create the spi device and pins we will need
spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)
ecs = DigitalInOut(board.D8)
dc = DigitalInOut(board.D22)
rst = DigitalInOut(board.D27)
busy = DigitalInOut(board.D17)
# give them all to our driver
display = Adafruit_SSD1675B(
122,
250,
spi, # 2.13" HD mono display (rev B)
cs_pin=ecs,
dc_pin=dc,
sramcs_pin=None,
rst_pin=rst,
busy_pin=busy,
)
display.rotation = 1
# Create blank image for drawing.
# Make sure to create image with mode '1' for 1-bit color.
width = display.width
height = display.height
image = Image.new("RGB", (width, height))
WHITE = (0xFF, 0xFF, 0xFF)
BLACK = (0x00, 0x00, 0x00)
# clear the buffer
display.fill(Adafruit_EPD.WHITE)
# clear it out
display.display()
# Get drawing object to draw on image.
draw = ImageDraw.Draw(image)
# empty it
draw.rectangle((0, 0, width, height), fill=WHITE)
# Draw an outline box
draw.rectangle((1, 1, width - 2, height - 2), outline=BLACK, fill=WHITE)
# Draw some shapes.
# First define some constants to allow easy resizing of shapes.
padding = 5
shape_width = 30
top = padding
bottom = height - padding
# Move left to right keeping track of the current x position for drawing shapes.
x = padding
# Draw an ellipse.
draw.ellipse((x, top, x + shape_width, bottom), outline=BLACK, fill=WHITE)
x += shape_width + padding
# Draw a rectangle.
draw.rectangle((x, top, x + shape_width, bottom), outline=WHITE, fill=BLACK)
x += shape_width + padding
# Draw a triangle.
draw.polygon(
[(x, bottom), (x + shape_width / 2, top), (x + shape_width, bottom)],
outline=BLACK,
fill=WHITE,
)
x += shape_width + padding
# Draw an X.
draw.line((x, bottom, x + shape_width, top), fill=BLACK)
draw.line((x, top, x + shape_width, bottom), fill=BLACK)
x += shape_width + padding
# Load default font.
font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 20)
# Alternatively load a TTF font. Make sure the .ttf font
# file is in the same directory as the python script!
# Some other nice fonts to try: http://www.dafont.com/bitmap.php
# font = ImageFont.truetype('Minecraftia.ttf', 8)
# Write two lines of text.
draw.text((x, top), "Hello", font=font, fill=BLACK)
draw.text((x, top + 20), "World!", font=font, fill=BLACK)
while True:
if not switch1.value:
print("Switch 1")
display.image(image)
display.display()
while not switch1.value:
time.sleep(0.01)
if not switch2.value:
print("Switch 2")
display.fill(Adafruit_EPD.WHITE)
display.display()
while not switch2.value:
time.sleep(0.01)
time.sleep(0.01)

View file

@ -1,90 +0,0 @@
"""
ePaper Display Shapes and Text demo using the Pillow Library.
Written by Melissa LeBlanc-Williams for Adafruit Industries
"""
import digitalio
import busio
import board
from PIL import Image, ImageDraw, ImageFont
from adafruit_epd.il0373 import Adafruit_IL0373
from adafruit_epd.il91874 import Adafruit_IL91874 # pylint: disable=unused-import
from adafruit_epd.il0398 import Adafruit_IL0398 # pylint: disable=unused-import
from adafruit_epd.ssd1608 import Adafruit_SSD1608 # pylint: disable=unused-import
from adafruit_epd.ssd1675 import Adafruit_SSD1675 # pylint: disable=unused-import
# First define some color constants
WHITE = (0xFF, 0xFF, 0xFF)
BLACK = (0x00, 0x00, 0x00)
RED = (0xFF, 0x00, 0x00)
# Next define some constants to allow easy resizing of shapes and colors
BORDER = 20
FONTSIZE = 24
BACKGROUND_COLOR = BLACK
FOREGROUND_COLOR = WHITE
TEXT_COLOR = RED
# create the spi device and pins we will need
spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)
ecs = digitalio.DigitalInOut(board.CE0)
dc = digitalio.DigitalInOut(board.D22)
srcs = None
rst = digitalio.DigitalInOut(board.D27)
busy = digitalio.DigitalInOut(board.D17)
# give them all to our driver
# display = Adafruit_SSD1608(200, 200, # 1.54" HD mono display
# display = Adafruit_SSD1675(122, 250, # 2.13" HD mono display
# display = Adafruit_IL91874(176, 264, # 2.7" Tri-color display
# display = Adafruit_IL0373(152, 152, # 1.54" Tri-color display
# display = Adafruit_IL0373(128, 296, # 2.9" Tri-color display
# display = Adafruit_IL0398(400, 300, # 4.2" Tri-color display
display = Adafruit_IL0373(
104,
212, # 2.13" Tri-color display
spi,
cs_pin=ecs,
dc_pin=dc,
sramcs_pin=srcs,
rst_pin=rst,
busy_pin=busy,
)
# IF YOU HAVE A FLEXIBLE DISPLAY (2.13" or 2.9") uncomment these lines!
# display.set_black_buffer(1, False)
# display.set_color_buffer(1, False)
display.rotation = 1
image = Image.new("RGB", (display.width, display.height))
# Get drawing object to draw on image.
draw = ImageDraw.Draw(image)
# Draw a filled box as the background
draw.rectangle((0, 0, display.width, display.height), fill=BACKGROUND_COLOR)
# Draw a smaller inner foreground rectangle
draw.rectangle(
(BORDER, BORDER, display.width - BORDER - 1, display.height - BORDER - 1),
fill=FOREGROUND_COLOR,
)
# Load a TTF Font
font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", FONTSIZE)
# Draw Some Text
text = "Hello World!"
(font_width, font_height) = font.getsize(text)
draw.text(
(display.width // 2 - font_width // 2, display.height // 2 - font_height // 2),
text,
font=font,
fill=TEXT_COLOR,
)
# Display image.
display.image(image)
display.display()

View file

@ -1,72 +0,0 @@
"""
Image resizing and drawing using the Pillow Library. For the image, check out the
associated Adafruit Learn guide at:
https://learn.adafruit.com/adafruit-eink-display-breakouts/python-code
Written by Melissa LeBlanc-Williams for Adafruit Industries
"""
import digitalio
import busio
import board
from PIL import Image
from adafruit_epd.il0373 import Adafruit_IL0373
from adafruit_epd.il91874 import Adafruit_IL91874 # pylint: disable=unused-import
from adafruit_epd.il0398 import Adafruit_IL0398 # pylint: disable=unused-import
from adafruit_epd.ssd1608 import Adafruit_SSD1608 # pylint: disable=unused-import
from adafruit_epd.ssd1675 import Adafruit_SSD1675 # pylint: disable=unused-import
# create the spi device and pins we will need
spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)
ecs = digitalio.DigitalInOut(board.CE0)
dc = digitalio.DigitalInOut(board.D22)
srcs = None
rst = digitalio.DigitalInOut(board.D27)
busy = digitalio.DigitalInOut(board.D17)
# give them all to our driver
# display = Adafruit_SSD1608(200, 200, # 1.54" HD mono display
# display = Adafruit_SSD1675(122, 250, # 2.13" HD mono display
# display = Adafruit_IL91874(176, 264, # 2.7" Tri-color display
# display = Adafruit_IL0373(152, 152, # 1.54" Tri-color display
# display = Adafruit_IL0373(128, 296, # 2.9" Tri-color display
# display = Adafruit_IL0398(400, 300, # 4.2" Tri-color display
display = Adafruit_IL0373(
104,
212, # 2.13" Tri-color display
spi,
cs_pin=ecs,
dc_pin=dc,
sramcs_pin=srcs,
rst_pin=rst,
busy_pin=busy,
)
# IF YOU HAVE A FLEXIBLE DISPLAY (2.13" or 2.9") uncomment these lines!
# display.set_black_buffer(1, False)
# display.set_color_buffer(1, False)
display.rotation = 1
image = Image.open("blinka.png")
# Scale the image to the smaller screen dimension
image_ratio = image.width / image.height
screen_ratio = display.width / display.height
if screen_ratio < image_ratio:
scaled_width = image.width * display.height // image.height
scaled_height = display.height
else:
scaled_width = display.width
scaled_height = image.height * display.width // image.width
image = image.resize((scaled_width, scaled_height), Image.BICUBIC)
# Crop and center the image
x = scaled_width // 2 - display.width // 2
y = scaled_height // 2 - display.height // 2
image = image.crop((x, y, x + display.width, y + display.height))
# Display image.
display.image(image)
display.display()

View file

@ -1,69 +0,0 @@
# EInk Shield test
import time
import digitalio
import busio
import board
from analogio import AnalogIn
from adafruit_epd.epd import Adafruit_EPD
from adafruit_epd.il91874 import Adafruit_IL91874
# create the spi device and pins we will need
spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)
ecs = digitalio.DigitalInOut(board.D10)
dc = digitalio.DigitalInOut(board.D9)
srcs = digitalio.DigitalInOut(board.D8) # can be None to use internal memory
# give them all to our driver
print("Creating display")
display = Adafruit_IL91874(
176,
264,
spi, # 2.7" Tri-color display
cs_pin=ecs,
dc_pin=dc,
sramcs_pin=srcs,
rst_pin=None,
busy_pin=None,
)
display.rotation = 1
def read_buttons():
with AnalogIn(board.A3) as ain:
reading = ain.value / 65535
if reading > 0.75:
return None
if reading > 0.4:
return 4
if reading > 0.25:
return 3
if reading > 0.13:
return 2
return 1
while True:
button = read_buttons()
if not button:
continue
print("Button #%d pressed" % button)
if button == 1:
print("Clear buffer")
display.fill(Adafruit_EPD.WHITE)
display.display()
if button == 2:
print("Draw Rectangles")
display.fill_rect(5, 5, 10, 10, Adafruit_EPD.RED)
display.rect(0, 0, 20, 30, Adafruit_EPD.BLACK)
display.display()
if button == 3:
print("Draw lines")
display.line(0, 0, display.width - 1, display.height - 1, Adafruit_EPD.BLACK)
display.line(0, display.height - 1, display.width - 1, 0, Adafruit_EPD.RED)
display.display()
if button == 4:
print("Draw text")
display.text("hello world", 25, 10, Adafruit_EPD.BLACK)
display.display()
time.sleep(0.01)

View file

@ -3,57 +3,31 @@ import busio
import board import board
from adafruit_epd.epd import Adafruit_EPD from adafruit_epd.epd import Adafruit_EPD
from adafruit_epd.il0373 import Adafruit_IL0373 from adafruit_epd.il0373 import Adafruit_IL0373
from adafruit_epd.il91874 import Adafruit_IL91874 # pylint: disable=unused-import
from adafruit_epd.il0398 import Adafruit_IL0398 # pylint: disable=unused-import
from adafruit_epd.ssd1608 import Adafruit_SSD1608 # pylint: disable=unused-import
from adafruit_epd.ssd1675 import Adafruit_SSD1675 # pylint: disable=unused-import
# create the spi device and pins we will need # create the spi device and pins we will need
spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO) spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)
ecs = digitalio.DigitalInOut(board.D12) ecs = digitalio.DigitalInOut(board.D10)
dc = digitalio.DigitalInOut(board.D11) dc = digitalio.DigitalInOut(board.D9)
srcs = digitalio.DigitalInOut(board.D10) # can be None to use internal memory srcs = digitalio.DigitalInOut(board.D8)
rst = digitalio.DigitalInOut(board.D9) # can be None to not use this pin rst = digitalio.DigitalInOut(board.D7)
busy = digitalio.DigitalInOut(board.D5) # can be None to not use this pin busy = digitalio.DigitalInOut(board.D6)
# give them all to our driver # give them all to our driver
print("Creating display") display = Adafruit_IL0373(152, 152, rst, dc, busy, srcs, ecs, spi)
# display = Adafruit_SSD1608(200, 200, spi, # 1.54" HD mono display
# display = Adafruit_SSD1675(122, 250, spi, # 2.13" HD mono display
# display = Adafruit_IL91874(176, 264, spi, # 2.7" Tri-color display
# display = Adafruit_IL0373(152, 152, spi, # 1.54" Tri-color display
# display = Adafruit_IL0373(128, 296, spi, # 2.9" Tri-color display
# display = Adafruit_IL0398(400, 300, spi, # 4.2" Tri-color display
display = Adafruit_IL0373(
104,
212,
spi, # 2.13" Tri-color display
cs_pin=ecs,
dc_pin=dc,
sramcs_pin=srcs,
rst_pin=rst,
busy_pin=busy,
)
# IF YOU HAVE A FLEXIBLE DISPLAY (2.13" or 2.9") uncomment these lines!
# display.set_black_buffer(1, False)
# display.set_color_buffer(1, False)
display.rotation = 1
# clear the buffer # clear the buffer
print("Clear buffer") display.clear_buffer()
display.fill(Adafruit_EPD.WHITE)
display.pixel(10, 100, Adafruit_EPD.BLACK)
print("Draw Rectangles") r_width = 5
display.fill_rect(5, 5, 10, 10, Adafruit_EPD.RED) r_pos = display.height
display.rect(0, 0, 20, 30, Adafruit_EPD.BLACK)
print("Draw lines") color = Adafruit_EPD.BLACK
display.line(0, 0, display.width - 1, display.height - 1, Adafruit_EPD.BLACK) while r_pos > display.height/2:
display.line(0, display.height - 1, display.width - 1, 0, Adafruit_EPD.RED) if r_pos < display.height - 50:
color = Adafruit_EPD.RED
display.rect(display.width - r_pos, display.height - r_pos,
display.width - 2*(display.width - r_pos),
display.height - 2*(display.height - r_pos), color)
r_pos = r_pos - r_width
print("Draw text")
display.text("hello world", 25, 10, Adafruit_EPD.BLACK)
display.display() display.display()

View file

@ -1,3 +1,2 @@
Adafruit-Blinka Adafruit-Blinka
adafruit-circuitpython-busdevice adafruit-circuitpython-busdevice
adafruit-circuitpython-framebuf

View file

@ -7,7 +7,6 @@ https://github.com/pypa/sampleproject
# Always prefer setuptools over distutils # Always prefer setuptools over distutils
from setuptools import setup, find_packages from setuptools import setup, find_packages
# To use a consistent encoding # To use a consistent encoding
from codecs import open from codecs import open
from os import path from os import path
@ -15,42 +14,47 @@ from os import path
here = path.abspath(path.dirname(__file__)) here = path.abspath(path.dirname(__file__))
# Get the long description from the README file # Get the long description from the README file
with open(path.join(here, "README.rst"), encoding="utf-8") as f: with open(path.join(here, 'README.rst'), encoding='utf-8') as f:
long_description = f.read() long_description = f.read()
setup( setup(
name="adafruit-circuitpython-epd", name='adafruit-circuitpython-epd',
use_scm_version=True, use_scm_version=True,
setup_requires=["setuptools_scm"], setup_requires=['setuptools_scm'],
description="CircuitPython library for EPD e-ink displays.",
description='CircuitPython library for EPD e-ink displays.',
long_description=long_description, long_description=long_description,
long_description_content_type="text/x-rst", long_description_content_type='text/x-rst',
# The project's main homepage. # The project's main homepage.
url="https://github.com/adafruit/Adafruit_CircuitPython_EPD", url='https://github.com/adafruit/Adafruit_CircuitPython_EPD',
# Author details # Author details
author="Adafruit Industries", author='Adafruit Industries',
author_email="circuitpython@adafruit.com", author_email='circuitpython@adafruit.com',
install_requires=[
"Adafruit-Blinka", install_requires=['Adafruit-Blinka', 'adafruit-circuitpython-busdevice'],
"adafruit-circuitpython-busdevice",
"adafruit-circuitpython-framebuf",
],
# Choose your license # Choose your license
license="MIT", license='MIT',
# See https://pypi.python.org/pypi?%3Aaction=list_classifiers # See https://pypi.python.org/pypi?%3Aaction=list_classifiers
classifiers=[ classifiers=[
"Development Status :: 3 - Alpha", 'Development Status :: 3 - Alpha',
"Intended Audience :: Developers", 'Intended Audience :: Developers',
"Topic :: Software Development :: Libraries", 'Topic :: Software Development :: Libraries',
"Topic :: System :: Hardware", 'Topic :: System :: Hardware',
"License :: OSI Approved :: MIT License", 'License :: OSI Approved :: MIT License',
"Programming Language :: Python :: 3", 'Programming Language :: Python :: 3',
"Programming Language :: Python :: 3.4", 'Programming Language :: Python :: 3.4',
"Programming Language :: Python :: 3.5", 'Programming Language :: Python :: 3.5',
], ],
# What does your project relate to? # What does your project relate to?
keywords="adafruit eink e-ink display epd hardware micropython circuitpython", keywords='adafruit eink e-ink display epd hardware micropython circuitpython',
# You can just specify the packages manually here if your project is # You can just specify the packages manually here if your project is
# simple. Or you can use find_packages(). # simple. Or you can use find_packages().
packages=["adafruit_epd"], packages=['adafruit_epd'],
) )