Compare commits

..

30 Commits

Author SHA1 Message Date
7abf9ff8da Update faces.py
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-23 09:49:46 +01:00
18fb956251 Update setup.py
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-23 09:46:32 +01:00
afb1d11cd8 Added Adafruit 2in13_V3 display
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-23 09:24:52 +01:00
627be80e6c add system wide aliases, if you were to use custom users
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-22 19:09:49 +01:00
c4c4d6c417 in case you use an unsupported display it will default to dummy display, displaying nothing
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-22 19:09:27 +01:00
8dcae13ce9 add commented dtoverlay=disable-wifi
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-22 19:09:00 +01:00
1352e99774 Fix wrong imports
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-22 18:34:49 +01:00
2182d7c29d Update Frysian Language
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-22 09:56:47 +01:00
703c05a93b Full SSID again
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-22 09:06:04 +01:00
697cc5d88b Add DummyDisplay
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-22 08:37:56 +01:00
4b04f9b7a5 Install OS packages from auto-update
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-22 08:37:22 +01:00
c7b94a0707 Version 2.8.8 starts here
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-22 08:37:01 +01:00
5116bac2a7 Multiple changes
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-20 22:32:04 +01:00
51625e61f9 Multiple changes
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-20 22:25:36 +01:00
bf9a0a96c1 Update raspberrypi64.yml 2024-03-20 21:17:20 +01:00
bd03f07aa8 Update raspberrypi32.yml 2024-03-20 21:16:50 +01:00
3f13df8f20 Merge pull request #104
Update defaults.toml
2024-03-20 07:20:19 +01:00
ce0275f2ae Update defaults.toml
Removed main.filter since it's no longer referenced in agent.py as of this commit 1a55afd74a (diff-0548f0a21e1984ecf3c32d6cd9c17e6a62f4f139c001360935890f649b745cc7)

Signed-off-by: seelenamt <dandrewe@gmail.com>
2024-03-19 10:51:59 -05:00
b971f18f75 Update Sponsor links
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-19 13:19:54 +01:00
ea9d11d018 Update Sponsor links
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-19 13:19:00 +01:00
8a572f1b70 Update Sponsor links
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-19 13:16:14 +01:00
0c4f2a5093 small change
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-19 09:25:17 +01:00
7edd752664 small change
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-19 07:56:06 +01:00
cc550aa236 small change
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-18 15:05:00 +01:00
ff033d41d3 Revert "fallback to older 32bit image"
This reverts commit b33af167d4.
2024-03-18 14:56:59 +01:00
6d0a0d8d5f fallback to older 32bit image
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-18 13:04:19 +01:00
b33af167d4 fallback to older 32bit image
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-18 12:03:20 +01:00
9053762e71 2.8.7.2
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-18 11:59:32 +01:00
26fef7dd99 Merge remote-tracking branch 'origin/master'
# Conflicts:
#	builder/data/64bit/raspberrypi64.yml
2024-03-18 11:58:33 +01:00
5dd17291f7 Fix a lot of stuff
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-18 11:58:22 +01:00
53 changed files with 718 additions and 2286 deletions

1
.github/FUNDING.yml vendored
View File

@ -1,3 +1,4 @@
# These are supported funding model platforms
github: jayofelony
custom: https://tikkie.me/pay/dubcto94hnskg539kar0

View File

@ -23,8 +23,6 @@ jobs:
- name: Get latest tag
uses: actions-ecosystem/action-get-latest-tag@v1
id: get-latest-tag
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Set LAST_VERSION as an environment variable
run: echo "LAST_VERSION=${{ steps.get-latest-tag.outputs.tag }}" >> $GITHUB_ENV

View File

@ -51,13 +51,11 @@ image: clean packer
bullseye: clean packer
export LC_ALL=en_GB.UTF-8
cd builder && sudo /usr/bin/packer init data/32bit/raspberrypi32.json.pkr.hcl && sudo $(UNSHARE) /usr/bin/packer build -var "pwn_hostname=$(PWN_HOSTNAME)" -var "pwn_version=$(PWN_VERSION)" data/32bit/raspberrypi32.json.pkr.hcl
sudo pishrink -vaZ pwnagotchi-32bit.img
cd builder && sudo /usr/bin/packer init raspberrypi32.json.pkr.hcl && sudo $(UNSHARE) /usr/bin/packer build -var "pwn_hostname=$(PWN_HOSTNAME)" -var "pwn_version=$(PWN_VERSION)" raspberrypi32.json.pkr.hcl
bookworm: clean packer
export LC_ALL=en_GB.UTF-8
cd builder && sudo /usr/bin/packer init data/64bit/raspberrypi64.json.pkr.hcl && sudo $(UNSHARE) /usr/bin/packer build -var "pwn_hostname=$(PWN_HOSTNAME)" -var "pwn_version=$(PWN_VERSION)" data/64bit/raspberrypi64.json.pkr.hcl
sudo pishrink -vaZ pwnagotchi-64bit.img
cd builder && sudo /usr/bin/packer init raspberrypi64.json.pkr.hcl && sudo $(UNSHARE) /usr/bin/packer build -var "pwn_hostname=$(PWN_HOSTNAME)" -var "pwn_version=$(PWN_VERSION)" raspberrypi64.json.pkr.hcl
clean:
- rm -rf /tmp/packer*

1
apt_packages.txt Normal file
View File

@ -0,0 +1 @@
bluez-tools

View File

@ -123,7 +123,7 @@ build {
provisioner "ansible-local" {
command = "ANSIBLE_FORCE_COLOR=1 PYTHONUNBUFFERED=1 PWN_VERSION=${var.pwn_version} PWN_HOSTNAME=${var.pwn_hostname} ansible-playbook"
extra_arguments = ["--extra-vars \"ansible_python_interpreter=/usr/bin/python3\""]
playbook_file = "data/64bit/raspberrypi64.yml"
playbook_file = "raspberrypi64.yml"
}
}
@ -167,7 +167,7 @@ build {
provisioner "ansible-local" {
command = "ANSIBLE_FORCE_COLOR=1 PYTHONUNBUFFERED=1 PWN_VERSION=${var.pwn_version} PWN_HOSTNAME=${var.pwn_hostname} ansible-playbook"
extra_arguments = ["--extra-vars \"ansible_python_interpreter=/usr/bin/python3\""]
playbook_dir = "data/32bit/extras/"
playbook_file = "data/32bit/raspberrypi32.yml"
playbook_dir = "extras/"
playbook_file = "raspberrypi32.yml"
}
}

View File

@ -0,0 +1,67 @@
# For more options and information see
# http://rptl.io/configtxt
# Some settings may impact device functionality. See link above for details
# Uncomment some or all of these to enable the optional hardware interfaces
#dtparam=i2c_arm=on
#dtparam=i2s=on
#dtparam=spi=on
# Enable audio (loads snd_bcm2835)
dtparam=audio=on
# Additional overlays and parameters are documented
# /boot/overlays/README
# Automatically load overlays for detected cameras
camera_auto_detect=1
# Automatically load overlays for detected DSI displays
display_auto_detect=1
# Automatically load initramfs files, if found
auto_initramfs=1
# Enable DRM VC4 V3D driver
dtoverlay=vc4-kms-v3d
max_framebuffers=2
# Don't have the firmware create an initial video= setting in cmdline.txt.
# Use the kernel's default instead.
disable_fw_kms_setup=1
# Run in 64-bit mode
arm_64bit=0
# Disable compensation for displays with overscan
disable_overscan=1
# Run as fast as firmware / board allows
arm_boost=1
[cm4]
# Enable host mode on the 2711 built-in XHCI USB controller.
# This line should be removed if the legacy DWC2 controller is required
# (e.g. for USB device mode) or if USB support is not required.
otg_mode=1
[all]
dtoverlay=dwc2
dtparam=i2c1=on
dtparam=i2c_arm=on
dtparam=spi=on
gpu_mem=1
dtoverlay=dwc2
#dtoverlay=disable-wifi
[pi0]
dtoverlay=spi1-3cs
#dtoverlay=disable-wifi
[pi3]
dtoverlay=spi1-3cs
#dtoverlay=disable-wifi
[pi4]
dtoverlay=spi1-3cs
#dtoverlay=disable-wifi

View File

@ -0,0 +1,6 @@
# /etc/modules: kernel modules to load at boot time.
#
# This file contains the names of kernel modules that should be loaded
# at boot time, one per line. Lines beginning with "#" are ignored.
# Parameters can be specified after the module name.
i2c-dev

View File

