Merge remote-tracking branch 'upstream/main'

This commit is contained in:
Bernhard Sessner 2023-12-28 15:12:56 +01:00
commit 6d04685f10
48 changed files with 1912 additions and 1543 deletions

View File

@ -51,7 +51,7 @@ jobs:
python -m pip install --upgrade pip python -m pip install --upgrade pip
pip install wheel pip install wheel
pip install -e ./ pip install -e ./
pip install RPi.GPIO==0.7.1 spidev==3.5 pip install RPi.GPIO==0.7.1 spidev==3.5 gpiozero==2.0
wget https://raw.githubusercontent.com/aceinnolab/Inkycal/assets/tests/settings.json wget https://raw.githubusercontent.com/aceinnolab/Inkycal/assets/tests/settings.json
pip install pytest pip install pytest
python -m pytest python -m pytest

View File

@ -46,7 +46,7 @@ jobs:
python -m pip install --upgrade pip python -m pip install --upgrade pip
pip install wheel pip install wheel
pip install -e ./ pip install -e ./
pip install RPi.GPIO==0.7.1 spidev==3.5 pip install RPi.GPIO==0.7.1 spidev==3.5 gpiozero==2.0
wget https://raw.githubusercontent.com/aceinnolab/Inkycal/assets/tests/settings.json wget https://raw.githubusercontent.com/aceinnolab/Inkycal/assets/tests/settings.json
pip install pytest pip install pytest
python -m pytest python -m pytest
@ -84,8 +84,8 @@ jobs:
- name: Compress the release image - name: Compress the release image
run: | run: |
mv ${{ steps.build_image.outputs.image }} inkycal_os_lite.img mv ${{ steps.build_image.outputs.image }} InkycalOS_Lite.img
xz -0 -T 0 -v inkycal_os_lite.img xz -0 -T 0 -v InkycalOS_Lite.img
- name: Get latest release version - name: Get latest release version
run: | run: |
@ -99,4 +99,4 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with: with:
tag_name: ${{ env.version }} tag_name: ${{ env.version }}
files: inkycal_os_lite.img.xz files: InkycalOS_Lite.img.xz

303
README.md
View File

