Initial backup of LTP-305G matrix clock setup on matrixpi

Captures everything needed to redeploy the two-display clock (hour on I2C
0x61, minute on I2C 0x63) on a fresh Pi:

- Both systemd units (matrix0x61.service, matrix0x63.service)
- Deployed Pimoroni script tree, including the local %I (12-hour) clock
  customization
- Vendored upstream sources (ltp305-python, breakout-garden) so restore is
  fully offline-capable
- Boot config snippet enabling I2C
- install.sh that wires it all back up idempotently
- Inventory doc cross-referencing every live-system path

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
dissimulo
2026-05-06 01:32:39 -07:00
commit 030172f523
99 changed files with 4445 additions and 0 deletions

View File

@@ -0,0 +1,37 @@
name: Python Tests
on:
pull_request:
push:
branches:
- master
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python: [2.7, 3.5, 3.7, 3.9]
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python }}
- name: Install Dependencies
run: |
python -m pip install --upgrade setuptools tox
- name: Run Tests
working-directory: library
run: |
tox -e py
- name: Coverage
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
working-directory: library
run: |
python -m pip install coveralls
coveralls --service=github
if: ${{ matrix.python == '3.9' }}

20
vendor/ltp305-python/.gitignore vendored Normal file
View File

@@ -0,0 +1,20 @@
build/
_build/
*.o
*.so
*.a
*.py[cod]
*.egg-info
dist/
__pycache__
.DS_Store
*.deb
*.dsc
*.build
*.changes
*.orig.*
packaging/*tar.xz
library/debian/
.coverage
.pytest_cache
.tox

5
vendor/ltp305-python/.stickler.yml vendored Normal file
View File

@@ -0,0 +1,5 @@
---
linters:
flake8:
python: 3
max-line-length: 160

21
vendor/ltp305-python/LICENSE vendored Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 Pimoroni Ltd.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

70
vendor/ltp305-python/Makefile vendored Normal file
View File

@@ -0,0 +1,70 @@
LIBRARY_VERSION=$(shell grep version library/setup.cfg | awk -F" = " '{print $$2}')
LIBRARY_NAME=$(shell grep name library/setup.cfg | awk -F" = " '{print $$2}')
.PHONY: usage install uninstall
usage:
@echo "Library: ${LIBRARY_NAME}"
@echo "Version: ${LIBRARY_VERSION}\n"
@echo "Usage: make <target>, where target is one of:\n"
@echo "install: install the library locally from source"
@echo "uninstall: uninstall the local library"
@echo "check: peform basic integrity checks on the codebase"
@echo "python-readme: generate library/README.md from README.md + library/CHANGELOG.txt"
@echo "python-wheels: build python .whl files for distribution"
@echo "python-sdist: build python source distribution"
@echo "python-clean: clean python build and dist directories"
@echo "python-dist: build all python distribution files"
@echo "python-testdeploy: build all and deploy to test PyPi"
@echo "tag: tag the repository with the current version"
install:
./install.sh
uninstall:
./uninstall.sh
check:
@echo "Checking for trailing whitespace"
@! grep -IUrn --color "[[:blank:]]$$" --exclude-dir=sphinx --exclude-dir=.tox --exclude-dir=.git --exclude=PKG-INFO
@echo "Checking for DOS line-endings"
@! grep -IUrn --color "
" --exclude-dir=sphinx --exclude-dir=.tox --exclude-dir=.git --exclude=Makefile
@echo "Checking library/CHANGELOG.txt"
@cat library/CHANGELOG.txt | grep ^${LIBRARY_VERSION}
@echo "Checking library/${LIBRARY_NAME}/__init__.py"
@cat library/${LIBRARY_NAME}/__init__.py | grep "^__version__ = '${LIBRARY_VERSION}'"
tag:
git tag -a "v${LIBRARY_VERSION}" -m "Version ${LIBRARY_VERSION}"
python-readme: library/README.md
python-license: library/LICENSE.txt
library/README.md: README.md library/CHANGELOG.txt
cp README.md library/README.md
printf "\n# Changelog\n" >> library/README.md
cat library/CHANGELOG.txt >> library/README.md
library/LICENSE.txt: LICENSE
cp LICENSE library/LICENSE.txt
python-wheels: python-readme python-license
cd library; python3 setup.py bdist_wheel
cd library; python setup.py bdist_wheel
python-sdist: python-readme python-license
cd library; python setup.py sdist
python-clean:
-rm -r library/dist
-rm -r library/build
-rm -r library/*.egg-info
python-dist: python-clean python-wheels python-sdist
ls library/dist
python-testdeploy: python-dist
twine upload --repository-url https://test.pypi.org/legacy/ library/dist/*
python-deploy: check python-dist

27
vendor/ltp305-python/README.md vendored Normal file
View File

@@ -0,0 +1,27 @@
# LTP305 - Breakout Garden dual 5x7 LED matrix driver
[![Build Status](https://travis-ci.com/pimoroni/ltp305-python.svg?branch=master)](https://travis-ci.com/pimoroni/ltp305-python)
[![Coverage Status](https://coveralls.io/repos/github/pimoroni/ltp305-python/badge.svg?branch=master)](https://coveralls.io/github/pimoroni/ltp305-python?branch=master)
[![PyPi Package](https://img.shields.io/pypi/v/ltp305.svg)](https://pypi.python.org/pypi/ltp305)
[![Python Versions](https://img.shields.io/pypi/pyversions/ltp305.svg)](https://pypi.python.org/pypi/ltp305)
# Pre-requisites
You must enable i2c:
* i2c: `sudo raspi-config nonint do_i2c 0`
You can optionally run `sudo raspi-config` or the graphical Raspberry Pi Configuration UI to enable interfaces.
# Installing
Stable library from PyPi:
* Just run `sudo pip3 install ltp305`
Latest/development library from GitHub:
* `git clone https://github.com/pimoroni/ltp305-python`
* `cd ltp305-python`
* `sudo ./install.sh`

128
vendor/ltp305-python/REFERENCE.md vendored Normal file
View File

@@ -0,0 +1,128 @@
# Pimoroni LTP305 LED Matrices Breakout <!-- omit in toc -->
The LTP305 breakout includes two LTP305 displays and an i2c dual matrix driver to drive them.
- [Getting Started](#getting-started)
- [Pre-requisites](#pre-requisites)
- [Python 3 & pip](#python-3--pip)
- [Enabling i2c](#enabling-i2c)
- [Installing the library](#installing-the-library)
- [Reference](#reference)
- [set_pixel](#set_pixel)
- [set_decimal](#set_decimal)
- [set_character](#set_character)
- [set_image](#set_image)
- [get_shape](#get_shape)
- [clear](#clear)
- [show](#show)
## Getting Started
You'll need to install the LTP305 software library and enable i2c on your Raspberry Pi.
### Pre-requisites
#### Python 3 & pip
You should use Python 3, which may need installing on your Pi:
```
sudo apt update
sudo apt install python3 python3-pip
```
#### Enabling i2c
You can use `sudo raspi-config` on the command line, the GUI Raspberry Pi Configuration app from the Pi desktop menu, or use the following command to enable i2c:
```
sudo raspi-config nonint do_i2c 0
```
### Installing the library
```python
python3 -m pip install ltp305
```
## Reference
In all cases you'll want to create an instance of the LTP305 class with the appropriate i2c address for your device.
The following addresses are available:
* `0x61` - Default address
* `0x62` - Solder bridge applied to Addr+1
* `0x63` - Cut Addr+2
```python
from ltp305 import LTP305
display = LTP305(address=0x61)
```
### set_pixel
Set a single pixel. Treats both matrices as a single display that's 10 pixels wide and 7 pixels high.
```python
display.set_pixel(0, 0, 1)
display.show()
```
### set_decimal
Set the decimal dot on one or both matrix displays:
```python
display.set_decimal(left=True, right=False) # Just the left
display.set_decimal(left=False, right=True) # Just the right
display.set_decimal(left=True, right=True) # Both
display.show()
```
### set_character
The library includes a font with a range of ASCII and Unicode characters, each matrix can display a single character.
```python
display.set_character(0, "a")
display.set_character(5, "b")
display.show()
```
### set_image
Set a 1-bit PIL image to the display.
```python
from PIL import Image, ImageDraw
image = Image.new("1", display.get_shape())
draw = ImageDraw.draw(image)
draw.rectangle((0, 0, 4, 6), 1)
display.set_image(image)
display.show()
```
### get_shape
Return the width and height of the display:
```python
width, height = display.get_shape()
```
### clear
Clear the display. Sets all pixels in the buffer to 0 (off). You must call `show()` to update the display.
```python
display.clear()
```
### show
Once you've finished setting pixels or drawing characters into the buffer, you must call `show` to update the matrices with the buffer:
```python
display.show()
```

View File

@@ -0,0 +1,43 @@
import time
import math
import random
from ltp305 import LTP305
print("""bargraph.py - A basic graph example
Displays an animated rising/falling bar on the left matrix,
and a scrolling bar graph on the right.
Press Ctrl+C to exit!
""")
display = LTP305()
width, height = display.get_shape()
values = [0, 0, 0, 0, 0]
while True:
# Add a new random value to our list and prune the list to visible values
values.insert(0, random.randint(0, height))
values = values[:width]
# Animate a value from 0 to height + 1
value = (math.sin(time.time() * math.pi) + 1) / 2.0
value *= height + 1
value = math.floor(value)
for y in range(height):
y = height - 1 - y
for x in range(width // 2):
# Left
display.set_pixel(x, y, value <= y)
# Right
display.set_pixel(x + (width // 2), y, values[x] <= y)
time.sleep(1.0 / height)
display.show()

50
vendor/ltp305-python/examples/clock.py vendored Normal file
View File

@@ -0,0 +1,50 @@
import sys
import time
from ltp305 import LTP305
print("""clock.py - clock segment example.
Usage: python3 clock.py <hour/minute/second> <i2c-address>
This simple clock example will display the hour, minute or second on a single matrix display breakout.
Press Ctrl+C to exit.
""")
fmt = "%M"
address = 0x61
available = {
"hour": "%H",
"minute": "%M",
"second": "%S"
}
if len(sys.argv) > 1:
try:
fmt = available[sys.argv[1]]
except KeyError:
raise ValueError("{} is not supported!".format(sys.argv[1]))
if len(sys.argv) > 2:
address = int(sys.argv[2], 16)
if address not in [0x61, 0x62, 0x63]:
raise ValueError("Invalid i2c address: 0x{:02x}. Run `i2c-detect -y 1` to discover breakouts.".format(address))
try:
display = LTP305(address=address)
display.clear()
display.show()
except OSError:
raise OSError("Unable to find LTP305 on i2c address: 0x{:02x}. Run `i2c-detect -y 1` to discover breakouts".format(address))
while True:
minute = time.strftime(fmt)
left, right = minute
display.set_character(0, left)
display.set_character(5, right)
display.show()
time.sleep(1.0 / 60)

49
vendor/ltp305-python/examples/eyes.py vendored Normal file
View File

@@ -0,0 +1,49 @@
import math
import time
import random
print("""eyes.py - They're watching you!
Press Ctrl+C to exit!
""")
from ltp305 import LTP305
display = LTP305()
def eye(x, y):
display.set_pixel(x, y, True)
display.set_pixel(x, y + 1, True)
display.set_pixel(x + 1, y, True)
display.set_pixel(x + 1, y + 1, True)
while True:
t = time.time() * math.pi
# Get eye x and y positions in the range 0.0 to 1.0
# You can plug in your own 0.0 to 1.0 values here
x = (math.sin(t / 2) + 1) / 2
y = (math.sin(t / 4) + 1) / 2
# Multiply them up to display coords and convert to itn
x = math.floor(x * 4)
y = math.floor(y * 6)
# Clear the display
display.clear()
# Blink occasionally
if not random.randint(0, 20) == 2:
# Draw the eyes if not blinking
eye(x, y)
eye(x + 5, y)
# Update the display at 10FPS
# This gives our crude blink code time to not look like a random flicker
display.show()
time.sleep(1.0 / 10)

254
vendor/ltp305-python/install-bullseye.sh vendored Executable file
View File

@@ -0,0 +1,254 @@
#!/bin/bash
CONFIG=/boot/config.txt
DATESTAMP=`date "+%Y-%m-%d-%H-%M-%S"`
CONFIG_BACKUP=false
APT_HAS_UPDATED=false
USER_HOME=/home/$SUDO_USER
RESOURCES_TOP_DIR=$USER_HOME/Pimoroni
WD=`pwd`
USAGE="sudo ./install.sh (--unstable)"
POSITIONAL_ARGS=()
UNSTABLE=false
PYTHON="/usr/bin/python3"
CODENAME=`lsb_release -sc`
distro_check() {
if [[ $CODENAME != "bullseye" ]]; then
printf "This installer is for Raspberry Pi OS: Bullseye only, current distro: $CODENAME\n"
exit 1
fi
}
user_check() {
if [ $(id -u) -ne 0 ]; then
printf "Script must be run as root. Try 'sudo ./install.sh'\n"
exit 1
fi
}
confirm() {
if [ "$FORCE" == '-y' ]; then
true
else
read -r -p "$1 [y/N] " response < /dev/tty
if [[ $response =~ ^(yes|y|Y)$ ]]; then
true
else
false
fi
fi
}
prompt() {
read -r -p "$1 [y/N] " response < /dev/tty
if [[ $response =~ ^(yes|y|Y)$ ]]; then
true
else
false
fi
}
success() {
echo -e "$(tput setaf 2)$1$(tput sgr0)"
}
inform() {
echo -e "$(tput setaf 6)$1$(tput sgr0)"
}
warning() {
echo -e "$(tput setaf 1)$1$(tput sgr0)"
}
function do_config_backup {
if [ ! $CONFIG_BACKUP == true ]; then
CONFIG_BACKUP=true
FILENAME="config.preinstall-$LIBRARY_NAME-$DATESTAMP.txt"
inform "Backing up $CONFIG to /boot/$FILENAME\n"
cp $CONFIG /boot/$FILENAME
mkdir -p $RESOURCES_TOP_DIR/config-backups/
cp $CONFIG $RESOURCES_TOP_DIR/config-backups/$FILENAME
if [ -f "$UNINSTALLER" ]; then
echo "cp $RESOURCES_TOP_DIR/config-backups/$FILENAME $CONFIG" >> $UNINSTALLER
fi
fi
}
function apt_pkg_install {
PACKAGES=()
PACKAGES_IN=("$@")
for ((i = 0; i < ${#PACKAGES_IN[@]}; i++)); do
PACKAGE="${PACKAGES_IN[$i]}"
if [ "$PACKAGE" == "" ]; then continue; fi
printf "Checking for $PACKAGE\n"
dpkg -L $PACKAGE > /dev/null 2>&1
if [ "$?" == "1" ]; then
PACKAGES+=("$PACKAGE")
fi
done
PACKAGES="${PACKAGES[@]}"
if ! [ "$PACKAGES" == "" ]; then
echo "Installing missing packages: $PACKAGES"
if [ ! $APT_HAS_UPDATED ]; then
apt update
APT_HAS_UPDATED=true
fi
apt install -y $PACKAGES
if [ -f "$UNINSTALLER" ]; then
echo "apt uninstall -y $PACKAGES"
fi
fi
}
while [[ $# -gt 0 ]]; do
K="$1"
case $K in
-u|--unstable)
UNSTABLE=true
shift
;;
-p|--python)
PYTHON=$2
shift
shift
;;
*)
if [[ $1 == -* ]]; then
printf "Unrecognised option: $1\n";
printf "Usage: $USAGE\n";
exit 1
fi
POSITIONAL_ARGS+=("$1")
shift
esac
done
distro_check
user_check
if [ ! -f "$PYTHON" ]; then
printf "Python path $PYTHON not found!\n"
exit 1
fi
PYTHON_VER=`$PYTHON --version`
inform "Installing. Please wait..."
$PYTHON -m pip install --upgrade configparser
CONFIG_VARS=`$PYTHON - <<EOF
from configparser import ConfigParser
c = ConfigParser()
c.read('library/setup.cfg')
p = dict(c['pimoroni'])
# Convert multi-line config entries into bash arrays
for k in p.keys():
fmt = '"{}"'
if '\n' in p[k]:
p[k] = "'\n\t'".join(p[k].split('\n')[1:])
fmt = "('{}')"
p[k] = fmt.format(p[k])
print("""
LIBRARY_NAME="{name}"
LIBRARY_VERSION="{version}"
""".format(**c['metadata']))
print("""
PY3_DEPS={py3deps}
PY2_DEPS={py2deps}
SETUP_CMDS={commands}
CONFIG_TXT={configtxt}
""".format(**p))
EOF`
if [ $? -ne 0 ]; then
warning "Error parsing configuration...\n"
exit 1
fi
eval $CONFIG_VARS
RESOURCES_DIR=$RESOURCES_TOP_DIR/$LIBRARY_NAME
UNINSTALLER=$RESOURCES_DIR/uninstall.sh
mkdir -p $RESOURCES_DIR
cat << EOF > $UNINSTALLER
printf "It's recommended you run these steps manually.\n"
printf "If you want to run the full script, open it in\n"
printf "an editor and remove 'exit 1' from below.\n"
exit 1
EOF
printf "$LIBRARY_NAME $LIBRARY_VERSION Python Library: Installer\n\n"
if $UNSTABLE; then
warning "Installing unstable library from source.\n\n"
else
printf "Installing stable library from pypi.\n\n"
fi
cd library
printf "Installing for $PYTHON_VER...\n"
apt_pkg_install "${PY3_DEPS[@]}"
if $UNSTABLE; then
$PYTHON setup.py install > /dev/null
else
$PYTHON -m pip install --upgrade $LIBRARY_NAME
fi
if [ $? -eq 0 ]; then
success "Done!\n"
echo "$PYTHON -m pip uninstall $LIBRARY_NAME" >> $UNINSTALLER
fi
cd $WD
for ((i = 0; i < ${#SETUP_CMDS[@]}; i++)); do
CMD="${SETUP_CMDS[$i]}"
# Attempt to catch anything that touches /boot/config.txt and trigger a backup
if [[ "$CMD" == *"raspi-config"* ]] || [[ "$CMD" == *"$CONFIG"* ]] || [[ "$CMD" == *"\$CONFIG"* ]]; then
do_config_backup
fi
eval $CMD
done
for ((i = 0; i < ${#CONFIG_TXT[@]}; i++)); do
CONFIG_LINE="${CONFIG_TXT[$i]}"
if ! [ "$CONFIG_LINE" == "" ]; then
do_config_backup
inform "Adding $CONFIG_LINE to $CONFIG\n"
sed -i "s/^#$CONFIG_LINE/$CONFIG_LINE/" $CONFIG
if ! grep -q "^$CONFIG_LINE" $CONFIG; then
printf "$CONFIG_LINE\n" >> $CONFIG
fi
fi
done
if [ -d "examples" ]; then
if confirm "Would you like to copy examples to $RESOURCES_DIR?"; then
inform "Copying examples to $RESOURCES_DIR"
cp -r examples/ $RESOURCES_DIR
echo "rm -r $RESOURCES_DIR" >> $UNINSTALLER
success "Done!"
fi
fi
printf "\n"
if [ -f "/usr/bin/pydoc" ]; then
printf "Generating documentation.\n"
pydoc -w $LIBRARY_NAME > /dev/null
if [ -f "$LIBRARY_NAME.html" ]; then
cp $LIBRARY_NAME.html $RESOURCES_DIR/docs.html
rm -f $LIBRARY_NAME.html
inform "Documentation saved to $RESOURCES_DIR/docs.html"
success "Done!"
else
warning "Error: Failed to generate documentation."
fi
fi
success "\nAll done!"
inform "If this is your first time installing you should reboot for hardware changes to take effect.\n"
inform "Find uninstall steps in $UNINSTALLER\n"

251
vendor/ltp305-python/install.sh vendored Executable file
View File

@@ -0,0 +1,251 @@
#!/bin/bash
CONFIG=/boot/config.txt
DATESTAMP=`date "+%Y-%m-%d-%H-%M-%S"`
CONFIG_BACKUP=false
APT_HAS_UPDATED=false
USER_HOME=/home/$SUDO_USER
RESOURCES_TOP_DIR=$USER_HOME/Pimoroni
WD=`pwd`
USAGE="sudo ./install.sh (--unstable)"
POSITIONAL_ARGS=()
UNSTABLE=false
CODENAME=`lsb_release -sc`
if [[ $CODENAME == "bullseye" ]]; then
bash ./install-bullseye.sh
exit $?
fi
user_check() {
if [ $(id -u) -ne 0 ]; then
printf "Script must be run as root. Try 'sudo ./install.sh'\n"
exit 1
fi
}
confirm() {
if [ "$FORCE" == '-y' ]; then
true
else
read -r -p "$1 [y/N] " response < /dev/tty
if [[ $response =~ ^(yes|y|Y)$ ]]; then
true
else
false
fi
fi
}
prompt() {
read -r -p "$1 [y/N] " response < /dev/tty
if [[ $response =~ ^(yes|y|Y)$ ]]; then
true
else
false
fi
}
success() {
echo -e "$(tput setaf 2)$1$(tput sgr0)"
}
inform() {
echo -e "$(tput setaf 6)$1$(tput sgr0)"
}
warning() {
echo -e "$(tput setaf 1)$1$(tput sgr0)"
}
function do_config_backup {
if [ ! $CONFIG_BACKUP == true ]; then
CONFIG_BACKUP=true
FILENAME="config.preinstall-$LIBRARY_NAME-$DATESTAMP.txt"
inform "Backing up $CONFIG to /boot/$FILENAME\n"
cp $CONFIG /boot/$FILENAME
mkdir -p $RESOURCES_TOP_DIR/config-backups/
cp $CONFIG $RESOURCES_TOP_DIR/config-backups/$FILENAME
if [ -f "$UNINSTALLER" ]; then
echo "cp $RESOURCES_TOP_DIR/config-backups/$FILENAME $CONFIG" >> $UNINSTALLER
fi
fi
}
function apt_pkg_install {
PACKAGES=()
PACKAGES_IN=("$@")
for ((i = 0; i < ${#PACKAGES_IN[@]}; i++)); do
PACKAGE="${PACKAGES_IN[$i]}"
if [ "$PACKAGE" == "" ]; then continue; fi
printf "Checking for $PACKAGE\n"
dpkg -L $PACKAGE > /dev/null 2>&1
if [ "$?" == "1" ]; then
PACKAGES+=("$PACKAGE")
fi
done
PACKAGES="${PACKAGES[@]}"
if ! [ "$PACKAGES" == "" ]; then
echo "Installing missing packages: $PACKAGES"
if [ ! $APT_HAS_UPDATED ]; then
apt update
APT_HAS_UPDATED=true
fi
apt install -y $PACKAGES
if [ -f "$UNINSTALLER" ]; then
echo "apt uninstall -y $PACKAGES"
fi
fi
}
while [[ $# -gt 0 ]]; do
K="$1"
case $K in
-u|--unstable)
UNSTABLE=true
shift
;;
*)
if [[ $1 == -* ]]; then
printf "Unrecognised option: $1\n";
printf "Usage: $USAGE\n";
exit 1
fi
POSITIONAL_ARGS+=("$1")
shift
esac
done
user_check
apt_pkg_install python-configparser
CONFIG_VARS=`python - <<EOF
from configparser import ConfigParser
c = ConfigParser()
c.read('library/setup.cfg')
p = dict(c['pimoroni'])
# Convert multi-line config entries into bash arrays
for k in p.keys():
fmt = '"{}"'
if '\n' in p[k]:
p[k] = "'\n\t'".join(p[k].split('\n')[1:])
fmt = "('{}')"
p[k] = fmt.format(p[k])
print("""
LIBRARY_NAME="{name}"
LIBRARY_VERSION="{version}"
""".format(**c['metadata']))
print("""
PY3_DEPS={py3deps}
PY2_DEPS={py2deps}
SETUP_CMDS={commands}
CONFIG_TXT={configtxt}
""".format(**p))
EOF`
if [ $? -ne 0 ]; then
warning "Error parsing configuration...\n"
exit 1
fi
eval $CONFIG_VARS
RESOURCES_DIR=$RESOURCES_TOP_DIR/$LIBRARY_NAME
UNINSTALLER=$RESOURCES_DIR/uninstall.sh
mkdir -p $RESOURCES_DIR
cat << EOF > $UNINSTALLER
printf "It's recommended you run these steps manually.\n"
printf "If you want to run the full script, open it in\n"
printf "an editor and remove 'exit 1' from below.\n"
exit 1
EOF
printf "$LIBRARY_NAME $LIBRARY_VERSION Python Library: Installer\n\n"
if $UNSTABLE; then
warning "Installing unstable library from source.\n\n"
else
printf "Installing stable library from pypi.\n\n"
fi
cd library
printf "Installing for Python 2..\n"
apt_pkg_install "${PY2_DEPS[@]}"
if $UNSTABLE; then
python setup.py install > /dev/null
else
pip install --upgrade $LIBRARY_NAME
fi
if [ $? -eq 0 ]; then
success "Done!\n"
echo "pip uninstall $LIBRARY_NAME" >> $UNINSTALLER
fi
if [ -f "/usr/bin/python3" ]; then
printf "Installing for Python 3..\n"
apt_pkg_install "${PY3_DEPS[@]}"
if $UNSTABLE; then
python3 setup.py install > /dev/null
else
pip3 install --upgrade $LIBRARY_NAME
fi
if [ $? -eq 0 ]; then
success "Done!\n"
echo "pip3 uninstall $LIBRARY_NAME" >> $UNINSTALLER
fi
fi
cd $WD
for ((i = 0; i < ${#SETUP_CMDS[@]}; i++)); do
CMD="${SETUP_CMDS[$i]}"
# Attempt to catch anything that touches /boot/config.txt and trigger a backup
if [[ "$CMD" == *"raspi-config"* ]] || [[ "$CMD" == *"$CONFIG"* ]] || [[ "$CMD" == *"\$CONFIG"* ]]; then
do_config_backup
fi
eval $CMD
done
for ((i = 0; i < ${#CONFIG_TXT[@]}; i++)); do
CONFIG_LINE="${CONFIG_TXT[$i]}"
if ! [ "$CONFIG_LINE" == "" ]; then
do_config_backup
inform "Adding $CONFIG_LINE to $CONFIG\n"
sed -i "s/^#$CONFIG_LINE/$CONFIG_LINE/" $CONFIG
if ! grep -q "^$CONFIG_LINE" $CONFIG; then
printf "$CONFIG_LINE\n" >> $CONFIG
fi
fi
done
if [ -d "examples" ]; then
if confirm "Would you like to copy examples to $RESOURCES_DIR?"; then
inform "Copying examples to $RESOURCES_DIR"
cp -r examples/ $RESOURCES_DIR
echo "rm -r $RESOURCES_DIR" >> $UNINSTALLER
success "Done!"
fi
fi
printf "\n"
if [ -f "/usr/bin/pydoc" ]; then
printf "Generating documentation.\n"
pydoc -w $LIBRARY_NAME > /dev/null
if [ -f "$LIBRARY_NAME.html" ]; then
cp $LIBRARY_NAME.html $RESOURCES_DIR/docs.html
rm -f $LIBRARY_NAME.html
inform "Documentation saved to $RESOURCES_DIR/docs.html"
success "Done!"
else
warning "Error: Failed to generate documentation."
fi
fi
success "\nAll done!"
inform "If this is your first time installing you should reboot for hardware changes to take effect.\n"
inform "Find uninstall steps in $UNINSTALLER\n"

View File

@@ -0,0 +1,4 @@
[run]
source = ltp305
omit =
.tox/*

View File

@@ -0,0 +1,4 @@
0.0.1
-----
* Initial Release

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 Pimoroni Ltd.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,5 @@
include CHANGELOG.txt
include LICENSE.txt
include README.md
include setup.py
recursive-include ltp305 *.py

33
vendor/ltp305-python/library/README.md vendored Normal file
View File

@@ -0,0 +1,33 @@
# LTP305 - Breakout Garden dual 5x7 LED matrix driver
[![Build Status](https://travis-ci.com/pimoroni/ltp305-python.svg?branch=master)](https://travis-ci.com/pimoroni/ltp305-python)
[![Coverage Status](https://coveralls.io/repos/github/pimoroni/ltp305-python/badge.svg?branch=master)](https://coveralls.io/github/pimoroni/ltp305-python?branch=master)
[![PyPi Package](https://img.shields.io/pypi/v/ltp305.svg)](https://pypi.python.org/pypi/ltp305)
[![Python Versions](https://img.shields.io/pypi/pyversions/ltp305.svg)](https://pypi.python.org/pypi/ltp305)
# Pre-requisites
You must enable i2c:
* i2c: `sudo raspi-config nonint do_i2c 0`
You can optionally run `sudo raspi-config` or the graphical Raspberry Pi Configuration UI to enable interfaces.
# Installing
Stable library from PyPi:
* Just run `sudo pip3 install ltp305`
Latest/development library from GitHub:
* `git clone https://github.com/pimoroni/ltp305-python`
* `cd ltp305-python`
* `sudo ./install.sh`
# Changelog
0.0.1
-----
* Initial Release

View File

@@ -0,0 +1,205 @@
import smbus
from .font import font
__version__ = '0.0.1'
MODE = 0b00011000
OPTS = 0b00001110 # 1110 = 35mA, 0000 = 40mA
CMD_BRIGHTNESS = 0x19
CMD_MODE = 0x00
CMD_UPDATE = 0x0C
CMD_OPTIONS = 0x0D
CMD_MATRIX_L = 0x0E
CMD_MATRIX_R = 0x01
class LTP305:
"""
_buf_matrix_left = [
# Row 7654321
0b01111111, # col 1, bottom = msb
0b01111111, # col 2
0b01111111, # col 3
0b01111111, # col 4
0b01111111, # col 5
0b00000000,
0b00000000,
0b01000000 # bit 7 = decimal dot
]
_buf_matrix_right = [
# Col 12345
0b00011111, # row 1
0b00011111, # row 2
0b00011111, # row 3
0b00011111, # row 4
0b00011111, # row 5
0b00011111, # row 6
0b10011111, # row 7 + bit 8 = decimal dot
0b00000000
]
"""
def __init__(self, address=0x61, brightness=0.5):
"""LTP305 5x7 x 2 Matrix Driver
:param address: i2c address, one of 0x61, 0x62 or 0x63 (default 0x61)
:param brightness: LED brightness from 0.0 to 1.0 (default 0.5)
"""
self.bus = smbus.SMBus(1)
self.address = address
self.set_brightness(brightness)
self.clear()
def clear(self):
"""Clear both LED matrices.
Must call .show() to display changes.
"""
self._buf_matrix_left = [0 for _ in range(8)]
self._buf_matrix_right = [0 for _ in range(8)]
def set_brightness(self, brightness, update=False):
"""Set brightness of both LED matrices.
:param brightnes: LED brightness from 0.0 to 1.0
:param update: Push change to display immediately (otherwise you must call .show())
"""
self._brightness = int(brightness * 127.0)
self._brightness = min(127, max(0, self._brightness))
if update:
self.bus.write_byte_data(self.address, CMD_BRIGHTNESS, self._brightness)
def set_decimal(self, left=None, right=None):
"""Set decimal of left and/or right matrix.
:param left: State of left decimal dot
:param right: State of right decimal dot
"""
if left is not None:
if left:
self._buf_matrix_left[7] |= 0b01000000
else:
self._buf_matrix_left[7] &= 0b10111111
if right is not None:
if right:
self._buf_matrix_right[6] |= 0b10000000
else:
self._buf_matrix_right[6] &= 0b01111111
def set_pixel(self, x, y, c):
"""Set a single pixel on the matrix.
:param x: x position from 0 to 9 (0-4 on left matrix, 5-9 on right)
:param y: y position
:param c: state on/off
"""
if x < 5: # Left Matrix
if c:
self._buf_matrix_left[x] |= (0b1 << y)
else:
self._buf_matrix_left[x] &= ~(0b1 << y)
else: # Right Matrix
x -= 5
if c:
self._buf_matrix_right[y] |= (0b1 << x)
else:
self._buf_matrix_right[y] &= ~(0b1 << x)
def set_character(self, x, char):
"""Set a single character.
:param x: x position, 0 for left, 5 for right, or in between if you fancy
:param char: string character or char ordinal
"""
if type(char) is not int:
char = ord(char)
char = font[char]
for cx in range(5):
for cy in range(8):
c = char[cx] & (0b1 << cy)
self.set_pixel(x + cx, cy, c)
def get_shape(self):
"""Set the width/height of the display."""
return 10, 7
def set_image(self, image, offset_x=0, offset_y=0, wrap=False, bg=0):
"""Set a PIL image to the display buffer."""
image_width, image_height = image.size
if image.mode != "1":
image = image.convert("1")
display_width, display_height = self.get_shape()
for y in range(display_height):
for x in range(display_width):
p = bg
i_x = x + offset_x
i_y = y + offset_y
if wrap:
while i_x >= image_width:
i_x -= image_width
while i_y >= image_height:
i_y -= image_height
if i_x < image_width and i_y < image_height:
p = image.getpixel((i_x, i_y))
self.set_pixel(x, y, p)
def show(self):
"""Update the LED matrixes from the buffer."""
self.bus.write_i2c_block_data(self.address, CMD_MATRIX_L, self._buf_matrix_left)
self.bus.write_i2c_block_data(self.address, CMD_MATRIX_R, self._buf_matrix_right)
self.bus.write_byte_data(self.address, CMD_MODE, MODE)
self.bus.write_byte_data(self.address, CMD_OPTIONS, OPTS)
self.bus.write_byte_data(self.address, CMD_BRIGHTNESS, self._brightness)
self.bus.write_byte_data(self.address, CMD_UPDATE, 0x01)
if __name__ == "__main__":
import time
matrix = LTP305(0x61)
delay = 1.0 / 72 * 4
c = True
while True:
for n in range(10):
matrix.set_character(0, str(n))
matrix.set_character(5, 'abcdefghij'[n])
matrix.show()
time.sleep(0.1)
matrix.set_character(0, "=")
matrix.set_character(5, ")")
matrix.show()
time.sleep(1.0)
matrix.clear()
matrix.show()
time.sleep(0.5)
for _ in range(2):
for y in range(7):
for x in range(10):
matrix.set_pixel(x, y, c)
matrix.show()
time.sleep(delay)
matrix.set_decimal(left=c)
matrix.show()
time.sleep(delay)
matrix.set_decimal(right=c)
matrix.show()
time.sleep(delay)
c = not c

View File

@@ -0,0 +1,408 @@
# -*- coding: utf-8 -*-
tinynumbers = [
[0b11111, 0b11111],
[0b11111],
[0b10111, 0b11101],
[0b10101, 0b11111],
[0b11110, 0b00011],
[0b11101, 0b10111],
[0b11111, 0b00111],
[0b10000, 0b11111],
[0b10101, 0b10101],
[0b11100, 0b11111]
]
# add japanese
font = {
32: [0x00, 0x00, 0x00, 0x00, 0x00], # (space)
33: [0x00, 0x00, 0x5f, 0x00, 0x00], # !
34: [0x00, 0x07, 0x00, 0x07, 0x00], # "
35: [0x14, 0x7f, 0x14, 0x7f, 0x14], # #
36: [0x24, 0x2a, 0x7f, 0x2a, 0x12], # $
37: [0x23, 0x13, 0x08, 0x64, 0x62], # %
38: [0x36, 0x49, 0x55, 0x22, 0x50], # &
39: [0x00, 0x05, 0x03, 0x00, 0x00], # '
40: [0x00, 0x1c, 0x22, 0x41, 0x00], # (
41: [0x00, 0x41, 0x22, 0x1c, 0x00], # )
42: [0x08, 0x2a, 0x1c, 0x2a, 0x08], # *
43: [0x08, 0x08, 0x3e, 0x08, 0x08], # +
44: [0x00, 0x50, 0x30, 0x00, 0x00], # ,
45: [0x08, 0x08, 0x08, 0x08, 0x08], # -
46: [0x00, 0x60, 0x60, 0x00, 0x00], # .
47: [0x20, 0x10, 0x08, 0x04, 0x02], # /
48: [0x3e, 0x51, 0x49, 0x45, 0x3e], # 0
49: [0x00, 0x42, 0x7f, 0x40, 0x00], # 1
50: [0x42, 0x61, 0x51, 0x49, 0x46], # 2
51: [0x21, 0x41, 0x45, 0x4b, 0x31], # 3
52: [0x18, 0x14, 0x12, 0x7f, 0x10], # 4
53: [0x27, 0x45, 0x45, 0x45, 0x39], # 5
54: [0x3c, 0x4a, 0x49, 0x49, 0x30], # 6
55: [0x01, 0x71, 0x09, 0x05, 0x03], # 7
56: [0x36, 0x49, 0x49, 0x49, 0x36], # 8
57: [0x06, 0x49, 0x49, 0x29, 0x1e], # 9
58: [0x00, 0x36, 0x36, 0x00, 0x00], # :
59: [0x00, 0x56, 0x36, 0x00, 0x00], # ;
60: [0x00, 0x08, 0x14, 0x22, 0x41], # <
61: [0x14, 0x14, 0x14, 0x14, 0x14], # =
62: [0x41, 0x22, 0x14, 0x08, 0x00], # >
63: [0x02, 0x01, 0x51, 0x09, 0x06], # ?
64: [0x32, 0x49, 0x79, 0x41, 0x3e], # @
65: [0x7e, 0x11, 0x11, 0x11, 0x7e], # A
66: [0x7f, 0x49, 0x49, 0x49, 0x36], # B
67: [0x3e, 0x41, 0x41, 0x41, 0x22], # C
68: [0x7f, 0x41, 0x41, 0x22, 0x1c], # D
69: [0x7f, 0x49, 0x49, 0x49, 0x41], # E
70: [0x7f, 0x09, 0x09, 0x01, 0x01], # F
71: [0x3e, 0x41, 0x41, 0x51, 0x32], # G
72: [0x7f, 0x08, 0x08, 0x08, 0x7f], # H
73: [0x00, 0x41, 0x7f, 0x41, 0x00], # I
74: [0x20, 0x40, 0x41, 0x3f, 0x01], # J
75: [0x7f, 0x08, 0x14, 0x22, 0x41], # K
76: [0x7f, 0x40, 0x40, 0x40, 0x40], # L
77: [0x7f, 0x02, 0x04, 0x02, 0x7f], # M
78: [0x7f, 0x04, 0x08, 0x10, 0x7f], # N
79: [0x3e, 0x41, 0x41, 0x41, 0x3e], # O
80: [0x7f, 0x09, 0x09, 0x09, 0x06], # P
81: [0x3e, 0x41, 0x51, 0x21, 0x5e], # Q
82: [0x7f, 0x09, 0x19, 0x29, 0x46], # R
83: [0x46, 0x49, 0x49, 0x49, 0x31], # S
84: [0x01, 0x01, 0x7f, 0x01, 0x01], # T
85: [0x3f, 0x40, 0x40, 0x40, 0x3f], # U
86: [0x1f, 0x20, 0x40, 0x20, 0x1f], # V
87: [0x7f, 0x20, 0x18, 0x20, 0x7f], # W
88: [0x63, 0x14, 0x08, 0x14, 0x63], # X
89: [0x03, 0x04, 0x78, 0x04, 0x03], # Y
90: [0x61, 0x51, 0x49, 0x45, 0x43], # Z
91: [0x00, 0x00, 0x7f, 0x41, 0x41], # [
92: [0x02, 0x04, 0x08, 0x10, 0x20], # \
93: [0x41, 0x41, 0x7f, 0x00, 0x00], # ]
94: [0x04, 0x02, 0x01, 0x02, 0x04], # ^
95: [0x40, 0x40, 0x40, 0x40, 0x40], # _
96: [0x00, 0x01, 0x02, 0x04, 0x00], # `
97: [0x20, 0x54, 0x54, 0x54, 0x78], # a
98: [0x7f, 0x48, 0x44, 0x44, 0x38], # b
99: [0x38, 0x44, 0x44, 0x44, 0x20], # c
100: [0x38, 0x44, 0x44, 0x48, 0x7f], # d
101: [0x38, 0x54, 0x54, 0x54, 0x18], # e
102: [0x08, 0x7e, 0x09, 0x01, 0x02], # f
103: [0x08, 0x14, 0x54, 0x54, 0x3c], # g
104: [0x7f, 0x08, 0x04, 0x04, 0x78], # h
105: [0x00, 0x44, 0x7d, 0x40, 0x00], # i
106: [0x20, 0x40, 0x44, 0x3d, 0x00], # j
107: [0x00, 0x7f, 0x10, 0x28, 0x44], # k
108: [0x00, 0x41, 0x7f, 0x40, 0x00], # l
109: [0x7c, 0x04, 0x18, 0x04, 0x78], # m
110: [0x7c, 0x08, 0x04, 0x04, 0x78], # n
111: [0x38, 0x44, 0x44, 0x44, 0x38], # o
112: [0x7c, 0x14, 0x14, 0x14, 0x08], # p
113: [0x08, 0x14, 0x14, 0x18, 0x7c], # q
114: [0x7c, 0x08, 0x04, 0x04, 0x08], # r
115: [0x48, 0x54, 0x54, 0x54, 0x20], # s
116: [0x04, 0x3f, 0x44, 0x40, 0x20], # t
117: [0x3c, 0x40, 0x40, 0x20, 0x7c], # u
118: [0x1c, 0x20, 0x40, 0x20, 0x1c], # v
119: [0x3c, 0x40, 0x30, 0x40, 0x3c], # w
120: [0x44, 0x28, 0x10, 0x28, 0x44], # x
121: [0x0c, 0x50, 0x50, 0x50, 0x3c], # y
122: [0x44, 0x64, 0x54, 0x4c, 0x44], # z
123: [0x00, 0x08, 0x36, 0x41, 0x00], # {
124: [0x00, 0x00, 0x7f, 0x00, 0x00], # |
125: [0x00, 0x41, 0x36, 0x08, 0x00], # }
126: [0x08, 0x08, 0x2a, 0x1c, 0x08], # ~
8221: [0x00, 0x07, 0x00, 0x07, 0x00], # ”
8592: [0x08, 0x1C, 0x2A, 0x08, 0x08], # ←
8593: [0x08, 0x04, 0x7E, 0x04, 0x08], # ↑
8594: [0x08, 0x08, 0x2A, 0x1C, 0x08], # →
8595: [0x08, 0x10, 0x3F, 0x10, 0x08], # ↓
9472: [0x08, 0x08, 0x08, 0x08, 0x08], # ─
9474: [0x00, 0x00, 0x7F, 0x00, 0x00], # │
9484: [0x00, 0x00, 0x78, 0x08, 0x08], # ┌
9488: [0x08, 0x08, 0x78, 0x00, 0x00], # ┐
9492: [0x00, 0x00, 0x0F, 0x08, 0x08], # └
9496: [0x08, 0x08, 0x0F, 0x00, 0x00], # ┘
9500: [0x00, 0x00, 0x7F, 0x08, 0x08], # ├
9508: [0x08, 0x08, 0x7F, 0x00, 0x00], # ┤
9516: [0x08, 0x08, 0x78, 0x08, 0x08], # ┬
9524: [0x08, 0x08, 0x0F, 0x08, 0x08], # ┴
9532: [0x08, 0x08, 0x7F, 0x08, 0x08], # ┼
9632: [0x7F, 0x7F, 0x7F, 0x7F, 0x7F], # ■
9633: [0x7F, 0x41, 0x41, 0x41, 0x7F], # □
9650: [0x10, 0x1C, 0x1E, 0x1C, 0x10], # ▲
9651: [0x10, 0x1C, 0x12, 0x1C, 0x10], # △
9660: [0x04, 0x1C, 0x3C, 0x1C, 0x04], # ▼
9661: [0x04, 0x1C, 0x24, 0x1C, 0x04], # ▽
9670: [0x08, 0x1C, 0x3E, 0x1C, 0x08], # ◆
9675: [0x1C, 0x22, 0x22, 0x22, 0x1C], # ○
9679: [0x1C, 0x3E, 0x3E, 0x3E, 0x1C], # ●
9733: [0x64, 0x3E, 0x1F, 0x3E, 0x64], # ★
12288: [0x00, 0x00, 0x00, 0x00, 0x00], #
12289: [0x10, 0x20, 0x40, 0x00, 0x00], # 、
12290: [0x70, 0x50, 0x70, 0x00, 0x00], # 。
12300: [0x00, 0x0F, 0x01, 0x01, 0x01], # 「
12301: [0x40, 0x40, 0x40, 0x78, 0x00], # 」
12316: [0x02, 0x01, 0x02, 0x04, 0x02], # 〜
12353: [0x28, 0x58, 0x3C, 0x68, 0x00], # ぁ
12354: [0x32, 0x7A, 0x2F, 0x1A, 0x72], # あ
12355: [0x38, 0x40, 0x08, 0x30, 0x00], # ぃ
12356: [0x3E, 0x40, 0x20, 0x00, 0x1C], # い
12357: [0x10, 0x0C, 0x4C, 0x30, 0x00], # ぅ
12358: [0x04, 0x05, 0x45, 0x25, 0x18], # う
12359: [0x48, 0x2C, 0x5C, 0x48, 0x00], # ぇ
12360: [0x44, 0x24, 0x35, 0x4D, 0x44], # え
12361: [0x68, 0x7C, 0x10, 0x64, 0x00], # ぉ
12362: [0x32, 0x7F, 0x0A, 0x48, 0x32], # お
12363: [0x34, 0x0F, 0x44, 0x38, 0x06], # か
12365: [0x22, 0x4A, 0x4F, 0x5A, 0x08], # き
12367: [0x00, 0x18, 0x24, 0x43, 0x00], # く
12369: [0x3E, 0x00, 0x44, 0x3F, 0x04], # け
12371: [0x22, 0x52, 0x42, 0x42, 0x44], # こ
12373: [0x24, 0x44, 0x47, 0x5C, 0x12], # さ
12375: [0x3F, 0x40, 0x40, 0x20, 0x10], # し
12377: [0x02, 0x0A, 0x56, 0x3F, 0x02], # す
12379: [0x04, 0x3E, 0x44, 0x5F, 0x44], # せ
12381: [0x08, 0x2D, 0x5B, 0x45, 0x44], # そ
12383: [0x72, 0x0F, 0x22, 0x4A, 0x48], # た
12385: [0x0A, 0x0E, 0x4B, 0x4A, 0x32], # ち
12387: [0x08, 0x48, 0x48, 0x30, 0x00], # っ
12388: [0x02, 0x02, 0x42, 0x22, 0x1C], # つ
12390: [0x02, 0x32, 0x4A, 0x46, 0x42], # て
12392: [0x30, 0x4B, 0x44, 0x44, 0x42], # と
12394: [0x0A, 0x27, 0x52, 0x38, 0x26], # な
12395: [0x3E, 0x00, 0x22, 0x42, 0x42], # に
12396: [0x38, 0x6F, 0x1C, 0x67, 0x78], # ぬ
12397: [0x12, 0x7F, 0x0A, 0x64, 0x78], # ね
12398: [0x3C, 0x62, 0x1E, 0x44, 0x38], # の
12399: [0x3E, 0x00, 0x32, 0x7F, 0x22], # は
12402: [0x04, 0x3E, 0x40, 0x47, 0x3C], # ひ
12405: [0x30, 0x05, 0x7A, 0x00, 0x38], # ふ
12411: [0x3E, 0x00, 0x35, 0x7F, 0x25], # ほ
12414: [0x2A, 0x5A, 0x7F, 0x2A, 0x4A], # ま
12415: [0x71, 0x3F, 0x08, 0x7E, 0x08], # み
12416: [0x1A, 0x3F, 0x42, 0x40, 0x26], # む
12417: [0x38, 0x4E, 0x34, 0x1F, 0x78], # め
12418: [0x14, 0x3F, 0x54, 0x40, 0x20], # も
12419: [0x1C, 0x68, 0x0C, 0x30, 0x00], # ゃ
12420: [0x04, 0x7F, 0x04, 0x2E, 0x18], # や
12421: [0x18, 0x50, 0x3C, 0x18, 0x00], # ゅ
12422: [0x1E, 0x44, 0x3F, 0x12, 0x0C], # ゆ
12423: [0x60, 0x7C, 0x28, 0x40, 0x00], # ょ
12424: [0x20, 0x50, 0x3F, 0x24, 0x44], # よ
12425: [0x10, 0x0D, 0x49, 0x4A, 0x30], # ら
12426: [0x0E, 0x00, 0x40, 0x21, 0x1E], # り
12427: [0x20, 0x55, 0x65, 0x4B, 0x30], # る
12428: [0x34, 0x7F, 0x04, 0x3E, 0x40], # れ
12429: [0x10, 0x49, 0x4D, 0x4B, 0x30], # ろ
12431: [0x24, 0x7F, 0x0A, 0x44, 0x38], # わ
12434: [0x22, 0x5F, 0x4A, 0x56, 0x42], # を
12435: [0x70, 0x0F, 0x30, 0x40, 0x20], # ん
12443: [0x02, 0x04, 0x01, 0x02, 0x00], # ゛
12444: [0x07, 0x05, 0x07, 0x00, 0x00], # ゜
12449: [0x44, 0x44, 0x3C, 0x14, 0x0C], # ァ
12450: [0x42, 0x42, 0x3A, 0x12, 0x0E], # ア
12451: [0x20, 0x10, 0x78, 0x04, 0x00], # ィ
12452: [0x10, 0x08, 0x04, 0x7E, 0x01], # イ
12453: [0x18, 0x08, 0x4C, 0x48, 0x38], # ゥ
12454: [0x0E, 0x42, 0x43, 0x22, 0x1E], # ウ
12455: [0x48, 0x48, 0x78, 0x48, 0x48], # ェ
12456: [0x42, 0x42, 0x7E, 0x42, 0x42], # エ
12457: [0x48, 0x38, 0x08, 0x7C, 0x08], # ォ
12458: [0x22, 0x12, 0x0A, 0x7F, 0x02], # オ
12459: [0x42, 0x3F, 0x02, 0x02, 0x7E], # カ
12461: [0x0A, 0x0A, 0x7F, 0x0A, 0x0A], # キ
12463: [0x08, 0x06, 0x42, 0x22, 0x1E], # ク
12465: [0x0F, 0x42, 0x42, 0x3E, 0x02], # ケ
12467: [0x42, 0x42, 0x42, 0x42, 0x7E], # コ
12469: [0x02, 0x4F, 0x42, 0x3F, 0x02], # サ
12471: [0x4A, 0x4A, 0x40, 0x20, 0x1C], # シ
12473: [0x42, 0x22, 0x12, 0x2A, 0x46], # ス
12475: [0x02, 0x3F, 0x42, 0x42, 0x4E], # セ
12477: [0x06, 0x48, 0x40, 0x30, 0x0E], # ソ
12479: [0x08, 0x4E, 0x52, 0x32, 0x0E], # タ
12481: [0x08, 0x4A, 0x4A, 0x3F, 0x09], # チ
12483: [0x18, 0x40, 0x58, 0x40, 0x30], # ッ
12484: [0x0E, 0x40, 0x4E, 0x20, 0x1E], # ツ
12486: [0x04, 0x45, 0x45, 0x3D, 0x04], # テ
12488: [0x00, 0x7F, 0x08, 0x10, 0x10], # ト
12490: [0x44, 0x44, 0x44, 0x3F, 0x04], # ナ
12491: [0x40, 0x42, 0x42, 0x42, 0x40], # ニ
12492: [0x42, 0x4A, 0x2A, 0x12, 0x2E], # ヌ
12493: [0x22, 0x12, 0x73, 0x0A, 0x16], # ネ
12494: [0x40, 0x40, 0x20, 0x10, 0x0E], #
12495: [0x70, 0x0E, 0x00, 0x07, 0x78], # ハ
12498: [0x3F, 0x44, 0x44, 0x44, 0x44], # ヒ
12501: [0x02, 0x42, 0x42, 0x22, 0x1E], # フ
12504: [0x08, 0x04, 0x02, 0x0C, 0x30], # ヘ
12507: [0x32, 0x02, 0x7F, 0x02, 0x32], # ホ
12510: [0x02, 0x12, 0x22, 0x52, 0x0E], # マ
12511: [0x20, 0x2A, 0x2A, 0x2A, 0x40], # ミ
12512: [0x30, 0x2C, 0x22, 0x28, 0x70], # ム
12513: [0x40, 0x44, 0x28, 0x10, 0x2E], # メ
12514: [0x0A, 0x0A, 0x3E, 0x4A, 0x4A], # モ
12515: [0x08, 0x7C, 0x08, 0x28, 0x18], # ャ
12516: [0x04, 0x7F, 0x04, 0x14, 0x0C], # ヤ
12517: [0x48, 0x48, 0x48, 0x78, 0x40], # ュ
12518: [0x42, 0x42, 0x42, 0x7E, 0x40], # ユ
12519: [0x54, 0x54, 0x54, 0x7C, 0x00], # ョ
12520: [0x4A, 0x4A, 0x4A, 0x4A, 0x7E], # ヨ
12521: [0x04, 0x45, 0x45, 0x25, 0x1C], # ラ
12522: [0x0E, 0x40, 0x40, 0x20, 0x1E], # リ
12523: [0x7E, 0x00, 0x7E, 0x40, 0x38], # ル
12524: [0x7E, 0x40, 0x40, 0x20, 0x10], # レ
12525: [0x7E, 0x42, 0x42, 0x42, 0x7E], # ロ
12527: [0x0E, 0x42, 0x42, 0x22, 0x1E], # ワ
12530: [0x0A, 0x4A, 0x4A, 0x2A, 0x1E], # ヲ
12531: [0x42, 0x42, 0x40, 0x20, 0x1C], # ン
12539: [0x00, 0x00, 0x08, 0x00, 0x00], # ・
12540: [0x04, 0x08, 0x08, 0x08, 0x08], # ー
65281: [0x00, 0x00, 0x5F, 0x00, 0x00], #
65283: [0x14, 0x7F, 0x14, 0x7F, 0x14], #
65284: [0x24, 0x2A, 0x7F, 0x2A, 0x12], #
65285: [0x23, 0x13, 0x08, 0x64, 0x62], #
65286: [0x36, 0x49, 0x56, 0x20, 0x50], #
65288: [0x00, 0x1C, 0x22, 0x41, 0x00], #
65289: [0x00, 0x41, 0x22, 0x1C, 0x00], #
65290: [0x2A, 0x1C, 0x3E, 0x1C, 0x2A], #
65291: [0x08, 0x08, 0x3E, 0x08, 0x08], #
65292: [0x00, 0x10, 0x30, 0x00, 0x00], #
65294: [0x00, 0x60, 0x60, 0x00, 0x00], #
65295: [0x20, 0x10, 0x08, 0x04, 0x02], #
65296: [0x3E, 0x51, 0x49, 0x45, 0x3E], #
65297: [0x42, 0x42, 0x7F, 0x40, 0x40], #
65298: [0x42, 0x61, 0x51, 0x49, 0x46], #
65299: [0x22, 0x41, 0x49, 0x49, 0x36], #
65300: [0x38, 0x24, 0x22, 0x7F, 0x20], #
65301: [0x2F, 0x45, 0x45, 0x45, 0x39], #
65302: [0x3C, 0x4A, 0x49, 0x49, 0x30], #
65303: [0x03, 0x01, 0x79, 0x05, 0x03], #
65304: [0x36, 0x49, 0x49, 0x49, 0x36], #
65305: [0x06, 0x49, 0x49, 0x49, 0x3E], #
65306: [0x00, 0x00, 0x12, 0x00, 0x00], #
65307: [0x00, 0x40, 0x32, 0x00, 0x00], #
65308: [0x08, 0x14, 0x22, 0x41, 0x00], #
65309: [0x14, 0x14, 0x14, 0x14, 0x14], #
65310: [0x00, 0x41, 0x22, 0x14, 0x08], #
65311: [0x02, 0x01, 0x51, 0x09, 0x06], #
65312: [0x1C, 0x22, 0x49, 0x55, 0x4E], #
65313: [0x7C, 0x12, 0x11, 0x12, 0x7C], #
65314: [0x7F, 0x49, 0x49, 0x49, 0x36], #
65315: [0x3E, 0x41, 0x41, 0x41, 0x22], #
65316: [0x7F, 0x41, 0x41, 0x22, 0x1C], #
65317: [0x7F, 0x49, 0x49, 0x49, 0x41], #
65318: [0x7F, 0x09, 0x09, 0x09, 0x01], #
65319: [0x3E, 0x41, 0x49, 0x49, 0x79], #
65320: [0x7F, 0x08, 0x08, 0x08, 0x7F], #
65321: [0x00, 0x41, 0x7F, 0x41, 0x00], #
65322: [0x20, 0x40, 0x41, 0x3F, 0x01], #
65323: [0x7F, 0x08, 0x14, 0x22, 0x41], #
65324: [0x7F, 0x40, 0x40, 0x40, 0x40], #
65325: [0x7F, 0x02, 0x04, 0x02, 0x7F], #
65326: [0x7F, 0x02, 0x04, 0x08, 0x7F], #
65327: [0x3E, 0x41, 0x41, 0x41, 0x3E], #
65328: [0x7F, 0x09, 0x09, 0x09, 0x06], #
65329: [0x3E, 0x41, 0x51, 0x21, 0x5E], #
65330: [0x7F, 0x09, 0x19, 0x29, 0x46], #
65331: [0x26, 0x49, 0x49, 0x49, 0x32], #
65332: [0x01, 0x01, 0x7F, 0x01, 0x01], #
65333: [0x3F, 0x40, 0x40, 0x40, 0x3F], #
65334: [0x07, 0x18, 0x60, 0x18, 0x07], #
65335: [0x7F, 0x20, 0x10, 0x20, 0x7F], #
65336: [0x63, 0x14, 0x08, 0x14, 0x63], #
65337: [0x03, 0x04, 0x78, 0x04, 0x03], #
65338: [0x61, 0x51, 0x49, 0x45, 0x43], #
65339: [0x00, 0x7F, 0x41, 0x41, 0x00], #
65340: [0x02, 0x04, 0x08, 0x10, 0x20], #
65341: [0x00, 0x41, 0x41, 0x7F, 0x00], #
65342: [0x04, 0x02, 0x01, 0x02, 0x04], #
65343: [0x40, 0x40, 0x40, 0x40, 0x40], # _
65344: [0x00, 0x01, 0x02, 0x00, 0x00], #
65345: [0x24, 0x54, 0x54, 0x54, 0x78], #
65346: [0x7F, 0x44, 0x44, 0x44, 0x38], #
65347: [0x38, 0x44, 0x44, 0x44, 0x44], #
65348: [0x38, 0x44, 0x44, 0x44, 0x7F], #
65349: [0x38, 0x54, 0x54, 0x54, 0x18], #
65350: [0x08, 0x08, 0x7E, 0x09, 0x09], #
65351: [0x0C, 0x52, 0x52, 0x52, 0x3E], #
65352: [0x7F, 0x08, 0x04, 0x04, 0x78], #
65353: [0x00, 0x44, 0x7D, 0x40, 0x00], #
65354: [0x20, 0x40, 0x40, 0x44, 0x3D], #
65355: [0x7F, 0x20, 0x10, 0x28, 0x44], #
65356: [0x00, 0x41, 0x7F, 0x40, 0x00], #
65357: [0x7C, 0x04, 0x7C, 0x04, 0x78], #
65358: [0x7C, 0x04, 0x04, 0x04, 0x78], #
65359: [0x38, 0x44, 0x44, 0x44, 0x38], #
65360: [0x7E, 0x12, 0x12, 0x12, 0x0C], #
65361: [0x0C, 0x12, 0x12, 0x12, 0x7E], #
65362: [0x7C, 0x08, 0x04, 0x04, 0x08], #
65363: [0x48, 0x54, 0x54, 0x54, 0x24], #
65364: [0x04, 0x04, 0x3F, 0x44, 0x44], #
65365: [0x3C, 0x40, 0x40, 0x40, 0x7C], #
65366: [0x1C, 0x20, 0x40, 0x20, 0x1C], #
65367: [0x3C, 0x40, 0x38, 0x40, 0x3C], #
65368: [0x44, 0x28, 0x10, 0x28, 0x44], #
65369: [0x0E, 0x50, 0x50, 0x50, 0x3E], #
65370: [0x44, 0x64, 0x54, 0x4C, 0x44], #
65371: [0x00, 0x08, 0x36, 0x41, 0x41], #
65372: [0x00, 0x00, 0x77, 0x00, 0x00], #
65373: [0x41, 0x41, 0x36, 0x08, 0x00], #
65374: [0x08, 0x04, 0x08, 0x10, 0x08], #
65383: [0x44, 0x44, 0x3C, 0x14, 0x0C], # ァ
65384: [0x42, 0x42, 0x3A, 0x12, 0x0E], # ィ
65385: [0x20, 0x10, 0x78, 0x04, 0x00], # ゥ
65386: [0x10, 0x08, 0x04, 0x7E, 0x01], # ェ
65387: [0x18, 0x08, 0x4C, 0x48, 0x38], # ォ
65388: [0x0E, 0x42, 0x43, 0x22, 0x1E], # ャ
65389: [0x48, 0x48, 0x78, 0x48, 0x48], # ュ
65390: [0x42, 0x42, 0x7E, 0x42, 0x42], # ョ
65391: [0x48, 0x38, 0x08, 0x7C, 0x08], # ッ
65392: [0x22, 0x12, 0x0A, 0x7F, 0x02], # ー
65393: [0x42, 0x3F, 0x02, 0x02, 0x7E], # ア
65394: [0x0A, 0x0A, 0x7F, 0x0A, 0x0A], # イ
65395: [0x08, 0x06, 0x42, 0x22, 0x1E], # ウ
65396: [0x0F, 0x42, 0x42, 0x3E, 0x02], # エ
65397: [0x42, 0x42, 0x42, 0x42, 0x7E], # オ
65398: [0x02, 0x4F, 0x42, 0x3F, 0x02], # カ
65399: [0x4A, 0x4A, 0x40, 0x20, 0x1C], # キ
65400: [0x42, 0x22, 0x12, 0x2A, 0x46], # ク
65401: [0x02, 0x3F, 0x42, 0x42, 0x4E], # ケ
65402: [0x06, 0x48, 0x40, 0x30, 0x0E], # コ
65403: [0x08, 0x4E, 0x52, 0x32, 0x0E], # サ
65404: [0x08, 0x4A, 0x4A, 0x3F, 0x09], # シ
65405: [0x18, 0x40, 0x58, 0x40, 0x30], # ス
65406: [0x0E, 0x40, 0x4E, 0x20, 0x1E], # セ
65407: [0x04, 0x45, 0x45, 0x3D, 0x04], # ソ
65408: [0x00, 0x7F, 0x08, 0x10, 0x10], # タ
65409: [0x44, 0x44, 0x44, 0x3F, 0x04], # チ
65410: [0x40, 0x42, 0x42, 0x42, 0x40], # ツ
65411: [0x42, 0x4A, 0x2A, 0x12, 0x2E], # テ
65412: [0x22, 0x12, 0x73, 0x0A, 0x16], # ト
65413: [0x40, 0x40, 0x20, 0x10, 0x0E], # ナ
65414: [0x70, 0x0E, 0x00, 0x07, 0x78], # ニ
65415: [0x3F, 0x44, 0x44, 0x44, 0x44], # ヌ
65416: [0x02, 0x42, 0x42, 0x22, 0x1E], # ネ
65417: [0x08, 0x04, 0x02, 0x0C, 0x30], # ノ
65418: [0x32, 0x02, 0x7F, 0x02, 0x32], # ハ
65419: [0x02, 0x12, 0x22, 0x52, 0x0E], # ヒ
65420: [0x20, 0x2A, 0x2A, 0x2A, 0x40], # フ
65421: [0x30, 0x2C, 0x22, 0x28, 0x70], # ヘ
65422: [0x40, 0x44, 0x28, 0x10, 0x2E], # ホ
65423: [0x0A, 0x0A, 0x3E, 0x4A, 0x4A], # マ
65424: [0x08, 0x7C, 0x08, 0x28, 0x18], # ミ
65425: [0x04, 0x7F, 0x04, 0x14, 0x0C], # ム
65426: [0x48, 0x48, 0x48, 0x78, 0x40], # メ
65427: [0x42, 0x42, 0x42, 0x7E, 0x40], # モ
65428: [0x54, 0x54, 0x54, 0x7C, 0x00], # ヤ
65429: [0x4A, 0x4A, 0x4A, 0x4A, 0x7E], # ユ
65430: [0x04, 0x45, 0x45, 0x25, 0x1C], # ヨ
65431: [0x0E, 0x40, 0x40, 0x20, 0x1E], # ラ
65432: [0x7E, 0x00, 0x7E, 0x40, 0x38], # リ
65433: [0x7E, 0x40, 0x40, 0x20, 0x10], # ル
65434: [0x7E, 0x42, 0x42, 0x42, 0x7E], # レ
65435: [0x0E, 0x42, 0x42, 0x22, 0x1E], # ロ
65436: [0x0A, 0x4A, 0x4A, 0x2A, 0x1E], # ワ
65437: [0x42, 0x42, 0x40, 0x20, 0x1C], # ン
65438: [0x02, 0x04, 0x01, 0x02, 0x00], # ゙
65439: [0x07, 0x05, 0x07, 0x00, 0x00], # ゚
}

View File

@@ -0,0 +1,3 @@
[build-system]
requires = ["setuptools>=40.8.0", "wheel"]
build-backend = "setuptools.build_meta"

49
vendor/ltp305-python/library/setup.cfg vendored Normal file
View File

@@ -0,0 +1,49 @@
# -*- coding: utf-8 -*-
[metadata]
name = ltp305
version = 0.0.1
author = Philip Howard
author_email = phil@pimoroni.com
description = Python library for dual LTP305 LED matrix breakout
long_description = file: README.md
long_description_content_type = text/markdown
keywords = Raspberry Pi
url = https://www.pimoroni.com
project_urls =
GitHub=https://www.github.com/pimoroni/ltp305-python
license = MIT
# This includes the license file(s) in the wheel.
# https://wheel.readthedocs.io/en/stable/user_guide.html#including-license-files-in-the-generated-wheel-file
license_files = LICENSE.txt
classifiers =
Development Status :: 4 - Beta
Operating System :: POSIX :: Linux
License :: OSI Approved :: MIT License
Intended Audience :: Developers
Programming Language :: Python :: 2.7
Programming Language :: Python :: 3
Topic :: Software Development
Topic :: Software Development :: Libraries
Topic :: System :: Hardware
[options]
python_requires = >= 2.7
packages = ltp305
install_requires = smbus2
[flake8]
exclude =
.tox,
.eggs,
.git,
__pycache__,
build,
dist
ignore =
E501
[pimoroni]
py2deps =
py3deps =
configtxt =
commands =

33
vendor/ltp305-python/library/setup.py vendored Executable file
View File

@@ -0,0 +1,33 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Copyright (c) 2016 Pimoroni
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""
from setuptools import setup, __version__
from pkg_resources import parse_version
minimum_version = parse_version('30.4.0')
if parse_version(__version__) < minimum_version:
raise RuntimeError("Package setuptools must be at least version {}".format(minimum_version))
setup()

View File

@@ -0,0 +1,22 @@
import sys
import mock
import pytest
@pytest.fixture(scope='function', autouse=True)
def cleanup():
"""Force module reimport between tests."""
yield None
try:
del sys.modules['ltp305']
except KeyError:
pass
@pytest.fixture(scope='function', autouse=False)
def smbus():
"""Mock smbus module."""
smbus = mock.MagicMock()
sys.modules['smbus'] = smbus
yield smbus
del sys.modules['smbus']

View File

@@ -0,0 +1,51 @@
import mock
def test_set_pixel(smbus):
from ltp305 import LTP305, CMD_MATRIX_L, CMD_MATRIX_R
display = LTP305()
display.set_pixel(0, 0, 1)
display.set_pixel(5, 0, 1)
display.show()
smbus.SMBus(1).write_i2c_block_data.assert_has_calls((
mock.call(display.address, CMD_MATRIX_L, [1, 0, 0, 0, 0, 0, 0, 0]),
mock.call(display.address, CMD_MATRIX_R, [1, 0, 0, 0, 0, 0, 0, 0])
))
smbus.reset_mock()
display.set_pixel(0, 0, 0)
display.set_pixel(5, 0, 0)
display.show()
smbus.SMBus(1).write_i2c_block_data.assert_has_calls((
mock.call(display.address, CMD_MATRIX_L, [0, 0, 0, 0, 0, 0, 0, 0]),
mock.call(display.address, CMD_MATRIX_R, [0, 0, 0, 0, 0, 0, 0, 0])
))
def test_set_decimal(smbus):
from ltp305 import LTP305, CMD_MATRIX_L, CMD_MATRIX_R
display = LTP305()
display.set_decimal(left=True, right=True)
display.show()
smbus.SMBus(1).write_i2c_block_data.assert_has_calls((
mock.call(display.address, CMD_MATRIX_L, [0, 0, 0, 0, 0, 0, 0, 0b01000000]),
mock.call(display.address, CMD_MATRIX_R, [0, 0, 0, 0, 0, 0, 0b10000000, 0])
))
smbus.reset_mock()
display.set_decimal(left=False, right=False)
display.show()
smbus.SMBus(1).write_i2c_block_data.assert_has_calls((
mock.call(display.address, CMD_MATRIX_L, [0, 0, 0, 0, 0, 0, 0, 0]),
mock.call(display.address, CMD_MATRIX_R, [0, 0, 0, 0, 0, 0, 0, 0])
))
def test_set_character(smbus):
from ltp305 import LTP305, CMD_MATRIX_L, CMD_MATRIX_R
display = LTP305()
display.set_character(0, "A")
display.set_character(5, "B")
display.show()
smbus.SMBus(1).write_i2c_block_data.assert_has_calls((
mock.call(display.address, CMD_MATRIX_L, [126, 17, 17, 17, 126, 0, 0, 0]),
mock.call(display.address, CMD_MATRIX_R, [15, 17, 17, 15, 17, 17, 15, 0])
))

View File

@@ -0,0 +1,5 @@
def test_setup(smbus):
import ltp305
display = ltp305.LTP305()
smbus.SMBus.assert_called_with(1)
del display

25
vendor/ltp305-python/library/tox.ini vendored Normal file
View File

@@ -0,0 +1,25 @@
[tox]
envlist = py{27,35,37,39},qa
skip_missing_interpreters = True
[testenv]
commands =
python setup.py install
coverage run -m py.test -v -r wsx
coverage report -m
deps =
mock
pytest>=3.1
pytest-cov
[testenv:qa]
commands =
check-manifest --ignore tox.ini,tests/*,.coveragerc
python setup.py sdist bdist_wheel
twine check dist/*
flake8 --ignore E501
deps =
check-manifest
flake8
twine

25
vendor/ltp305-python/uninstall.sh vendored Executable file
View File

@@ -0,0 +1,25 @@
#!/bin/bash
LIBRARY_VERSION=`cat library/setup.cfg | grep version | awk -F" = " '{print $2}'`
LIBRARY_NAME=`cat library/setup.cfg | grep name | awk -F" = " '{print $2}'`
printf "$LIBRARY_NAME $LIBRARY_VERSION Python Library: Uninstaller\n\n"
if [ $(id -u) -ne 0 ]; then
printf "Script must be run as root. Try 'sudo ./uninstall.sh'\n"
exit 1
fi
cd library
printf "Unnstalling for Python 2..\n"
pip uninstall $LIBRARY_NAME
if [ -f "/usr/bin/pip3" ]; then
printf "Uninstalling for Python 3..\n"
pip3 uninstall $LIBRARY_NAME
fi
cd ..
printf "Done!\n"