Merge remote-tracking branch 'upstream/main'
This commit is contained in:
		
							
								
								
									
										2
									
								
								.github/workflows/test-on-rpi.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/test-on-rpi.yml
									
									
									
									
										vendored
									
									
								
							| @@ -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 | ||||||
|   | |||||||
							
								
								
									
										8
									
								
								.github/workflows/update-os.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								.github/workflows/update-os.yml
									
									
									
									
										vendored
									
									
								
							| @@ -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
									
									
									
									
									
								
							
							
						
						
									
										303
									
								
								README.md
									
									
									
									
									
								
							| @@ -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: | ||||||
|  |  | ||||||
|  | [](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/) | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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> | ||||||
|   | |||||||
| @@ -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> | ||||||
|   | |||||||
| @@ -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> | ||||||
|   | |||||||
| @@ -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> | ||||||
|   | |||||||
| @@ -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 & 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">>>> </span><span class="s1">'bwr'</span> <span class="c1"># black-white-red</span> | <div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="s1">'bwr'</span> <span class="c1"># black-white-red</span> | ||||||
| <span class="gp">>>> </span><span class="s1">'bwy'</span> <span class="c1"># black-white-yellow</span> | <span class="gp">>>> </span><span class="s1">'bwy'</span> <span class="c1"># black-white-yellow</span> | ||||||
| <span class="gp">>>> </span><span class="s1">'bw'</span>  <span class="c1"># black-white</span> | <span class="gp">>>> </span><span class="s1">'bw'</span>  <span class="c1"># black-white</span> | ||||||
|  | <span class="gp">>>> </span><span class="s1">'16gray'</span> <span class="c1"># 16 shades of gray</span> | ||||||
| </pre></div> | </pre></div> | ||||||
| </div> | </div> | ||||||
| </dd></dl> | </dd></dl> | ||||||
|   | |||||||
							
								
								
									
										
											BIN
										
									
								
								docs/objects.inv
									
									
									
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								docs/objects.inv
									
									
									
									
									
								
							
										
											Binary file not shown.
										
									
								
							| @@ -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>    |        <td>    | ||||||
|        <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>    |  | ||||||
|        <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>    |  | ||||||
|        <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>    |  | ||||||
|        <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> | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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> | ||||||
|   | |||||||
| @@ -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
											
										
									
								
							| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -1,4 +1,3 @@ | |||||||
| #!python3 |  | ||||||
| """ | """ | ||||||
| Inkycal custom Exceptions | Inkycal custom Exceptions | ||||||
| """ | """ | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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) | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -1,34 +1,34 @@ | |||||||
| # ***************************************************************************** | """ | ||||||
| # * | 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 | ||||||
| @@ -37,6 +37,7 @@ 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): | ||||||
|   | |||||||
| @@ -1,37 +1,39 @@ | |||||||
| # /***************************************************************************** | """ | ||||||
| # * | 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 | ||||||
| @@ -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,96 +87,96 @@ 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() | ||||||
|  |  | ||||||
| @@ -202,6 +204,7 @@ class EPD(object): | |||||||
|         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 | ||||||
|   | |||||||
| @@ -1,37 +1,39 @@ | |||||||
| # /***************************************************************************** | """ | ||||||
| # * | 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 | ||||||
| @@ -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) | ||||||
| @@ -89,9 +91,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) | ||||||
| @@ -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,67 +153,67 @@ 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): | ||||||
| @@ -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,54 +380,59 @@ 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 = [ | ||||||
| @@ -482,26 +497,26 @@ class EPD(object): | |||||||
|     ] |     ] | ||||||
|  |  | ||||||
|     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 | ||||||
|   | |||||||
| @@ -1,37 +1,40 @@ | |||||||
| # /***************************************************************************** | """ | ||||||
| # * | 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 | ||||||
| @@ -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,67 +129,67 @@ 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): | ||||||
| @@ -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,54 +356,59 @@ 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 = [ | ||||||
| @@ -457,27 +473,27 @@ class EPD(object): | |||||||
|     ] |     ] | ||||||
|  |  | ||||||
|     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 | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 ### |  | ||||||
|   | |||||||
| @@ -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 ### | ||||||
|   | |||||||
| @@ -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 ### | ||||||
|   | |||||||
| @@ -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 ### |  | ||||||
|   | |||||||
| @@ -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 | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,7 +1,10 @@ | |||||||
|  | """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): | ||||||
|         pass |         pass | ||||||
|   | |||||||
| @@ -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: | ||||||
|   | |||||||
| @@ -1,5 +1,3 @@ | |||||||
| #!python3 |  | ||||||
|  |  | ||||||
| """ | """ | ||||||
| Third party module template (inkycal-compatible module) | Third party module template (inkycal-compatible module) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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') | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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() | ||||||
|   | |||||||
| @@ -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__) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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__) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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__) | ||||||
|  |  | ||||||
| @@ -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,7 +456,8 @@ 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'), | ||||||
|  |                                       now.shift(days=days_from_today).ceil('day') | ||||||
|                                       ))[::3] |                                       ))[::3] | ||||||
|  |  | ||||||
|                 # Get forecasts for each time-object |                 # Get forecasts for each time-object | ||||||
| @@ -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"]) | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| #!python3 | """Inkycal module template""" | ||||||
|  |  | ||||||
| import abc | import abc | ||||||
|  |  | ||||||
| from inkycal.custom import * | from inkycal.custom import * | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										3
									
								
								setup.py
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								setup.py
									
									
									
									
									
								
							| @@ -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: | ||||||
|   | |||||||
| @@ -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" | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user