@ -0,0 +1,40 @@
# /etc/profile: system-wide .profile file for the Bourne shell (sh(1))
# and Bourne compatible shells (bash(1), ksh(1), ash(1), ...).
if [ "$(id -u)" -eq 0 ]; then
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
else
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games"
fi
export PATH
if [ "${PS1-}" ]; then
if [ "${BASH-}" ] && [ "$BASH" != "/bin/sh" ]; then
# The file bash.bashrc already sets the default PS1.
# PS1='\h:\w\$ '
if [ -f /etc/bash.bashrc ]; then
. /etc/bash.bashrc
fi
else
if [ "$(id -u)" -eq 0 ]; then
PS1='# '
else
PS1='$ '
fi
fi
fi
if [ -d /etc/profile.d ]; then
for i in /etc/profile.d/*.sh; do
if [ -r $i ]; then
. $i
fi
done
unset i
fi
alias custom='cd /usr/local/share/pwnagotchi/custom-plugins/'
alias config='sudo nano /etc/pwnagotchi/config.toml'
alias pwnlog='tail -f -n300 /etc/pwnagotchi/log/pwn*.log | sed --unbuffered "s/,[[:digit:]]\\{3\\}\\]//g" | cut -d " " -f 2-'
alias pwnver='python3 -c "import pwnagotchi as p; print(p.__version__)"'
alias pwnkill='sudo killall -USR1 pwnagotchi'

View File

@ -0,0 +1,70 @@
# For more options and information see
# http://rptl.io/configtxt
# Some settings may impact device functionality. See link above for details
# Uncomment some or all of these to enable the optional hardware interfaces
#dtparam=i2c_arm=on
#dtparam=i2s=on
#dtparam=spi=on
# Enable audio (loads snd_bcm2835)
dtparam=audio=on
# Additional overlays and parameters are documented
# /boot/firmware/overlays/README
# Automatically load overlays for detected cameras
camera_auto_detect=1
# Automatically load overlays for detected DSI displays
display_auto_detect=1
# Automatically load initramfs files, if found
auto_initramfs=1
# Enable DRM VC4 V3D driver
dtoverlay=vc4-kms-v3d
max_framebuffers=2
# Don't have the firmware create an initial video= setting in cmdline.txt.
# Use the kernel's default instead.
disable_fw_kms_setup=1
# Run in 64-bit mode
arm_64bit=1
# Disable compensation for displays with overscan
disable_overscan=1
# Run as fast as firmware / board allows
arm_boost=1
[cm4]
# Enable host mode on the 2711 built-in XHCI USB controller.
# This line should be removed if the legacy DWC2 controller is required
# (e.g. for USB device mode) or if USB support is not required.
otg_mode=1
[all]
dtparam=i2c1=on
dtparam=i2c_arm=on
dtparam=spi=on
gpu_mem=1
dtoverlay=dwc2
#dtoverlay=disable-wifi
[pi0]
dtoverlay=spi0-0cs
#dtoverlay=disable-wifi
[pi3]
dtoverlay=spi0-0cs
#dtoverlay=disable-wifi
[pi4]
dtoverlay=spi0-0cs
#dtoverlay=disable-wifi
[pi5]
dtoverlay=spi0-0cs
#dtoverlay=disable-wifi

View File

@ -0,0 +1,6 @@
# /etc/modules: kernel modules to load at boot time.
#
# This file contains the names of kernel modules that should be loaded
# at boot time, one per line. Lines beginning with "#" are ignored.
# Parameters can be specified after the module name.
i2c-dev

View File

@ -0,0 +1,40 @@
# /etc/profile: system-wide .profile file for the Bourne shell (sh(1))
# and Bourne compatible shells (bash(1), ksh(1), ash(1), ...).
if [ "$(id -u)" -eq 0 ]; then
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
else
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games"
fi
export PATH
if [ "${PS1-}" ]; then
if [ "${BASH-}" ] && [ "$BASH" != "/bin/sh" ]; then
# The file bash.bashrc already sets the default PS1.
# PS1='\h:\w\$ '
if [ -f /etc/bash.bashrc ]; then
. /etc/bash.bashrc
fi
else
if [ "$(id -u)" -eq 0 ]; then
PS1='# '
else
PS1='$ '
fi
fi
fi
if [ -d /etc/profile.d ]; then
for i in /etc/profile.d/*.sh; do
if [ -r $i ]; then
. $i
fi
done
unset i
fi
alias custom='cd /usr/local/share/pwnagotchi/custom-plugins/'
alias config='sudo nano /etc/pwnagotchi/config.toml'
alias pwnlog='tail -f -n300 /etc/pwnagotchi/log/pwn*.log | sed --unbuffered "s/,[[:digit:]]\\{3\\}\\]//g" | cut -d " " -f 2-'
alias pwnver='python3 -c "import pwnagotchi as p; print(p.__version__)"'
alias pwnkill='sudo killall -USR1 pwnagotchi'

View File

@ -1,18 +1,5 @@
#!/usr/bin/env bash
# well ... it blinks the led
blink_led() {
# shellcheck disable=SC2034
for i in $(seq 1 "$1"); do
echo 0 >/sys/class/leds/led0/brightness
sleep 0.3
echo 1 >/sys/class/leds/led0/brightness
sleep 0.3
done
echo 0 >/sys/class/leds/led0/brightness
sleep 0.3
}
# reload mod
reload_brcm() {
if ! modprobe -r brcmfmac; then

View File

@ -88,7 +88,7 @@ build {
provisioner "ansible-local" {
command = "ANSIBLE_FORCE_COLOR=1 PYTHONUNBUFFERED=1 PWN_VERSION=${var.pwn_version} PWN_HOSTNAME=${var.pwn_hostname} ansible-playbook"
extra_arguments = ["--extra-vars \"ansible_python_interpreter=/usr/bin/python3\""]
playbook_dir = "data/32bit/extras/"
playbook_file = "data/32bit/raspberrypi32.yml"
playbook_dir = "extras/"
playbook_file = "raspberrypi32.yml"
}
}

View File

@ -39,26 +39,6 @@
hostname: "{{ lookup('env', 'PWN_HOSTNAME') | default('pwnagotchi', true) }}"
version: "{{ lookup('env', 'PWN_VERSION') | default('pwnagotchi-torch', true) }}"
custom_plugin_dir: "/usr/local/share/pwnagotchi/custom-plugins"
system:
boot_options:
- "#### pwnagotchi additions"
- "# this pwnagotchi image is 32-bit only no v8+ headers to build nexmon for 64 bit"
- "arm_64bit=0"
- "# dwc2 for RNDIS. comment out, and remove dwc2 and g_ether from cmdline.txt for X306 usb battery hat"
- "dtoverlay=dwc2"
- "dtoverlay=spi0-0cs"
- "dtparam=i2c1=on"
- "dtparam=i2c_arm=on"
- "dtparam=spi=on"
- "gpu_mem=16"
- "#### audio out on pins 18 and 19"
- "#dtoverlay=audremap,pins_18_19"
- "#### touchscreen on waveshare touch e-paper"
- "#dtoverlay=goodix,interrupt=27,reset=22"
- "#### for PWM backlighting on pimoroni displayhatmini"
- "dtoverlay=pwm-2chan,pin=12,func=4,pin2=13,func2=4"
modules:
- "i2c-dev"
services:
enable:
- bettercap.service
@ -117,6 +97,7 @@
- bc
- bison
- bluez
- bluez-tools
- build-essential
- curl
- dkms
@ -178,6 +159,7 @@
- lsof
- make
- ntp
- python3-dbus
- python3-flask
- python3-flask-cors
- python3-flaskext.wtf
@ -389,11 +371,6 @@
block: |
export GOPATH=$HOME/go
export PATH=/usr/local/go/bin:$PATH:$GOPATH/bin
alias custom='cd /usr/local/share/pwnagotchi/custom-plugins/'
alias config='sudo nano /etc/pwnagotchi/config.toml'
alias pwnlog='tail -f -n300 /etc/pwnagotchi/log/pwn*.log | sed --unbuffered "s/,[[:digit:]]\\{3\\}\\]//g" | cut -d " " -f 2-'
alias pwnver='python3 -c "import pwnagotchi as p; print(p.__version__)"'
alias pwnkill='sudo killall -USR1 pwnagotchi'
when: golang.changed
- name: download pwngrid
@ -475,20 +452,6 @@
path: /boot/ssh
state: touch
- name: adjust /boot/config.txt
lineinfile:
dest: /boot/config.txt
insertafter: EOF
line: '{{ item }}'
with_items: "{{system.boot_options}}"
- name: adjust /etc/modules
lineinfile:
dest: /etc/modules
insertafter: EOF
line: '{{ item }}'
with_items: "{{system.modules}}"
- name: change root partition
replace:
dest: /boot/cmdline.txt

View File

@ -95,6 +95,6 @@ build {
provisioner "ansible-local" {
command = "ANSIBLE_FORCE_COLOR=1 PYTHONUNBUFFERED=1 PWN_VERSION=${var.pwn_version} PWN_HOSTNAME=${var.pwn_hostname} ansible-playbook"
extra_arguments = ["--extra-vars \"ansible_python_interpreter=/usr/bin/python3\""]
playbook_file = "data/64bit/raspberrypi64.yml"
playbook_file = "raspberrypi64.yml"
}
}

View File

@ -11,23 +11,6 @@
pwnagotchi:
hostname: "{{ lookup('env', 'PWN_HOSTNAME') | default('pwnagotchi', true) }}"
version: "{{ lookup('env', 'PWN_VERSION') | default('pwnagotchi', true) }}"
system:
boot_options:
- "dtoverlay=dwc2"
- "dtparam=i2c1=on"
- "dtparam=i2c_arm=on"
- "dtparam=spi=on"
- "gpu_mem=16"
- "[pi0]"
- "dtoverlay=spi0-0cs"
- "[pi3]"
- "dtoverlay=spi0-0cs"
- "[pi4]"
- "dtoverlay=spi0-0cs"
- "[pi5]"
- "dtoverlay=spi0-0cs"
modules:
- "i2c-dev"
services:
enable:
- bettercap.service
@ -81,6 +64,7 @@
- bc
- bison
- bluez
- bluez-tools
- build-essential
- curl
- dkms
@ -211,25 +195,6 @@
path: /etc/rc.local
state: absent
- name: adjust /boot/firmware/config.txt
blockinfile:
dest: /boot/firmware/config.txt
insertafter: EOF
block: |
dtoverlay=dwc2
dtparam=i2c1=on
dtparam=i2c_arm=on"
dtparam=spi=on
gpu_mem=16
[pi0]
dtoverlay=spi0-0cs
[pi3]
dtoverlay=spi0-0cs
[pi4]
dtoverlay=spi0-0cs
[pi5]
dtoverlay=spi0-0cs
- name: change root partition
replace:
dest: /boot/firmware/cmdline.txt
@ -517,16 +482,11 @@
- name: Update .bashrc for go-1.21
blockinfile:
dest: /home/pi/.bashrc
dest: /etc/profile
state: present
block: |
export GOPATH=$HOME/go
export PATH=/usr/local/go/bin:$PATH:$GOPATH/bin
alias custom='cd /usr/local/share/pwnagotchi/custom-plugins/'
alias config='sudo nano /etc/pwnagotchi/config.toml'
alias pwnlog='tail -f -n300 /etc/pwnagotchi/log/pwn*.log | sed --unbuffered "s/,[[:digit:]]\\{3\\}\\]//g" | cut -d " " -f 2-'
alias pwnver='python3 -c "import pwnagotchi as p; print(p.__version__)"'
alias pwnkill='sudo killall -USR1 pwnagotchi'
when: golang.changed
- name: download pwngrid

View File

@ -1 +1 @@
__version__ = '2.8.7.1'
__version__ = '2.8.8'

View File

@ -254,7 +254,7 @@ class Agent(Client, Automata, AsyncAdvertiser, AsyncTrainer):
txt = '%d (%d)' % (len(self._handshakes), tot)
if self._last_pwnd is not None:
txt += ' [%s]' % self._last_pwnd[:11] # So it doesn't overlap with fix_brcmfmac_plugin
txt += ' [%s]' % self._last_pwnd
self._view.set('shakes', txt)

View File

@ -100,7 +100,6 @@ class Client(object):
await asyncio.sleep(sleep_time)
continue
except OSError:
sleep_time = min_sleep + max_sleep * random.random()
logging.warning('connection to the bettercap endpoint failed...')
pwnagotchi.restart("AUTO")

View File

@ -112,8 +112,6 @@ main.mon_stop_cmd = "/usr/bin/monstop"
main.mon_max_blind_epochs = 50
main.no_restart = false
main.filter = ""
main.log.path = "/etc/pwnagotchi/log/pwnagotchi.log"
main.log.rotation.enabled = true
main.log.rotation.size = "10M"

View File

@ -248,7 +248,7 @@ msgid "minutes"
msgstr "minuten"
msgid "seconds"
msgstr "seconds"
msgstr "sekondes"
msgid "hour"
msgstr "oere"

View File

@ -4,6 +4,8 @@ import subprocess
import time
import random
from io import TextIOWrapper
import os
import platform
import pwnagotchi
from pwnagotchi import plugins
@ -32,6 +34,8 @@ class FixServices(plugins.Plugin):
self.pattern2 = re.compile(r'wifi error while hopping to channel')
self.pattern3 = re.compile(r'Firmware has halted or crashed')
self.pattern4 = re.compile(r'error 400: could not find interface wlan0mon')
self.pattern5 = re.compile(r'fatal error: concurrent map iteration and map write')
self.pattern6 = re.compile(r'panic: runtime error')
self.isReloadingMon = False
self.connection = None
self.LASTTRY = 0
@ -113,6 +117,7 @@ class FixServices(plugins.Plugin):
logging.debug("[Fix_Services]**** checking")
# Look for pattern 1
if platform.machine().startswith('arm'):
if len(self.pattern.findall(last_lines)) >= 3:
logging.debug("[Fix_Services]**** Should trigger a reload of the wlan0mon device:\n%s" % last_lines)
if hasattr(agent, 'view'):
@ -127,6 +132,7 @@ class FixServices(plugins.Plugin):
# Look for pattern 2
elif len(self.pattern2.findall(other_last_lines)) >= 5:
if platform.machine().startswith('arm'):
logging.debug("[Fix_Services]**** Should trigger a reload of the wlan0mon device:\n%s" % last_lines)
if hasattr(agent, 'view'):
display = agent.view()
@ -177,6 +183,25 @@ class FixServices(plugins.Plugin):
except Exception as err:
logging.error("[Fix_Services monstart]: %s" % repr(err))
# Look for pattern 5
elif len(self.pattern5.findall(other_other_last_lines)) >= 1:
logging.debug("[Fix_Services] Bettercap has crashed!")
if hasattr(agent, 'view'):
display = agent.view()
display.set('status', 'Restarting pwnagotchi!')
display.update(force=True)
os.system("systemctl restart bettercap")
pwnagotchi.restart("AUTO")
# Look for pattern 6
elif len(self.pattern6.findall(other_other_last_lines)) >= 1:
logging.debug("[Fix_Services] Bettercap has crashed!")
if hasattr(agent, 'view'):
display = agent.view()
display.set('status', 'Restarting pwnagotchi!')
display.update(force=True)
os.system("systemctl restart bettercap")
pwnagotchi.restart("AUTO")
else:
print("logs look good")

View File

View File

@ -202,6 +202,9 @@ class Display(View):
def is_inky(self):
return self._implementation.name == 'inky'
def is_dummy_display(self):
return self._implementation.name == 'dummydisplay'
def is_papirus(self):
return self._implementation.name == 'papirus'
@ -232,6 +235,9 @@ class Display(View):
def is_waveshare35lcd(self):
return self._implementation.name == 'waveshare35lcd'
def is_adfruit213v3(self):
return self._implementation.name == 'adafruit2in13_v3'
def is_waveshare_any(self):
return self.is_waveshare_v1() or self.is_waveshare_v2()

View File

@ -27,6 +27,7 @@ PNG = False
POSITION_X = 0
POSITION_Y = 40
def load_from_config(config):
for face_name, face_value in config.items():
globals()[face_name.upper()] = face_value

View File

@ -1,4 +1,5 @@
from pwnagotchi.ui.hw.inky import Inky
from pwnagotchi.ui.hw.dummydisplay import DummyDisplay
from pwnagotchi.ui.hw.papirus import Papirus
from pwnagotchi.ui.hw.oledhat import OledHat
from pwnagotchi.ui.hw.lcdhat import LcdHat
@ -24,6 +25,7 @@ from pwnagotchi.ui.hw.displayhatmini import DisplayHatMini
from pwnagotchi.ui.hw.pirateaudio import PirateAudio
from pwnagotchi.ui.hw.pitft import Pitft
from pwnagotchi.ui.hw.tftbonnet import TftBonnet
from pwnagotchi.ui.hw.adafruit2in13 import Adafruit2in13V3
from pwnagotchi.ui.hw.waveshareoledlcd import Waveshareoledlcd
from pwnagotchi.ui.hw.waveshare1in02 import Waveshare1in02
from pwnagotchi.ui.hw.waveshare1in54 import Waveshare154
@ -75,6 +77,9 @@ def display_for(config):
if config['ui']['display']['type'] == 'inky':
return Inky(config)
elif config['ui']['display']['type'] == 'dummydisplay':
return DummyDisplay(config)
elif config['ui']['display']['type'] == 'papirus':
return Papirus(config)
@ -177,6 +182,9 @@ def display_for(config):
elif config['ui']['display']['type'] == 'waveshare_4':
return WaveshareV4(config)
elif config['ui']['display']['type'] == 'adafruit2in13':
return Adafruit2in13(config)
elif config['ui']['display']['type'] == 'waveshare2in13bc':
return Waveshare213bc(config)

View File

@ -0,0 +1,45 @@
import logging
import pwnagotchi.ui.fonts as fonts
from pwnagotchi.ui.hw.base import DisplayImpl
class Adafruit2in13V3(DisplayImpl):
def __init__(self, config):
super(Adafruit2in13V3, self).__init__(config, 'adafruit2in13_v3')
def layout(self):
fonts.setup(10, 9, 10, 35, 25, 9)
self._layout['width'] = 250
self._layout['height'] = 122
self._layout['face'] = (0, 40)
self._layout['name'] = (5, 20)
self._layout['channel'] = (0, 0)
self._layout['aps'] = (28, 0)
self._layout['uptime'] = (185, 0)
self._layout['line1'] = [0, 14, 250, 14]
self._layout['line2'] = [0, 108, 250, 108]
self._layout['friend_face'] = (0, 92)
self._layout['friend_name'] = (40, 94)
self._layout['shakes'] = (0, 109)
self._layout['mode'] = (225, 109)
self._layout['status'] = {
'pos': (125, 20),
'font': fonts.status_font(fonts.Medium),
'max': 20
}
return self._layout
def initialize(self):
logging.info("initializing adafruit 2in13 V3 display")
from pwnagotchi.ui.hw.libs.adafruit.v2in13_v3.epd2in13_v3 import EPD
self._display = EPD()
self._display.init()
self._display.Clear(0xFF)
def render(self, canvas):
buf = self._display.getbuffer(canvas)
self._display.displayPartial(buf)
def clear(self):
self._display.Clear(0xFF)

View File

@ -0,0 +1,43 @@
import logging
import pwnagotchi.ui.fonts as fonts
from pwnagotchi.ui.hw.base import DisplayImpl
class DummyDisplay(DisplayImpl):
def __init__(self, config):
super(DummyDisplay, self).__init__(config, 'DummyDisplay')
def layout(self):
width = 480 if 'width' not in self.config else self.config['width']
height = 720 if 'height' not in self.config else self.config['height']
fonts.setup(int(height/30), int(height/40), int(height/30), int(height/6), int(height/30), int(height/35))
self._layout['width'] = width
self._layout['height'] = height
self._layout['face'] = (0, int(width/12))
self._layout['name'] = (5, int(width/25))
self._layout['channel'] = (0, 0)
self._layout['aps'] = (int(width/8), 0)
self._layout['uptime'] = (width-int(width/12), 0)
self._layout['line1'] = [0, int(height/32), width, int(height/32)]
self._layout['line2'] = [0, height-int(height/25)-1, width, height-int(height/25)-1]
self._layout['friend_face'] = (0, int(height/10))
self._layout['friend_name'] = (int(width/12), int(height/10))
self._layout['shakes'] = (0, height-int(height/25))
self._layout['mode'] = (width-int(width/8), height - int (height/25))
lw, lh = fonts.Small.getsize("W")
self._layout['status'] = {
'pos': (int(width/48), int(height/3)),
'font': fonts.status_font(fonts.Small),
'max': int(width / lw)
}
return self._layout
def initialize(self):
return
def render(self, canvas):
return
def clear(self):
return

View File

@ -0,0 +1,132 @@
# /*****************************************************************************
# * | File : epdconfig.py
# * | Author : Waveshare team
# * | Function : Hardware underlying interface
# * | Info :
# *----------------
# * | This version: V1.2
# * | Date : 2022-10-29
# * | Info :
# ******************************************************************************
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documnetation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# 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 os
import logging
import sys
import time
import subprocess
logger = logging.getLogger(__name__)
class RaspberryPi:
# Pin definition
RST_PIN = 27
DC_PIN = 22
CS_PIN = 8
BUSY_PIN = 17
PWR_PIN = 18
def __init__(self):
import spidev
import gpiozero
self.SPI = spidev.SpiDev()
self.GPIO_RST_PIN = gpiozero.LED(self.RST_PIN)
self.GPIO_DC_PIN = gpiozero.LED(self.DC_PIN)
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):
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):
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):
time.sleep(delaytime / 1000.0)
def spi_writebyte(self, data):
self.SPI.writebytes(data)
def spi_writebyte2(self, data):
self.SPI.writebytes2(data)
def module_init(self):
self.GPIO_PWR_PIN.on()
# SPI device, bus = 0, device = 0
self.SPI.open(0, 0)
self.SPI.max_speed_hz = 4000000
self.SPI.mode = 0b00
return 0
def module_exit(self, cleanup=False):
logger.debug("spi end")
self.SPI.close()
self.GPIO_RST_PIN.off()
self.GPIO_DC_PIN.off()
self.GPIO_PWR_PIN.off()
logger.debug("close 5V, Module enters 0 power consumption ...")
if cleanup:
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()
implementation = RaspberryPi()
for func in [x for x in dir(implementation) if not x.startswith('_')]:
setattr(sys.modules[__name__], func, getattr(implementation, func))
### END OF FILE ###

View File

@ -4,8 +4,8 @@
# * | Function : Electronic paper driver
# * | Info :
# *----------------
# * | This version: V1.1
# * | Date : 2021-10-30
# * | This version: V1.2
# * | Date : 2022-08-9
# # | Info : python demo
# -----------------------------------------------------------------------------
# Permission is hereby granted, free of charge, to any person obtaining a copy
@ -29,8 +29,7 @@
import logging
from . import epdconfig
import numpy as np
from .. import epdconfig
# Display resolution
EPD_WIDTH = 122
@ -38,6 +37,7 @@ EPD_HEIGHT = 250
logger = logging.getLogger(__name__)
class EPD:
def __init__(self):
self.reset_pin = epdconfig.RST_PIN
@ -95,6 +95,7 @@ class EPD:
function :Hardware reset
parameter:
'''
def reset(self):
epdconfig.digital_write(self.reset_pin, 1)
epdconfig.delay_ms(20)
@ -108,6 +109,7 @@ class EPD:
parameter:
command : Command register
'''
def send_command(self, command):
epdconfig.digital_write(self.dc_pin, 0)
epdconfig.digital_write(self.cs_pin, 0)
@ -119,16 +121,25 @@ class EPD:
parameter:
data : Write data
'''
def send_data(self, data):
epdconfig.digital_write(self.dc_pin, 1)
epdconfig.digital_write(self.cs_pin, 0)
epdconfig.spi_writebyte([data])
epdconfig.digital_write(self.cs_pin, 1)
# send a lot of data
def send_data2(self, data):
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)
'''
function :Wait until the busy_pin goes LOW
parameter:
'''
def ReadBusy(self):
logger.debug("e-Paper busy")
while (epdconfig.digital_read(self.busy_pin) == 1): # 0: idle, 1: busy
@ -139,6 +150,7 @@ class EPD:
function : Turn On Display
parameter:
'''
def TurnOnDisplay(self):
self.send_command(0x22) # Display Update Control
self.send_data(0xC7)
@ -149,6 +161,7 @@ class EPD:
function : Turn On Display Part
parameter:
'''
def TurnOnDisplayPart(self):
self.send_command(0x22) # Display Update Control
self.send_data(0x0f) # fast:0x0c, quality:0x0f, 0xcf
@ -160,6 +173,7 @@ class EPD:
parameter:
lut : lut data
'''
def Lut(self, lut):
self.send_command(0x32)
for i in range(0, 153):
@ -171,6 +185,7 @@ class EPD:
parameter:
lut : lut data
'''
def SetLut(self, lut):
self.Lut(lut)
self.send_command(0x3f)
@ -192,6 +207,7 @@ class EPD:
xend : End position of X-axis
yend : End position of Y-axis
'''
def SetWindow(self, x_start, y_start, x_end, y_end):
self.send_command(0x44) # SET_RAM_X_ADDRESS_START_END_POSITION
# x point must be the multiple of 8 or the last 3 bits will be ignored
@ -210,6 +226,7 @@ class EPD:
x : X-axis starting position
y : Y-axis starting position
'''
def SetCursor(self, x, y):
self.send_command(0x4E) # SET_RAM_X_ADDRESS_COUNTER
# x point must be the multiple of 8 or the last 3 bits will be ignored
@ -223,6 +240,7 @@ class EPD:
function : Initialize the e-Paper register
parameter:
'''
def init(self):
if (epdconfig.module_init() != 0):
return -1
@ -264,6 +282,7 @@ class EPD:
parameter:
image : Image data
'''
def getbuffer(self, image):
img = image
imwidth, imheight = img.size
@ -285,6 +304,7 @@ class EPD:
parameter:
image : Image data
'''
def display(self, image):
if self.width % 8 == 0:
linewidth = int(self.width / 8)
@ -302,12 +322,8 @@ class EPD:
parameter:
image : Image data
'''
def displayPartial(self, image):
if self.width%8 == 0:
linewidth = int(self.width/8)
else:
linewidth = int(self.width/8) + 1
def displayPartial(self, image):
epdconfig.digital_write(self.reset_pin, 0)
epdconfig.delay_ms(1)
epdconfig.digital_write(self.reset_pin, 1)
@ -337,9 +353,10 @@ class EPD:
self.SetCursor(0, 0)
self.send_command(0x24) # WRITE_RAM
for j in range(0, self.height):
for i in range(0, linewidth):
self.send_data(image[i + j * linewidth])
# for j in range(0, self.height):
# for i in range(0, linewidth):
# self.send_data(image[i + j * linewidth])
self.send_data2(image)
self.TurnOnDisplayPart()
'''
@ -347,28 +364,21 @@ class EPD:
parameter:
image : Image data
'''
def displayPartBaseImage(self, image):
if self.width%8 == 0:
linewidth = int(self.width/8)
else:
linewidth = int(self.width/8) + 1
def displayPartBaseImage(self, image):
self.send_command(0x24)
for j in range(0, self.height):
for i in range(0, linewidth):
self.send_data(image[i + j * linewidth])
self.send_data2(image)
self.send_command(0x26)
for j in range(0, self.height):
for i in range(0, linewidth):
self.send_data(image[i + j * linewidth])
self.send_data2(image)
self.TurnOnDisplay()
'''
function : Clear screen
parameter:
'''
def Clear(self, color):
def Clear(self, color=0xFF):
if self.width % 8 == 0:
linewidth = int(self.width / 8)
else:
@ -376,16 +386,14 @@ class EPD:
# logger.debug(linewidth)
self.send_command(0x24)
for j in range(0, self.height):
for i in range(0, linewidth):
self.send_data(color)
self.send_data2([color] * int(self.height * linewidth))
self.TurnOnDisplay()
'''
function : Enter sleep mode
parameter:
'''
def sleep(self):
self.send_command(0x10) # enter deep sleep
self.send_data(0x01)
@ -394,4 +402,3 @@ class EPD:
epdconfig.module_exit()
### END OF FILE ###

View File

@ -90,8 +90,8 @@ ST7789_PWCTR6 = 0xFC
class ST7789(object):
"""Representation of an ST7789 TFT LCD."""
def __init__(self, port, cs, dc, backlight, rst=None, width=320,
height=240, rotation=0, invert=True, spi_speed_hz=60 * 1000 * 1000,
def __init__(self, port, cs, dc, backlight=None, rst=None, width=240,
height=240, rotation=90, invert=True, spi_speed_hz=4000000,
offset_left=0,
offset_top=0):
"""Create an instance of the display using SPI communication.

View File

@ -1,224 +0,0 @@
# *****************************************************************************
# * | File : epd2in13.py
# * | Author : Waveshare team
# * | Function : Electronic paper driver
# * | Info :
# *----------------
# * | This version: V4.0
# * | Date : 2019-06-20
# # | Info : python demo
# -----------------------------------------------------------------------------
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS 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
from . import epdconfig
# Display resolution
EPD_WIDTH = 122
EPD_HEIGHT = 250
class EPD:
def __init__(self):
self.reset_pin = epdconfig.RST_PIN
self.dc_pin = epdconfig.DC_PIN
self.busy_pin = epdconfig.BUSY_PIN
self.cs_pin = epdconfig.CS_PIN
self.width = EPD_WIDTH
self.height = EPD_HEIGHT
lut_full_update = [
0x22, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x11,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00
]
lut_partial_update = [
0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
]
# Hardware reset
def reset(self):
epdconfig.digital_write(self.cs_pin, 0)
epdconfig.digital_write(self.reset_pin, 1)
epdconfig.delay_ms(200)
epdconfig.digital_write(self.reset_pin, 0)
epdconfig.delay_ms(10)
epdconfig.digital_write(self.reset_pin, 1)
epdconfig.delay_ms(200)
epdconfig.digital_write(self.cs_pin, 1)
def send_command(self, command):
epdconfig.digital_write(self.cs_pin, 0)
epdconfig.digital_write(self.dc_pin, 0)
epdconfig.spi_writebyte([command])
epdconfig.digital_write(self.cs_pin, 1)
def send_data(self, data):
epdconfig.digital_write(self.cs_pin, 0)
epdconfig.digital_write(self.dc_pin, 1)
epdconfig.spi_writebyte([data])
epdconfig.digital_write(self.cs_pin, 1)
def ReadBusy(self):
while(epdconfig.digital_read(self.busy_pin) == 1): # 0: idle, 1: busy
epdconfig.delay_ms(100)
def TurnOnDisplay(self):
self.send_command(0x22) # DISPLAY_UPDATE_CONTROL_2
self.send_data(0xC4)
self.send_command(0x20) # MASTER_ACTIVATION
self.send_command(0xFF) # TERMINATE_FRAME_READ_WRITE
logging.debug("e-Paper busy")
self.ReadBusy()
logging.debug("e-Paper busy release")
def init(self, lut):
if (epdconfig.module_init() != 0):
return -1
# EPD hardware init start
self.reset()
self.send_command(0x01) # DRIVER_OUTPUT_CONTROL
self.send_data((EPD_HEIGHT - 1) & 0xFF)
self.send_data(((EPD_HEIGHT - 1) >> 8) & 0xFF)
self.send_data(0x00) # GD = 0 SM = 0 TB = 0
self.send_command(0x0C) # BOOSTER_SOFT_START_CONTROL
self.send_data(0xD7)
self.send_data(0xD6)
self.send_data(0x9D)
self.send_command(0x2C) # WRITE_VCOM_REGISTER
self.send_data(0xA8) # VCOM 7C
self.send_command(0x3A) # SET_DUMMY_LINE_PERIOD
self.send_data(0x1A) # 4 dummy lines per gate
self.send_command(0x3B) # SET_GATE_TIME
self.send_data(0x08) # 2us per line
self.send_command(0X3C) # BORDER_WAVEFORM_CONTROL
self.send_data(0x03)
self.send_command(0X11) # DATA_ENTRY_MODE_SETTING
self.send_data(0x03) # X increment; Y increment
# WRITE_LUT_REGISTER
self.send_command(0x32)
for count in range(30):
self.send_data(lut[count])
return 0
##
# @brief: specify the memory area for data R/W
##
def SetWindows(self, x_start, y_start, x_end, y_end):
self.send_command(0x44) # SET_RAM_X_ADDRESS_START_END_POSITION
self.send_data((x_start >> 3) & 0xFF)
self.send_data((x_end >> 3) & 0xFF)
self.send_command(0x45) # SET_RAM_Y_ADDRESS_START_END_POSITION
self.send_data(y_start & 0xFF)
self.send_data((y_start >> 8) & 0xFF)
self.send_data(y_end & 0xFF)
self.send_data((y_end >> 8) & 0xFF)
##
# @brief: specify the start point for data R/W
##
def SetCursor(self, x, y):
self.send_command(0x4E) # SET_RAM_X_ADDRESS_COUNTER
# x point must be the multiple of 8 or the last 3 bits will be ignored
self.send_data((x >> 3) & 0xFF)
self.send_command(0x4F) # SET_RAM_Y_ADDRESS_COUNTER
self.send_data(y & 0xFF)
self.send_data((y >> 8) & 0xFF)
self.ReadBusy()
def getbuffer(self, image):
if self.width%8 == 0:
linewidth = int(self.width/8)
else:
linewidth = int(self.width/8) + 1
buf = [0xFF] * (linewidth * self.height)
image_monocolor = image.convert('1')
imwidth, imheight = image_monocolor.size
pixels = image_monocolor.load()
if(imwidth == self.width and imheight == self.height):
for y in range(imheight):
for x in range(imwidth):
if pixels[x, y] == 0:
# x = imwidth - x
buf[int(x / 8) + y * linewidth] &= ~(0x80 >> (x % 8))
elif(imwidth == self.height and imheight == self.width):
for y in range(imheight):
for x in range(imwidth):
newx = y
newy = self.height - x - 1
if pixels[x, y] == 0:
# newy = imwidth - newy - 1
buf[int(newx / 8) + newy*linewidth] &= ~(0x80 >> (y % 8))
return buf
def display(self, image):
if self.width%8 == 0:
linewidth = int(self.width/8)
else:
linewidth = int(self.width/8) + 1
self.SetWindows(0, 0, self.width, self.height);
for j in range(0, self.height):
self.SetCursor(0, j);
self.send_command(0x24);
for i in range(0, linewidth):
self.send_data(image[i + j * linewidth])
self.TurnOnDisplay()
def Clear(self, color):
if self.width%8 == 0:
linewidth = int(self.width/8)
else:
linewidth = int(self.width/8) + 1
self.SetWindows(0, 0, self.width, self.height);
for j in range(0, self.height):
self.SetCursor(0, j);
self.send_command(0x24);
for i in range(0, linewidth):
self.send_data(color)
self.TurnOnDisplay()
def sleep(self):
self.send_command(0x10) #enter deep sleep
self.send_data(0x01)
epdconfig.delay_ms(100)
epdconfig.module_exit()
### END OF FILE ###

View File

@ -1,164 +0,0 @@
# *****************************************************************************
# * | File : epd2in13bc.py
# * | Author : Waveshare team
# * | Function : Electronic paper driver
# * | Info :
# *----------------
# * | This version: V4.0
# * | Date : 2019-06-20
# # | Info : python demo
# -----------------------------------------------------------------------------
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS 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.
#
from . import epdconfig
import RPi.GPIO as GPIO
# import numpy as np
# Display resolution
EPD_WIDTH = 104
EPD_HEIGHT = 212
class EPD:
def __init__(self):
self.reset_pin = epdconfig.RST_PIN
self.dc_pin = epdconfig.DC_PIN
self.busy_pin = epdconfig.BUSY_PIN
self.cs_pin = epdconfig.CS_PIN
self.width = EPD_WIDTH
self.height = EPD_HEIGHT
# Hardware reset
def reset(self):
epdconfig.digital_write(self.reset_pin, GPIO.HIGH)
epdconfig.delay_ms(200)
epdconfig.digital_write(self.reset_pin, GPIO.LOW) # module reset
epdconfig.delay_ms(200)
epdconfig.digital_write(self.reset_pin, GPIO.HIGH)
epdconfig.delay_ms(200)
def send_command(self, command):
epdconfig.digital_write(self.dc_pin, GPIO.LOW)
epdconfig.digital_write(self.cs_pin, GPIO.LOW)
epdconfig.spi_writebyte([command])
epdconfig.digital_write(self.cs_pin, GPIO.HIGH)
def send_data(self, data):
epdconfig.digital_write(self.dc_pin, GPIO.HIGH)
epdconfig.digital_write(self.cs_pin, GPIO.LOW)
epdconfig.spi_writebyte([data])
epdconfig.digital_write(self.cs_pin, GPIO.HIGH)
def ReadBusy(self):
epdconfig.delay_ms(20)
while(epdconfig.digital_read(self.busy_pin) == 0): # 0: idle, 1: busy
epdconfig.delay_ms(100)
def init(self):
if (epdconfig.module_init() != 0):
return -1
# EPD hardware init start
self.reset()
self.send_command(0x06) # BOOSTER_SOFT_START
self.send_data(0x17)
self.send_data(0x17)
self.send_data(0x17)
self.send_command(0x04) # POWER_ON
self.ReadBusy()
self.send_command(0x00) # PANEL_SETTING
self.send_data(0x8F)
self.send_command(0x50) # VCOM_AND_DATA_INTERVAL_SETTING
self.send_data(0xF0)
self.send_command(0x61) # RESOLUTION_SETTING
self.send_data(self.width & 0xff)
self.send_data(self.height >> 8)
self.send_data(self.height & 0xff)
return 0
def getbuffer(self, image):
buf = [0xFF] * (int(self.width/8) * self.height)
image_monocolor = image.convert('1')
imwidth, imheight = image_monocolor.size
pixels = image_monocolor.load()
if(imwidth == self.width and imheight == self.height):
for y in range(imheight):
for x in range(imwidth):
# Set the bits for the column of pixels at the current position.
if pixels[x, y] == 0:
buf[int((x + y * self.width) / 8)] &= ~(0x80 >> (x % 8))
elif(imwidth == self.height and imheight == self.width):
for y in range(imheight):
for x in range(imwidth):
newx = y
newy = self.height - x - 1
if pixels[x, y] == 0:
buf[int((newx + newy*self.width) / 8)] &= ~(0x80 >> (y % 8))
return buf
def displayBlack(self, imageblack):
self.send_command(0x10)
for i in range(0, int(self.width * self.height / 8)):
self.send_data(imageblack[i])
self.send_command(0x92)
self.send_command(0x12) # REFRESH
self.ReadBusy()
def display(self, imageblack, imagecolor):
self.send_command(0x10)
for i in range(0, int(self.width * self.height / 8)):
self.send_data(imageblack[i])
self.send_command(0x92)
self.send_command(0x13)
for i in range(0, int(self.width * self.height / 8)):
self.send_data(imagecolor[i])
self.send_command(0x92)
self.send_command(0x12) # REFRESH
self.ReadBusy()
def Clear(self):
self.send_command(0x10)
for i in range(0, int(self.width * self.height / 8)):
self.send_data(0xFF)
self.send_command(0x92)
self.send_command(0x13)
for i in range(0, int(self.width * self.height / 8)):
self.send_data(0xFF)
self.send_command(0x92)
self.send_command(0x12) # REFRESH
self.ReadBusy()
def sleep(self):
self.send_command(0x02) # POWER_OFF
self.ReadBusy()
self.send_command(0x07) # DEEP_SLEEP
self.send_data(0xA5) # check code
# epdconfig.module_exit()
### END OF FILE ###

View File

@ -1,359 +0,0 @@
# *****************************************************************************
# * | File : epd2in13d.py
# * | Author : Waveshare team
# * | Function : Electronic paper driver
# * | Info :
# *----------------
# * | This version: V4.0
# * | Date : 2019-06-20
# # | Info : python demo
# -----------------------------------------------------------------------------
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documnetation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# 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.
#
# =============================================================================
# THIS FILE HAS BEEN MODIFIED FROM ORIGINAL, IT HAS BEEN MODIFIED TO RUN THE
# THREE COLOR WAVESHARE 2.13IN DISPLAY AT A MUCH, MUCH FASTER RATE THAN NORMAL
# AND IT COULD DAMAGE YOUR DISPLAY. THERE IS NO WARRANTY INCLUDED AND YOU USE
# THIS CODE AT YOUR OWN RISK. WE ARE NOT RESPONSIBLE FOR ANYTHING THAT HAPPENS
# INCLUDING BUT NOT LIMITED TO: DESTRUCTION OF YOUR DISPLAY, PI, HOUSE, CAR,
# SPACE-TIME-CONTINUUM, OR IF THE CODE KILLS YOUR CAT. IF YOU AREN'T WILLING TO
# TAKE THESE RISKS, PLEASE DO NOT USE THIS CODE.
# =============================================================================
import logging
from . import epdconfig
from PIL import Image
import RPi.GPIO as GPIO
# Display resolution
EPD_WIDTH = 104
EPD_HEIGHT = 212
class EPD:
def __init__(self):
self.reset_pin = epdconfig.RST_PIN
self.dc_pin = epdconfig.DC_PIN
self.busy_pin = epdconfig.BUSY_PIN
self.cs_pin = epdconfig.CS_PIN
self.width = EPD_WIDTH
self.height = EPD_HEIGHT
lut_vcomDC = [
0x00, 0x08, 0x00, 0x00, 0x00, 0x02,
0x60, 0x28, 0x28, 0x00, 0x00, 0x01,
0x00, 0x14, 0x00, 0x00, 0x00, 0x01,
0x00, 0x12, 0x12, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
]
lut_ww = [
0x40, 0x08, 0x00, 0x00, 0x00, 0x02,
0x90, 0x28, 0x28, 0x00, 0x00, 0x01,
0x40, 0x14, 0x00, 0x00, 0x00, 0x01,
0xA0, 0x12, 0x12, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]
lut_bw = [
0x40, 0x17, 0x00, 0x00, 0x00, 0x02,
0x90, 0x0F, 0x0F, 0x00, 0x00, 0x03,
0x40, 0x0A, 0x01, 0x00, 0x00, 0x01,
0xA0, 0x0E, 0x0E, 0x00, 0x00, 0x02,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]
lut_wb = [
0x80, 0x08, 0x00, 0x00, 0x00, 0x02,
0x90, 0x28, 0x28, 0x00, 0x00, 0x01,
0x80, 0x14, 0x00, 0x00, 0x00, 0x01,
0x50, 0x12, 0x12, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]
lut_bb = [
0x80, 0x08, 0x00, 0x00, 0x00, 0x02,
0x90, 0x28, 0x28, 0x00, 0x00, 0x00,
0x80, 0x14, 0x00, 0x00, 0x00, 0x01,
0x50, 0x12, 0x12, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]
lut_vcom1 = [
0xA0, 0x10, 0x10, 0x00, 0x00, 0x02,
0x00, 0x10, 0x10, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
]
lut_ww1 = [
0x50, 0x01, 0x01, 0x00, 0x00, 0x01,
0xA0, 0x42, 0x42, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]
lut_bw1 = [
0x50, 0x01, 0x01, 0x00, 0x00, 0x01,
0xA0, 0x42, 0x42, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]
lut_wb1 = [
0xA0, 0x01, 0x01, 0x00, 0x00, 0x01,
0x50, 0x42, 0x42, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]
lut_bb1 = [
0xA0, 0x01, 0x01, 0x00, 0x00, 0x01,
0x50, 0x42, 0x42, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]
# Hardware reset
def reset(self):
epdconfig.digital_write(self.reset_pin, 1)
epdconfig.delay_ms(200)
epdconfig.digital_write(self.reset_pin, 0)
epdconfig.delay_ms(10)
epdconfig.digital_write(self.reset_pin, 1)
epdconfig.delay_ms(200)
def send_command(self, command):
epdconfig.digital_write(self.dc_pin, 0)
epdconfig.digital_write(self.cs_pin, 0)
epdconfig.spi_writebyte([command])
epdconfig.digital_write(self.cs_pin, 1)
def send_data(self, data):
epdconfig.digital_write(self.dc_pin, 1)
epdconfig.digital_write(self.cs_pin, 0)
epdconfig.spi_writebyte([data])
epdconfig.digital_write(self.cs_pin, 1)
def ReadBusy(self):
logging.debug("e-Paper busy")
while(epdconfig.digital_read(self.busy_pin) == 0): # 0: idle, 1: busy
self.send_command(0x71)
epdconfig.delay_ms(100)
logging.debug("e-Paper busy release")
def TurnOnDisplay(self):
self.send_command(0x12)
epdconfig.delay_ms(10)
self.ReadBusy()
def init(self):
if (epdconfig.module_init() != 0):
return -1
# EPD hardware init start
self.reset()
self.send_command(0x01) # POWER SETTING
self.send_data(0x03)
self.send_data(0x00)
self.send_data(0x2b)
self.send_data(0x2b)
self.send_data(0x03)
self.send_command(0x06) # boost soft start
self.send_data(0x17) # A
self.send_data(0x17) # B
self.send_data(0x17) # C
self.send_command(0x04)
self.ReadBusy()
self.send_command(0x00) # panel setting
self.send_data(0xbf) # LUT from OTP,128x296
self.send_data(0x0d) # VCOM to 0V fast
self.send_command(0x30) # PLL setting
self.send_data(0x21) # 3a 100HZ 29 150Hz 39 200HZ 31 171HZ
self.send_command(0x61) # resolution setting
self.send_data(self.width)
self.send_data((self.height >> 8) & 0xff)
self.send_data(self.height& 0xff)
self.send_command(0x82) # vcom_DC setting
self.send_data(0x28)
return 0
def SetFullReg(self):
self.send_command(0x82)
self.send_data(0x00)
self.send_command(0X50)
self.send_data(0x97)
# self.send_command(0x00) # panel setting
# self.send_data(0x9f) # LUT from OTP,128x296
def SetPartReg(self):
# self.send_command(0x00) # panel setting
# self.send_data(0xbf) # LUT from OTP,128x296
self.send_command(0x82)
self.send_data(0x03)
self.send_command(0X50)
self.send_data(0x47)
self.send_command(0x20) # vcom
for count in range(0, 44):
self.send_data(self.lut_vcom1[count])
self.send_command(0x21) # ww --
for count in range(0, 42):
self.send_data(self.lut_ww1[count])
self.send_command(0x22) # bw r
for count in range(0, 42):
self.send_data(self.lut_bw1[count])
self.send_command(0x23) # wb w
for count in range(0, 42):
self.send_data(self.lut_wb1[count])
self.send_command(0x24) # bb b
for count in range(0, 42):
self.send_data(self.lut_bb1[count])
def getbuffer(self, image):
# logging.debug("bufsiz = ",int(self.width/8) * self.height)
buf = [0xFF] * (int(self.width/8) * self.height)
image_monocolor = image.convert('1')
imwidth, imheight = image_monocolor.size
pixels = image_monocolor.load()
# logging.debug("imwidth = %d, imheight = %d",imwidth,imheight)
if(imwidth == self.width and imheight == self.height):
logging.debug("Vertical")
for y in range(imheight):
for x in range(imwidth):
# Set the bits for the column of pixels at the current position.
if pixels[x, y] == 0:
buf[int((x + y * self.width) / 8)] &= ~(0x80 >> (x % 8))
elif(imwidth == self.height and imheight == self.width):
logging.debug("Horizontal")
for y in range(imheight):
for x in range(imwidth):
newx = y
newy = self.height - x - 1
if pixels[x, y] == 0:
buf[int((newx + newy*self.width) / 8)] &= ~(0x80 >> (y % 8))
return buf
def display(self, image):
if (Image == None):
return
self.send_command(0x10)
for i in range(0, int(self.width * self.height / 8)):
self.send_data(0x00)
epdconfig.delay_ms(10)
self.send_command(0x13)
for i in range(0, int(self.width * self.height / 8)):
self.send_data(image[i])
epdconfig.delay_ms(10)
self.SetFullReg()
self.TurnOnDisplay()
def DisplayPartial(self, image):
if (Image == None):
return
self.SetPartReg()
self.send_command(0x91)
self.send_command(0x90)
self.send_data(0)
self.send_data(self.width - 1)
self.send_data(0)
self.send_data(0)
self.send_data(int(self.height / 256))
self.send_data(self.height % 256 - 1)
self.send_data(0x28)
self.send_command(0x10)
for i in range(0, int(self.width * self.height / 8)):
self.send_data(image[i])
epdconfig.delay_ms(10)
self.send_command(0x13)
for i in range(0, int(self.width * self.height / 8)):
self.send_data(~image[i])
epdconfig.delay_ms(10)
self.TurnOnDisplay()
def Clear(self):
self.send_command(0x10)
for i in range(0, int(self.width * self.height / 8)):
self.send_data(0x00)
epdconfig.delay_ms(10)
self.send_command(0x13)
for i in range(0, int(self.width * self.height / 8)):
self.send_data(0x00)
epdconfig.delay_ms(10)
self.SetFullReg()
self.TurnOnDisplay()
def sleep(self):
self.send_command(0X50)
self.send_data(0xf7)
self.send_command(0X02) # power off
self.send_command(0X07) # deep sleep
self.send_data(0xA5)
epdconfig.module_exit()
### END OF FILE ###

View File

@ -1,154 +0,0 @@
# /*****************************************************************************
# * | File : epdconfig.py
# * | Author : Waveshare team
# * | Function : Hardware underlying interface
# * | Info :
# *----------------
# * | This version: V1.0
# * | Date : 2019-06-21
# * | Info :
# ******************************************************************************
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS 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 os
import logging
import sys
import time
class RaspberryPi:
# Pin definition
RST_PIN = 17
DC_PIN = 25
CS_PIN = 8
BUSY_PIN = 24
def __init__(self):
import spidev
import RPi.GPIO
self.GPIO = RPi.GPIO
# SPI device, bus = 0, device = 0
self.SPI = spidev.SpiDev(0, 0)
def digital_write(self, pin, value):
self.GPIO.output(pin, value)
def digital_read(self, pin):
return self.GPIO.input(self.BUSY_PIN)
def delay_ms(self, delaytime):
time.sleep(delaytime / 1000.0)
def spi_writebyte(self, data):
self.SPI.writebytes(data)
def module_init(self):
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.BUSY_PIN, self.GPIO.IN)
self.SPI.max_speed_hz = 4000000
self.SPI.mode = 0b00
return 0
def module_exit(self):
logging.debug("spi end")
self.SPI.close()
logging.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:
# Pin definition
RST_PIN = 17
DC_PIN = 25
CS_PIN = 8
BUSY_PIN = 24
def __init__(self):
import ctypes
find_dirs = [
os.path.dirname(os.path.realpath(__file__)),
'/usr/local/lib',
'/usr/lib',
]
self.SPI = None
for find_dir in find_dirs:
so_filename = os.path.join(find_dir, 'sysfs_software_spi.so')
if os.path.exists(so_filename):
self.SPI = ctypes.cdll.LoadLibrary(so_filename)
break
if self.SPI is None:
raise RuntimeError('Cannot find sysfs_software_spi.so')
import Jetson.GPIO
self.GPIO = Jetson.GPIO
def digital_write(self, pin, value):
self.GPIO.output(pin, value)
def digital_read(self, pin):
return self.GPIO.input(self.BUSY_PIN)
def delay_ms(self, delaytime):
time.sleep(delaytime / 1000.0)
def spi_writebyte(self, data):
self.SPI.SYSFS_software_spi_transfer(data[0])
def module_init(self):
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.BUSY_PIN, self.GPIO.IN)
self.SPI.SYSFS_software_spi_begin()
return 0
def module_exit(self):
logging.debug("spi end")
self.SPI.SYSFS_software_spi_end()
logging.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()
if os.path.exists('/sys/bus/platform/drivers/gpiomem-bcm2835'):
implementation = RaspberryPi()
else:
implementation = JetsonNano()
for func in [x for x in dir(implementation) if not x.startswith('_')]:
setattr(sys.modules[__name__], func, getattr(implementation, func))
### END OF FILE ###

View File

@ -1,338 +0,0 @@
# //*****************************************************************************
# * | File : epd2in13.py
# * | Author : Waveshare team
# * | Function : Electronic paper driver
# * | Info :
# *----------------
# * | This version: V3.0
# * | Date : 2018-11-01
# * | Info : python2 demo
# * 1.Remove:
# digital_write(self, pin, value)
# digital_read(self, pin)
# delay_ms(self, delaytime)
# set_lut(self, lut)
# self.lut = self.lut_full_update
# * 2.Change:
# display_frame -> TurnOnDisplay
# set_memory_area -> SetWindow
# set_memory_pointer -> SetCursor
# * 3.How to use
# epd = epd2in13.EPD()
# epd.init(epd.lut_full_update)
# image = Image.new('1', (epd2in13.EPD_WIDTH, epd2in13.EPD_HEIGHT), 255)
# ...
# drawing ......
# ...
# epd.display(getbuffer(image))
# ******************************************************************************//
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and//or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS 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 time
import spidev
import RPi.GPIO as GPIO
from PIL import Image
# Pin definition
RST_PIN = 17
DC_PIN = 25
CS_PIN = 8
BUSY_PIN = 24
# SPI device, bus = 0, device = 0
SPI = spidev.SpiDev(0, 0)
def digital_write(pin, value):
GPIO.output(pin, value)
def digital_read(pin):
return GPIO.input(BUSY_PIN)
def delay_ms(delaytime):
time.sleep(delaytime / 1000.0)
def spi_writebyte(data):
SPI.writebytes(data)
def module_init():
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(RST_PIN, GPIO.OUT)
GPIO.setup(DC_PIN, GPIO.OUT)
GPIO.setup(CS_PIN, GPIO.OUT)
GPIO.setup(BUSY_PIN, GPIO.IN)
SPI.max_speed_hz = 2000000
SPI.mode = 0b00
return 0;
# Display resolution
EPD_WIDTH = 122
EPD_HEIGHT = 250
class EPD:
def __init__(self):
self.reset_pin = RST_PIN
self.dc_pin = DC_PIN
self.busy_pin = BUSY_PIN
self.width = EPD_WIDTH
self.height = EPD_HEIGHT
FULL_UPDATE = 0
PART_UPDATE = 1
lut_full_update = [
0x80, 0x60, 0x40, 0x00, 0x00, 0x00, 0x00, # LUT0: BB: VS 0 ~7
0x10, 0x60, 0x20, 0x00, 0x00, 0x00, 0x00, # LUT1: BW: VS 0 ~7
0x80, 0x60, 0x40, 0x00, 0x00, 0x00, 0x00, # LUT2: WB: VS 0 ~7
0x10, 0x60, 0x20, 0x00, 0x00, 0x00, 0x00, # LUT3: WW: VS 0 ~7
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # LUT4: VCOM: VS 0 ~7
0x03, 0x03, 0x00, 0x00, 0x02, # TP0 A~D RP0
0x09, 0x09, 0x00, 0x00, 0x02, # TP1 A~D RP1
0x03, 0x03, 0x00, 0x00, 0x02, # TP2 A~D RP2
0x00, 0x00, 0x00, 0x00, 0x00, # TP3 A~D RP3
0x00, 0x00, 0x00, 0x00, 0x00, # TP4 A~D RP4
0x00, 0x00, 0x00, 0x00, 0x00, # TP5 A~D RP5
0x00, 0x00, 0x00, 0x00, 0x00, # TP6 A~D RP6
0x15, 0x41, 0xA8, 0x32, 0x30, 0x0A,
]
lut_partial_update = [ # 20 bytes
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # LUT0: BB: VS 0 ~7
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # LUT1: BW: VS 0 ~7
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # LUT2: WB: VS 0 ~7
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # LUT3: WW: VS 0 ~7
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # LUT4: VCOM: VS 0 ~7
0x0A, 0x00, 0x00, 0x00, 0x00, # TP0 A~D RP0
0x00, 0x00, 0x00, 0x00, 0x00, # TP1 A~D RP1
0x00, 0x00, 0x00, 0x00, 0x00, # TP2 A~D RP2
0x00, 0x00, 0x00, 0x00, 0x00, # TP3 A~D RP3
0x00, 0x00, 0x00, 0x00, 0x00, # TP4 A~D RP4
0x00, 0x00, 0x00, 0x00, 0x00, # TP5 A~D RP5
0x00, 0x00, 0x00, 0x00, 0x00, # TP6 A~D RP6
0x15, 0x41, 0xA8, 0x32, 0x30, 0x0A,
]
# Hardware reset
def reset(self):
digital_write(self.reset_pin, GPIO.HIGH)
delay_ms(200)
digital_write(self.reset_pin, GPIO.LOW) # module reset
delay_ms(200)
digital_write(self.reset_pin, GPIO.HIGH)
delay_ms(200)
def send_command(self, command):
digital_write(self.dc_pin, GPIO.LOW)
spi_writebyte([command])
def send_data(self, data):
digital_write(self.dc_pin, GPIO.HIGH)
spi_writebyte([data])
def wait_until_idle(self):
while (digital_read(self.busy_pin) == 1): # 0: idle, 1: busy
delay_ms(100)
def TurnOnDisplay(self):
self.send_command(0x22)
self.send_data(0xC7)
self.send_command(0x20)
self.wait_until_idle()
def init(self, update):
if (module_init() != 0):
return -1
# EPD hardware init start
self.reset()
if (update == self.FULL_UPDATE):
self.wait_until_idle()
self.send_command(0x12) # soft reset
self.wait_until_idle()
self.send_command(0x74) # set analog block control
self.send_data(0x54)
self.send_command(0x7E) # set digital block control
self.send_data(0x3B)
self.send_command(0x01) # Driver output control
self.send_data(0xF9)
self.send_data(0x00)
self.send_data(0x00)
self.send_command(0x11) # data entry mode
self.send_data(0x01)
self.send_command(0x44) # set Ram-X address start//end position
self.send_data(0x00)
self.send_data(0x0F) # 0x0C-->(15+1)*8=128
self.send_command(0x45) # set Ram-Y address start//end position
self.send_data(0xF9) # 0xF9-->(249+1)=250
self.send_data(0x00)
self.send_data(0x00)
self.send_data(0x00)
self.send_command(0x3C) # BorderWavefrom
self.send_data(0x03)
self.send_command(0x2C) # VCOM Voltage
self.send_data(0x55) #
self.send_command(0x03)
self.send_data(self.lut_full_update[70])
self.send_command(0x04) #
self.send_data(self.lut_full_update[71])
self.send_data(self.lut_full_update[72])
self.send_data(self.lut_full_update[73])
self.send_command(0x3A) # Dummy Line
self.send_data(self.lut_full_update[74])
self.send_command(0x3B) # Gate time
self.send_data(self.lut_full_update[75])
self.send_command(0x32)
for count in range(70):
self.send_data(self.lut_full_update[count])
self.send_command(0x4E) # set RAM x address count to 0
self.send_data(0x00)
self.send_command(0x4F) # set RAM y address count to 0X127
self.send_data(0xF9)
self.send_data(0x00)
self.wait_until_idle()
else:
self.send_command(0x2C) # VCOM Voltage
self.send_data(0x26)
self.wait_until_idle()
self.send_command(0x32)
for count in range(70):
self.send_data(self.lut_partial_update[count])
self.send_command(0x37)
self.send_data(0x00)
self.send_data(0x00)
self.send_data(0x00)
self.send_data(0x00)
self.send_data(0x40)
self.send_data(0x00)
self.send_data(0x00)
self.send_command(0x22)
self.send_data(0xC0)
self.send_command(0x20)
self.wait_until_idle()
self.send_command(0x3C) # BorderWavefrom
self.send_data(0x01)
return 0
def getbuffer(self, image):
if self.width % 8 == 0:
linewidth = self.width // 8
else:
linewidth = self.width // 8 + 1
buf = [0xFF] * (linewidth * self.height)
image_monocolor = image.convert('1')
imwidth, imheight = image_monocolor.size
pixels = image_monocolor.load()
if (imwidth == self.width and imheight == self.height):
# print("Vertical")
for y in range(imheight):
for x in range(imwidth):
if pixels[x, y] == 0:
x = imwidth - x
buf[x // 8 + y * linewidth] &= ~(0x80 >> (x % 8))
elif (imwidth == self.height and imheight == self.width):
# print("Horizontal")
for y in range(imheight):
for x in range(imwidth):
newx = y
newy = self.height - x - 1
if pixels[x, y] == 0:
newy = imwidth - newy - 1
buf[newx // 8 + newy * linewidth] &= ~(0x80 >> (y % 8))
return buf
def display(self, image):
if self.width % 8 == 0:
linewidth = self.width // 8
else:
linewidth = self.width // 8 + 1
self.send_command(0x24)
for j in range(0, self.height):
for i in range(0, linewidth):
self.send_data(image[i + j * linewidth])
self.TurnOnDisplay()
def displayPartial(self, image):
if self.width % 8 == 0:
linewidth = self.width // 8
else:
linewidth = self.width // 8 + 1
self.send_command(0x24)
for j in range(0, self.height):
for i in range(0, linewidth):
self.send_data(image[i + j * linewidth])
self.send_command(0x26)
for j in range(0, self.height):
for i in range(0, linewidth):
self.send_data(~image[i + j * linewidth])
self.TurnOnDisplay()
def Clear(self, color):
if self.width % 8 == 0:
linewidth = self.width // 8
else:
linewidth = self.width // 8 + 1
# print(linewidth)
self.send_command(0x24)
for j in range(0, self.height):
for i in range(0, linewidth):
self.send_data(color)
self.TurnOnDisplay()
def sleep(self):
self.send_command(0x22) # POWER OFF
self.send_data(0xC3)
self.send_command(0x20)
self.send_command(0x10) # enter deep sleep
self.send_data(0x01)
delay_ms(100)
### END OF FILE ###

View File

@ -28,7 +28,7 @@
#
import logging
from . import epdconfig
from .. import epdconfig
# Display resolution
EPD_WIDTH = 128

View File

@ -33,8 +33,6 @@
from distutils.command.build_scripts import build_scripts
import logging
from .. import epdconfig
from PIL import Image
import RPi.GPIO as GPIO
# Display resolution
EPD_WIDTH = 128

View File

@ -1,154 +0,0 @@
# /*****************************************************************************
# * | File : epdconfig.py
# * | Author : Waveshare team
# * | Function : Hardware underlying interface
# * | Info :
# *----------------
# * | This version: V1.0
# * | Date : 2019-06-21
# * | Info :
# ******************************************************************************
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documnetation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# 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 os
import logging
import sys
import time
class RaspberryPi:
# Pin definition
RST_PIN = 17
DC_PIN = 25
CS_PIN = 8
BUSY_PIN = 24
def __init__(self):
import spidev
import RPi.GPIO
self.GPIO = RPi.GPIO
# SPI device, bus = 0, device = 0
self.SPI = spidev.SpiDev(0, 0)
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 module_init(self):
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.BUSY_PIN, self.GPIO.IN)
self.SPI.max_speed_hz = 4000000
self.SPI.mode = 0b00
return 0
def module_exit(self):
logging.debug("spi end")
self.SPI.close()
logging.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:
# Pin definition
RST_PIN = 17
DC_PIN = 25
CS_PIN = 8
BUSY_PIN = 24
def __init__(self):
import ctypes
find_dirs = [
os.path.dirname(os.path.realpath(__file__)),
'/usr/local/lib',
'/usr/lib',
]
self.SPI = None
for find_dir in find_dirs:
so_filename = os.path.join(find_dir, 'sysfs_software_spi.so')
if os.path.exists(so_filename):
self.SPI = ctypes.cdll.LoadLibrary(so_filename)
break
if self.SPI is None:
raise RuntimeError('Cannot find sysfs_software_spi.so')
import Jetson.GPIO
self.GPIO = Jetson.GPIO
def digital_write(self, pin, value):
self.GPIO.output(pin, value)
def digital_read(self, pin):
return self.GPIO.input(self.BUSY_PIN)
def delay_ms(self, delaytime):
time.sleep(delaytime / 1000.0)
def spi_writebyte(self, data):
self.SPI.SYSFS_software_spi_transfer(data[0])
def module_init(self):
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.BUSY_PIN, self.GPIO.IN)
self.SPI.SYSFS_software_spi_begin()
return 0
def module_exit(self):
logging.debug("spi end")
self.SPI.SYSFS_software_spi_end()
logging.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()
if os.path.exists('/sys/bus/platform/drivers/gpiomem-bcm2835'):
implementation = RaspberryPi()
else:
implementation = JetsonNano()
for func in [x for x in dir(implementation) if not x.startswith('_')]:
setattr(sys.modules[__name__], func, getattr(implementation, func))
### END OF FILE ###