@ -1,9 +1,300 @@
# Inkycal-based full screen weather display (scraper solution) # Welcome to inkycal v2.0.3!
This fork of <https://github.com/aceinnolab/Inkycal/> was used to try out a webscraper approach for a openweathermap-based full screen weather display on a 7in5 waveshare v2 colour epd. <p align="center">
It didn't prove particularly robust, so I've decided to not further develop it. <img src="https://raw.githubusercontent.com/aceisace/Inkycal/assets/Repo/logo.png" width="900" alt="aceinnolab logo">
I'll leave it here in case someone wants to try and play around with it a little. </p>
<p align="center">
<img src="https://github.com/aceinnolab/Inkycal/blob/c1c274878ba81ddaee6186561e6ea892da54cd6a/Repo/inkycal-featured-gif.gif" width="900" alt="featured-image">
</p>
Since Selenium doesn't run on Pi Zero, I had to run the scraper part as a cron job on my Pi 4 and scp the resulting image to the Pi Zero that's connected to the e-paper display. <p align="center">
<a href="https://github.com/aceinnolab/Inkycal/actions/workflows/test-on-rpi.yml"><img src="https://github.com/aceinnolab/Inkycal/actions/workflows/test-on-rpi.yml/badge.svg"></a>
<a href="https://github.com/aceinnolab/Inkycal/actions/workflows/update-docs.yml"><img src="https://github.com/aceinnolab/Inkycal/actions/workflows/update-docs.yml/badge.svg"></a>
<a href="https://github.com/aceinnolab/Inkycal/releases"><img alt="Version" src="https://img.shields.io/github/release/aceisace/Inkycal.svg"/></a>
<a href="https://github.com/aceinnolab/Inkycal/blob/main/LICENSE"><img alt="Licence" src="https://img.shields.io/github/license/aceisace/Inkycal.svg" /></a>
<a href="https://github.com/aceinnolab/Inkycal/stargazers"><img alt="GitHub stars" src="https://img.shields.io/github/stars/aceisace/Inkycal?color=yellow"></a>
<a href="https://github.com/aceinnolab/Inkycal"><img alt="python" src="https://img.shields.io/badge/python-3.11-lightorange"></a>
</p>
For further information see the official Inkycal repo. Inkycal is a software written in python for selected E-Paper displays. It converts these displays into useful
information dashboards. It's open-source, free for personal use, fully modular and user-friendly. Despite all this,
Inkycal can run well even on the Raspberry Pi Zero. Oh, and it's open for third-party modules! Hooray!
## ⚠️ Warning: long installation time expected!
Starting october 2023, Raspberry Pi OS is now based on Debian bookworm and uses python 3.11 instead of 3.9 as the
default version. Inkycal has been updated to work with python3.11, but the installation of numpy can take a very long
time, in some cases even hours. If you do not want to wait this long to install Inkycal, you can also get a
ready-to-flash version of Inkycal called InkycalOS-Lite with everything pre-installed for you by sponsoring
via [Github Sponsors](https://github.com/sponsors/aceisace). This helps keep up maintenance costs, implement new
features and fixing bugs. Please choose the one-time sponsor option and select the one with the plug-and-play version of
Inkycal. Then, send your email-address to which InkycalOS-Lite should be sent.
Alternatively, you can also use the paypal.me link and send the same amount as Github sponsors to get access to InkycalOS-Lite!
## Main features
Inkycal is fully modular, you can mix and match any modules you like and configure them on the web-ui. For now, these
following built-in modules are supported:
* Calendar - Monthly Calendar with option to sync events from iCalendars, e.g. Google.
* Agenda - Agenda showing upcoming events from given iCalendar URLs.
* Image - Display an Image from URL or local file path.
* Slideshow - Cycle through images in a given folder and show them on the E-Paper.
* Feeds - Synchronise RSS/ATOM feeds from your favorite providers.
* Stocks - Display stocks using Tickers from Yahoo! Finance.
* Weather - Show current weather, daily or hourly weather forecasts from openweathermap.
* Todoist - Synchronise with Todoist app or website to show todos.
* iCanHazDad - Display a random joke from [iCanHazDad.com](iCanhazdad.com).
## Quickstart
Watch the one-minute video on getting started with Inkycal:
[![Inkycal quickstart](https://img.youtube.com/vi/IiIv_nWE5KI/0.jpg)](https://www.youtube.com/watch?v=IiIv_nWE5KI)
## Hardware guide
Before you can start, please ensure you have one of the supported displays and of the supported Raspberry
Pi: `|4|3A|3B|3B+|2B|0W|0WH|02W|`. We personally recommend the Raspberry Pi Zero W as this is relatively cheaper, uses
less power and is perfect to fit in a small photo frame once you have assembled everything.
**Serial** displays are usually cheaper, but slower. Their main advantage is ease of use, like being able to communicate
via SPI. A single update will cause flickering (fully normal on e-paper displays) ranging from a few seconds to half an
minute. We recommend these for users who want to get started quickly and for more compact setups, e.g. fitting inside a
photo frame. The resolution of these displays ranges from low to medium. Usually, these displays support 2-3 colours,
but no colours in between, e.g. fully black, fully red/yellow and fully-white.
**Parallel** displays on the other hand do not understand SPI and require their own dedicated driver boards individually
configured for these displays. Flickering also takes place here, but an update only takes about one to a few seconds.
The resolution is much better than serial e-paper displays, but the cost is also higher. These also have 16 different
grayscale levels, which does not compare to the 256 grayscales of LCDs, but far better than serial displays.
**❗Important note: e-paper displays cannot be simply connected to the Raspberry Pi, but require a driver board. The
links below may or may not contain the required driver board. Please ensure you get the correct driver board for the
display!**
| type | vendor | Where to buy |
|-------------------------------------------|-------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 7.5" Inkycal (plug-and-play) | Aceinnolab (author) |  [Buy on Tindie](https://www.tindie.com/products/aceisace4444/inkycal-build-v1/) Pre-configured version of Inkycal with custom frame and a web-ui. You do not need to buy anything extra. Includes Raspberry Pi Zero W, 7.5" e-paper, microSD card, driver board, custom packaging and 1m of cable. Comes pre-assembled for plug-and-play. |
| Inkycal frame (kit -> requires wires, 7.5" Display and Zero W with microSD card | Aceinnolab (author) | [Buy on Tindie](https://www.tindie.com/products/aceinnolab/inkycal-frame-custom-driver-board-only/) Ultraslim frame with custom-made front and backcover inkl. ultraslim driver board). You will need a Raspberry Pi, microSD card and a 7.5" e-paper display |
| `[serial]` 12.48" (1304×984px) display | waveshare / gooddisplay |  Search for `Waveshare 12.48" E-Paper 1304×984` on amazon or similar |
| `[serial]` 7.5" (640x384px) -> v1 display (2/3-colour) | waveshare / gooddisplay | Search for `Waveshare 7.5" E-Paper 640x384` on amazon or similar |
| `[serial]` 7.5" (800x480px) -> v2 display (2/3-colour) | waveshare / gooddisplay | Search for `Waveshare 7.5" E-Paper 800x480` on amazon or similar |
| `[serial]` 7.5" (880x528px) -> v3 display (2/3-colour) | waveshare / gooddisplay | Search for `Waveshare 7.5" E-Paper 800x528` on amazon or similar |
| `[serial]` 5.83" (400x300px) display | waveshare / gooddisplay | Search for `Waveshare 5.83" E-Paper 400x300` on amazon or similar |
| `[serial]` 4.2" (400x300px)display | waveshare / gooddisplay | Search for `Waveshare 4.2" E-Paper 400x300` on amazon or similar | |
| `[parallel]` 10.3" (1872×1404px) display | waveshare / gooddisplay |  Search for `Waveshare 10.3" E-Paper 1872×1404` on amazon or similar |
| `[parallel]` 9.7" (1200×825px) display | waveshare / gooddisplay | Search for `Waveshare 9.7" E-Paper 1200×825` on amazon or similar |
| `[parallel]` 7.8" (1872×1404px) display | waveshare / gooddisplay |  Search for `Waveshare 7.8" E-Paper 1872×1404` on amazon or similar |
| Raspberry Pi Zero W | Raspberry Pi |  Search for `Raspberry Pi Zero W` on amazon or similar |
| MicroSD card | Sandisk |  Search for `MicroSD card 8GB` on amazon or similar |
## Configuring the Raspberry Pi
Flash Raspberry Pi OS on your microSD card (min. 4GB) with [Raspberry Pi Imager](https://rptl.io/imager). Use the
following settings:
| option | value |
|:--------------------------|:---------------------------:|
| hostname | inkycal |
| enable ssh | yes |
| set username and password | yes |
| username | a username you like |
| password | a password you can remember |
| set Wi-Fi | yes |
| Wi-Fi SSID | your Wi-Fi name |
| Wi-Fi password | your Wi-Fi password |
| set timezone | your local timezone |
1. Create and download `settings.json` file for Inkycal from
the [WEB-UI](https://aceinnolab.com/inkycal/ui). Add the modules you want with the add
module button.
2. Copy the `settings.json` to the flashed microSD card.
3. Eject the microSD card from your computer now, insert it in the Raspberry Pi and power the Raspberry Pi.
4. Once the green LED has stopped blinking after ~3 minutes, you can connect to your Raspberry Pi via SSH using a SSH
Client. We suggest [Termius](https://termius.com/download/windows)
on your smartphone. Use the address: `inkycal.local` with the username and password you set earlier. For more
detailed instructions, check out the page from
the [Raspberry Pi website](https://www.raspberrypi.org/documentation/remote-access/ssh/)
5. After connecting via SSH, run the following commands, line by line:
```bash
sudo raspi-config --expand-rootfs
sudo sed -i s/#dtparam=spi=on/dtparam=spi=on/ /boot/config.txt
sudo dpkg-reconfigure tzdata
# If you have the 12.48" display, these steps are also required:
wget http://www.airspayce.com/mikem/bcm2835/bcm2835-1.71.tar.gz
tar zxvf bcm2835-1.71.tar.gz
cd bcm2835-1.71/
sudo ./configure && sudo make && sudo make check && sudo make install
wget https://project-downloads.drogon.net/wiringpi-latest.deb
sudo dpkg -i wiringpi-latest.deb
# If you are using the Raspberry Pi Zero models, you may need to increase the swapfile size to be able to install Inkycal:
sudo dphys-swapfile swapoff
sudo sed -i -E '/^CONF_SWAPSIZE=/s/=.*/=512/' /etc/dphys-swapfile
sudo dphys-swapfile setup
sudo dphys-swapfile swapon
```
These commands expand the filesystem, enable SPI and set up the correct timezone on the Raspberry Pi. When running the
last command, please select the continent you live in, press enter and then select the capital of the country you live
in. Lastly, press enter.
7. Follow the steps in `Installation` (see below) on how to install Inkycal.
## Installing Inkycal
⚠️ Please note that although the developers try to keep the installation as simple as possible, the full installation
can sometimes take hours on the Raspberry Pi Zero W and is not guaranteed to go smoothly each time. This is because
installing dependencies on the zero w takes a long time and is prone to copy-paste-, permission- and configuration
errors.
**Looking for a shortcut to safe a few hours?** We know about this problem and have spent a signifcant amount of time
to prepare a pre-configured image with the latest version of Inkycal for the Raspberry Pi Zero. It comes with the latest
version of Inkycal, is fully tested and uses the Raspberry Pi OS Lite as it's base image. You only need to copy your
settings.json file, we already took care of the rest, including auto-start at boot, enabling spi and installing all
dependencies in advance. Pretty neat right? Check the [sponsor button](https://github.com/sponsors/aceisace) at the very
top of the repo to get access to Inkycal-OS-Lite. Alternatively, you can also use the paypal.me link and send the same amount as Github sponsors to get access to InkycalOS-Lite!
This will help keep this project growing and cover the ongoing expenses too! Win-win for everyone! 🎊
### Manual installation
Run the following steps to install Inkycal. Do **not** use sudo for this, except where explicitly specified.
```bash
# the next line is for the Raspberry Pi only
sudo apt-get install zlib1g libjpeg-dev libatlas-base-dev rustc libopenjp2-7 python3-dev scons libssl-dev python3-venv python3-pip git libfreetype6-dev wkhtmltopdf
cd $HOME
git clone --branch main --single-branch https://github.com/aceinnolab/Inkycal
cd Inkycal
python3 -m venv venv
source venv/bin/activate
python -m pip install --upgrade pip
pip install wheel
pip install -e ./
# If you are running on the Raspberry Pi, please install the following too to allow rendering on the display
pip install RPi.GPIO==0.7.1 spidev==3.5 gpiozero==2.0
```
## Running Inkycal
To run Inkycal, type in the following command in the terminal:
```bash
cd $HOME/Inkycal
source venv/bin/activate
python3 inky_run.py
```
## Running on each boot
To make inkycal run on each boot automatically, you can use crontab. Do not use sudo for this
```bash
(crontab -l ; echo "@reboot sleep 60 && cd $HOME/Inkycal && venv/bin/python inky_run.py &")| crontab -
```
## Updating Inkycal
To update Inkycal to the latest version, navigate to the Inkycal folder, then run:
```bash
git pull
```
Yep. It's actually that simple!
But, if you have made changes to Inkycal, those will be overwritten.
If that is the case, backup your modified files somewhere else if you need them. Then run:
```bash
git reset --hard
git pull
```
## Uninstalling Inkycal
We'll miss you, but we don't want to make it hard for you to leave.
Just delete the Inkycal folder, and you're good to go!
Additionally, if you want to reset your crontab file, which runs inkycal at boot, run:
```bash
crontab -r
```
## Modifying Inkycal
Inkycal now runs in a virtual environment to support more devices than just the Raspberry Pi. Therefore, to make changes
to Inkycal, navigate to Inkycal, then run:
```bash
cd $HOME/Inkycal && source venv/bin/activate
```
Then modify the files as needed and experiment with Inkycal.
To deactivate the virtual environment, simply run:
```bash
deactivate
```
## 3D printed frames
With your setup being complete at this stage, you may want to 3d-print a case. The following files were shared by our
friendly community:
[3D-printable case](https://github.com/aceinnolab/Inkycal/wiki/3D-printable-files)
## Contributing
All sorts of contributions are most welcome and appreciated. To start contributing, please follow
the [Contribution Guidelines](https://github.com/aceisace/Inkycal/blob/main/.github/CONTRIBUTING.md)
The average response time for issues, PRs and emails is usually 24 hours. In some cases, it might be longer. If you want
to have some faster responses, please use Discord (link below)
**P.S:** Don't forget to star and/or watch the repo. For those who have done so already, thank you very much!
## Join us on Discord!
We're happy to help, to beginners and developers alike. In fact, you are more likely to get faster support on Discord
than on Github.
<a href="https://discord.gg/sHYKeSM">
<img src="https://github.com/aceisace/Inkycal/blob/assets/Repo/discord-logo.png?raw=true" alt="Inkycal chatroom Discord" width=200>
</a>
## Sponsoring
Inkycal relies on sponsors to keep up maintainance, development and bug-fixing. Please consider sponsoring Inkycal via
the sponsor button if you are happy with Inkycal.
We now offer perks depending on the amount contributed for sponsoring, ranging from pre-configured OS images for
plug-and-play to development of user-suggested modules. Check out the sponsor page to find out more.
If you have been a previous sponsor, please let us know on our Dicord server or by sending an email. We'll send you the
perks after confirming 💯
## As featured on
* [raspberrypi.com](https://www.raspberrypi.com/news/ashleys-top-five-projects-for-raspberry-pi-first-timers/)
* [hackster.io](https://www.hackster.io/news/ace-innovation-lab-s-inkycal-v3-puts-a-raspberry-pi-powered-modular-epaper-dashboard-on-your-desk-b55a83cc0f46)
* [raspberryme.com](https://www.raspberryme.com/inkycal-v3-est-un-tableau-de-bord-epaper-alimente-par-raspberry-pi-pour-votre-bureau/)
* [adafruit.com](https://blog.adafruit.com/2023/12/19/icymi-python-on-microcontrollers-newsletter-circuitpython-9-alpha-6-released-gpt-via-circuitpython-new-books-and-more-circuitpython-python-micropython-icymi-raspberry_pi/)
* [ittagesschau.de](https://www.ittagesschau.de/artikel/inkycal-v3-smartes-display-auf-grundlage-des-raspberry-pi-mit-elektronischem-papier-und-vielen-moglichkeiten_365893)
* [makeuseof - fantastic projects using an eink display](http://makeuseof.com/fantastic-projects-using-an-e-ink-display/)
* [notebookcheck.com](https://www.notebookcheck.com/Inkycal-V3-Smartes-Display-auf-Grundlage-des-Raspberry-Pi-mit-elektronischem-Papier-und-vielen-Moeglichkeiten.783012.0.html?ref=ittagesschau.de)
* [linkedin.com](https://www.linkedin.com/pulse/global-epaper-industry-weekly-bulletin-16epaper-jtcqe?trk=article-ssr-frontend-pulse_more-articles_related-content-card)
* [sohu.com](https://www.sohu.com/a/745630839_121311165)
* [moreware.com](https://www.moreware.org/wp/blog/2023/12/18/inkycal-v3-dashboard-con-display-e-paper-e-raspberry-pi/)
* [Waveshare - additional resources](https://www.waveshare.com/wiki/7.5inch_HD_e-Paper_HAT)
* [ereaderpro.co.uk](https://www.ereaderpro.co.uk/blogs/news/e-ink-product-made-in-germany-inkycal-v3)
* [cnx-software.com](https://www.cnx-software.com/2023/12/13/inkycal-v3-is-a-raspberry-pi-powered-epaper-dashboard-for-your-desk/)
* [magpi.de](https://www.magpi.de/news/maginkcal-ein-kalender-mit-epaper-display-und-raspberry-pi)
* [goodreader.com](https://goodereader.com/blog/e-paper/inkycal-v3-is-a-raspberry-pi-powered-e-paper-marvel-for-your-desk)
* [goodreader.com](https://goodereader.com/blog/e-paper/five-of-the-most-innovative-e-ink-display-projects?doing_wp_cron=1701869793.2312469482421875000000)
* [reddit - Inkycal](https://www.reddit.com/r/InkyCal/)
* [schuemann.it](https://schuemann.it/2019/09/11/e-ink-calendar-with-a-raspberry-pi/)
* [huernerfuerst.de](https://www.huenerfuerst.de/archives/e-ink-kalender-mit-einem-raspberry-pi-zero-teil-1-was-wird-benoetigt)
* [canox.net](https://canox.net/2019/06/raspberry-pi-als-e-ink-kalender/)

View File

@ -13,23 +13,6 @@ Display
:members: :members:
Modules
===========================
- Agenda
.. automodule:: inkycal.modules.inkycal_agenda.Agenda
:members:
- Calendar
.. automodule:: inkycal.modules.inkycal_calendar.Calendar
:members:
- Feeds Module (RSS & Atom)
.. automodule:: inkycal.modules.inkycal_feeds.Feeds
:members:
Custom functions Custom functions
=========================== ===========================
.. automodule:: inkycal.custom.functions .. automodule:: inkycal.custom.functions

View File

@ -49,7 +49,6 @@
<ul class="current"> <ul class="current">
<li class="toctree-l1"><a class="reference internal" href="inkycal.html">Inkycal</a></li> <li class="toctree-l1"><a class="reference internal" href="inkycal.html">Inkycal</a></li>
<li class="toctree-l1"><a class="reference internal" href="inkycal.html#module-inkycal.display.Display">Display</a></li> <li class="toctree-l1"><a class="reference internal" href="inkycal.html#module-inkycal.display.Display">Display</a></li>
<li class="toctree-l1"><a class="reference internal" href="inkycal.html#modules">Modules</a></li>
<li class="toctree-l1"><a class="reference internal" href="inkycal.html#module-inkycal.custom.functions">Custom functions</a></li> <li class="toctree-l1"><a class="reference internal" href="inkycal.html#module-inkycal.custom.functions">Custom functions</a></li>
<li class="toctree-l1"><a class="reference internal" href="inkycal.html#module-inkycal.modules.ical_parser">Helper classes</a></li> <li class="toctree-l1"><a class="reference internal" href="inkycal.html#module-inkycal.modules.ical_parser">Helper classes</a></li>
<li class="toctree-l1 current"><a class="current reference internal" href="#">About Inkycal</a></li> <li class="toctree-l1 current"><a class="current reference internal" href="#">About Inkycal</a></li>

View File

@ -48,7 +48,6 @@
<ul class="current"> <ul class="current">
<li class="toctree-l1"><a class="reference internal" href="inkycal.html">Inkycal</a></li> <li class="toctree-l1"><a class="reference internal" href="inkycal.html">Inkycal</a></li>
<li class="toctree-l1"><a class="reference internal" href="inkycal.html#module-inkycal.display.Display">Display</a></li> <li class="toctree-l1"><a class="reference internal" href="inkycal.html#module-inkycal.display.Display">Display</a></li>
<li class="toctree-l1"><a class="reference internal" href="inkycal.html#modules">Modules</a></li>
<li class="toctree-l1"><a class="reference internal" href="inkycal.html#module-inkycal.custom.functions">Custom functions</a></li> <li class="toctree-l1"><a class="reference internal" href="inkycal.html#module-inkycal.custom.functions">Custom functions</a></li>
<li class="toctree-l1"><a class="reference internal" href="inkycal.html#module-inkycal.modules.ical_parser">Helper classes</a></li> <li class="toctree-l1"><a class="reference internal" href="inkycal.html#module-inkycal.modules.ical_parser">Helper classes</a></li>
<li class="toctree-l1"><a class="reference internal" href="about.html">About Inkycal</a></li> <li class="toctree-l1"><a class="reference internal" href="about.html">About Inkycal</a></li>

View File

@ -46,7 +46,6 @@
<ul> <ul>
<li class="toctree-l1"><a class="reference internal" href="inkycal.html">Inkycal</a></li> <li class="toctree-l1"><a class="reference internal" href="inkycal.html">Inkycal</a></li>
<li class="toctree-l1"><a class="reference internal" href="inkycal.html#module-inkycal.display.Display">Display</a></li> <li class="toctree-l1"><a class="reference internal" href="inkycal.html#module-inkycal.display.Display">Display</a></li>
<li class="toctree-l1"><a class="reference internal" href="inkycal.html#modules">Modules</a></li>
<li class="toctree-l1"><a class="reference internal" href="inkycal.html#module-inkycal.custom.functions">Custom functions</a></li> <li class="toctree-l1"><a class="reference internal" href="inkycal.html#module-inkycal.custom.functions">Custom functions</a></li>
<li class="toctree-l1"><a class="reference internal" href="inkycal.html#module-inkycal.modules.ical_parser">Helper classes</a></li> <li class="toctree-l1"><a class="reference internal" href="inkycal.html#module-inkycal.modules.ical_parser">Helper classes</a></li>
<li class="toctree-l1"><a class="reference internal" href="about.html">About Inkycal</a></li> <li class="toctree-l1"><a class="reference internal" href="about.html">About Inkycal</a></li>
@ -188,6 +187,8 @@
<li><a href="inkycal.html#module-inkycal.main">module</a> <li><a href="inkycal.html#module-inkycal.main">module</a>
</li> </li>
</ul></li> </ul></li>
</ul></td>
<td style="width: 33%; vertical-align: top;"><ul>
<li> <li>
inkycal.modules.ical_parser inkycal.modules.ical_parser
@ -195,34 +196,11 @@
<li><a href="inkycal.html#module-inkycal.modules.ical_parser">module</a> <li><a href="inkycal.html#module-inkycal.modules.ical_parser">module</a>
</li> </li>
</ul></li> </ul></li>
</ul></td>
<td style="width: 33%; vertical-align: top;"><ul>
<li> <li>
inkycal.modules.inky_image inkycal.modules.inky_image
<ul> <ul>
<li><a href="inkycal.html#module-inkycal.modules.inky_image">module</a> <li><a href="inkycal.html#module-inkycal.modules.inky_image">module</a>
</li>
</ul></li>
<li>
inkycal.modules.inkycal_agenda.Agenda
<ul>
<li><a href="inkycal.html#module-inkycal.modules.inkycal_agenda.Agenda">module</a>
</li>
</ul></li>
<li>
inkycal.modules.inkycal_calendar.Calendar
<ul>
<li><a href="inkycal.html#module-inkycal.modules.inkycal_calendar.Calendar">module</a>
</li>
</ul></li>
<li>
inkycal.modules.inkycal_feeds.Feeds
<ul>
<li><a href="inkycal.html#module-inkycal.modules.inkycal_feeds.Feeds">module</a>
</li> </li>
</ul></li> </ul></li>
<li><a href="inkycal.html#inkycal.modules.inky_image.Inkyimage">Inkyimage (class in inkycal.modules.inky_image)</a> <li><a href="inkycal.html#inkycal.modules.inky_image.Inkyimage">Inkyimage (class in inkycal.modules.inky_image)</a>
@ -264,12 +242,6 @@
<li><a href="inkycal.html#module-inkycal.modules.ical_parser">inkycal.modules.ical_parser</a> <li><a href="inkycal.html#module-inkycal.modules.ical_parser">inkycal.modules.ical_parser</a>
</li> </li>
<li><a href="inkycal.html#module-inkycal.modules.inky_image">inkycal.modules.inky_image</a> <li><a href="inkycal.html#module-inkycal.modules.inky_image">inkycal.modules.inky_image</a>
</li>
<li><a href="inkycal.html#module-inkycal.modules.inkycal_agenda.Agenda">inkycal.modules.inkycal_agenda.Agenda</a>
</li>
<li><a href="inkycal.html#module-inkycal.modules.inkycal_calendar.Calendar">inkycal.modules.inkycal_calendar.Calendar</a>
</li>
<li><a href="inkycal.html#module-inkycal.modules.inkycal_feeds.Feeds">inkycal.modules.inkycal_feeds.Feeds</a>
</li> </li>
</ul></li> </ul></li>
</ul></td> </ul></td>

View File

@ -48,7 +48,6 @@
<ul> <ul>
<li class="toctree-l1"><a class="reference internal" href="inkycal.html">Inkycal</a></li> <li class="toctree-l1"><a class="reference internal" href="inkycal.html">Inkycal</a></li>
<li class="toctree-l1"><a class="reference internal" href="inkycal.html#module-inkycal.display.Display">Display</a></li> <li class="toctree-l1"><a class="reference internal" href="inkycal.html#module-inkycal.display.Display">Display</a></li>
<li class="toctree-l1"><a class="reference internal" href="inkycal.html#modules">Modules</a></li>
<li class="toctree-l1"><a class="reference internal" href="inkycal.html#module-inkycal.custom.functions">Custom functions</a></li> <li class="toctree-l1"><a class="reference internal" href="inkycal.html#module-inkycal.custom.functions">Custom functions</a></li>
<li class="toctree-l1"><a class="reference internal" href="inkycal.html#module-inkycal.modules.ical_parser">Helper classes</a></li> <li class="toctree-l1"><a class="reference internal" href="inkycal.html#module-inkycal.modules.ical_parser">Helper classes</a></li>
<li class="toctree-l1"><a class="reference internal" href="about.html">About Inkycal</a></li> <li class="toctree-l1"><a class="reference internal" href="about.html">About Inkycal</a></li>
@ -91,7 +90,6 @@
</ul> </ul>
</li> </li>
<li class="toctree-l1"><a class="reference internal" href="inkycal.html#module-inkycal.display.Display">Display</a></li> <li class="toctree-l1"><a class="reference internal" href="inkycal.html#module-inkycal.display.Display">Display</a></li>
<li class="toctree-l1"><a class="reference internal" href="inkycal.html#modules">Modules</a></li>
<li class="toctree-l1"><a class="reference internal" href="inkycal.html#module-inkycal.custom.functions">Custom functions</a><ul> <li class="toctree-l1"><a class="reference internal" href="inkycal.html#module-inkycal.custom.functions">Custom functions</a><ul>
<li class="toctree-l2"><a class="reference internal" href="inkycal.html#inkycal.custom.functions.auto_fontsize"><code class="docutils literal notranslate"><span class="pre">auto_fontsize()</span></code></a></li> <li class="toctree-l2"><a class="reference internal" href="inkycal.html#inkycal.custom.functions.auto_fontsize"><code class="docutils literal notranslate"><span class="pre">auto_fontsize()</span></code></a></li>
<li class="toctree-l2"><a class="reference internal" href="inkycal.html#inkycal.custom.functions.draw_border"><code class="docutils literal notranslate"><span class="pre">draw_border()</span></code></a></li> <li class="toctree-l2"><a class="reference internal" href="inkycal.html#inkycal.custom.functions.draw_border"><code class="docutils literal notranslate"><span class="pre">draw_border()</span></code></a></li>

View File

@ -58,7 +58,6 @@
</ul> </ul>
</li> </li>
<li class="toctree-l1"><a class="reference internal" href="#module-inkycal.display.Display">Display</a></li> <li class="toctree-l1"><a class="reference internal" href="#module-inkycal.display.Display">Display</a></li>
<li class="toctree-l1"><a class="reference internal" href="#modules">Modules</a></li>
<li class="toctree-l1"><a class="reference internal" href="#module-inkycal.custom.functions">Custom functions</a><ul> <li class="toctree-l1"><a class="reference internal" href="#module-inkycal.custom.functions">Custom functions</a><ul>
<li class="toctree-l2"><a class="reference internal" href="#inkycal.custom.functions.auto_fontsize"><code class="docutils literal notranslate"><span class="pre">auto_fontsize()</span></code></a></li> <li class="toctree-l2"><a class="reference internal" href="#inkycal.custom.functions.auto_fontsize"><code class="docutils literal notranslate"><span class="pre">auto_fontsize()</span></code></a></li>
<li class="toctree-l2"><a class="reference internal" href="#inkycal.custom.functions.draw_border"><code class="docutils literal notranslate"><span class="pre">draw_border()</span></code></a></li> <li class="toctree-l2"><a class="reference internal" href="#inkycal.custom.functions.draw_border"><code class="docutils literal notranslate"><span class="pre">draw_border()</span></code></a></li>
@ -195,24 +194,6 @@ rendering images and calibrating the E-Paper display</p>
</dd> </dd>
</dl> </dl>
</section> </section>
<section id="modules">
<h1>Modules<a class="headerlink" href="#modules" title="Link to this heading"></a></h1>
<ul class="simple">
<li><p>Agenda</p></li>
</ul>
<p id="module-inkycal.modules.inkycal_agenda.Agenda">Agenda class
Create agenda and show events from given icalendars</p>
<ul class="simple">
<li><p>Calendar</p></li>
</ul>
<p id="module-inkycal.modules.inkycal_calendar.Calendar">Calendar class
Create monthly calendar and show events from given icalendars</p>
<ul class="simple">
<li><p>Feeds Module (RSS &amp; Atom)</p></li>
</ul>
<p id="module-inkycal.modules.inkycal_feeds.Feeds">RSS class
parses rss/atom feeds from given urls</p>
</section>
<section id="module-inkycal.custom.functions"> <section id="module-inkycal.custom.functions">
<span id="custom-functions"></span><h1>Custom functions<a class="headerlink" href="#module-inkycal.custom.functions" title="Link to this heading"></a></h1> <span id="custom-functions"></span><h1>Custom functions<a class="headerlink" href="#module-inkycal.custom.functions" title="Link to this heading"></a></h1>
<p>Inkycal custom-functions for ease-of-use</p> <p>Inkycal custom-functions for ease-of-use</p>
@ -567,6 +548,7 @@ white pixels.</p>
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="s1">&#39;bwr&#39;</span> <span class="c1"># black-white-red</span> <div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="s1">&#39;bwr&#39;</span> <span class="c1"># black-white-red</span>
<span class="gp">&gt;&gt;&gt; </span><span class="s1">&#39;bwy&#39;</span> <span class="c1"># black-white-yellow</span> <span class="gp">&gt;&gt;&gt; </span><span class="s1">&#39;bwy&#39;</span> <span class="c1"># black-white-yellow</span>
<span class="gp">&gt;&gt;&gt; </span><span class="s1">&#39;bw&#39;</span> <span class="c1"># black-white</span> <span class="gp">&gt;&gt;&gt; </span><span class="s1">&#39;bw&#39;</span> <span class="c1"># black-white</span>
<span class="gp">&gt;&gt;&gt; </span><span class="s1">&#39;16gray&#39;</span> <span class="c1"># 16 shades of gray</span>
</pre></div> </pre></div>
</div> </div>
</dd></dl> </dd></dl>

Binary file not shown.

View File

@ -49,7 +49,6 @@
<ul> <ul>
<li class="toctree-l1"><a class="reference internal" href="inkycal.html">Inkycal</a></li> <li class="toctree-l1"><a class="reference internal" href="inkycal.html">Inkycal</a></li>
<li class="toctree-l1"><a class="reference internal" href="inkycal.html#module-inkycal.display.Display">Display</a></li> <li class="toctree-l1"><a class="reference internal" href="inkycal.html#module-inkycal.display.Display">Display</a></li>
<li class="toctree-l1"><a class="reference internal" href="inkycal.html#modules">Modules</a></li>
<li class="toctree-l1"><a class="reference internal" href="inkycal.html#module-inkycal.custom.functions">Custom functions</a></li> <li class="toctree-l1"><a class="reference internal" href="inkycal.html#module-inkycal.custom.functions">Custom functions</a></li>
<li class="toctree-l1"><a class="reference internal" href="inkycal.html#module-inkycal.modules.ical_parser">Helper classes</a></li> <li class="toctree-l1"><a class="reference internal" href="inkycal.html#module-inkycal.modules.ical_parser">Helper classes</a></li>
<li class="toctree-l1"><a class="reference internal" href="about.html">About Inkycal</a></li> <li class="toctree-l1"><a class="reference internal" href="about.html">About Inkycal</a></li>
@ -122,21 +121,6 @@
<td>&#160;&#160;&#160; <td>&#160;&#160;&#160;
<a href="inkycal.html#module-inkycal.modules.inky_image"><code class="xref">inkycal.modules.inky_image</code></a></td><td> <a href="inkycal.html#module-inkycal.modules.inky_image"><code class="xref">inkycal.modules.inky_image</code></a></td><td>
<em></em></td></tr> <em></em></td></tr>
<tr class="cg-1">
<td></td>
<td>&#160;&#160;&#160;
<a href="inkycal.html#module-inkycal.modules.inkycal_agenda.Agenda"><code class="xref">inkycal.modules.inkycal_agenda.Agenda</code></a></td><td>
<em></em></td></tr>
<tr class="cg-1">
<td></td>
<td>&#160;&#160;&#160;
<a href="inkycal.html#module-inkycal.modules.inkycal_calendar.Calendar"><code class="xref">inkycal.modules.inkycal_calendar.Calendar</code></a></td><td>
<em></em></td></tr>
<tr class="cg-1">
<td></td>
<td>&#160;&#160;&#160;
<a href="inkycal.html#module-inkycal.modules.inkycal_feeds.Feeds"><code class="xref">inkycal.modules.inkycal_feeds.Feeds</code></a></td><td>
<em></em></td></tr>
</table> </table>

View File

@ -49,7 +49,6 @@
<ul class="current"> <ul class="current">
<li class="toctree-l1"><a class="reference internal" href="inkycal.html">Inkycal</a></li> <li class="toctree-l1"><a class="reference internal" href="inkycal.html">Inkycal</a></li>
<li class="toctree-l1"><a class="reference internal" href="inkycal.html#module-inkycal.display.Display">Display</a></li> <li class="toctree-l1"><a class="reference internal" href="inkycal.html#module-inkycal.display.Display">Display</a></li>
<li class="toctree-l1"><a class="reference internal" href="inkycal.html#modules">Modules</a></li>
<li class="toctree-l1"><a class="reference internal" href="inkycal.html#module-inkycal.custom.functions">Custom functions</a></li> <li class="toctree-l1"><a class="reference internal" href="inkycal.html#module-inkycal.custom.functions">Custom functions</a></li>
<li class="toctree-l1"><a class="reference internal" href="inkycal.html#module-inkycal.modules.ical_parser">Helper classes</a></li> <li class="toctree-l1"><a class="reference internal" href="inkycal.html#module-inkycal.modules.ical_parser">Helper classes</a></li>
<li class="toctree-l1"><a class="reference internal" href="about.html">About Inkycal</a></li> <li class="toctree-l1"><a class="reference internal" href="about.html">About Inkycal</a></li>

View File

@ -49,7 +49,6 @@
<ul> <ul>
<li class="toctree-l1"><a class="reference internal" href="inkycal.html">Inkycal</a></li> <li class="toctree-l1"><a class="reference internal" href="inkycal.html">Inkycal</a></li>
<li class="toctree-l1"><a class="reference internal" href="inkycal.html#module-inkycal.display.Display">Display</a></li> <li class="toctree-l1"><a class="reference internal" href="inkycal.html#module-inkycal.display.Display">Display</a></li>
<li class="toctree-l1"><a class="reference internal" href="inkycal.html#modules">Modules</a></li>
<li class="toctree-l1"><a class="reference internal" href="inkycal.html#module-inkycal.custom.functions">Custom functions</a></li> <li class="toctree-l1"><a class="reference internal" href="inkycal.html#module-inkycal.custom.functions">Custom functions</a></li>
<li class="toctree-l1"><a class="reference internal" href="inkycal.html#module-inkycal.modules.ical_parser">Helper classes</a></li> <li class="toctree-l1"><a class="reference internal" href="inkycal.html#module-inkycal.modules.ical_parser">Helper classes</a></li>
<li class="toctree-l1"><a class="reference internal" href="about.html">About Inkycal</a></li> <li class="toctree-l1"><a class="reference internal" href="about.html">About Inkycal</a></li>

File diff suppressed because one or more lines are too long

View File

@ -13,23 +13,6 @@ Display
:members: :members:
Modules
===========================
- Agenda
.. automodule:: inkycal.modules.inkycal_agenda.Agenda
:members:
- Calendar
.. automodule:: inkycal.modules.inkycal_calendar.Calendar
:members:
- Feeds Module (RSS & Atom)
.. automodule:: inkycal.modules.inkycal_feeds.Feeds
:members:
Custom functions Custom functions
=========================== ===========================
.. automodule:: inkycal.custom.functions .. automodule:: inkycal.custom.functions

View File

@ -8,6 +8,7 @@ import os
import time import time
import traceback import traceback
import PIL
import requests import requests
from PIL import ImageFont, ImageDraw, Image from PIL import ImageFont, ImageDraw, Image
@ -335,7 +336,7 @@ def draw_border(image, xy, size, radius=5, thickness=1, shrinkage=(0.1, 0.1)):
draw.arc((c7, c8), 90, 180, fill=colour, width=thickness) draw.arc((c7, c8), 90, 180, fill=colour, width=thickness)
def draw_border_2(im: Image, xy: tuple, size: tuple, radius: int): def draw_border_2(im: PIL.Image, xy: tuple, size: tuple, radius: int):
draw = ImageDraw.Draw(im) draw = ImageDraw.Draw(im)
x, y = xy x, y = xy

View File

@ -1,4 +1,3 @@
#!python3
""" """
Inkycal custom Exceptions Inkycal custom Exceptions
""" """

View File

@ -2,18 +2,21 @@
Inkycal ePaper driving functions Inkycal ePaper driving functions
Copyright by aceisace Copyright by aceisace
""" """
import os
import logging import logging
import os
import traceback import traceback
from importlib import import_module from importlib import import_module
import PIL
from PIL import Image from PIL import Image
from inkycal.custom import top_level from inkycal.custom import top_level
import glob
def import_driver(model): def import_driver(model):
return import_module(f'inkycal.display.drivers.{model}') return import_module(f'inkycal.display.drivers.{model}')
class Display: class Display:
"""Display class for inkycal """Display class for inkycal
@ -44,7 +47,14 @@ class Display:
except FileNotFoundError: except FileNotFoundError:
raise Exception('SPI could not be found. Please check if SPI is enabled') raise Exception('SPI could not be found. Please check if SPI is enabled')
def render(self, im_black: Image, im_colour:Image or None=None) -> None:
def test(self) -> None:
"""Test the display by showing a test image"""
# TODO implement test image
raise NotImplementedError("Devs were too lazy again, sorry, please try again later")
def render(self, im_black: PIL.Image, im_colour: PIL.Image or None=None) -> None:
"""Renders an image on the selected E-Paper display. """Renders an image on the selected E-Paper display.
Initlializes the E-Paper display, sends image data and executes command Initlializes the E-Paper display, sends image data and executes command

View File

@ -1,13 +1,13 @@
#!python3
""" """
10.3" driver class 10.3" driver class
Copyright by aceinnolab Copyright by aceinnolab
""" """
from subprocess import run from subprocess import run
from inkycal.custom import image_folder, top_level
from os.path import exists
from PIL import Image from PIL import Image
from inkycal.custom import image_folder, top_level
# Display resolution # Display resolution
EPD_WIDTH = 1872 EPD_WIDTH = 1872
EPD_HEIGHT = 1404 EPD_HEIGHT = 1404
@ -19,6 +19,7 @@ driver_dir = top_level + '/inkycal/display/drivers/parallel_drivers/'
command = f'sudo {driver_dir}epd -{VCOM} 0 {image_folder + "canvas.bmp"}' command = f'sudo {driver_dir}epd -{VCOM} 0 {image_folder + "canvas.bmp"}'
class EPD: class EPD:
def __init__(self): def __init__(self):
@ -38,7 +39,7 @@ class EPD:
def getbuffer(self, image): def getbuffer(self, image):
"""ad-hoc""" """ad-hoc"""
image = image.rotate(90, expand=True) image = image.rotate(90, expand=True).transpose(Image.FLIP_LEFT_RIGHT)
image.convert('RGB').save(image_folder + 'canvas.bmp', 'BMP') image.convert('RGB').save(image_folder + 'canvas.bmp', 'BMP')
command = f'sudo {driver_dir}epd -{VCOM} 0 {image_folder + "canvas.bmp"}' command = f'sudo {driver_dir}epd -{VCOM} 0 {image_folder + "canvas.bmp"}'
print(command) print(command)

View File

@ -1,12 +1,10 @@
#!python3
""" """
7.8" parallel driver class 7.8" parallel driver class
Copyright by aceinnolab Copyright by aceinnolab
""" """
from subprocess import run from subprocess import run
from inkycal.custom import image_folder, top_level from inkycal.custom import image_folder, top_level
from os.path import exists
from PIL import Image
# Display resolution # Display resolution
EPD_WIDTH = 1872 EPD_WIDTH = 1872

View File

@ -1,12 +1,10 @@
#!python3
""" """
9.7" driver class 9.7" driver class
Copyright by aceinnolab Copyright by aceinnolab
""" """
from subprocess import run from subprocess import run
from inkycal.custom import image_folder, top_level from inkycal.custom import image_folder, top_level
from os.path import exists
from PIL import Image
# Display resolution # Display resolution
EPD_WIDTH = 1200 EPD_WIDTH = 1200

View File

@ -1,42 +1,43 @@
# ***************************************************************************** """
# * | File : epd5in83b_V2.py * | File : epd5in83b_V2.py
# * | Author : Waveshare team * | Author : Waveshare team
# * | Function : Electronic paper driver * | Function : Electronic paper driver
# * | Info : * | Info :
# *---------------- *----------------
# * | This version: V1.1 * | This version: V1.1
# * | Date : 2022-08-10 * | Date : 2022-08-10
# # | Info : python demo # | Info : python demo
# ----------------------------------------------------------------------------- -----------------------------------------------------------------------------
# Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documnetation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
# furished to do so, subject to the following conditions: furished 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 OR 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.
#
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 OR 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.
"""
import logging import logging
from . import epdconfig from . import epdconfig
# Display resolution # Display resolution
EPD_WIDTH = 648 EPD_WIDTH = 648
EPD_HEIGHT = 480 EPD_HEIGHT = 480
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class EPD: class EPD:
def __init__(self): def __init__(self):
self.reset_pin = epdconfig.RST_PIN self.reset_pin = epdconfig.RST_PIN
@ -77,7 +78,7 @@ class EPD:
def ReadBusy(self): def ReadBusy(self):
logger.debug("e-Paper busy") logger.debug("e-Paper busy")
self.send_command(0X71) self.send_command(0X71)
while(epdconfig.digital_read(self.busy_pin) == 0): # 0: idle, 1: busy while (epdconfig.digital_read(self.busy_pin) == 0): # 0: idle, 1: busy
self.send_command(0X71) self.send_command(0X71)
epdconfig.delay_ms(200) epdconfig.delay_ms(200)
logger.debug("e-Paper busy release") logger.debug("e-Paper busy release")
@ -88,59 +89,59 @@ class EPD:
self.reset() self.reset()
self.send_command(0x01) #POWER SETTING self.send_command(0x01) # POWER SETTING
self.send_data (0x07) self.send_data(0x07)
self.send_data (0x07) #VGH=20V,VGL=-20V self.send_data(0x07) # VGH=20V,VGL=-20V
self.send_data (0x3f) #VDH=15V self.send_data(0x3f) # VDH=15V
self.send_data (0x3f) #VDL=-15V self.send_data(0x3f) # VDL=-15V
self.send_command(0x04) #POWER ON self.send_command(0x04) # POWER ON
epdconfig.delay_ms(100) epdconfig.delay_ms(100)
self.ReadBusy() #waiting for the electronic paper IC to release the idle signal self.ReadBusy() # waiting for the electronic paper IC to release the idle signal
self.send_command(0X00) #PANNEL SETTING self.send_command(0X00) # PANNEL SETTING
self.send_data(0x0F) #KW-3f KWR-2F BWROTP 0f BWOTP 1f self.send_data(0x0F) # KW-3f KWR-2F BWROTP 0f BWOTP 1f
self.send_command(0x61) #tres self.send_command(0x61) # tres
self.send_data (0x02) #source 648 self.send_data(0x02) # source 648
self.send_data (0x88) self.send_data(0x88)
self.send_data (0x01) #gate 480 self.send_data(0x01) # gate 480
self.send_data (0xe0) self.send_data(0xe0)
self.send_command(0X15) self.send_command(0X15)
self.send_data(0x00) self.send_data(0x00)
self.send_command(0X50) #VCOM AND DATA INTERVAL SETTING self.send_command(0X50) # VCOM AND DATA INTERVAL SETTING
self.send_data(0x11) self.send_data(0x11)
self.send_data(0x07) self.send_data(0x07)
self.send_command(0X60) #TCON SETTING self.send_command(0X60) # TCON SETTING
self.send_data(0x22) self.send_data(0x22)
return 0 return 0
def getbuffer(self, image): def getbuffer(self, image):
# logger.debug("bufsiz = ",int(self.width/8) * self.height) # logger.debug("bufsiz = ",int(self.width/8) * self.height)
buf = [0xFF] * (int(self.width/8) * self.height) buf = [0xFF] * (int(self.width / 8) * self.height)
image_monocolor = image.convert('1') image_monocolor = image.convert('1')
imwidth, imheight = image_monocolor.size imwidth, imheight = image_monocolor.size
pixels = image_monocolor.load() pixels = image_monocolor.load()
# logger.debug("imwidth = %d, imheight = %d",imwidth,imheight) # logger.debug("imwidth = %d, imheight = %d",imwidth,imheight)
if(imwidth == self.width and imheight == self.height): if (imwidth == self.width and imheight == self.height):
logger.debug("Vertical") logger.debug("Vertical")
for y in range(imheight): for y in range(imheight):
for x in range(imwidth): for x in range(imwidth):
# Set the bits for the column of pixels at the current position. # Set the bits for the column of pixels at the current position.
if pixels[x, y] == 0: if pixels[x, y] == 0:
buf[int((x + y * self.width) / 8)] &= ~(0x80 >> (x % 8)) buf[int((x + y * self.width) / 8)] &= ~(0x80 >> (x % 8))
elif(imwidth == self.height and imheight == self.width): elif (imwidth == self.height and imheight == self.width):
logger.debug("Horizontal") logger.debug("Horizontal")
for y in range(imheight): for y in range(imheight):
for x in range(imwidth): for x in range(imwidth):
newx = y newx = y
newy = self.height - x - 1 newy = self.height - x - 1
if pixels[x, y] == 0: if pixels[x, y] == 0:
buf[int((newx + newy*self.width) / 8)] &= ~(0x80 >> (y % 8)) buf[int((newx + newy * self.width) / 8)] &= ~(0x80 >> (y % 8))
return buf return buf
def display(self, imageblack, imagered): def display(self, imageblack, imagered):
@ -170,9 +171,9 @@ class EPD:
self.ReadBusy() self.ReadBusy()
def sleep(self): def sleep(self):
self.send_command(0X02) # power off self.send_command(0X02) # power off
self.ReadBusy() self.ReadBusy()
self.send_command(0X07) # deep sleep self.send_command(0X07) # deep sleep
self.send_data(0xA5) self.send_data(0xA5)
epdconfig.delay_ms(2000) epdconfig.delay_ms(2000)

View File

@ -1,57 +1,59 @@
# /***************************************************************************** """
# * | File : epd12in48.py * | File : epd12in48.py
# * | Author : Waveshare electrices * | Author : Waveshare electrices
# * | Function : Hardware underlying interface * | Function : Hardware underlying interface
# * | Info : * | Info :
# *---------------- *----------------
# * | This version: V1.0 * | This version: V1.0
# * | Date : 2019-11-01 * | Date : 2019-11-01
# * | Info : * | Info :
# ******************************************************************************/ ******************************************************************************/
# Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documnetation files (the "Software"), to deal of this software and associated documnetation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
# furished to do so, subject to the following conditions: furished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software. all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 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 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE. THE SOFTWARE.
# """
import time import time
from inkycal.display.drivers import epdconfig_12_in_48 as epdconfig from inkycal.display.drivers import epdconfig_12_in_48 as epdconfig
EPD_WIDTH = 1304 EPD_WIDTH = 1304
EPD_HEIGHT = 984 EPD_HEIGHT = 984
class EPD(object): class EPD(object):
def __init__(self): def __init__(self):
self.width = EPD_WIDTH self.width = EPD_WIDTH
self.height = EPD_HEIGHT self.height = EPD_HEIGHT
self.EPD_M1_CS_PIN = epdconfig.EPD_M1_CS_PIN self.EPD_M1_CS_PIN = epdconfig.EPD_M1_CS_PIN
self.EPD_S1_CS_PIN = epdconfig.EPD_S1_CS_PIN self.EPD_S1_CS_PIN = epdconfig.EPD_S1_CS_PIN
self.EPD_M2_CS_PIN = epdconfig.EPD_M2_CS_PIN self.EPD_M2_CS_PIN = epdconfig.EPD_M2_CS_PIN
self.EPD_S2_CS_PIN = epdconfig.EPD_S2_CS_PIN self.EPD_S2_CS_PIN = epdconfig.EPD_S2_CS_PIN
self.EPD_M1S1_DC_PIN = epdconfig.EPD_M1S1_DC_PIN self.EPD_M1S1_DC_PIN = epdconfig.EPD_M1S1_DC_PIN
self.EPD_M2S2_DC_PIN = epdconfig.EPD_M2S2_DC_PIN self.EPD_M2S2_DC_PIN = epdconfig.EPD_M2S2_DC_PIN
self.EPD_M1S1_RST_PIN = epdconfig.EPD_M1S1_RST_PIN self.EPD_M1S1_RST_PIN = epdconfig.EPD_M1S1_RST_PIN
self.EPD_M2S2_RST_PIN = epdconfig.EPD_M2S2_RST_PIN self.EPD_M2S2_RST_PIN = epdconfig.EPD_M2S2_RST_PIN
self.EPD_M1_BUSY_PIN = epdconfig.EPD_M1_BUSY_PIN self.EPD_M1_BUSY_PIN = epdconfig.EPD_M1_BUSY_PIN
self.EPD_S1_BUSY_PIN = epdconfig.EPD_S1_BUSY_PIN self.EPD_S1_BUSY_PIN = epdconfig.EPD_S1_BUSY_PIN
self.EPD_M2_BUSY_PIN = epdconfig.EPD_M2_BUSY_PIN self.EPD_M2_BUSY_PIN = epdconfig.EPD_M2_BUSY_PIN
self.EPD_S2_BUSY_PIN = epdconfig.EPD_S2_BUSY_PIN self.EPD_S2_BUSY_PIN = epdconfig.EPD_S2_BUSY_PIN
def init(self): def init(self):
print("EPD init...") print("EPD init...")
@ -63,9 +65,9 @@ class EPD(object):
epdconfig.digital_write(self.EPD_S2_CS_PIN, 1) epdconfig.digital_write(self.EPD_S2_CS_PIN, 1)
self.Reset() self.Reset()
#panel setting # panel setting
self.M1_SendCommand(0x00) self.M1_SendCommand(0x00)
self.M1_SendData(0x1f) #KW-3f KWR-2F BWROTP 0f BWOTP 1f self.M1_SendData(0x1f) # KW-3f KWR-2F BWROTP 0f BWOTP 1f
self.S1_SendCommand(0x00) self.S1_SendCommand(0x00)
self.S1_SendData(0x1f) self.S1_SendData(0x1f)
self.M2_SendCommand(0x00) self.M2_SendCommand(0x00)
@ -75,9 +77,9 @@ class EPD(object):
# booster soft start # booster soft start
self.M1_SendCommand(0x06) self.M1_SendCommand(0x06)
self.M1_SendData(0x17) #A self.M1_SendData(0x17) # A
self.M1_SendData(0x17) #B self.M1_SendData(0x17) # B
self.M1_SendData(0x39) #C self.M1_SendData(0x39) # C
self.M1_SendData(0x17) self.M1_SendData(0x17)
self.M2_SendCommand(0x06) self.M2_SendCommand(0x06)
self.M2_SendData(0x17) self.M2_SendData(0x17)
@ -85,123 +87,124 @@ class EPD(object):
self.M2_SendData(0x39) self.M2_SendData(0x39)
self.M2_SendData(0x17) self.M2_SendData(0x17)
#resolution setting # resolution setting
self.M1_SendCommand(0x61) self.M1_SendCommand(0x61)
self.M1_SendData(0x02) self.M1_SendData(0x02)
self.M1_SendData(0x88) #source 648 self.M1_SendData(0x88) # source 648
self.M1_SendData(0x01) #gate 492 self.M1_SendData(0x01) # gate 492
self.M1_SendData(0xEC) self.M1_SendData(0xEC)
self.S1_SendCommand(0x61) self.S1_SendCommand(0x61)
self.S1_SendData(0x02) self.S1_SendData(0x02)
self.S1_SendData(0x90) #source 656 self.S1_SendData(0x90) # source 656
self.S1_SendData(0x01) #gate 492 self.S1_SendData(0x01) # gate 492
self.S1_SendData(0xEC) self.S1_SendData(0xEC)
self.M2_SendCommand(0x61) self.M2_SendCommand(0x61)
self.M2_SendData(0x02) self.M2_SendData(0x02)
self.M2_SendData(0x90) #source 656 self.M2_SendData(0x90) # source 656
self.M2_SendData(0x01) #gate 492 self.M2_SendData(0x01) # gate 492
self.M2_SendData(0xEC) self.M2_SendData(0xEC)
self.S2_SendCommand(0x61) self.S2_SendCommand(0x61)
self.S2_SendData(0x02) self.S2_SendData(0x02)
self.S2_SendData(0x88) #source 648 self.S2_SendData(0x88) # source 648
self.S2_SendData(0x01) #gate 492 self.S2_SendData(0x01) # gate 492
self.S2_SendData(0xEC) self.S2_SendData(0xEC)
self.M1S1M2S2_SendCommand(0x15) #DUSPI self.M1S1M2S2_SendCommand(0x15) # DUSPI
self.M1S1M2S2_SendData(0x20) self.M1S1M2S2_SendData(0x20)
self.M1S1M2S2_SendCommand(0x50) #Vcom and data interval setting self.M1S1M2S2_SendCommand(0x50) # Vcom and data interval setting
self.M1S1M2S2_SendData(0x21) #Border KW self.M1S1M2S2_SendData(0x21) # Border KW
self.M1S1M2S2_SendData(0x07) self.M1S1M2S2_SendData(0x07)
self.M1S1M2S2_SendCommand(0x60) #TCON self.M1S1M2S2_SendCommand(0x60) # TCON
self.M1S1M2S2_SendData(0x22) self.M1S1M2S2_SendData(0x22)
self.M1S1M2S2_SendCommand(0xE3) self.M1S1M2S2_SendCommand(0xE3)
self.M1S1M2S2_SendData(0x00) self.M1S1M2S2_SendData(0x00)
#temperature # temperature
temp = self.M1_ReadTemperature() temp = self.M1_ReadTemperature()
self.M1S1M2S2_SendCommand(0xe0) #Cascade setting self.M1S1M2S2_SendCommand(0xe0) # Cascade setting
self.M1S1M2S2_SendData(0x03) self.M1S1M2S2_SendData(0x03)
self.M1S1M2S2_SendCommand(0xe5) #Force temperature self.M1S1M2S2_SendCommand(0xe5) # Force temperature
self.M1S1M2S2_SendData(temp) self.M1S1M2S2_SendData(temp)
def getbuffer(self, image): def getbuffer(self, image):
# logging.debug("bufsiz = ",int(self.width/8) * self.height) # logging.debug("bufsiz = ",int(self.width/8) * self.height)
buf = [0xFF] * (int(self.width/8) * self.height) buf = [0xFF] * (int(self.width / 8) * self.height)
image_monocolor = image.convert('1') image_monocolor = image.convert('1')
imwidth, imheight = image_monocolor.size imwidth, imheight = image_monocolor.size
pixels = image_monocolor.load() pixels = image_monocolor.load()
if(imwidth == self.width and imheight == self.height): if (imwidth == self.width and imheight == self.height):
for y in range(imheight): for y in range(imheight):
for x in range(imwidth): for x in range(imwidth):
# Set the bits for the column of pixels at the current position. # Set the bits for the column of pixels at the current position.
if pixels[x, y] == 0: if pixels[x, y] == 0:
buf[int((x + y * self.width) / 8)] &= ~(0x80 >> (x % 8)) buf[int((x + y * self.width) / 8)] &= ~(0x80 >> (x % 8))
elif(imwidth == self.height and imheight == self.width): elif (imwidth == self.height and imheight == self.width):
for y in range(imheight): for y in range(imheight):
for x in range(imwidth): for x in range(imwidth):
newx = y newx = y
newy = self.height - x - 1 newy = self.height - x - 1
if pixels[x, y] == 0: if pixels[x, y] == 0:
buf[int((newx + newy*self.width) / 8)] &= ~(0x80 >> (y % 8)) buf[int((newx + newy * self.width) / 8)] &= ~(0x80 >> (y % 8))
return buf return buf
def display(self, buf): def display(self, buf):
#M1 part 648*492 # M1 part 648*492
self.M1_SendCommand(0x13) self.M1_SendCommand(0x13)
for y in range(492, 984): for y in range(492, 984):
for x in range(0, 81): for x in range(0, 81):
self.M1_SendData(buf[y*163 + x]) self.M1_SendData(buf[y * 163 + x])
#S1 part 656*492 # S1 part 656*492
self.S1_SendCommand(0x13) self.S1_SendCommand(0x13)
for y in range(492, 984): for y in range(492, 984):
for x in range(81, 163): for x in range(81, 163):
self.S1_SendData(buf[y*163 + x]) self.S1_SendData(buf[y * 163 + x])
#M2 part 656*492 # M2 part 656*492
self.M2_SendCommand(0x13) self.M2_SendCommand(0x13)
for y in range(0, 492): for y in range(0, 492):
for x in range(81, 163): for x in range(81, 163):
self.M2_SendData(buf[y*163 + x]) self.M2_SendData(buf[y * 163 + x])
#S2 part 648*492 # S2 part 648*492
self.S2_SendCommand(0x13) self.S2_SendCommand(0x13)
for y in range(0, 492): for y in range(0, 492):
for x in range(0, 81): for x in range(0, 81):
self.S2_SendData(buf[y*163 + x]) self.S2_SendData(buf[y * 163 + x])
self.TurnOnDisplay() self.TurnOnDisplay()
def clear(self): def clear(self):
"""Clear contents of image buffer""" """Clear contents of image buffer"""
self.M1_SendCommand(0x13) self.M1_SendCommand(0x13)
for y in range(492, 984): for y in range(492, 984):
for x in range(0, 81): for x in range(0, 81):
self.M1_SendData(0xff) self.M1_SendData(0xff)
self.S1_SendCommand(0x13) self.S1_SendCommand(0x13)
for y in range(492, 984): for y in range(492, 984):
for x in range(81, 163): for x in range(81, 163):
self.S1_SendData(0xff) self.S1_SendData(0xff)
self.M2_SendCommand(0x13) self.M2_SendCommand(0x13)
for y in range(0, 492): for y in range(0, 492):
for x in range(81, 163): for x in range(81, 163):
self.M2_SendData(0xff) self.M2_SendData(0xff)
self.S2_SendCommand(0x13) self.S2_SendCommand(0x13)
for y in range(0, 492): for y in range(0, 492):
for x in range(0, 81): for x in range(0, 81):
self.S2_SendData(0xff) self.S2_SendData(0xff)
self.TurnOnDisplay() self.TurnOnDisplay()
""" M1S1M2S2 Write register address and data """ """ M1S1M2S2 Write register address and data """
def M1S1M2S2_SendCommand(self, cmd): def M1S1M2S2_SendCommand(self, cmd):
epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 0) epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 0)
epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 0) epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 0)
@ -231,6 +234,7 @@ class EPD(object):
epdconfig.digital_write(self.EPD_S2_CS_PIN, 1) epdconfig.digital_write(self.EPD_S2_CS_PIN, 1)
""" M1M2 Write register address and data """ """ M1M2 Write register address and data """
def M1M2_SendCommand(self, cmd): def M1M2_SendCommand(self, cmd):
epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 0) epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 0)
epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 0) epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 0)
@ -250,13 +254,13 @@ class EPD(object):
epdconfig.digital_write(self.EPD_M2_CS_PIN, 1) epdconfig.digital_write(self.EPD_M2_CS_PIN, 1)
""" S2 Write register address and data """ """ S2 Write register address and data """
def S2_SendCommand(self, cmd): def S2_SendCommand(self, cmd):
epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 0) epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 0)
epdconfig.digital_write(self.EPD_S2_CS_PIN, 0) epdconfig.digital_write(self.EPD_S2_CS_PIN, 0)
epdconfig.spi_writebyte(cmd) epdconfig.spi_writebyte(cmd)
epdconfig.digital_write(self.EPD_S2_CS_PIN, 1) epdconfig.digital_write(self.EPD_S2_CS_PIN, 1)
def S2_SendData(self, val): def S2_SendData(self, val):
epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 1) epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 1)
epdconfig.digital_write(self.EPD_S2_CS_PIN, 0) epdconfig.digital_write(self.EPD_S2_CS_PIN, 0)
@ -264,6 +268,7 @@ class EPD(object):
epdconfig.digital_write(self.EPD_S2_CS_PIN, 1) epdconfig.digital_write(self.EPD_S2_CS_PIN, 1)
""" M2 Write register address and data """ """ M2 Write register address and data """
def M2_SendCommand(self, cmd): def M2_SendCommand(self, cmd):
epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 0) epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 0)
epdconfig.digital_write(self.EPD_M2_CS_PIN, 0) epdconfig.digital_write(self.EPD_M2_CS_PIN, 0)
@ -277,6 +282,7 @@ class EPD(object):
epdconfig.digital_write(self.EPD_M2_CS_PIN, 1) epdconfig.digital_write(self.EPD_M2_CS_PIN, 1)
""" S1 Write register address and data """ """ S1 Write register address and data """
def S1_SendCommand(self, cmd): def S1_SendCommand(self, cmd):
epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 0) epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 0)
epdconfig.digital_write(self.EPD_S1_CS_PIN, 0) epdconfig.digital_write(self.EPD_S1_CS_PIN, 0)
@ -290,6 +296,7 @@ class EPD(object):
epdconfig.digital_write(self.EPD_S1_CS_PIN, 1) epdconfig.digital_write(self.EPD_S1_CS_PIN, 1)
""" M1 Write register address and data """ """ M1 Write register address and data """
def M1_SendCommand(self, cmd): def M1_SendCommand(self, cmd):
epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 0) epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 0)
epdconfig.digital_write(self.EPD_M1_CS_PIN, 0) epdconfig.digital_write(self.EPD_M1_CS_PIN, 0)
@ -323,7 +330,6 @@ class EPD(object):
print("module_exit") print("module_exit")
epdconfig.module_exit() epdconfig.module_exit()
def TurnOnDisplay(self): def TurnOnDisplay(self):
self.M1M2_SendCommand(0x04) self.M1M2_SendCommand(0x04)
time.sleep(0.3) time.sleep(0.3)
@ -333,49 +339,49 @@ class EPD(object):
self.M2_ReadBusy() self.M2_ReadBusy()
self.S2_ReadBusy() self.S2_ReadBusy()
#Busy # Busy
def M1_ReadBusy(self): def M1_ReadBusy(self):
self.M1_SendCommand(0x71) self.M1_SendCommand(0x71)
busy = epdconfig.digital_read(self.EPD_M1_BUSY_PIN) busy = epdconfig.digital_read(self.EPD_M1_BUSY_PIN)
busy = not(busy & 0x01) busy = not (busy & 0x01)
print("M1_ReadBusy") print("M1_ReadBusy")
while(busy): while (busy):
self.M1_SendCommand(0x71) self.M1_SendCommand(0x71)
busy = epdconfig.digital_read(self.EPD_M1_BUSY_PIN) busy = epdconfig.digital_read(self.EPD_M1_BUSY_PIN)
busy = not(busy & 0x01) busy = not (busy & 0x01)
time.sleep(0.2) time.sleep(0.2)
def M2_ReadBusy(self): def M2_ReadBusy(self):
self.M2_SendCommand(0x71) self.M2_SendCommand(0x71)
busy = epdconfig.digital_read(self.EPD_M2_BUSY_PIN) busy = epdconfig.digital_read(self.EPD_M2_BUSY_PIN)
busy = not(busy & 0x01) busy = not (busy & 0x01)
print("M2_ReadBusy") print("M2_ReadBusy")
while(busy): while (busy):
self.M2_SendCommand(0x71) self.M2_SendCommand(0x71)
busy = epdconfig.digital_read(self.EPD_M2_BUSY_PIN) busy = epdconfig.digital_read(self.EPD_M2_BUSY_PIN)
busy =not(busy & 0x01) busy = not (busy & 0x01)
time.sleep(0.2) time.sleep(0.2)
def S1_ReadBusy(self): def S1_ReadBusy(self):
self.S1_SendCommand(0x71) self.S1_SendCommand(0x71)
busy = epdconfig.digital_read(self.EPD_S1_BUSY_PIN) busy = epdconfig.digital_read(self.EPD_S1_BUSY_PIN)
busy = not(busy & 0x01) busy = not (busy & 0x01)
print("s1_ReadBusy") print("s1_ReadBusy")
while(busy): while (busy):
self.S1_SendCommand(0x71) self.S1_SendCommand(0x71)
busy = epdconfig.digital_read(self.EPD_S1_BUSY_PIN) busy = epdconfig.digital_read(self.EPD_S1_BUSY_PIN)
busy = not(busy & 0x01) busy = not (busy & 0x01)
time.sleep(0.2) time.sleep(0.2)
def S2_ReadBusy(self): def S2_ReadBusy(self):
self.S2_SendCommand(0x71) self.S2_SendCommand(0x71)
busy = epdconfig.digital_read(self.EPD_S2_BUSY_PIN) busy = epdconfig.digital_read(self.EPD_S2_BUSY_PIN)
busy = not(busy & 0x01) busy = not (busy & 0x01)
print("S2_ReadBusy") print("S2_ReadBusy")
while(busy): while (busy):
self.S2_SendCommand(0x71) self.S2_SendCommand(0x71)
busy = epdconfig.digital_read(self.EPD_S2_BUSY_PIN) busy = epdconfig.digital_read(self.EPD_S2_BUSY_PIN)
busy = not(busy & 0x01) busy = not (busy & 0x01)
time.sleep(0.2) time.sleep(0.2)
def M1_ReadTemperature(self): def M1_ReadTemperature(self):
@ -393,7 +399,7 @@ class EPD(object):
# temp = epdconfig.spi_readbyte(0x00) # temp = epdconfig.spi_readbyte(0x00)
temp = 25 temp = 25
print("Read Temperature Reg:%d"%temp) print("Read Temperature Reg:%d" % temp)
epdconfig.digital_write(self.EPD_M1_CS_PIN, 1) epdconfig.digital_write(self.EPD_M1_CS_PIN, 1)
# temp =0x29 # temp =0x29
return temp return temp

View File

@ -1,57 +1,59 @@
# /***************************************************************************** """
# * | File : epd12in48.py * | File : epd12in48.py
# * | Author : Waveshare electrices * | Author : Waveshare electrices
# * | Function : Hardware underlying interface * | Function : Hardware underlying interface
# * | Info : * | Info :
# *---------------- *----------------
# * | This version: V1.0 * | This version: V1.0
# * | Date : 2019-11-01 * | Date : 2019-11-01
# * | Info : * | Info :
# ******************************************************************************/ ******************************************************************************/
# Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documnetation files (the "Software"), to deal of this software and associated documnetation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
# furished to do so, subject to the following conditions: furished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software. all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 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 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE. THE SOFTWARE.
# """
import time import time
from inkycal.display.drivers import epdconfig_12_in_48 as epdconfig from inkycal.display.drivers import epdconfig_12_in_48 as epdconfig
EPD_WIDTH = 1304 EPD_WIDTH = 1304
EPD_HEIGHT = 984 EPD_HEIGHT = 984
class EPD(object): class EPD(object):
def __init__(self): def __init__(self):
self.width = EPD_WIDTH self.width = EPD_WIDTH
self.height = EPD_HEIGHT self.height = EPD_HEIGHT
self.EPD_M1_CS_PIN = epdconfig.EPD_M1_CS_PIN self.EPD_M1_CS_PIN = epdconfig.EPD_M1_CS_PIN
self.EPD_S1_CS_PIN = epdconfig.EPD_S1_CS_PIN self.EPD_S1_CS_PIN = epdconfig.EPD_S1_CS_PIN
self.EPD_M2_CS_PIN = epdconfig.EPD_M2_CS_PIN self.EPD_M2_CS_PIN = epdconfig.EPD_M2_CS_PIN
self.EPD_S2_CS_PIN = epdconfig.EPD_S2_CS_PIN self.EPD_S2_CS_PIN = epdconfig.EPD_S2_CS_PIN
self.EPD_M1S1_DC_PIN = epdconfig.EPD_M1S1_DC_PIN self.EPD_M1S1_DC_PIN = epdconfig.EPD_M1S1_DC_PIN
self.EPD_M2S2_DC_PIN = epdconfig.EPD_M2S2_DC_PIN self.EPD_M2S2_DC_PIN = epdconfig.EPD_M2S2_DC_PIN
self.EPD_M1S1_RST_PIN = epdconfig.EPD_M1S1_RST_PIN self.EPD_M1S1_RST_PIN = epdconfig.EPD_M1S1_RST_PIN
self.EPD_M2S2_RST_PIN = epdconfig.EPD_M2S2_RST_PIN self.EPD_M2S2_RST_PIN = epdconfig.EPD_M2S2_RST_PIN
self.EPD_M1_BUSY_PIN = epdconfig.EPD_M1_BUSY_PIN self.EPD_M1_BUSY_PIN = epdconfig.EPD_M1_BUSY_PIN
self.EPD_S1_BUSY_PIN = epdconfig.EPD_S1_BUSY_PIN self.EPD_S1_BUSY_PIN = epdconfig.EPD_S1_BUSY_PIN
self.EPD_M2_BUSY_PIN = epdconfig.EPD_M2_BUSY_PIN self.EPD_M2_BUSY_PIN = epdconfig.EPD_M2_BUSY_PIN
self.EPD_S2_BUSY_PIN = epdconfig.EPD_S2_BUSY_PIN self.EPD_S2_BUSY_PIN = epdconfig.EPD_S2_BUSY_PIN
def init(self): def init(self):
print("EPD init...") print("EPD init...")
@ -63,9 +65,9 @@ class EPD(object):
epdconfig.digital_write(self.EPD_S2_CS_PIN, 1) epdconfig.digital_write(self.EPD_S2_CS_PIN, 1)
self.Reset() self.Reset()
#panel setting # panel setting
self.M1_SendCommand(0x00) self.M1_SendCommand(0x00)
self.M1_SendData(0x2f) #KW-3f KWR-2F BWROTP 0f BWOTP 1f self.M1_SendData(0x2f) # KW-3f KWR-2F BWROTP 0f BWOTP 1f
self.S1_SendCommand(0x00) self.S1_SendCommand(0x00)
self.S1_SendData(0x2f) self.S1_SendData(0x2f)
self.M2_SendCommand(0x00) self.M2_SendCommand(0x00)
@ -76,22 +78,22 @@ class EPD(object):
# POWER SETTING # POWER SETTING
self.M1_SendCommand(0x01) self.M1_SendCommand(0x01)
self.M1_SendData(0x07) self.M1_SendData(0x07)
self.M1_SendData(0x17) # VGH=20V,VGL=-20V self.M1_SendData(0x17) # VGH=20V,VGL=-20V
self.M1_SendData(0x3F) # VDH=15V self.M1_SendData(0x3F) # VDH=15V
self.M1_SendData(0x3F) # VDL=-15V self.M1_SendData(0x3F) # VDL=-15V
self.M1_SendData(0x0d) self.M1_SendData(0x0d)
self.M2_SendCommand(0x01) self.M2_SendCommand(0x01)
self.M2_SendData(0x07) self.M2_SendData(0x07)
self.M2_SendData(0x17) # VGH=20V,VGL=-20V self.M2_SendData(0x17) # VGH=20V,VGL=-20V
self.M2_SendData(0x3F) # VDH=15V self.M2_SendData(0x3F) # VDH=15V
self.M2_SendData(0x3F) # VDL=-15V self.M2_SendData(0x3F) # VDL=-15V
self.M2_SendData(0x0d) self.M2_SendData(0x0d)
# booster soft start # booster soft start
self.M1_SendCommand(0x06) self.M1_SendCommand(0x06)
self.M1_SendData(0x17) #A self.M1_SendData(0x17) # A
self.M1_SendData(0x17) #B self.M1_SendData(0x17) # B
self.M1_SendData(0x39) #C self.M1_SendData(0x39) # C
self.M1_SendData(0x17) self.M1_SendData(0x17)
self.M2_SendCommand(0x06) self.M2_SendCommand(0x06)
self.M2_SendData(0x17) self.M2_SendData(0x17)
@ -99,44 +101,44 @@ class EPD(object):
self.M2_SendData(0x39) self.M2_SendData(0x39)
self.M2_SendData(0x17) self.M2_SendData(0x17)
#resolution setting # resolution setting
self.M1_SendCommand(0x61) self.M1_SendCommand(0x61)
self.M1_SendData(0x02) self.M1_SendData(0x02)
self.M1_SendData(0x88) #source 648 self.M1_SendData(0x88) # source 648
self.M1_SendData(0x01) #gate 492 self.M1_SendData(0x01) # gate 492
self.M1_SendData(0xEC) self.M1_SendData(0xEC)
self.S1_SendCommand(0x61) self.S1_SendCommand(0x61)
self.S1_SendData(0x02) self.S1_SendData(0x02)
self.S1_SendData(0x90) #source 656 self.S1_SendData(0x90) # source 656
self.S1_SendData(0x01) #gate 492 self.S1_SendData(0x01) # gate 492
self.S1_SendData(0xEC) self.S1_SendData(0xEC)
self.M2_SendCommand(0x61) self.M2_SendCommand(0x61)
self.M2_SendData(0x02) self.M2_SendData(0x02)
self.M2_SendData(0x90) #source 656 self.M2_SendData(0x90) # source 656
self.M2_SendData(0x01) #gate 492 self.M2_SendData(0x01) # gate 492
self.M2_SendData(0xEC) self.M2_SendData(0xEC)
self.S2_SendCommand(0x61) self.S2_SendCommand(0x61)
self.S2_SendData(0x02) self.S2_SendData(0x02)
self.S2_SendData(0x88) #source 648 self.S2_SendData(0x88) # source 648
self.S2_SendData(0x01) #gate 492 self.S2_SendData(0x01) # gate 492
self.S2_SendData(0xEC) self.S2_SendData(0xEC)
self.M1S1M2S2_SendCommand(0x15) #DUSPI self.M1S1M2S2_SendCommand(0x15) # DUSPI
self.M1S1M2S2_SendData(0x20) self.M1S1M2S2_SendData(0x20)
self.M1S1M2S2_SendCommand(0x30) # PLL self.M1S1M2S2_SendCommand(0x30) # PLL
self.M1S1M2S2_SendData(0x08) self.M1S1M2S2_SendData(0x08)
self.M1S1M2S2_SendCommand(0x50) #Vcom and data interval setting self.M1S1M2S2_SendCommand(0x50) # Vcom and data interval setting
self.M1S1M2S2_SendData(0x31) self.M1S1M2S2_SendData(0x31)
self.M1S1M2S2_SendData(0x07) self.M1S1M2S2_SendData(0x07)
self.M1S1M2S2_SendCommand(0x60)#TCON self.M1S1M2S2_SendCommand(0x60) # TCON
self.M1S1M2S2_SendData(0x22) self.M1S1M2S2_SendData(0x22)
self.M1_SendCommand(0xE0) #POWER SETTING self.M1_SendCommand(0xE0) # POWER SETTING
self.M1_SendData(0x01) self.M1_SendData(0x01)
self.M2_SendCommand(0xE0) #POWER SETTING self.M2_SendCommand(0xE0) # POWER SETTING
self.M2_SendData(0x01) self.M2_SendData(0x01)
self.M1S1M2S2_SendCommand(0xE3) self.M1S1M2S2_SendCommand(0xE3)
@ -151,106 +153,106 @@ class EPD(object):
def getbuffer(self, image): def getbuffer(self, image):
# logging.debug("bufsiz = ",int(self.width/8) * self.height) # logging.debug("bufsiz = ",int(self.width/8) * self.height)
buf = [0xFF] * (int(self.width/8) * self.height) buf = [0xFF] * (int(self.width / 8) * self.height)
image_monocolor = image.convert('1') image_monocolor = image.convert('1')
imwidth, imheight = image_monocolor.size imwidth, imheight = image_monocolor.size
pixels = image_monocolor.load() pixels = image_monocolor.load()
if(imwidth == self.width and imheight == self.height): if (imwidth == self.width and imheight == self.height):
for y in range(imheight): for y in range(imheight):
for x in range(imwidth): for x in range(imwidth):
# Set the bits for the column of pixels at the current position. # Set the bits for the column of pixels at the current position.
if pixels[x, y] == 0: if pixels[x, y] == 0:
buf[int((x + y * self.width) / 8)] &= ~(0x80 >> (x % 8)) buf[int((x + y * self.width) / 8)] &= ~(0x80 >> (x % 8))
elif(imwidth == self.height and imheight == self.width): elif (imwidth == self.height and imheight == self.width):
for y in range(imheight): for y in range(imheight):
for x in range(imwidth): for x in range(imwidth):
newx = y newx = y
newy = self.height - x - 1 newy = self.height - x - 1
if pixels[x, y] == 0: if pixels[x, y] == 0:
buf[int((newx + newy*self.width) / 8)] &= ~(0x80 >> (y % 8)) buf[int((newx + newy * self.width) / 8)] &= ~(0x80 >> (y % 8))
return buf return buf
def display(self, blackbuf, redbuf): def display(self, blackbuf, redbuf):
#S2 part 648*492 # S2 part 648*492
self.S2_SendCommand(0x10) self.S2_SendCommand(0x10)
for y in range(0, 492): for y in range(0, 492):
for x in range(0, 81): for x in range(0, 81):
self.S2_SendData(blackbuf[y*163 + x]) self.S2_SendData(blackbuf[y * 163 + x])
self.S2_SendCommand(0x13) self.S2_SendCommand(0x13)
for y in range(0, 492): for y in range(0, 492):
for x in range(0, 81): for x in range(0, 81):
self.S2_SendData(~redbuf[y*163 + x]) self.S2_SendData(~redbuf[y * 163 + x])
#M2 part 656*492 # M2 part 656*492
self.M2_SendCommand(0x10) self.M2_SendCommand(0x10)
for y in range(0, 492): for y in range(0, 492):
for x in range(81, 163): for x in range(81, 163):
self.M2_SendData(blackbuf[y*163 + x]) self.M2_SendData(blackbuf[y * 163 + x])
self.M2_SendCommand(0x13) self.M2_SendCommand(0x13)
for y in range(0, 492): for y in range(0, 492):
for x in range(81, 163): for x in range(81, 163):
self.M2_SendData(~redbuf[y*163 + x]) self.M2_SendData(~redbuf[y * 163 + x])
#M1 part 648*492 # M1 part 648*492
self.M1_SendCommand(0x10) self.M1_SendCommand(0x10)
for y in range(492, 984): for y in range(492, 984):
for x in range(0, 81): for x in range(0, 81):
self.M1_SendData(blackbuf[y*163 + x]) self.M1_SendData(blackbuf[y * 163 + x])
self.M1_SendCommand(0x13) self.M1_SendCommand(0x13)
for y in range(492, 984): for y in range(492, 984):
for x in range(0, 81): for x in range(0, 81):
self.M1_SendData(~redbuf[y*163 + x]) self.M1_SendData(~redbuf[y * 163 + x])
#S1 part 656*492 # S1 part 656*492
self.S1_SendCommand(0x10) self.S1_SendCommand(0x10)
for y in range(492, 984): for y in range(492, 984):
for x in range(81, 163): for x in range(81, 163):
self.S1_SendData(blackbuf[y*163 + x]) self.S1_SendData(blackbuf[y * 163 + x])
self.S1_SendCommand(0x13) self.S1_SendCommand(0x13)
for y in range(492, 984): for y in range(492, 984):
for x in range(81, 163): for x in range(81, 163):
self.S1_SendData(~redbuf[y*163 + x]) self.S1_SendData(~redbuf[y * 163 + x])
self.TurnOnDisplay() self.TurnOnDisplay()
def clear(self): def clear(self):
"""Clear contents of image buffer""" """Clear contents of image buffer"""
self.S2_SendCommand(0x10) self.S2_SendCommand(0x10)
for y in range(0, 492): for y in range(0, 492):
for x in range(0, 81): for x in range(0, 81):
self.S2_SendData(0xff) self.S2_SendData(0xff)
self.S2_SendCommand(0x13) self.S2_SendCommand(0x13)
for y in range(0, 492): for y in range(0, 492):
for x in range(0, 81): for x in range(0, 81):
self.S2_SendData(0x00) self.S2_SendData(0x00)
self.M2_SendCommand(0x10) self.M2_SendCommand(0x10)
for y in range(0, 492): for y in range(0, 492):
for x in range(81, 163): for x in range(81, 163):
self.M2_SendData(0xff) self.M2_SendData(0xff)
self.M2_SendCommand(0x13) self.M2_SendCommand(0x13)
for y in range(0, 492): for y in range(0, 492):
for x in range(81, 163): for x in range(81, 163):
self.M2_SendData(0x00) self.M2_SendData(0x00)
self.M1_SendCommand(0x10) self.M1_SendCommand(0x10)
for y in range(492, 984): for y in range(492, 984):
for x in range(0, 81): for x in range(0, 81):
self.M1_SendData(0xff) self.M1_SendData(0xff)
self.M1_SendCommand(0x13) self.M1_SendCommand(0x13)
for y in range(492, 984): for y in range(492, 984):
for x in range(0, 81): for x in range(0, 81):
self.M1_SendData(0x00) self.M1_SendData(0x00)
self.S1_SendCommand(0x10) self.S1_SendCommand(0x10)
for y in range(492, 984): for y in range(492, 984):
for x in range(81, 163): for x in range(81, 163):
self.S1_SendData(0xff) self.S1_SendData(0xff)
self.S1_SendCommand(0x13) self.S1_SendCommand(0x13)
for y in range(492, 984): for y in range(492, 984):
for x in range(81, 163): for x in range(81, 163):
self.S1_SendData(0x00) self.S1_SendData(0x00)
self.TurnOnDisplay() self.TurnOnDisplay()
@ -286,6 +288,7 @@ class EPD(object):
self.S2_ReadBusy() self.S2_ReadBusy()
""" M1S1M2S2 Write register address and data """ """ M1S1M2S2 Write register address and data """
def M1S1M2S2_SendCommand(self, cmd): def M1S1M2S2_SendCommand(self, cmd):
epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 0) epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 0)
epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 0) epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 0)
@ -315,6 +318,7 @@ class EPD(object):
epdconfig.digital_write(self.EPD_S2_CS_PIN, 1) epdconfig.digital_write(self.EPD_S2_CS_PIN, 1)
""" M1M2 Write register address and data """ """ M1M2 Write register address and data """
def M1M2_SendCommand(self, cmd): def M1M2_SendCommand(self, cmd):
epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 0) epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 0)
epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 0) epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 0)
@ -334,11 +338,13 @@ class EPD(object):
epdconfig.digital_write(self.EPD_M2_CS_PIN, 1) epdconfig.digital_write(self.EPD_M2_CS_PIN, 1)
""" S2 Write register address and data """ """ S2 Write register address and data """
def S2_SendCommand(self, cmd): def S2_SendCommand(self, cmd):
epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 0) epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 0)
epdconfig.digital_write(self.EPD_S2_CS_PIN, 0) epdconfig.digital_write(self.EPD_S2_CS_PIN, 0)
epdconfig.spi_writebyte(cmd) epdconfig.spi_writebyte(cmd)
epdconfig.digital_write(self.EPD_S2_CS_PIN, 1) epdconfig.digital_write(self.EPD_S2_CS_PIN, 1)
def S2_SendData(self, val): def S2_SendData(self, val):
epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 1) epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 1)
epdconfig.digital_write(self.EPD_S2_CS_PIN, 0) epdconfig.digital_write(self.EPD_S2_CS_PIN, 0)
@ -346,11 +352,13 @@ class EPD(object):
epdconfig.digital_write(self.EPD_S2_CS_PIN, 1) epdconfig.digital_write(self.EPD_S2_CS_PIN, 1)
""" M2 Write register address and data """ """ M2 Write register address and data """
def M2_SendCommand(self, cmd): def M2_SendCommand(self, cmd):
epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 0) epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 0)
epdconfig.digital_write(self.EPD_M2_CS_PIN, 0) epdconfig.digital_write(self.EPD_M2_CS_PIN, 0)
epdconfig.spi_writebyte(cmd) epdconfig.spi_writebyte(cmd)
epdconfig.digital_write(self.EPD_M2_CS_PIN, 1) epdconfig.digital_write(self.EPD_M2_CS_PIN, 1)
def M2_SendData(self, val): def M2_SendData(self, val):
epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 1) epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 1)
epdconfig.digital_write(self.EPD_M2_CS_PIN, 0) epdconfig.digital_write(self.EPD_M2_CS_PIN, 0)
@ -358,11 +366,13 @@ class EPD(object):
epdconfig.digital_write(self.EPD_M2_CS_PIN, 1) epdconfig.digital_write(self.EPD_M2_CS_PIN, 1)
""" S1 Write register address and data """ """ S1 Write register address and data """
def S1_SendCommand(self, cmd): def S1_SendCommand(self, cmd):
epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 0) epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 0)
epdconfig.digital_write(self.EPD_S1_CS_PIN, 0) epdconfig.digital_write(self.EPD_S1_CS_PIN, 0)
epdconfig.spi_writebyte(cmd) epdconfig.spi_writebyte(cmd)
epdconfig.digital_write(self.EPD_S1_CS_PIN, 1) epdconfig.digital_write(self.EPD_S1_CS_PIN, 1)
def S1_SendData(self, val): def S1_SendData(self, val):
epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 1) epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 1)
epdconfig.digital_write(self.EPD_S1_CS_PIN, 0) epdconfig.digital_write(self.EPD_S1_CS_PIN, 0)
@ -370,138 +380,143 @@ class EPD(object):
epdconfig.digital_write(self.EPD_S1_CS_PIN, 1) epdconfig.digital_write(self.EPD_S1_CS_PIN, 1)
""" M1 Write register address and data """ """ M1 Write register address and data """
def M1_SendCommand(self, cmd): def M1_SendCommand(self, cmd):
epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 0) epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 0)
epdconfig.digital_write(self.EPD_M1_CS_PIN, 0) epdconfig.digital_write(self.EPD_M1_CS_PIN, 0)
epdconfig.spi_writebyte(cmd) epdconfig.spi_writebyte(cmd)
epdconfig.digital_write(self.EPD_M1_CS_PIN, 1) epdconfig.digital_write(self.EPD_M1_CS_PIN, 1)
def M1_SendData(self, val): def M1_SendData(self, val):
epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 1) epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 1)
epdconfig.digital_write(self.EPD_M1_CS_PIN, 0) epdconfig.digital_write(self.EPD_M1_CS_PIN, 0)
epdconfig.spi_writebyte(val) epdconfig.spi_writebyte(val)
epdconfig.digital_write(self.EPD_M1_CS_PIN, 1) epdconfig.digital_write(self.EPD_M1_CS_PIN, 1)
#Busy # Busy
def M1_ReadBusy(self): def M1_ReadBusy(self):
self.M1_SendCommand(0x71) self.M1_SendCommand(0x71)
busy = epdconfig.digital_read(self.EPD_M1_BUSY_PIN) busy = epdconfig.digital_read(self.EPD_M1_BUSY_PIN)
busy = not(busy & 0x01) busy = not (busy & 0x01)
while(busy): while (busy):
self.M1_SendCommand(0x71) self.M1_SendCommand(0x71)
busy = epdconfig.digital_read(self.EPD_M1_BUSY_PIN) busy = epdconfig.digital_read(self.EPD_M1_BUSY_PIN)
busy = not(busy & 0x01) busy = not (busy & 0x01)
time.sleep(0.2) time.sleep(0.2)
def M2_ReadBusy(self): def M2_ReadBusy(self):
self.M2_SendCommand(0x71) self.M2_SendCommand(0x71)
busy = epdconfig.digital_read(self.EPD_M2_BUSY_PIN) busy = epdconfig.digital_read(self.EPD_M2_BUSY_PIN)
busy = not(busy & 0x01) busy = not (busy & 0x01)
self.M2_SendCommand(0x71) self.M2_SendCommand(0x71)
while(busy): while (busy):
self.M2_SendCommand(0x71) self.M2_SendCommand(0x71)
busy = epdconfig.digital_read(self.EPD_M2_BUSY_PIN) busy = epdconfig.digital_read(self.EPD_M2_BUSY_PIN)
busy =not(busy & 0x01) busy = not (busy & 0x01)
time.sleep(0.2) time.sleep(0.2)
def S1_ReadBusy(self): def S1_ReadBusy(self):
self.S1_SendCommand(0x71) self.S1_SendCommand(0x71)
busy = epdconfig.digital_read(self.EPD_S1_BUSY_PIN) busy = epdconfig.digital_read(self.EPD_S1_BUSY_PIN)
busy = not(busy & 0x01) busy = not (busy & 0x01)
while(busy): while (busy):
self.S1_SendCommand(0x71) self.S1_SendCommand(0x71)
busy = epdconfig.digital_read(self.EPD_S1_BUSY_PIN) busy = epdconfig.digital_read(self.EPD_S1_BUSY_PIN)
busy = not(busy & 0x01) busy = not (busy & 0x01)
time.sleep(0.2) time.sleep(0.2)
def S2_ReadBusy(self): def S2_ReadBusy(self):
self.S2_SendCommand(0x71) self.S2_SendCommand(0x71)
busy = epdconfig.digital_read(self.EPD_S2_BUSY_PIN) busy = epdconfig.digital_read(self.EPD_S2_BUSY_PIN)
busy = not(busy & 0x01) busy = not (busy & 0x01)
while(busy): while (busy):
self.S2_SendCommand(0x71) self.S2_SendCommand(0x71)
busy = epdconfig.digital_read(self.EPD_S2_BUSY_PIN) busy = epdconfig.digital_read(self.EPD_S2_BUSY_PIN)
busy = not(busy & 0x01) busy = not (busy & 0x01)
time.sleep(0.2) time.sleep(0.2)
lut_vcom1 = [ lut_vcom1 = [
0x00, 0x10, 0x10, 0x01, 0x08, 0x01, 0x00, 0x10, 0x10, 0x01, 0x08, 0x01,
0x00, 0x06, 0x01, 0x06, 0x01, 0x05, 0x00, 0x06, 0x01, 0x06, 0x01, 0x05,
0x00, 0x08, 0x01, 0x08, 0x01, 0x06, 0x00, 0x08, 0x01, 0x08, 0x01, 0x06,
0x00, 0x06, 0x01, 0x06, 0x01, 0x05, 0x00, 0x06, 0x01, 0x06, 0x01, 0x05,
0x00, 0x05, 0x01, 0x1E, 0x0F, 0x06, 0x00, 0x05, 0x01, 0x1E, 0x0F, 0x06,
0x00, 0x05, 0x01, 0x1E, 0x0F, 0x01, 0x00, 0x05, 0x01, 0x1E, 0x0F, 0x01,
0x00, 0x04, 0x05, 0x08, 0x08, 0x01, 0x00, 0x04, 0x05, 0x08, 0x08, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
] ]
lut_ww1 = [ lut_ww1 = [
0x91, 0x10, 0x10, 0x01, 0x08, 0x01, 0x91, 0x10, 0x10, 0x01, 0x08, 0x01,
0x04, 0x06, 0x01, 0x06, 0x01, 0x05, 0x04, 0x06, 0x01, 0x06, 0x01, 0x05,
0x84, 0x08, 0x01, 0x08, 0x01, 0x06, 0x84, 0x08, 0x01, 0x08, 0x01, 0x06,
0x80, 0x06, 0x01, 0x06, 0x01, 0x05, 0x80, 0x06, 0x01, 0x06, 0x01, 0x05,
0x00, 0x05, 0x01, 0x1E, 0x0F, 0x06, 0x00, 0x05, 0x01, 0x1E, 0x0F, 0x06,
0x00, 0x05, 0x01, 0x1E, 0x0F, 0x01, 0x00, 0x05, 0x01, 0x1E, 0x0F, 0x01,
0x08, 0x04, 0x05, 0x08, 0x08, 0x01, 0x08, 0x04, 0x05, 0x08, 0x08, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
] ]
lut_bw1 = [ lut_bw1 = [
0xA8, 0x10, 0x10, 0x01, 0x08, 0x01, 0xA8, 0x10, 0x10, 0x01, 0x08, 0x01,
0x84, 0x06, 0x01, 0x06, 0x01, 0x05, 0x84, 0x06, 0x01, 0x06, 0x01, 0x05,
0x84, 0x08, 0x01, 0x08, 0x01, 0x06, 0x84, 0x08, 0x01, 0x08, 0x01, 0x06,
0x86, 0x06, 0x01, 0x06, 0x01, 0x05, 0x86, 0x06, 0x01, 0x06, 0x01, 0x05,
0x8C, 0x05, 0x01, 0x1E, 0x0F, 0x06, 0x8C, 0x05, 0x01, 0x1E, 0x0F, 0x06,
0x8C, 0x05, 0x01, 0x1E, 0x0F, 0x01, 0x8C, 0x05, 0x01, 0x1E, 0x0F, 0x01,
0xF0, 0x04, 0x05, 0x08, 0x08, 0x01, 0xF0, 0x04, 0x05, 0x08, 0x08, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
] ]
lut_wb1 = [ lut_wb1 = [
0x91, 0x10, 0x10, 0x01, 0x08, 0x01, 0x91, 0x10, 0x10, 0x01, 0x08, 0x01,
0x04, 0x06, 0x01, 0x06, 0x01, 0x05, 0x04, 0x06, 0x01, 0x06, 0x01, 0x05,
0x84, 0x08, 0x01, 0x08, 0x01, 0x06, 0x84, 0x08, 0x01, 0x08, 0x01, 0x06,
0x80, 0x06, 0x01, 0x06, 0x01, 0x05, 0x80, 0x06, 0x01, 0x06, 0x01, 0x05,
0x00, 0x05, 0x01, 0x1E, 0x0F, 0x06, 0x00, 0x05, 0x01, 0x1E, 0x0F, 0x06,
0x00, 0x05, 0x01, 0x1E, 0x0F, 0x01, 0x00, 0x05, 0x01, 0x1E, 0x0F, 0x01,
0x08, 0x04, 0x05, 0x08, 0x08, 0x01, 0x08, 0x04, 0x05, 0x08, 0x08, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
] ]
lut_bb1 = [ lut_bb1 = [
0x92, 0x10, 0x10, 0x01, 0x08, 0x01, 0x92, 0x10, 0x10, 0x01, 0x08, 0x01,
0x80, 0x06, 0x01, 0x06, 0x01, 0x05, 0x80, 0x06, 0x01, 0x06, 0x01, 0x05,
0x84, 0x08, 0x01, 0x08, 0x01, 0x06, 0x84, 0x08, 0x01, 0x08, 0x01, 0x06,
0x04, 0x06, 0x01, 0x06, 0x01, 0x05, 0x04, 0x06, 0x01, 0x06, 0x01, 0x05,
0x00, 0x05, 0x01, 0x1E, 0x0F, 0x06, 0x00, 0x05, 0x01, 0x1E, 0x0F, 0x06,
0x00, 0x05, 0x01, 0x1E, 0x0F, 0x01, 0x00, 0x05, 0x01, 0x1E, 0x0F, 0x01,
0x01, 0x04, 0x05, 0x08, 0x08, 0x01, 0x01, 0x04, 0x05, 0x08, 0x08, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
] ]
def SetLut(self): def SetLut(self):
self.M1S1M2S2_SendCommand(0x20) #vcom self.M1S1M2S2_SendCommand(0x20) # vcom
for count in range(0, 60): for count in range(0, 60):
self.M1S1M2S2_SendData(self.lut_vcom1[count]) self.M1S1M2S2_SendData(self.lut_vcom1[count])
self.M1S1M2S2_SendCommand(0x21) #red not use self.M1S1M2S2_SendCommand(0x21) # red not use
for count in range(0, 60): for count in range(0, 60):
self.M1S1M2S2_SendData(self.lut_ww1[count]) self.M1S1M2S2_SendData(self.lut_ww1[count])
self.M1S1M2S2_SendCommand(0x22) #bw r self.M1S1M2S2_SendCommand(0x22) # bw r
for count in range(0, 60): for count in range(0, 60):
self.M1S1M2S2_SendData(self.lut_bw1[count]) # bw=r self.M1S1M2S2_SendData(self.lut_bw1[count]) # bw=r
self.M1S1M2S2_SendCommand(0x23) #wb w self.M1S1M2S2_SendCommand(0x23) # wb w
for count in range(0, 60): for count in range(0, 60):
self.M1S1M2S2_SendData(self.lut_wb1[count]) # wb=w self.M1S1M2S2_SendData(self.lut_wb1[count]) # wb=w
self.M1S1M2S2_SendCommand(0x24) #bb b self.M1S1M2S2_SendCommand(0x24) # bb b
for count in range(0, 60): for count in range(0, 60):
self.M1S1M2S2_SendData(self.lut_bb1[count]) # bb=b self.M1S1M2S2_SendData(self.lut_bb1[count]) # bb=b
self.M1S1M2S2_SendCommand(0x25) #bb b self.M1S1M2S2_SendCommand(0x25) # bb b
for count in range(0, 60): for count in range(0, 60):
self.M1S1M2S2_SendData(self.lut_ww1[count]) # bb=b self.M1S1M2S2_SendData(self.lut_ww1[count]) # bb=b

View File

@ -1,57 +1,60 @@
# /***************************************************************************** """
# * | File : epd_12_in_48_colour.py * | File : epd_12_in_48_colour.py
# * | Author : Waveshare electrices, modified by Sebastien Harnist * | Author : Waveshare electrices, modified by Sebastien Harnist
# * | Function : Hardware underlying interface * | Function : Hardware underlying interface
# * | Info : * | Info :
# *---------------- *----------------
# * | This version: V1.1 * | This version: V1.1
# * | Date : 2022-11-23 * | Date : 2022-11-23
# * | Info : * | Info :
# ******************************************************************************/ ******************************************************************************/
# Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documnetation files (the "Software"), to deal of this software and associated documnetation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
# furished to do so, subject to the following conditions: furished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software. all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 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 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE. THE SOFTWARE.
# """
import time import time
from inkycal.display.drivers import epdconfig_12_in_48 as epdconfig from inkycal.display.drivers import epdconfig_12_in_48 as epdconfig
EPD_WIDTH = 1304 EPD_WIDTH = 1304
EPD_HEIGHT = 984 EPD_HEIGHT = 984
class EPD(object): class EPD(object):
def __init__(self): def __init__(self):
self.width = EPD_WIDTH self.width = EPD_WIDTH
self.height = EPD_HEIGHT self.height = EPD_HEIGHT
self.EPD_M1_CS_PIN = epdconfig.EPD_M1_CS_PIN self.EPD_M1_CS_PIN = epdconfig.EPD_M1_CS_PIN
self.EPD_S1_CS_PIN = epdconfig.EPD_S1_CS_PIN self.EPD_S1_CS_PIN = epdconfig.EPD_S1_CS_PIN
self.EPD_M2_CS_PIN = epdconfig.EPD_M2_CS_PIN self.EPD_M2_CS_PIN = epdconfig.EPD_M2_CS_PIN
self.EPD_S2_CS_PIN = epdconfig.EPD_S2_CS_PIN self.EPD_S2_CS_PIN = epdconfig.EPD_S2_CS_PIN
self.EPD_M1S1_DC_PIN = epdconfig.EPD_M1S1_DC_PIN self.EPD_M1S1_DC_PIN = epdconfig.EPD_M1S1_DC_PIN
self.EPD_M2S2_DC_PIN = epdconfig.EPD_M2S2_DC_PIN self.EPD_M2S2_DC_PIN = epdconfig.EPD_M2S2_DC_PIN
self.EPD_M1S1_RST_PIN = epdconfig.EPD_M1S1_RST_PIN self.EPD_M1S1_RST_PIN = epdconfig.EPD_M1S1_RST_PIN
self.EPD_M2S2_RST_PIN = epdconfig.EPD_M2S2_RST_PIN self.EPD_M2S2_RST_PIN = epdconfig.EPD_M2S2_RST_PIN
self.EPD_M1_BUSY_PIN = epdconfig.EPD_M1_BUSY_PIN self.EPD_M1_BUSY_PIN = epdconfig.EPD_M1_BUSY_PIN
self.EPD_S1_BUSY_PIN = epdconfig.EPD_S1_BUSY_PIN self.EPD_S1_BUSY_PIN = epdconfig.EPD_S1_BUSY_PIN
self.EPD_M2_BUSY_PIN = epdconfig.EPD_M2_BUSY_PIN self.EPD_M2_BUSY_PIN = epdconfig.EPD_M2_BUSY_PIN
self.EPD_S2_BUSY_PIN = epdconfig.EPD_S2_BUSY_PIN self.EPD_S2_BUSY_PIN = epdconfig.EPD_S2_BUSY_PIN
def init(self): def init(self):
print("EPD init...") print("EPD init...")
@ -65,7 +68,7 @@ class EPD(object):
# panel setting for Display # panel setting for Display
self.M1_SendCommand(0x00) self.M1_SendCommand(0x00)
self.M1_SendData(0x0f) #KW-3f KWR-2F BWROTP 0f BWOTP 1f self.M1_SendData(0x0f) # KW-3f KWR-2F BWROTP 0f BWOTP 1f
self.S1_SendCommand(0x00) self.S1_SendCommand(0x00)
self.S1_SendData(0x0f) self.S1_SendData(0x0f)
self.M2_SendCommand(0x00) self.M2_SendCommand(0x00)
@ -75,9 +78,9 @@ class EPD(object):
# booster soft start # booster soft start
self.M1_SendCommand(0x06) self.M1_SendCommand(0x06)
self.M1_SendData(0x17) #A self.M1_SendData(0x17) # A
self.M1_SendData(0x17) #B self.M1_SendData(0x17) # B
self.M1_SendData(0x39) #C self.M1_SendData(0x39) # C
self.M1_SendData(0x17) self.M1_SendData(0x17)
self.M2_SendCommand(0x06) self.M2_SendCommand(0x06)
self.M2_SendData(0x17) self.M2_SendData(0x17)
@ -85,36 +88,36 @@ class EPD(object):
self.M2_SendData(0x39) self.M2_SendData(0x39)
self.M2_SendData(0x17) self.M2_SendData(0x17)
#resolution setting # resolution setting
self.M1_SendCommand(0x61) self.M1_SendCommand(0x61)
self.M1_SendData(0x02) self.M1_SendData(0x02)
self.M1_SendData(0x88) #source 648 self.M1_SendData(0x88) # source 648
self.M1_SendData(0x01) #gate 492 self.M1_SendData(0x01) # gate 492
self.M1_SendData(0xEC) self.M1_SendData(0xEC)
self.S1_SendCommand(0x61) self.S1_SendCommand(0x61)
self.S1_SendData(0x02) self.S1_SendData(0x02)
self.S1_SendData(0x90) #source 656 self.S1_SendData(0x90) # source 656
self.S1_SendData(0x01) #gate 492 self.S1_SendData(0x01) # gate 492
self.S1_SendData(0xEC) self.S1_SendData(0xEC)
self.M2_SendCommand(0x61) self.M2_SendCommand(0x61)
self.M2_SendData(0x02) self.M2_SendData(0x02)
self.M2_SendData(0x90) #source 656 self.M2_SendData(0x90) # source 656
self.M2_SendData(0x01) #gate 492 self.M2_SendData(0x01) # gate 492
self.M2_SendData(0xEC) self.M2_SendData(0xEC)
self.S2_SendCommand(0x61) self.S2_SendCommand(0x61)
self.S2_SendData(0x02) self.S2_SendData(0x02)
self.S2_SendData(0x88) #source 648 self.S2_SendData(0x88) # source 648
self.S2_SendData(0x01) #gate 492 self.S2_SendData(0x01) # gate 492
self.S2_SendData(0xEC) self.S2_SendData(0xEC)
self.M1S1M2S2_SendCommand(0x15) #DUSPI self.M1S1M2S2_SendCommand(0x15) # DUSPI
self.M1S1M2S2_SendData(0x20) self.M1S1M2S2_SendData(0x20)
self.M1S1M2S2_SendCommand(0x50) #Vcom and data interval setting self.M1S1M2S2_SendCommand(0x50) # Vcom and data interval setting
self.M1S1M2S2_SendData(0x11) self.M1S1M2S2_SendData(0x11)
self.M1S1M2S2_SendData(0x07) self.M1S1M2S2_SendData(0x07)
self.M1S1M2S2_SendCommand(0x60)#TCON self.M1S1M2S2_SendCommand(0x60) # TCON
self.M1S1M2S2_SendData(0x22) self.M1S1M2S2_SendData(0x22)
self.M1S1M2S2_SendCommand(0xE3) self.M1S1M2S2_SendCommand(0xE3)
@ -126,106 +129,106 @@ class EPD(object):
def getbuffer(self, image): def getbuffer(self, image):
# logging.debug("bufsiz = ",int(self.width/8) * self.height) # logging.debug("bufsiz = ",int(self.width/8) * self.height)
buf = [0xFF] * (int(self.width/8) * self.height) buf = [0xFF] * (int(self.width / 8) * self.height)
image_monocolor = image.convert('1') image_monocolor = image.convert('1')
imwidth, imheight = image_monocolor.size imwidth, imheight = image_monocolor.size
pixels = image_monocolor.load() pixels = image_monocolor.load()
if(imwidth == self.width and imheight == self.height): if (imwidth == self.width and imheight == self.height):
for y in range(imheight): for y in range(imheight):
for x in range(imwidth): for x in range(imwidth):
# Set the bits for the column of pixels at the current position. # Set the bits for the column of pixels at the current position.
if pixels[x, y] == 0: if pixels[x, y] == 0:
buf[int((x + y * self.width) / 8)] &= ~(0x80 >> (x % 8)) buf[int((x + y * self.width) / 8)] &= ~(0x80 >> (x % 8))
elif(imwidth == self.height and imheight == self.width): elif (imwidth == self.height and imheight == self.width):
for y in range(imheight): for y in range(imheight):
for x in range(imwidth): for x in range(imwidth):
newx = y newx = y
newy = self.height - x - 1 newy = self.height - x - 1
if pixels[x, y] == 0: if pixels[x, y] == 0:
buf[int((newx + newy*self.width) / 8)] &= ~(0x80 >> (y % 8)) buf[int((newx + newy * self.width) / 8)] &= ~(0x80 >> (y % 8))
return buf return buf
def display(self, blackbuf, redbuf): def display(self, blackbuf, redbuf):
#S2 part 648*492 # S2 part 648*492
self.S2_SendCommand(0x10) self.S2_SendCommand(0x10)
for y in range(0, 492): for y in range(0, 492):
for x in range(0, 81): for x in range(0, 81):
self.S2_SendData(blackbuf[y*163 + x]) self.S2_SendData(blackbuf[y * 163 + x])
self.S2_SendCommand(0x13) self.S2_SendCommand(0x13)
for y in range(0, 492): for y in range(0, 492):
for x in range(0, 81): for x in range(0, 81):
self.S2_SendData(~redbuf[y*163 + x]) self.S2_SendData(~redbuf[y * 163 + x])
#M2 part 656*492 # M2 part 656*492
self.M2_SendCommand(0x10) self.M2_SendCommand(0x10)
for y in range(0, 492): for y in range(0, 492):
for x in range(81, 163): for x in range(81, 163):
self.M2_SendData(blackbuf[y*163 + x]) self.M2_SendData(blackbuf[y * 163 + x])
self.M2_SendCommand(0x13) self.M2_SendCommand(0x13)
for y in range(0, 492): for y in range(0, 492):
for x in range(81, 163): for x in range(81, 163):
self.M2_SendData(~redbuf[y*163 + x]) self.M2_SendData(~redbuf[y * 163 + x])
#M1 part 648*492 # M1 part 648*492
self.M1_SendCommand(0x10) self.M1_SendCommand(0x10)
for y in range(492, 984): for y in range(492, 984):
for x in range(0, 81): for x in range(0, 81):
self.M1_SendData(blackbuf[y*163 + x]) self.M1_SendData(blackbuf[y * 163 + x])
self.M1_SendCommand(0x13) self.M1_SendCommand(0x13)
for y in range(492, 984): for y in range(492, 984):
for x in range(0, 81): for x in range(0, 81):
self.M1_SendData(~redbuf[y*163 + x]) self.M1_SendData(~redbuf[y * 163 + x])
#S1 part 656*492 # S1 part 656*492
self.S1_SendCommand(0x10) self.S1_SendCommand(0x10)
for y in range(492, 984): for y in range(492, 984):
for x in range(81, 163): for x in range(81, 163):
self.S1_SendData(blackbuf[y*163 + x]) self.S1_SendData(blackbuf[y * 163 + x])
self.S1_SendCommand(0x13) self.S1_SendCommand(0x13)
for y in range(492, 984): for y in range(492, 984):
for x in range(81, 163): for x in range(81, 163):
self.S1_SendData(~redbuf[y*163 + x]) self.S1_SendData(~redbuf[y * 163 + x])
self.TurnOnDisplay() self.TurnOnDisplay()
def clear(self): def clear(self):
"""Clear contents of image buffer""" """Clear contents of image buffer"""
self.S2_SendCommand(0x10) self.S2_SendCommand(0x10)
for y in range(0, 492): for y in range(0, 492):
for x in range(0, 81): for x in range(0, 81):
self.S2_SendData(0xff) self.S2_SendData(0xff)
self.S2_SendCommand(0x13) self.S2_SendCommand(0x13)
for y in range(0, 492): for y in range(0, 492):
for x in range(0, 81): for x in range(0, 81):
self.S2_SendData(0x00) self.S2_SendData(0x00)
self.M2_SendCommand(0x10) self.M2_SendCommand(0x10)
for y in range(0, 492): for y in range(0, 492):
for x in range(81, 163): for x in range(81, 163):
self.M2_SendData(0xff) self.M2_SendData(0xff)
self.M2_SendCommand(0x13) self.M2_SendCommand(0x13)
for y in range(0, 492): for y in range(0, 492):
for x in range(81, 163): for x in range(81, 163):
self.M2_SendData(0x00) self.M2_SendData(0x00)
self.M1_SendCommand(0x10) self.M1_SendCommand(0x10)
for y in range(492, 984): for y in range(492, 984):
for x in range(0, 81): for x in range(0, 81):
self.M1_SendData(0xff) self.M1_SendData(0xff)
self.M1_SendCommand(0x13) self.M1_SendCommand(0x13)
for y in range(492, 984): for y in range(492, 984):
for x in range(0, 81): for x in range(0, 81):
self.M1_SendData(0x00) self.M1_SendData(0x00)
self.S1_SendCommand(0x10) self.S1_SendCommand(0x10)
for y in range(492, 984): for y in range(492, 984):
for x in range(81, 163): for x in range(81, 163):
self.S1_SendData(0xff) self.S1_SendData(0xff)
self.S1_SendCommand(0x13) self.S1_SendCommand(0x13)
for y in range(492, 984): for y in range(492, 984):
for x in range(81, 163): for x in range(81, 163):
self.S1_SendData(0x00) self.S1_SendData(0x00)
self.TurnOnDisplay() self.TurnOnDisplay()
@ -261,6 +264,7 @@ class EPD(object):
self.S2_ReadBusy() self.S2_ReadBusy()
""" M1S1M2S2 Write register address and data """ """ M1S1M2S2 Write register address and data """
def M1S1M2S2_SendCommand(self, cmd): def M1S1M2S2_SendCommand(self, cmd):
epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 0) epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 0)
epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 0) epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 0)
@ -290,6 +294,7 @@ class EPD(object):
epdconfig.digital_write(self.EPD_S2_CS_PIN, 1) epdconfig.digital_write(self.EPD_S2_CS_PIN, 1)
""" M1M2 Write register address and data """ """ M1M2 Write register address and data """
def M1M2_SendCommand(self, cmd): def M1M2_SendCommand(self, cmd):
epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 0) epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 0)
epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 0) epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 0)
@ -309,11 +314,13 @@ class EPD(object):
epdconfig.digital_write(self.EPD_M2_CS_PIN, 1) epdconfig.digital_write(self.EPD_M2_CS_PIN, 1)
""" S2 Write register address and data """ """ S2 Write register address and data """
def S2_SendCommand(self, cmd): def S2_SendCommand(self, cmd):
epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 0) epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 0)
epdconfig.digital_write(self.EPD_S2_CS_PIN, 0) epdconfig.digital_write(self.EPD_S2_CS_PIN, 0)
epdconfig.spi_writebyte(cmd) epdconfig.spi_writebyte(cmd)
epdconfig.digital_write(self.EPD_S2_CS_PIN, 1) epdconfig.digital_write(self.EPD_S2_CS_PIN, 1)
def S2_SendData(self, val): def S2_SendData(self, val):
epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 1) epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 1)
epdconfig.digital_write(self.EPD_S2_CS_PIN, 0) epdconfig.digital_write(self.EPD_S2_CS_PIN, 0)
@ -321,11 +328,13 @@ class EPD(object):
epdconfig.digital_write(self.EPD_S2_CS_PIN, 1) epdconfig.digital_write(self.EPD_S2_CS_PIN, 1)
""" M2 Write register address and data """ """ M2 Write register address and data """
def M2_SendCommand(self, cmd): def M2_SendCommand(self, cmd):
epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 0) epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 0)
epdconfig.digital_write(self.EPD_M2_CS_PIN, 0) epdconfig.digital_write(self.EPD_M2_CS_PIN, 0)
epdconfig.spi_writebyte(cmd) epdconfig.spi_writebyte(cmd)
epdconfig.digital_write(self.EPD_M2_CS_PIN, 1) epdconfig.digital_write(self.EPD_M2_CS_PIN, 1)
def M2_SendData(self, val): def M2_SendData(self, val):
epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 1) epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 1)
epdconfig.digital_write(self.EPD_M2_CS_PIN, 0) epdconfig.digital_write(self.EPD_M2_CS_PIN, 0)
@ -333,11 +342,13 @@ class EPD(object):
epdconfig.digital_write(self.EPD_M2_CS_PIN, 1) epdconfig.digital_write(self.EPD_M2_CS_PIN, 1)
""" S1 Write register address and data """ """ S1 Write register address and data """
def S1_SendCommand(self, cmd): def S1_SendCommand(self, cmd):
epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 0) epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 0)
epdconfig.digital_write(self.EPD_S1_CS_PIN, 0) epdconfig.digital_write(self.EPD_S1_CS_PIN, 0)
epdconfig.spi_writebyte(cmd) epdconfig.spi_writebyte(cmd)
epdconfig.digital_write(self.EPD_S1_CS_PIN, 1) epdconfig.digital_write(self.EPD_S1_CS_PIN, 1)
def S1_SendData(self, val): def S1_SendData(self, val):
epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 1) epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 1)
epdconfig.digital_write(self.EPD_S1_CS_PIN, 0) epdconfig.digital_write(self.EPD_S1_CS_PIN, 0)
@ -345,141 +356,146 @@ class EPD(object):
epdconfig.digital_write(self.EPD_S1_CS_PIN, 1) epdconfig.digital_write(self.EPD_S1_CS_PIN, 1)
""" M1 Write register address and data """ """ M1 Write register address and data """
def M1_SendCommand(self, cmd): def M1_SendCommand(self, cmd):
epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 0) epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 0)
epdconfig.digital_write(self.EPD_M1_CS_PIN, 0) epdconfig.digital_write(self.EPD_M1_CS_PIN, 0)
epdconfig.spi_writebyte(cmd) epdconfig.spi_writebyte(cmd)
epdconfig.digital_write(self.EPD_M1_CS_PIN, 1) epdconfig.digital_write(self.EPD_M1_CS_PIN, 1)
def M1_SendData(self, val): def M1_SendData(self, val):
epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 1) epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 1)
epdconfig.digital_write(self.EPD_M1_CS_PIN, 0) epdconfig.digital_write(self.EPD_M1_CS_PIN, 0)
epdconfig.spi_writebyte(val) epdconfig.spi_writebyte(val)
epdconfig.digital_write(self.EPD_M1_CS_PIN, 1) epdconfig.digital_write(self.EPD_M1_CS_PIN, 1)
#Busy # Busy
def M1_ReadBusy(self): def M1_ReadBusy(self):
self.M1_SendCommand(0x71) self.M1_SendCommand(0x71)
busy = epdconfig.digital_read(self.EPD_M1_BUSY_PIN) busy = epdconfig.digital_read(self.EPD_M1_BUSY_PIN)
busy = not(busy & 0x01) busy = not (busy & 0x01)
while(busy): while (busy):
self.M1_SendCommand(0x71) self.M1_SendCommand(0x71)
busy = epdconfig.digital_read(self.EPD_M1_BUSY_PIN) busy = epdconfig.digital_read(self.EPD_M1_BUSY_PIN)
busy = not(busy & 0x01) busy = not (busy & 0x01)
time.sleep(0.2) time.sleep(0.2)
def M2_ReadBusy(self): def M2_ReadBusy(self):
self.M2_SendCommand(0x71) self.M2_SendCommand(0x71)
busy = epdconfig.digital_read(self.EPD_M2_BUSY_PIN) busy = epdconfig.digital_read(self.EPD_M2_BUSY_PIN)
busy = not(busy & 0x01) busy = not (busy & 0x01)
self.M2_SendCommand(0x71) self.M2_SendCommand(0x71)
while(busy): while (busy):
self.M2_SendCommand(0x71) self.M2_SendCommand(0x71)
busy = epdconfig.digital_read(self.EPD_M2_BUSY_PIN) busy = epdconfig.digital_read(self.EPD_M2_BUSY_PIN)
busy =not(busy & 0x01) busy = not (busy & 0x01)
time.sleep(0.2) time.sleep(0.2)
def S1_ReadBusy(self): def S1_ReadBusy(self):
self.S1_SendCommand(0x71) self.S1_SendCommand(0x71)
busy = epdconfig.digital_read(self.EPD_S1_BUSY_PIN) busy = epdconfig.digital_read(self.EPD_S1_BUSY_PIN)
busy = not(busy & 0x01) busy = not (busy & 0x01)
while(busy): while (busy):
self.S1_SendCommand(0x71) self.S1_SendCommand(0x71)
busy = epdconfig.digital_read(self.EPD_S1_BUSY_PIN) busy = epdconfig.digital_read(self.EPD_S1_BUSY_PIN)
busy = not(busy & 0x01) busy = not (busy & 0x01)
time.sleep(0.2) time.sleep(0.2)
def S2_ReadBusy(self): def S2_ReadBusy(self):
self.S2_SendCommand(0x71) self.S2_SendCommand(0x71)
busy = epdconfig.digital_read(self.EPD_S2_BUSY_PIN) busy = epdconfig.digital_read(self.EPD_S2_BUSY_PIN)
busy = not(busy & 0x01) busy = not (busy & 0x01)
while(busy): while (busy):
self.S2_SendCommand(0x71) self.S2_SendCommand(0x71)
busy = epdconfig.digital_read(self.EPD_S2_BUSY_PIN) busy = epdconfig.digital_read(self.EPD_S2_BUSY_PIN)
busy = not(busy & 0x01) busy = not (busy & 0x01)
time.sleep(0.2) time.sleep(0.2)
lut_vcom1 = [ lut_vcom1 = [
0x00, 0x10, 0x10, 0x01, 0x08, 0x01, 0x00, 0x10, 0x10, 0x01, 0x08, 0x01,
0x00, 0x06, 0x01, 0x06, 0x01, 0x05, 0x00, 0x06, 0x01, 0x06, 0x01, 0x05,
0x00, 0x08, 0x01, 0x08, 0x01, 0x06, 0x00, 0x08, 0x01, 0x08, 0x01, 0x06,
0x00, 0x06, 0x01, 0x06, 0x01, 0x05, 0x00, 0x06, 0x01, 0x06, 0x01, 0x05,
0x00, 0x05, 0x01, 0x1E, 0x0F, 0x06, 0x00, 0x05, 0x01, 0x1E, 0x0F, 0x06,
0x00, 0x05, 0x01, 0x1E, 0x0F, 0x01, 0x00, 0x05, 0x01, 0x1E, 0x0F, 0x01,
0x00, 0x04, 0x05, 0x08, 0x08, 0x01, 0x00, 0x04, 0x05, 0x08, 0x08, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
] ]
lut_ww1 = [ lut_ww1 = [
0x91, 0x10, 0x10, 0x01, 0x08, 0x01, 0x91, 0x10, 0x10, 0x01, 0x08, 0x01,
0x04, 0x06, 0x01, 0x06, 0x01, 0x05, 0x04, 0x06, 0x01, 0x06, 0x01, 0x05,
0x84, 0x08, 0x01, 0x08, 0x01, 0x06, 0x84, 0x08, 0x01, 0x08, 0x01, 0x06,
0x80, 0x06, 0x01, 0x06, 0x01, 0x05, 0x80, 0x06, 0x01, 0x06, 0x01, 0x05,
0x00, 0x05, 0x01, 0x1E, 0x0F, 0x06, 0x00, 0x05, 0x01, 0x1E, 0x0F, 0x06,
0x00, 0x05, 0x01, 0x1E, 0x0F, 0x01, 0x00, 0x05, 0x01, 0x1E, 0x0F, 0x01,
0x08, 0x04, 0x05, 0x08, 0x08, 0x01, 0x08, 0x04, 0x05, 0x08, 0x08, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
] ]
lut_bw1 = [ lut_bw1 = [
0xA8, 0x10, 0x10, 0x01, 0x08, 0x01, 0xA8, 0x10, 0x10, 0x01, 0x08, 0x01,
0x84, 0x06, 0x01, 0x06, 0x01, 0x05, 0x84, 0x06, 0x01, 0x06, 0x01, 0x05,
0x84, 0x08, 0x01, 0x08, 0x01, 0x06, 0x84, 0x08, 0x01, 0x08, 0x01, 0x06,
0x86, 0x06, 0x01, 0x06, 0x01, 0x05, 0x86, 0x06, 0x01, 0x06, 0x01, 0x05,
0x8C, 0x05, 0x01, 0x1E, 0x0F, 0x06, 0x8C, 0x05, 0x01, 0x1E, 0x0F, 0x06,
0x8C, 0x05, 0x01, 0x1E, 0x0F, 0x01, 0x8C, 0x05, 0x01, 0x1E, 0x0F, 0x01,
0xF0, 0x04, 0x05, 0x08, 0x08, 0x01, 0xF0, 0x04, 0x05, 0x08, 0x08, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
] ]
lut_wb1 = [ lut_wb1 = [
0x91, 0x10, 0x10, 0x01, 0x08, 0x01, 0x91, 0x10, 0x10, 0x01, 0x08, 0x01,
0x04, 0x06, 0x01, 0x06, 0x01, 0x05, 0x04, 0x06, 0x01, 0x06, 0x01, 0x05,
0x84, 0x08, 0x01, 0x08, 0x01, 0x06, 0x84, 0x08, 0x01, 0x08, 0x01, 0x06,
0x80, 0x06, 0x01, 0x06, 0x01, 0x05, 0x80, 0x06, 0x01, 0x06, 0x01, 0x05,
0x00, 0x05, 0x01, 0x1E, 0x0F, 0x06, 0x00, 0x05, 0x01, 0x1E, 0x0F, 0x06,
0x00, 0x05, 0x01, 0x1E, 0x0F, 0x01, 0x00, 0x05, 0x01, 0x1E, 0x0F, 0x01,
0x08, 0x04, 0x05, 0x08, 0x08, 0x01, 0x08, 0x04, 0x05, 0x08, 0x08, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
] ]
lut_bb1 = [ lut_bb1 = [
0x92, 0x10, 0x10, 0x01, 0x08, 0x01, 0x92, 0x10, 0x10, 0x01, 0x08, 0x01,
0x80, 0x06, 0x01, 0x06, 0x01, 0x05, 0x80, 0x06, 0x01, 0x06, 0x01, 0x05,
0x84, 0x08, 0x01, 0x08, 0x01, 0x06, 0x84, 0x08, 0x01, 0x08, 0x01, 0x06,
0x04, 0x06, 0x01, 0x06, 0x01, 0x05, 0x04, 0x06, 0x01, 0x06, 0x01, 0x05,
0x00, 0x05, 0x01, 0x1E, 0x0F, 0x06, 0x00, 0x05, 0x01, 0x1E, 0x0F, 0x06,
0x00, 0x05, 0x01, 0x1E, 0x0F, 0x01, 0x00, 0x05, 0x01, 0x1E, 0x0F, 0x01,
0x01, 0x04, 0x05, 0x08, 0x08, 0x01, 0x01, 0x04, 0x05, 0x08, 0x08, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
] ]
def SetLut(self): def SetLut(self):
self.M1S1M2S2_SendCommand(0x20) #vcom self.M1S1M2S2_SendCommand(0x20) # vcom
for count in range(0, 60): for count in range(0, 60):
self.M1S1M2S2_SendData(self.lut_vcom1[count]) self.M1S1M2S2_SendData(self.lut_vcom1[count])
self.M1S1M2S2_SendCommand(0x21) #red not use self.M1S1M2S2_SendCommand(0x21) # red not use
for count in range(0, 60): for count in range(0, 60):
self.M1S1M2S2_SendData(self.lut_ww1[count]) self.M1S1M2S2_SendData(self.lut_ww1[count])
self.M1S1M2S2_SendCommand(0x22) #bw r self.M1S1M2S2_SendCommand(0x22) # bw r
for count in range(0, 60): for count in range(0, 60):
self.M1S1M2S2_SendData(self.lut_bw1[count]) # bw=r self.M1S1M2S2_SendData(self.lut_bw1[count]) # bw=r
self.M1S1M2S2_SendCommand(0x23) #wb w self.M1S1M2S2_SendCommand(0x23) # wb w
for count in range(0, 60): for count in range(0, 60):
self.M1S1M2S2_SendData(self.lut_wb1[count]) # wb=w self.M1S1M2S2_SendData(self.lut_wb1[count]) # wb=w
self.M1S1M2S2_SendCommand(0x24) #bb b self.M1S1M2S2_SendCommand(0x24) # bb b
for count in range(0, 60): for count in range(0, 60):
self.M1S1M2S2_SendData(self.lut_bb1[count]) # bb=b self.M1S1M2S2_SendData(self.lut_bb1[count]) # bb=b
self.M1S1M2S2_SendCommand(0x25) #bb b self.M1S1M2S2_SendCommand(0x25) # bb b
for count in range(0, 60): for count in range(0, 60):
self.M1S1M2S2_SendData(self.lut_ww1[count]) # bb=b self.M1S1M2S2_SendData(self.lut_ww1[count]) # bb=b
def M1_ReadTemperature(self): def M1_ReadTemperature(self):
self.M1_SendCommand(0x40) self.M1_SendCommand(0x40)

View File

@ -1,37 +1,35 @@
# ***************************************************************************** """
# * | File : epd4in2.py * | File : epd4in2.py
# * | Author : Waveshare team * | Author : Waveshare team
# * | Function : Electronic paper driver * | Function : Electronic paper driver
# * | Info : * | Info :
# *---------------- *----------------
# * | This version: V4.0 * | This version: V4.0
# * | Date : 2019-06-20 * | Date : 2019-06-20
# # | Info : python demo # | Info : python demo
# ----------------------------------------------------------------------------- -----------------------------------------------------------------------------
# Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documnetation files (the "Software"), to deal of this software and associated documnetation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
# furished to do so, subject to the following conditions: furished 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 OR 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.
#
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 OR 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.
"""
import logging import logging
from inkycal.display.drivers import epdconfig from inkycal.display.drivers import epdconfig
from PIL import Image
import RPi.GPIO as GPIO
# Display resolution # Display resolution
EPD_WIDTH = 400 EPD_WIDTH = 400
@ -354,8 +352,8 @@ class EPD:
i = i + 1 i = i + 1
if (i % 4 == 0): if (i % 4 == 0):
buf[int((x + (y * self.width)) / 4)] = ( buf[int((x + (y * self.width)) / 4)] = (
(pixels[x - 3, y] & 0xc0) | (pixels[x - 2, y] & 0xc0) >> 2 | ( (pixels[x - 3, y] & 0xc0) | (pixels[x - 2, y] & 0xc0) >> 2 | (
pixels[x - 1, y] & 0xc0) >> 4 | (pixels[x, y] & 0xc0) >> 6) pixels[x - 1, y] & 0xc0) >> 4 | (pixels[x, y] & 0xc0) >> 6)
elif (imwidth == self.height and imheight == self.width): elif (imwidth == self.height and imheight == self.width):
logging.debug("Horizontal") logging.debug("Horizontal")
@ -370,8 +368,8 @@ class EPD:
i = i + 1 i = i + 1
if (i % 4 == 0): if (i % 4 == 0):
buf[int((newx + (newy * self.width)) / 4)] = ( buf[int((newx + (newy * self.width)) / 4)] = (
(pixels[x, y - 3] & 0xc0) | (pixels[x, y - 2] & 0xc0) >> 2 | ( (pixels[x, y - 3] & 0xc0) | (pixels[x, y - 2] & 0xc0) >> 2 | (
pixels[x, y - 1] & 0xc0) >> 4 | (pixels[x, y] & 0xc0) >> 6) pixels[x, y - 1] & 0xc0) >> 4 | (pixels[x, y] & 0xc0) >> 6)
return buf return buf

View File

@ -1,33 +1,34 @@
# ***************************************************************************** """
# * | File : epd4in2bc.py * | File : epd4in2bc.py
# * | Author : Waveshare team * | Author : Waveshare team
# * | Function : Electronic paper driver * | Function : Electronic paper driver
# * | Info : * | Info :
# *---------------- *----------------
# * | This version: V4.0 * | This version: V4.0
# * | Date : 2019-06-20 * | Date : 2019-06-20
# # | Info : python demo # | Info : python demo
# ----------------------------------------------------------------------------- -----------------------------------------------------------------------------
# Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documnetation files (the "Software"), to deal of this software and associated documnetation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
# furished to do so, subject to the following conditions: furished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software. all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 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 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE. THE SOFTWARE.
# """
import logging import logging
from inkycal.display.drivers import epdconfig from inkycal.display.drivers import epdconfig
# Display resolution # Display resolution

View File

@ -1,34 +1,34 @@
# ***************************************************************************** """
# * | File : epd5in83.py * | File : epd5in83.py
# * | Author : Waveshare team * | Author : Waveshare team
# * | Function : Electronic paper driver * | Function : Electronic paper driver
# * | Info : * | Info :
# *---------------- *----------------
# * | This version: V4.0 * | This version: V4.0
# * | Date : 2019-06-20 * | Date : 2019-06-20
# # | Info : python demo # | Info : python demo
# ----------------------------------------------------------------------------- -----------------------------------------------------------------------------
# Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documnetation files (the "Software"), to deal of this software and associated documnetation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
# furished to do so, subject to the following conditions: furished 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 OR 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.
#
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 OR 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.
"""
import logging import logging
from inkycal.display.drivers import epdconfig from inkycal.display.drivers import epdconfig
# Display resolution # Display resolution

View File

@ -1,34 +1,34 @@
# ***************************************************************************** """
# * | File : epd5in83b.py * | File : epd5in83b.py
# * | Author : Waveshare team * | Author : Waveshare team
# * | Function : Electronic paper driver * | Function : Electronic paper driver
# * | Info : * | Info :
# *---------------- *----------------
# * | This version: V4.0 * | This version: V4.0
# * | Date : 2019-06-20 * | Date : 2019-06-20
# # | Info : python demo # | Info : python demo
# ----------------------------------------------------------------------------- -----------------------------------------------------------------------------
# Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documnetation files (the "Software"), to deal of this software and associated documnetation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
# furished to do so, subject to the following conditions: furished 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 OR 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.
#
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 OR 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.
"""
import logging import logging
from inkycal.display.drivers import epdconfig from inkycal.display.drivers import epdconfig
# Display resolution # Display resolution

View File

@ -1,34 +1,34 @@
# ***************************************************************************** """
# * | File : epd7in5.py * | File : epd7in5.py
# * | Author : Waveshare team * | Author : Waveshare team
# * | Function : Electronic paper driver * | Function : Electronic paper driver
# * | Info : * | Info :
# *---------------- *----------------
# * | This version: V4.0 * | This version: V4.0
# * | Date : 2019-06-20 * | Date : 2019-06-20
# # | Info : python demo # | Info : python demo
# ----------------------------------------------------------------------------- -----------------------------------------------------------------------------
# Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documnetation files (the "Software"), to deal of this software and associated documnetation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
# furished to do so, subject to the following conditions: furished 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 OR 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.
#
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 OR 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.
"""
import logging import logging
from inkycal.display.drivers import epdconfig from inkycal.display.drivers import epdconfig
# Display resolution # Display resolution

View File

@ -1,34 +1,34 @@
# ***************************************************************************** """
# * | File : epd7in5bc.py * | File : epd7in5bc.py
# * | Author : Waveshare team * | Author : Waveshare team
# * | Function : Electronic paper driver * | Function : Electronic paper driver
# * | Info : * | Info :
# *---------------- *----------------
# * | This version: V4.0 * | This version: V4.0
# * | Date : 2019-06-20 * | Date : 2019-06-20
# # | Info : python demo # | Info : python demo
# ----------------------------------------------------------------------------- -----------------------------------------------------------------------------
# Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documnetation files (the "Software"), to deal of this software and associated documnetation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
# furished to do so, subject to the following conditions: furished 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 OR 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.
#
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 OR 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.
"""
import logging import logging
from inkycal.display.drivers import epdconfig from inkycal.display.drivers import epdconfig
# Display resolution # Display resolution

View File

@ -1,34 +1,34 @@
# ***************************************************************************** """
# * | File : epd7in5.py * | File : epd7in5.py
# * | Author : Waveshare team * | Author : Waveshare team
# * | Function : Electronic paper driver * | Function : Electronic paper driver
# * | Info : * | Info :
# *---------------- *----------------
# * | This version: V4.0 * | This version: V4.0
# * | Date : 2019-06-20 * | Date : 2019-06-20
# # | Info : python demo # | Info : python demo
# ----------------------------------------------------------------------------- -----------------------------------------------------------------------------
# Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documnetation files (the "Software"), to deal of this software and associated documnetation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
# furished to do so, subject to the following conditions: furished 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 OR 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.
#
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 OR 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.
"""
import logging import logging
from inkycal.display.drivers import epdconfig from inkycal.display.drivers import epdconfig
# Display resolution # Display resolution

View File

@ -1,15 +1,15 @@
# ***************************************************************************** # *****************************************************************************
# * | File : epd7in5bc.py # * | File : epd7in5b_V2.py
# * | Author : Waveshare team # * | Author : Waveshare team
# * | Function : Electronic paper driver # * | Function : Electronic paper driver
# * | Info : # * | Info :
# *---------------- # *----------------
# * | This version: V4.0 # * | This version: V4.2
# * | Date : 2019-06-20 # * | Date : 2022-01-08
# # | Info : python demo # # | Info : python demo
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
# Permission is hereby granted, free of charge, to any person obtaining a copy # Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documnetation files (the "Software"), to deal # of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights # in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is # copies of the Software, and to permit persons to whom the Software is
@ -29,12 +29,15 @@
import logging import logging
from inkycal.display.drivers import epdconfig
from . import epdconfig
# Display resolution # Display resolution
EPD_WIDTH = 800 EPD_WIDTH = 800
EPD_HEIGHT = 480 EPD_HEIGHT = 480
logger = logging.getLogger(__name__)
class EPD: class EPD:
def __init__(self): def __init__(self):
@ -66,97 +69,107 @@ class EPD:
epdconfig.spi_writebyte([data]) epdconfig.spi_writebyte([data])
epdconfig.digital_write(self.cs_pin, 1) epdconfig.digital_write(self.cs_pin, 1)
def send_data2(self, data): # faster
epdconfig.digital_write(self.dc_pin, 1)
epdconfig.digital_write(self.cs_pin, 0)
epdconfig.spi_writebyte2(data)
epdconfig.digital_write(self.cs_pin, 1)
def ReadBusy(self): def ReadBusy(self):
logging.debug("e-Paper busy") logger.debug("e-Paper busy")
self.send_command(0x71) self.send_command(0x71)
busy = epdconfig.digital_read(self.busy_pin) busy = epdconfig.digital_read(self.busy_pin)
while (busy == 0): while (busy == 0):
self.send_command(0x71) self.send_command(0x71)
busy = epdconfig.digital_read(self.busy_pin) busy = epdconfig.digital_read(self.busy_pin)
epdconfig.delay_ms(200) epdconfig.delay_ms(200)
logger.debug("e-Paper busy release")
def init(self): def init(self):
if (epdconfig.module_init() != 0): if epdconfig.module_init() != 0:
return -1 return -1
self.reset() self.reset()
self.send_command(0x01); # POWER SETTING self.send_command(0x01) # POWER SETTING
self.send_data(0x07); self.send_data(0x07)
self.send_data(0x07); # VGH=20V,VGL=-20V self.send_data(0x07) # VGH=20V,VGL=-20V
self.send_data(0x3f); # VDH=15V self.send_data(0x3f) # VDH=15V
self.send_data(0x3f); # VDL=-15V self.send_data(0x3f) # VDL=-15V
self.send_command(0x04); # POWER ON self.send_command(0x04) # POWER ON
epdconfig.delay_ms(100); epdconfig.delay_ms(100)
self.ReadBusy(); self.ReadBusy()
self.send_command(0X00); # PANNEL SETTING self.send_command(0X00) # PANNEL SETTING
self.send_data(0x0F); # KW-3f KWR-2F BWROTP 0f BWOTP 1f self.send_data(0x0F) # KW-3f KWR-2F BWROTP-0f BWOTP-1f
self.send_command(0x61); # tres self.send_command(0x61) # tres
self.send_data(0x03); # source 800 self.send_data(0x03) # source 800
self.send_data(0x20); self.send_data(0x20)
self.send_data(0x01); # gate 480 self.send_data(0x01) # gate 480
self.send_data(0xE0); self.send_data(0xE0)
self.send_command(0X15); self.send_command(0X15)
self.send_data(0x00); self.send_data(0x00)
self.send_command(0X50); # VCOM AND DATA INTERVAL SETTING self.send_command(0X50) # VCOM AND DATA INTERVAL SETTING
self.send_data(0x11); self.send_data(0x11)
self.send_data(0x07); self.send_data(0x07)
self.send_command(0X60); # TCON SETTING self.send_command(0X60) # TCON SETTING
self.send_data(0x22); self.send_data(0x22)
self.send_command(0x65)
self.send_data(0x00)
self.send_data(0x00)
self.send_data(0x00)
self.send_data(0x00)
return 0 return 0
def getbuffer(self, image): def getbuffer(self, image):
# logging.debug("bufsiz = ",int(self.width/8) * self.height) img = image
buf = [0xFF] * (int(self.width / 8) * self.height) imwidth, imheight = img.size
image_monocolor = image.convert('1') if imwidth == self.width and imheight == self.height:
imwidth, imheight = image_monocolor.size img = img.convert('1')
pixels = image_monocolor.load() elif imwidth == self.height and imheight == self.width:
logging.debug('imwidth = %d imheight = %d ', imwidth, imheight) # image has correct dimensions, but needs to be rotated
if (imwidth == self.width and imheight == self.height): img = img.rotate(90, expand=True).convert('1')
logging.debug("Horizontal") else:
for y in range(imheight): logger.warning("Wrong image dimensions: must be " + str(self.width) + "x" + str(self.height))
for x in range(imwidth): # return a blank buffer
# Set the bits for the column of pixels at the current position. return [0x00] * (int(self.width / 8) * self.height)
if pixels[x, y] == 0:
buf[int((x + y * self.width) / 8)] &= ~(0x80 >> (x % 8)) buf = bytearray(img.tobytes('raw'))
elif (imwidth == self.height and imheight == self.width): # The bytes need to be inverted, because in the PIL world 0=black and 1=white, but
logging.debug("Vertical") # in the e-paper world 0=white and 1=black.
for y in range(imheight): for i in range(len(buf)):
for x in range(imwidth): buf[i] ^= 0xFF
newx = y
newy = self.height - x - 1
if pixels[x, y] == 0:
buf[int((newx + newy * self.width) / 8)] &= ~(0x80 >> (y % 8))
return buf return buf
def display(self, imageblack, imagered): def display(self, imageblack, imagered):
self.send_command(0x10) self.send_command(0x10)
for i in range(0, int(self.width * self.height / 8)): # The black bytes need to be inverted back from what getbuffer did
self.send_data(imageblack[i]); for i in range(len(imageblack)):
imageblack[i] ^= 0xFF
self.send_data2(imageblack)
self.send_command(0x13) self.send_command(0x13)
for i in range(0, int(self.width * self.height / 8)): self.send_data2(imagered)
self.send_data(~imagered[i]);
self.send_command(0x12) self.send_command(0x12)
epdconfig.delay_ms(100) epdconfig.delay_ms(100)
self.ReadBusy() self.ReadBusy()
def Clear(self): def Clear(self):
buf = [0x00] * (int(self.width / 8) * self.height)
buf2 = [0xff] * (int(self.width / 8) * self.height)
self.send_command(0x10) self.send_command(0x10)
for i in range(0, int(self.width * self.height / 8)): self.send_data2(buf2)
self.send_data(0xff)
self.send_command(0x13) self.send_command(0x13)
for i in range(0, int(self.width * self.height / 8)): self.send_data2(buf)
self.send_data(0x00)
self.send_command(0x12) self.send_command(0x12)
epdconfig.delay_ms(100) epdconfig.delay_ms(100)
@ -169,5 +182,5 @@ class EPD:
self.send_command(0x07) # DEEP_SLEEP self.send_command(0x07) # DEEP_SLEEP
self.send_data(0XA5) self.send_data(0XA5)
epdconfig.delay_ms(2000)
epdconfig.module_exit() epdconfig.module_exit()
### END OF FILE ###

View File

@ -1,31 +1,31 @@
# ***************************************************************************** """
# * | File : epd7in5.py * | File : epd7in5.py
# * | Author : Waveshare team * | Author : Waveshare team
# * | Function : Electronic paper driver * | Function : Electronic paper driver
# * | Info : * | Info :
# *---------------- *----------------
# * | This version: V4.0 * | This version: V4.0
# * | Date : 2019-06-20 * | Date : 2019-06-20
# # | Info : python demo # | Info : python demo
# ----------------------------------------------------------------------------- -----------------------------------------------------------------------------
# Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documnetation files (the "Software"), to deal of this software and associated documnetation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
# furished to do so, subject to the following conditions: furished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software. all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 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 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE. THE SOFTWARE.
# """
import logging import logging
@ -79,60 +79,60 @@ class EPD:
# EPD hardware init start # EPD hardware init start
self.reset() self.reset()
self.ReadBusy(); self.ReadBusy()
self.send_command(0x12); # SWRESET self.send_command(0x12) # SWRESET
self.ReadBusy(); self.ReadBusy()
self.send_command(0x46); # Auto Write Red RAM self.send_command(0x46) # Auto Write Red RAM
self.send_data(0xf7); self.send_data(0xf7)
self.ReadBusy(); self.ReadBusy()
self.send_command(0x47); # Auto Write B/W RAM self.send_command(0x47) # Auto Write B/W RAM
self.send_data(0xf7); self.send_data(0xf7)
self.ReadBusy(); self.ReadBusy()
self.send_command(0x0C); # Soft start setting self.send_command(0x0C) # Soft start setting
self.send_data(0xAE); self.send_data(0xAE)
self.send_data(0xC7); self.send_data(0xC7)
self.send_data(0xC3); self.send_data(0xC3)
self.send_data(0xC0); self.send_data(0xC0)
self.send_data(0x40); self.send_data(0x40)
self.send_command(0x01); # Set MUX as 527 self.send_command(0x01) # Set MUX as 527
self.send_data(0xAF); self.send_data(0xAF)
self.send_data(0x02); self.send_data(0x02)
self.send_data(0x01); # 0x01 self.send_data(0x01) # 0x01
self.send_command(0x11); # Data entry mode self.send_command(0x11) # Data entry mode
self.send_data(0x01); self.send_data(0x01)
self.send_command(0x44); self.send_command(0x44)
self.send_data(0x00); # RAM x address start at 0 self.send_data(0x00) # RAM x address start at 0
self.send_data(0x00); self.send_data(0x00)
self.send_data(0x6F); self.send_data(0x6F)
self.send_data(0x03); self.send_data(0x03)
self.send_command(0x45); self.send_command(0x45)
self.send_data(0xAF); self.send_data(0xAF)
self.send_data(0x02); self.send_data(0x02)
self.send_data(0x00); self.send_data(0x00)
self.send_data(0x00); self.send_data(0x00)
self.send_command(0x3C); # VBD self.send_command(0x3C) # VBD
self.send_data(0x05); # LUT1, for white self.send_data(0x05) # LUT1, for white
self.send_command(0x18); self.send_command(0x18)
self.send_data(0X80); self.send_data(0X80)
self.send_command(0x22); self.send_command(0x22)
self.send_data(0XB1); # Load Temperature and waveform setting. self.send_data(0XB1) # Load Temperature and waveform setting.
self.send_command(0x20); self.send_command(0x20)
self.ReadBusy(); self.ReadBusy()
self.send_command(0x4E); # set RAM x address count to 0; self.send_command(0x4E) # set RAM x address count to 0
self.send_data(0x00); self.send_data(0x00)
self.send_data(0x00); self.send_data(0x00)
self.send_command(0x4F); self.send_command(0x4F)
self.send_data(0x00); self.send_data(0x00)
self.send_data(0x00); self.send_data(0x00)
# EPD hardware init end # EPD hardware init end
return 0 return 0
@ -161,23 +161,23 @@ class EPD:
return buf return buf
def display(self, image): def display(self, image):
self.send_command(0x4F); self.send_command(0x4F)
self.send_data(0x00); self.send_data(0x00)
self.send_data(0x00); self.send_data(0x00)
self.send_command(0x24); self.send_command(0x24)
for i in range(0, int(self.width * self.height / 8)): for i in range(0, int(self.width * self.height / 8)):
self.send_data(image[i]); self.send_data(image[i])
self.send_command(0x22); self.send_command(0x22)
self.send_data(0xF7); # Load LUT from MCU(0x32) self.send_data(0xF7) # Load LUT from MCU(0x32)
self.send_command(0x20); self.send_command(0x20)
epdconfig.delay_ms(10); epdconfig.delay_ms(10)
self.ReadBusy(); self.ReadBusy()
def Clear(self): def Clear(self):
self.send_command(0x4F); self.send_command(0x4F)
self.send_data(0x00); self.send_data(0x00)
self.send_data(0x00); self.send_data(0x00)
self.send_command(0x24) self.send_command(0x24)
for i in range(0, int(self.width * self.height / 8)): for i in range(0, int(self.width * self.height / 8)):
self.send_data(0xff) self.send_data(0xff)
@ -186,15 +186,15 @@ class EPD:
for i in range(0, int(self.width * self.height / 8)): for i in range(0, int(self.width * self.height / 8)):
self.send_data(0xff) self.send_data(0xff)
self.send_command(0x22); self.send_command(0x22)
self.send_data(0xF7); # Load LUT from MCU(0x32) self.send_data(0xF7) # Load LUT from MCU(0x32)
self.send_command(0x20); self.send_command(0x20)
epdconfig.delay_ms(10); epdconfig.delay_ms(10)
self.ReadBusy(); self.ReadBusy()
def sleep(self): def sleep(self):
self.send_command(0x10); self.send_command(0x10)
self.send_data(0x01); self.send_data(0x01)
epdconfig.module_exit() epdconfig.module_exit()
### END OF FILE ### ### END OF FILE ###

View File

@ -1,31 +1,31 @@
# ***************************************************************************** """
# * | File : epd7in5bc.py * | File : epd7in5bc.py
# * | Author : Waveshare team * | Author : Waveshare team
# * | Function : Electronic paper driver * | Function : Electronic paper driver
# * | Info : * | Info :
# *---------------- *----------------
# * | This version: V4.0 * | This version: V4.0
# * | Date : 2019-06-20 * | Date : 2019-06-20
# # | Info : python demo # | Info : python demo
# ----------------------------------------------------------------------------- -----------------------------------------------------------------------------
# Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documnetation files (the "Software"), to deal of this software and associated documnetation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
# furished to do so, subject to the following conditions: furished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software. all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 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 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE. THE SOFTWARE.
# """
import logging import logging
@ -79,59 +79,59 @@ class EPD:
self.reset() self.reset()
self.send_command(0x12); # SWRESET self.send_command(0x12) # SWRESET
self.ReadBusy(); # waiting for the electronic paper IC to release the idle signal self.ReadBusy() # waiting for the electronic paper IC to release the idle signal
self.send_command(0x46); # Auto Write RAM self.send_command(0x46) # Auto Write RAM
self.send_data(0xF7); self.send_data(0xF7)
self.ReadBusy(); # waiting for the electronic paper IC to release the idle signal self.ReadBusy() # waiting for the electronic paper IC to release the idle signal
self.send_command(0x47); # Auto Write RAM self.send_command(0x47) # Auto Write RAM
self.send_data(0xF7); self.send_data(0xF7)
self.ReadBusy(); # waiting for the electronic paper IC to release the idle signal self.ReadBusy() # waiting for the electronic paper IC to release the idle signal
self.send_command(0x0C); # Soft start setting self.send_command(0x0C) # Soft start setting
self.send_data(0xAE); self.send_data(0xAE)
self.send_data(0xC7); self.send_data(0xC7)
self.send_data(0xC3); self.send_data(0xC3)
self.send_data(0xC0); self.send_data(0xC0)
self.send_data(0x40); self.send_data(0x40)
self.send_command(0x01); # Set MUX as 527 self.send_command(0x01) # Set MUX as 527
self.send_data(0xAF); self.send_data(0xAF)
self.send_data(0x02); self.send_data(0x02)
self.send_data(0x01); self.send_data(0x01)
self.send_command(0x11); # Data entry mode self.send_command(0x11) # Data entry mode
self.send_data(0x01); self.send_data(0x01)
self.send_command(0x44); self.send_command(0x44)
self.send_data(0x00); # RAM x address start at 0 self.send_data(0x00) # RAM x address start at 0
self.send_data(0x00); self.send_data(0x00)
self.send_data(0x6F); # RAM x address end at 36Fh -> 879 self.send_data(0x6F) # RAM x address end at 36Fh -> 879
self.send_data(0x03); self.send_data(0x03)
self.send_command(0x45); self.send_command(0x45)
self.send_data(0xAF); # RAM y address start at 20Fh; self.send_data(0xAF) # RAM y address start at 20Fh
self.send_data(0x02); self.send_data(0x02)
self.send_data(0x00); # RAM y address end at 00h; self.send_data(0x00) # RAM y address end at 00h
self.send_data(0x00); self.send_data(0x00)
self.send_command(0x3C); # VBD self.send_command(0x3C) # VBD
self.send_data(0x01); # LUT1, for white self.send_data(0x01) # LUT1, for white
self.send_command(0x18); self.send_command(0x18)
self.send_data(0X80); self.send_data(0X80)
self.send_command(0x22); self.send_command(0x22)
self.send_data(0XB1); # Load Temperature and waveform setting. self.send_data(0XB1) # Load Temperature and waveform setting.
self.send_command(0x20); self.send_command(0x20)
self.ReadBusy(); # waiting for the electronic paper IC to release the idle signal self.ReadBusy() # waiting for the electronic paper IC to release the idle signal
self.send_command(0x4E); self.send_command(0x4E)
self.send_data(0x00); self.send_data(0x00)
self.send_data(0x00); self.send_data(0x00)
self.send_command(0x4F); self.send_command(0x4F)
self.send_data(0xAF); self.send_data(0xAF)
self.send_data(0x02); self.send_data(0x02)
return 0 return 0
@ -160,44 +160,44 @@ class EPD:
return buf return buf
def display(self, imageblack, imagered): def display(self, imageblack, imagered):
self.send_command(0x4F); self.send_command(0x4F)
self.send_data(0xAf); self.send_data(0xAf)
self.send_command(0x24) self.send_command(0x24)
for i in range(0, int(self.width * self.height / 8)): for i in range(0, int(self.width * self.height / 8)):
self.send_data(imageblack[i]); self.send_data(imageblack[i])
self.send_command(0x26) self.send_command(0x26)
for i in range(0, int(self.width * self.height / 8)): for i in range(0, int(self.width * self.height / 8)):
self.send_data(~imagered[i]); self.send_data(~imagered[i])
self.send_command(0x22); self.send_command(0x22)
self.send_data(0xC7); # Load LUT from MCU(0x32) self.send_data(0xC7) # Load LUT from MCU(0x32)
self.send_command(0x20); self.send_command(0x20)
epdconfig.delay_ms(200); # !!!The delay here is necessary, 200uS at least!!! epdconfig.delay_ms(200) # !!!The delay here is necessary, 200uS at least!!!
self.ReadBusy(); self.ReadBusy()
def Clear(self): def Clear(self):
self.send_command(0x4F); self.send_command(0x4F)
self.send_data(0xAf); self.send_data(0xAf)
self.send_command(0x24) self.send_command(0x24)
for i in range(0, int(self.width * self.height / 8)): for i in range(0, int(self.width * self.height / 8)):
self.send_data(0xff); self.send_data(0xff)
self.send_command(0x26) self.send_command(0x26)
for i in range(0, int(self.width * self.height / 8)): for i in range(0, int(self.width * self.height / 8)):
self.send_data(0x00); self.send_data(0x00)
self.send_command(0x22); self.send_command(0x22)
self.send_data(0xC7); # Load LUT from MCU(0x32) self.send_data(0xC7) # Load LUT from MCU(0x32)
self.send_command(0x20); self.send_command(0x20)
epdconfig.delay_ms(200); # !!!The delay here is necessary, 200uS at least!!! epdconfig.delay_ms(200) # !!!The delay here is necessary, 200uS at least!!!
self.ReadBusy(); self.ReadBusy()
def sleep(self): def sleep(self):
self.send_command(0x10); # deep sleep self.send_command(0x10) # deep sleep
self.send_data(0x01); self.send_data(0x01)
epdconfig.module_exit() epdconfig.module_exit()
### END OF FILE ### ### END OF FILE ###

View File

@ -1,34 +1,35 @@
# /***************************************************************************** """
# * | File : epdconfig.py * | File : epdconfig.py
# * | Author : Waveshare team * | Author : Waveshare team
# * | Function : Hardware underlying interface * | Function : Hardware underlying interface
# * | Info : * | Info :
# *---------------- *----------------
# * | This version: V1.0 * | This version: V1.2
# * | Date : 2019-06-21 * | Date : 2022-10-29
# * | Info : * | Info :
# ******************************************************************************
# Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documnetation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
# furished to do so, subject to the following conditions: furished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software. all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 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 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE. THE SOFTWARE.
# """
import os
import logging import logging
import os
import subprocess
import sys import sys
import time import time
@ -41,21 +42,52 @@ class RaspberryPi:
DC_PIN = 25 DC_PIN = 25
CS_PIN = 8 CS_PIN = 8
BUSY_PIN = 24 BUSY_PIN = 24
PWR_PIN = 18
def __init__(self): def __init__(self):
import spidev import spidev
import RPi.GPIO import gpiozero
self.GPIO = RPi.GPIO self.SPI = spidev.SpiDev()
self.GPIO_RST_PIN = gpiozero.LED(self.RST_PIN)
# SPI device, bus = 0, device = 0 self.GPIO_DC_PIN = gpiozero.LED(self.DC_PIN)
self.SPI = spidev.SpiDev(0, 0) # self.GPIO_CS_PIN = gpiozero.LED(self.CS_PIN)
self.GPIO_PWR_PIN = gpiozero.LED(self.PWR_PIN)
self.GPIO_BUSY_PIN = gpiozero.Button(self.BUSY_PIN, pull_up=False)
def digital_write(self, pin, value): def digital_write(self, pin, value):
self.GPIO.output(pin, value) if pin == self.RST_PIN:
if value:
self.GPIO_RST_PIN.on()
else:
self.GPIO_RST_PIN.off()
elif pin == self.DC_PIN:
if value:
self.GPIO_DC_PIN.on()
else:
self.GPIO_DC_PIN.off()
# elif pin == self.CS_PIN:
# if value:
# self.GPIO_CS_PIN.on()
# else:
# self.GPIO_CS_PIN.off()
elif pin == self.PWR_PIN:
if value:
self.GPIO_PWR_PIN.on()
else:
self.GPIO_PWR_PIN.off()
def digital_read(self, pin): def digital_read(self, pin):
return self.GPIO.input(pin) if pin == self.BUSY_PIN:
return self.GPIO_BUSY_PIN.value
elif pin == self.RST_PIN:
return self.RST_PIN.value
elif pin == self.DC_PIN:
return self.DC_PIN.value
# elif pin == self.CS_PIN:
# return self.CS_PIN.value
elif pin == self.PWR_PIN:
return self.PWR_PIN.value
def delay_ms(self, delaytime): def delay_ms(self, delaytime):
time.sleep(delaytime / 1000.0) time.sleep(delaytime / 1000.0)
@ -63,26 +95,33 @@ class RaspberryPi:
def spi_writebyte(self, data): def spi_writebyte(self, data):
self.SPI.writebytes(data) self.SPI.writebytes(data)
def spi_writebyte2(self, data):
self.SPI.writebytes2(data)
def module_init(self): def module_init(self):
self.GPIO.setmode(self.GPIO.BCM) self.GPIO_PWR_PIN.on()
self.GPIO.setwarnings(False)
self.GPIO.setup(self.RST_PIN, self.GPIO.OUT) # SPI device, bus = 0, device = 0
self.GPIO.setup(self.DC_PIN, self.GPIO.OUT) self.SPI.open(0, 0)
self.GPIO.setup(self.CS_PIN, self.GPIO.OUT)
self.GPIO.setup(self.BUSY_PIN, self.GPIO.IN)
self.SPI.max_speed_hz = 4000000 self.SPI.max_speed_hz = 4000000
self.SPI.mode = 0b00 self.SPI.mode = 0b00
return 0 return 0
def module_exit(self): def module_exit(self):
logger.debug("spi end") logger.debug("spi end")
# self.SPI.close() #removed as it causes some problems self.SPI.close()
self.GPIO_RST_PIN.off()
self.GPIO_DC_PIN.off()
self.GPIO_PWR_PIN.off()
self.GPIO_RST_PIN.close()
self.GPIO_DC_PIN.close()
# self.GPIO_CS_PIN.close()
self.GPIO_PWR_PIN.close()
self.GPIO_BUSY_PIN.close()
logger.debug("close 5V, Module enters 0 power consumption ...") logger.debug("close 5V, Module enters 0 power consumption ...")
self.GPIO.output(self.RST_PIN, 0)
self.GPIO.output(self.DC_PIN, 0)
self.GPIO.cleanup()
class JetsonNano: class JetsonNano:
@ -91,6 +130,7 @@ class JetsonNano:
DC_PIN = 25 DC_PIN = 25
CS_PIN = 8 CS_PIN = 8
BUSY_PIN = 24 BUSY_PIN = 24
PWR_PIN = 18
def __init__(self): def __init__(self):
import ctypes import ctypes
@ -123,13 +163,21 @@ class JetsonNano:
def spi_writebyte(self, data): def spi_writebyte(self, data):
self.SPI.SYSFS_software_spi_transfer(data[0]) self.SPI.SYSFS_software_spi_transfer(data[0])
def spi_writebyte2(self, data):
for i in range(len(data)):
self.SPI.SYSFS_software_spi_transfer(data[i])
def module_init(self): def module_init(self):
self.GPIO.setmode(self.GPIO.BCM) self.GPIO.setmode(self.GPIO.BCM)
self.GPIO.setwarnings(False) self.GPIO.setwarnings(False)
self.GPIO.setup(self.RST_PIN, self.GPIO.OUT) self.GPIO.setup(self.RST_PIN, self.GPIO.OUT)
self.GPIO.setup(self.DC_PIN, self.GPIO.OUT) self.GPIO.setup(self.DC_PIN, self.GPIO.OUT)
self.GPIO.setup(self.CS_PIN, self.GPIO.OUT) self.GPIO.setup(self.CS_PIN, self.GPIO.OUT)
self.GPIO.setup(self.PWR_PIN, self.GPIO.OUT)
self.GPIO.setup(self.BUSY_PIN, self.GPIO.IN) self.GPIO.setup(self.BUSY_PIN, self.GPIO.IN)
self.GPIO.output(self.PWR_PIN, 1)
self.SPI.SYSFS_software_spi_begin() self.SPI.SYSFS_software_spi_begin()
return 0 return 0
@ -140,16 +188,93 @@ class JetsonNano:
logger.debug("close 5V, Module enters 0 power consumption ...") logger.debug("close 5V, Module enters 0 power consumption ...")
self.GPIO.output(self.RST_PIN, 0) self.GPIO.output(self.RST_PIN, 0)
self.GPIO.output(self.DC_PIN, 0) self.GPIO.output(self.DC_PIN, 0)
self.GPIO.output(self.PWR_PIN, 0)
self.GPIO.cleanup() self.GPIO.cleanup([self.RST_PIN, self.DC_PIN, self.CS_PIN, self.BUSY_PIN, self.PWR_PIN])
if os.path.exists('/sys/bus/platform/drivers/gpiomem-bcm2835'): class SunriseX3:
# Pin definition
RST_PIN = 17
DC_PIN = 25
CS_PIN = 8
BUSY_PIN = 24
PWR_PIN = 18
Flag = 0
def __init__(self):
import spidev
import Hobot.GPIO
self.GPIO = Hobot.GPIO
self.SPI = spidev.SpiDev()
def digital_write(self, pin, value):
self.GPIO.output(pin, value)
def digital_read(self, pin):
return self.GPIO.input(pin)
def delay_ms(self, delaytime):
time.sleep(delaytime / 1000.0)
def spi_writebyte(self, data):
self.SPI.writebytes(data)
def spi_writebyte2(self, data):
# for i in range(len(data)):
# self.SPI.writebytes([data[i]])
self.SPI.xfer3(data)
def module_init(self):
if self.Flag == 0:
self.Flag = 1
self.GPIO.setmode(self.GPIO.BCM)
self.GPIO.setwarnings(False)
self.GPIO.setup(self.RST_PIN, self.GPIO.OUT)
self.GPIO.setup(self.DC_PIN, self.GPIO.OUT)
self.GPIO.setup(self.CS_PIN, self.GPIO.OUT)
self.GPIO.setup(self.PWR_PIN, self.GPIO.OUT)
self.GPIO.setup(self.BUSY_PIN, self.GPIO.IN)
self.GPIO.output(self.PWR_PIN, 1)
# SPI device, bus = 0, device = 0
self.SPI.open(2, 0)
self.SPI.max_speed_hz = 4000000
self.SPI.mode = 0b00
return 0
else:
return 0
def module_exit(self):
logger.debug("spi end")
self.SPI.close()
logger.debug("close 5V, Module enters 0 power consumption ...")
self.Flag = 0
self.GPIO.output(self.RST_PIN, 0)
self.GPIO.output(self.DC_PIN, 0)
self.GPIO.output(self.PWR_PIN, 0)
self.GPIO.cleanup([self.RST_PIN, self.DC_PIN, self.CS_PIN, self.BUSY_PIN], self.PWR_PIN)
if sys.version_info[0] == 2:
process = subprocess.Popen("cat /proc/cpuinfo | grep Raspberry", shell=True, stdout=subprocess.PIPE)
else:
process = subprocess.Popen("cat /proc/cpuinfo | grep Raspberry", shell=True, stdout=subprocess.PIPE, text=True)
output, _ = process.communicate()
if sys.version_info[0] == 2:
output = output.decode(sys.stdout.encoding)
if "Raspberry" in output:
implementation = RaspberryPi() implementation = RaspberryPi()
elif os.path.exists('/sys/bus/platform/drivers/gpio-x3'):
implementation = SunriseX3()
else: else:
implementation = JetsonNano() implementation = JetsonNano()
for func in [x for x in dir(implementation) if not x.startswith('_')]: for func in [x for x in dir(implementation) if not x.startswith('_')]:
setattr(sys.modules[__name__], func, getattr(implementation, func)) setattr(sys.modules[__name__], func, getattr(implementation, func))
### END OF FILE ###

View File

@ -1,39 +1,38 @@
# /***************************************************************************** """
# * | File : epdconfig.py * | File : epdconfig.py
# * | Author : Waveshare electrices * | Author : Waveshare electrices
# * | Function : Hardware underlying interface * | Function : Hardware underlying interface
# * | Info : * | Info :
# *---------------- *----------------
# * | This version: V1.0 * | This version: V1.0
# * | Date : 2019-11-01 * | Date : 2019-11-01
# * | Info : * | Info :
# ******************************************************************************/ ******************************************************************************/
# Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documnetation files (the "Software"), to deal of this software and associated documnetation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
# furished to do so, subject to the following conditions: furished 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 OR 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.
#
import RPi.GPIO as GPIO
import time
import os
import logging
import sys
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 OR 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.
"""
import logging
import os
import time
from ctypes import * from ctypes import *
import RPi.GPIO as GPIO
EPD_SCK_PIN = 11 EPD_SCK_PIN = 11
EPD_MOSI_PIN = 10 EPD_MOSI_PIN = 10

View File

@ -1,6 +1,9 @@
"""Image file driver for testing"""
# Display resolution # Display resolution
EPD_WIDTH = 800 EPD_WIDTH = 800
EPD_HEIGHT = 480 EPD_HEIGHT = 480
class EPD: class EPD:
def init(self): def init(self):

View File

@ -98,6 +98,8 @@ class Inkycal:
except FileNotFoundError: except FileNotFoundError:
raise SettingsFileNotFoundError raise SettingsFileNotFoundError
self.disable_calibration = self.settings.get('disable_calibration', False)
if not os.path.exists(image_folder): if not os.path.exists(image_folder):
os.mkdir(image_folder) os.mkdir(image_folder)
@ -541,11 +543,16 @@ class Inkycal:
def _calibration_check(self): def _calibration_check(self):
"""Calibration scheduler """Calibration scheduler
uses calibration hours from settings file to check if calibration is due""" uses calibration hours from settings file to check if calibration is due.
If no calibration hours are set, calibration is skipped."""
# Check if calibration hours are not set or the list is empty
if not self._calibration_hours:
print("No calibration hours set. Skipping calibration.")
return
now = arrow.now() now = arrow.now()
# print('hour:', now.hour, 'hours:', self._calibration_hours) if now.hour in self._calibration_hours and not self._calibration_state:
# print('state:', self._calibration_state)
if now.hour in self._calibration_hours and self._calibration_state == False:
self.calibrate() self.calibrate()
self._calibration_state = True self._calibration_state = True
else: else:

View File

@ -1,5 +1,3 @@
#!python3
""" """
Third party module template (inkycal-compatible module) Third party module template (inkycal-compatible module)

View File

@ -1,6 +1,3 @@
#!python3
""" """
Custom image class for Inkycal Project Custom image class for Inkycal Project
Takes care of handling images. Made to be used by other modules to handle Takes care of handling images. Made to be used by other modules to handle
@ -10,9 +7,10 @@ Copyright by aceinnolab
""" """
import logging import logging
import os import os
import PIL
import numpy import numpy
import requests import requests
from PIL import Image from PIL import Image
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -114,7 +112,7 @@ class Inkyimage:
self.image = image self.image = image
logger.info(f'flipped image by {angle} degrees') logger.info(f'flipped image by {angle} degrees')
def autoflip(self, layout:str) -> None: def autoflip(self, layout: str) -> None:
"""flips the image automatically to the given layout. """flips the image automatically to the given layout.
Args: Args:
@ -215,7 +213,7 @@ class Inkyimage:
return image1 return image1
def to_palette(self, palette, dither=True) -> (Image, Image): def to_palette(self, palette, dither=True) -> (PIL.Image, PIL.Image):
"""Maps an image to a given colour palette. """Maps an image to a given colour palette.
Maps each pixel from the image to a colour from the palette. Maps each pixel from the image to a colour from the palette.
@ -235,6 +233,7 @@ class Inkyimage:
>>> 'bwr' # black-white-red >>> 'bwr' # black-white-red
>>> 'bwy' # black-white-yellow >>> 'bwy' # black-white-yellow
>>> 'bw' # black-white >>> 'bw' # black-white
>>> '16gray' # 16 shades of gray
""" """
# Check if an image is loaded # Check if an image is loaded
if self._image_loaded(): if self._image_loaded():
@ -252,6 +251,9 @@ class Inkyimage:
elif palette == 'bw': elif palette == 'bw':
pal = None pal = None
elif palette == '16gray':
pal = [x for x in range(0, 256, 16)] * 3
pal.sort()
else: else:
logger.error('The given palette is unsupported.') logger.error('The given palette is unsupported.')
@ -329,4 +331,3 @@ class Inkyimage:
if __name__ == '__main__': if __name__ == '__main__':
print(f'running {__name__} in standalone/debug mode') print(f'running {__name__} in standalone/debug mode')

View File

@ -1,14 +1,11 @@
#!python3
""" """
Inkycal Image Module Inkycal Image Module
Copyright by aceinnolab Copyright by aceinnolab
""" """
from inkycal.modules.template import inkycal_module
from inkycal.custom import * from inkycal.custom import *
from inkycal.modules.inky_image import Inkyimage as Images from inkycal.modules.inky_image import Inkyimage as Images
from inkycal.modules.template import inkycal_module
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -63,6 +60,9 @@ class Inkyimage(inkycal_module):
self.palette = config['palette'] self.palette = config['palette']
self.autoflip = config['autoflip'] self.autoflip = config['autoflip']
self.orientation = config['orientation'] self.orientation = config['orientation']
self.dither = True
if 'dither' in config and config["dither"] == False:
self.dither = False
# give an OK message # give an OK message
print(f'{__name__} loaded') print(f'{__name__} loaded')
@ -94,7 +94,7 @@ class Inkyimage(inkycal_module):
im.resize(width=im_width, height=im_height) im.resize(width=im_width, height=im_height)
# convert images according to specified palette # convert images according to specified palette
im_black, im_colour = im.to_palette(self.palette) im_black, im_colour = im.to_palette(self.palette, self.dither)
# with the images now send, clear the current image # with the images now send, clear the current image
im.clear() im.clear()

View File

@ -1,17 +1,12 @@
#!python3
""" """
Inkycal-server module for Inkycal Project Inkycal-server module for Inkycal Project
by Aterju (https://inkycal.robertsirre.nl/) by Aterju (https://inkycal.robertsirre.nl/)
Copyright by aceinnolab Copyright by aceinnolab
""" """
import requests
from inkycal.modules.template import inkycal_module
from inkycal.custom import * from inkycal.custom import *
from inkycal.modules.inky_image import Inkyimage as Images from inkycal.modules.inky_image import Inkyimage as Images
from inkycal.modules.template import inkycal_module
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)

View File

@ -1,16 +1,13 @@
#!python3
""" """
Inkycal Slideshow Module Inkycal Slideshow Module
Copyright by aceinnolab Copyright by aceinnolab
""" """
import glob import glob
from inkycal.modules.template import inkycal_module
from inkycal.custom import * from inkycal.custom import *
# PIL has a class named Image, use alias for Inkyimage -> Images # PIL has a class named Image, use alias for Inkyimage -> Images
from inkycal.modules.inky_image import Inkyimage as Images from inkycal.modules.inky_image import Inkyimage as Images
from inkycal.modules.template import inkycal_module
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)

View File

@ -1,18 +1,16 @@
#!python3
""" """
Inkycal weather module Inkycal weather module
Copyright by aceinnolab Copyright by aceinnolab
""" """
from inkycal.modules.template import inkycal_module
from inkycal.custom import *
import math
import decimal import decimal
import math
import arrow import arrow
from inkycal.custom import *
from inkycal.custom import OpenWeatherMap from inkycal.custom import OpenWeatherMap
from inkycal.modules.template import inkycal_module
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -95,7 +93,7 @@ class Weather(inkycal_module):
self.use_beaufort = config['use_beaufort'] self.use_beaufort = config['use_beaufort']
# additional configuration # additional configuration
self.owm = OpenWeatherMap(api_key=self.api_key, city_id=self.location, units=config['units']) self.owm = OpenWeatherMap(api_key=self.api_key, city_id=self.location, units=config['units'])
self.timezone = get_system_tz() self.timezone = get_system_tz()
self.locale = config['language'] self.locale = config['language']
self.weatherfont = ImageFont.truetype( self.weatherfont = ImageFont.truetype(
@ -104,9 +102,8 @@ class Weather(inkycal_module):
# give an OK message # give an OK message
print(f"{__name__} loaded") print(f"{__name__} loaded")
@staticmethod @staticmethod
def mps_to_beaufort(meters_per_second:float) -> int: def mps_to_beaufort(meters_per_second: float) -> int:
"""Map meters per second to the beaufort scale. """Map meters per second to the beaufort scale.
Args: Args:
@ -120,7 +117,7 @@ class Weather(inkycal_module):
return next((i for i, threshold in enumerate(thresholds) if meters_per_second < threshold), 11) return next((i for i, threshold in enumerate(thresholds) if meters_per_second < threshold), 11)
@staticmethod @staticmethod
def mps_to_mph(meters_per_second:float) -> float: def mps_to_mph(meters_per_second: float) -> float:
"""Map meters per second to miles per hour, rounded to one decimal place. """Map meters per second to miles per hour, rounded to one decimal place.
Args: Args:
@ -135,7 +132,7 @@ class Weather(inkycal_module):
return round(miles_per_hour, 1) return round(miles_per_hour, 1)
@staticmethod @staticmethod
def celsius_to_fahrenheit(celsius:int or float): def celsius_to_fahrenheit(celsius: int or float):
"""Converts the given temperate from degrees Celsius to Fahrenheit.""" """Converts the given temperate from degrees Celsius to Fahrenheit."""
fahrenheit = (celsius * 9 / 5) + 32 fahrenheit = (celsius * 9 / 5) + 32
return fahrenheit return fahrenheit
@ -180,7 +177,8 @@ class Weather(inkycal_module):
4: '\uf0a3', 4: '\uf0a3',
5: '\uf0a7', 5: '\uf0a7',
6: '\uf0aa', 6: '\uf0aa',
7: '\uf0ae'}[int(index) & 7] 7: '\uf0ae'
}[int(index) & 7]
def is_negative(temp): def is_negative(temp):
"""Check if temp is below freezing point of water (0°C/30°F) """Check if temp is below freezing point of water (0°C/30°F)
@ -458,8 +456,9 @@ class Weather(inkycal_module):
# Create a list containing time-objects for every 3rd hour of the day # Create a list containing time-objects for every 3rd hour of the day
time_range = list( time_range = list(
arrow.Arrow.range('hour', arrow.Arrow.range('hour',
now.shift(days=days_from_today).floor('day'),now.shift(days=days_from_today).ceil('day') now.shift(days=days_from_today).floor('day'),
))[::3] now.shift(days=days_from_today).ceil('day')
))[::3]
# Get forecasts for each time-object # Get forecasts for each time-object
forecasts = [_ for _ in forecast if arrow.get(_["dt"]) in time_range] forecasts = [_ for _ in forecast if arrow.get(_["dt"]) in time_range]
@ -493,7 +492,7 @@ class Weather(inkycal_module):
if dec_temp != 0: if dec_temp != 0:
temperature = f"{round(weather['main']['temp'])}°" temperature = f"{round(weather['main']['temp'])}°"
else: else:
temperature = f"{round(weather['main']['temp'],ndigits=dec_temp)}°" temperature = f"{round(weather['main']['temp'], ndigits=dec_temp)}°"
weather_icon = weather["weather"][0]["icon"] weather_icon = weather["weather"][0]["icon"]
humidity = str(weather["main"]["humidity"]) humidity = str(weather["main"]["humidity"])

View File

@ -1,6 +1,6 @@
#!python3 """Inkycal module template"""
import abc import abc
from inkycal.custom import * from inkycal.custom import *

View File

@ -1,7 +1,6 @@
#!python3 from os import path
from setuptools import setup from setuptools import setup
from os import path
this_directory = path.abspath(path.dirname(__file__)) this_directory = path.abspath(path.dirname(__file__))
with open(path.join(this_directory, 'README.md'), encoding='utf-8') as f: with open(path.join(this_directory, 'README.md'), encoding='utf-8') as f:

View File

@ -14,7 +14,7 @@ from tests import Config
preview = Inkyimage.preview preview = Inkyimage.preview
merge = Inkyimage.merge merge = Inkyimage.merge
url = "https://github.com/aceinnolab/Inkycal/raw/assets/Repo/coffee.png" url ="https://raw.githubusercontent.com/aceinnolab/Inkycal/assets/tests/mark-harpur-unsplash.jpg"
im = Image.open(requests.get(url, stream=True).raw) im = Image.open(requests.get(url, stream=True).raw)
im.save("test.png", "PNG") im.save("test.png", "PNG")
@ -27,9 +27,9 @@ tests = [
{ {
"name": "Inkyimage", "name": "Inkyimage",
"config": { "config": {
"size": [400, 200], "size": [800, 600],
"path": test_path, "path": test_path,
"palette": "bwr", "palette": "16gray",
"autoflip": True, "autoflip": True,
"orientation": "vertical", "orientation": "vertical",
"padding_x": 10, "padding_y": 10, "fontsize": 12, "language": "en" "padding_x": 10, "padding_y": 10, "fontsize": 12, "language": "en"