View File

@ -1,350 +0,0 @@
# *****************************************************************************
# * | File : epd2in13_V4.py
# * | Author : Waveshare team
# * | Function : Electronic paper driver
# * | Info :
# *----------------
# * | This version: V1.0
# * | Date : 2023-06-25
# # | Info : python demo
# -----------------------------------------------------------------------------
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documnetation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# 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 logging
from . import epdconfig
# Display resolution
EPD_WIDTH = 122
EPD_HEIGHT = 250
logger = logging.getLogger(__name__)
class EPD:
def __init__(self):
self.reset_pin = epdconfig.RST_PIN
self.dc_pin = epdconfig.DC_PIN
self.busy_pin = epdconfig.BUSY_PIN
self.cs_pin = epdconfig.CS_PIN
self.width = EPD_WIDTH
self.height = EPD_HEIGHT
'''
function :Hardware reset
parameter:
'''
def reset(self):
epdconfig.digital_write(self.reset_pin, 1)
epdconfig.delay_ms(20)
epdconfig.digital_write(self.reset_pin, 0)
epdconfig.delay_ms(2)
epdconfig.digital_write(self.reset_pin, 1)
epdconfig.delay_ms(20)
'''
function :send command
parameter:
command : Command register
'''
def send_command(self, command):
epdconfig.digital_write(self.dc_pin, 0)
epdconfig.digital_write(self.cs_pin, 0)
epdconfig.spi_writebyte([command])
epdconfig.digital_write(self.cs_pin, 1)
'''
function :send data
parameter:
data : Write data
'''
def send_data(self, data):
epdconfig.digital_write(self.dc_pin, 1)
epdconfig.digital_write(self.cs_pin, 0)
epdconfig.spi_writebyte([data])
epdconfig.digital_write(self.cs_pin, 1)
# send a lot of data
def send_data2(self, data):
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)
'''
function :Wait until the busy_pin goes LOW
parameter:
'''
def ReadBusy(self):
logger.debug("e-Paper busy")
while(epdconfig.digital_read(self.busy_pin) == 1): # 0: idle, 1: busy
epdconfig.delay_ms(10)
logger.debug("e-Paper busy release")
'''
function : Turn On Display
parameter:
'''
def TurnOnDisplay(self):
self.send_command(0x22) # Display Update Control
self.send_data(0xf7)
self.send_command(0x20) # Activate Display Update Sequence
self.ReadBusy()
'''
function : Turn On Display Fast
parameter:
'''
def TurnOnDisplay_Fast(self):
self.send_command(0x22) # Display Update Control
self.send_data(0xC7) # fast:0x0c, quality:0x0f, 0xcf
self.send_command(0x20) # Activate Display Update Sequence
self.ReadBusy()
'''
function : Turn On Display Part
parameter:
'''
def TurnOnDisplayPart(self):
self.send_command(0x22) # Display Update Control
self.send_data(0xff) # fast:0x0c, quality:0x0f, 0xcf
self.send_command(0x20) # Activate Display Update Sequence
self.ReadBusy()
'''
function : Setting the display window
parameter:
xstart : X-axis starting position
ystart : Y-axis starting position
xend : End position of X-axis
yend : End position of Y-axis
'''
def SetWindow(self, x_start, y_start, x_end, y_end):
self.send_command(0x44) # SET_RAM_X_ADDRESS_START_END_POSITION
# x point must be the multiple of 8 or the last 3 bits will be ignored
self.send_data((x_start>>3) & 0xFF)
self.send_data((x_end>>3) & 0xFF)
self.send_command(0x45) # SET_RAM_Y_ADDRESS_START_END_POSITION
self.send_data(y_start & 0xFF)
self.send_data((y_start >> 8) & 0xFF)
self.send_data(y_end & 0xFF)
self.send_data((y_end >> 8) & 0xFF)
'''
function : Set Cursor
parameter:
x : X-axis starting position
y : Y-axis starting position
'''
def SetCursor(self, x, y):
self.send_command(0x4E) # SET_RAM_X_ADDRESS_COUNTER
# x point must be the multiple of 8 or the last 3 bits will be ignored
self.send_data(x & 0xFF)
self.send_command(0x4F) # SET_RAM_Y_ADDRESS_COUNTER
self.send_data(y & 0xFF)
self.send_data((y >> 8) & 0xFF)
'''
function : Initialize the e-Paper register
parameter:
'''
def init(self):
if (epdconfig.module_init() != 0):
return -1
# EPD hardware init start
self.reset()
self.ReadBusy()
self.send_command(0x12) #SWRESET
self.ReadBusy()
self.send_command(0x01) #Driver output control
self.send_data(0xf9)
self.send_data(0x00)
self.send_data(0x00)
self.send_command(0x11) #data entry mode
self.send_data(0x03)
self.SetWindow(0, 0, self.width-1, self.height-1)
self.SetCursor(0, 0)
self.send_command(0x3c)
self.send_data(0x05)
self.send_command(0x21) # Display update control
self.send_data(0x00)
self.send_data(0x80)
self.send_command(0x18)
self.send_data(0x80)
self.ReadBusy()
return 0
'''
function : Initialize the e-Paper fast register
parameter:
'''
def init_fast(self):
if (epdconfig.module_init() != 0):
return -1
# EPD hardware init start
self.reset()
self.send_command(0x12) #SWRESET
self.ReadBusy()
self.send_command(0x18) # Read built-in temperature sensor
self.send_command(0x80)
self.send_command(0x11) # data entry mode
self.send_data(0x03)
self.SetWindow(0, 0, self.width-1, self.height-1)
self.SetCursor(0, 0)
self.send_command(0x22) # Load temperature value
self.send_data(0xB1)
self.send_command(0x20)
self.ReadBusy()
self.send_command(0x1A) # Write to temperature register
self.send_data(0x64)
self.send_data(0x00)
self.send_command(0x22) # Load temperature value
self.send_data(0x91)
self.send_command(0x20)
self.ReadBusy()
return 0
'''
function : Display images
parameter:
image : Image data
'''
def getbuffer(self, image):
img = image
imwidth, imheight = img.size
if(imwidth == self.width and imheight == self.height):
img = img.convert('1')
elif(imwidth == self.height and imheight == self.width):
# image has correct dimensions, but needs to be rotated
img = img.rotate(90, expand=True).convert('1')
else:
logger.warning("Wrong image dimensions: must be " + str(self.width) + "x" + str(self.height))
# return a blank buffer
return [0x00] * (int(self.width/8) * self.height)
buf = bytearray(img.tobytes('raw'))
return buf
'''
function : Sends the image buffer in RAM to e-Paper and displays
parameter:
image : Image data
'''
def display(self, image):
self.send_command(0x24)
self.send_data2(image)
self.TurnOnDisplay()
'''
function : Sends the image buffer in RAM to e-Paper and fast displays
parameter:
image : Image data
'''
def display_fast(self, image):
self.send_command(0x24)
self.send_data2(image)
self.TurnOnDisplay_Fast()
'''
function : Sends the image buffer in RAM to e-Paper and partial refresh
parameter:
image : Image data
'''
def displayPartial(self, image):
epdconfig.digital_write(self.reset_pin, 0)
epdconfig.delay_ms(1)
epdconfig.digital_write(self.reset_pin, 1)
self.send_command(0x3C) # BorderWavefrom
self.send_data(0x80)
self.send_command(0x01) # Driver output control
self.send_data(0xF9)
self.send_data(0x00)
self.send_data(0x00)
self.send_command(0x11) # data entry mode
self.send_data(0x03)
self.SetWindow(0, 0, self.width - 1, self.height - 1)
self.SetCursor(0, 0)
self.send_command(0x24) # WRITE_RAM
self.send_data2(image)
self.TurnOnDisplayPart()
'''
function : Refresh a base image
parameter:
image : Image data
'''
def displayPartBaseImage(self, image):
self.send_command(0x24)
self.send_data2(image)
self.send_command(0x26)
self.send_data2(image)
self.TurnOnDisplay()
'''
function : Clear screen
parameter:
'''
def Clear(self, color=0xFF):
if self.width%8 == 0:
linewidth = int(self.width/8)
else:
linewidth = int(self.width/8) + 1
# logger.debug(linewidth)
self.send_command(0x24)
self.send_data2([color] * int(self.height * linewidth))
self.TurnOnDisplay()
'''
function : Enter sleep mode
parameter:
'''
def sleep(self):
self.send_command(0x10) #enter deep sleep
self.send_data(0x01)
epdconfig.delay_ms(2000)
epdconfig.module_exit()
### END OF FILE ###

View File

@ -1,243 +0,0 @@
# /*****************************************************************************
# * | File : epdconfig.py
# * | Author : Waveshare team
# * | Function : Hardware underlying interface
# * | Info :
# *----------------
# * | This version: V1.2
# * | Date : 2022-10-29
# * | Info :
# ******************************************************************************
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documnetation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# 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 os
import logging
import sys
import time
logger = logging.getLogger(__name__)
class RaspberryPi:
# Pin definition
RST_PIN = 17
DC_PIN = 25
CS_PIN = 8
BUSY_PIN = 24
PWR_PIN = 18
def __init__(self):
import spidev
import RPi.GPIO
self.GPIO = RPi.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):
self.SPI.writebytes2(data)
def module_init(self):
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(0, 0)
self.SPI.max_speed_hz = 4000000
self.SPI.mode = 0b00
return 0
def module_exit(self):
logger.debug("spi end")
self.SPI.close()
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.output(self.PWR_PIN, 0)
self.GPIO.cleanup([self.RST_PIN, self.DC_PIN, self.CS_PIN, self.BUSY_PIN, self.PWR_PIN])
class JetsonNano:
# Pin definition
RST_PIN = 17
DC_PIN = 25
CS_PIN = 8
BUSY_PIN = 24
PWR_PIN = 18
def __init__(self):
import ctypes
find_dirs = [
os.path.dirname(os.path.realpath(__file__)),
'/usr/local/lib',
'/usr/lib',
]
self.SPI = None
for find_dir in find_dirs:
so_filename = os.path.join(find_dir, 'sysfs_software_spi.so')
if os.path.exists(so_filename):
self.SPI = ctypes.cdll.LoadLibrary(so_filename)
break
if self.SPI is None:
raise RuntimeError('Cannot find sysfs_software_spi.so')
import Jetson.GPIO
self.GPIO = Jetson.GPIO
def digital_write(self, pin, value):
self.GPIO.output(pin, value)
def digital_read(self, pin):
return self.GPIO.input(self.BUSY_PIN)
def delay_ms(self, delaytime):
time.sleep(delaytime / 1000.0)
def spi_writebyte(self, data):
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):
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)
self.SPI.SYSFS_software_spi_begin()
return 0
def module_exit(self):
logger.debug("spi end")
self.SPI.SYSFS_software_spi_end()
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.output(self.PWR_PIN, 0)
self.GPIO.cleanup([self.RST_PIN, self.DC_PIN, self.CS_PIN, self.BUSY_PIN, self.PWR_PIN])
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 os.path.exists('/sys/bus/platform/drivers/gpiomem-bcm2835'):
implementation = RaspberryPi()
elif os.path.exists('/sys/bus/platform/drivers/gpio-x3'):
implementation = SunriseX3()
else:
implementation = JetsonNano()
for func in [x for x in dir(implementation) if not x.startswith('_')]:
setattr(sys.modules[__name__], func, getattr(implementation, func))
### END OF FILE ###

View File

@ -29,7 +29,7 @@
import logging
from . import epdconfig
from .. import epdconfig
# Display resolution
EPD_WIDTH = 800

View File

@ -29,7 +29,7 @@
import logging
from . import epdconfig
from .. import epdconfig
# Display resolution
EPD_WIDTH = 800

View File

@ -42,6 +42,5 @@ class Waveshare3in52(DisplayImpl):
self._display.display(buf)
self._display.refresh()
def clear(self):
self._display.Clear()

View File

@ -47,6 +47,6 @@ class Server:
formatServerIpAddress = '[::]' if self._address == '::' else self._address
logging.info("web ui available at http://%s:%d/" % (formatServerIpAddress, self._port))
app.run(host=self._address, port=self._port, debug=False)
app.run(host=self._address, port=self._port)
else:
logging.info("could not get ip of usb0, video server not starting")

View File

@ -242,6 +242,9 @@ def load_config(args):
if config['ui']['display']['type'] in ('inky', 'inkyphat'):
config['ui']['display']['type'] = 'inky'
elif config['ui']['display']['type'] in ('dummy', 'dummydisplay'):
config['ui']['display']['type'] = 'dummydisplay'
elif config['ui']['display']['type'] in ('papirus', 'papi'):
config['ui']['display']['type'] = 'papirus'
@ -283,6 +286,13 @@ def load_config(args):
# E-INK DISPLAYS ------------------------------------------------------------------------
# Adafruit
elif config['ui']['display']['type'] in ('adafruit2in13v3', 'af213v3', 'adafruit_213v3', 'adafruit213inv3'):
config['ui']['display']['type'] = 'adafruit2in13_v3'
# Waveshare
elif config['ui']['display']['type'] in ('waveshare1in02', 'ws1in02', 'ws102', 'waveshare_102', 'waveshare_1in02'):
config['ui']['display']['type'] = 'waveshare1in02'
@ -304,16 +314,16 @@ def load_config(args):
elif config['ui']['display']['type'] in ('waveshare1in64g', 'ws1in64g', 'ws164g', 'waveshare_164g', 'waveshare_1in64g'):
config['ui']['display']['type'] = 'waveshare1in64g'
elif config['ui']['display']['type'] in ('ws_1', 'ws1', 'waveshare_1', 'waveshare1'):
elif config['ui']['display']['type'] in ('ws_1', 'ws1', 'waveshare_1', 'waveshare1', 'waveshare2in13'):
config['ui']['display']['type'] = 'waveshare_1'
elif config['ui']['display']['type'] in ('ws_2', 'ws2', 'waveshare_2', 'waveshare2'):
elif config['ui']['display']['type'] in ('ws_2', 'ws2', 'waveshare_2', 'waveshare2', 'waveshare2in13v2'):
config['ui']['display']['type'] = 'waveshare_2'
elif config['ui']['display']['type'] in ('ws_3', 'ws3', 'waveshare_3', 'waveshare3'):
elif config['ui']['display']['type'] in ('ws_3', 'ws3', 'waveshare_3', 'waveshare3', 'waveshare2in13v3'):
config['ui']['display']['type'] = 'waveshare_3'
elif config['ui']['display']['type'] in ('ws_4', 'ws4', 'waveshare_4', 'waveshare4'):
elif config['ui']['display']['type'] in ('ws_4', 'ws4', 'waveshare_4', 'waveshare4', 'waveshare2in13v4'):
config['ui']['display']['type'] = 'waveshare_4'
elif config['ui']['display']['type'] in ('waveshare2in13b_v3', 'waveshare2in13b_v3', 'ws213bv3', 'waveshare_213bv3', 'waveshare213inb_v3'):
@ -453,8 +463,8 @@ def load_config(args):
config['ui']['display']['type'] = 'weact2in9'
else:
print("unsupported display type %s" % config['ui']['display']['type'])
sys.exit(1)
logging.debug("using dummy display, as your display type is unsupported")
config['ui']['display']['type'] = 'dummydisplay'
return config

View File

@ -9,11 +9,13 @@ dependencies = [
"Pillow",
"PyYAML",
"RPi.GPIO",
"dbus-python",
"file-read-backwards",
"flask",
"flask-cors",
"flask-wtf",
"gast",
"gpiozero",
"gym",
"inky",
"pycryptodome",
@ -30,7 +32,7 @@ dependencies = [
"torch",
"torchvision",
"tweepy",
"websockets"
"websockets",
]
requires-python = ">=3.9"
authors = [

View File

@ -16,7 +16,10 @@ log = logging.getLogger(__name__)
def install_file(source_filename, dest_filename):
# do not overwrite network configuration if it exists already
# https://github.com/evilsocket/pwnagotchi/issues/483
if dest_filename.startswith('/etc/network/interfaces.d/') and dest_filename.startswith('/root/') and os.path.exists(dest_filename):
if dest_filename.startswith('/etc/network/interfaces.d/') and os.path.exists(dest_filename):
log.info(f"{dest_filename} exists, skipping ...")
return
elif dest_filename.startswith('/root/') and os.path.exists(dest_filename):
log.info(f"{dest_filename} exists, skipping ...")
return
@ -31,6 +34,11 @@ def install_file(source_filename, dest_filename):
def install_system_files():
f = open("apt_packages.txt", "r")
for x in f:
os.system(f"apt-get install -y {x}")
f.close()
setup_path = os.path.dirname(__file__)
if platform.machine().startswith('arm'):
data_path = os.path.join(setup_path, "builder/data/32bit")