Initial commit.

This commit is contained in:
Tony DiCola 2014-07-03 15:06:39 -07:00
parent 6510897c56
commit 48e025331f
16 changed files with 1249 additions and 1 deletions

4
.gitignore vendored Normal file
View file

@ -0,0 +1,4 @@
build
*.egg-info
*.pyc
setuptools-*

View file

@ -0,0 +1,213 @@
# Copyright (c) 2014 Adafruit Industries
# Author: Tony DiCola
#
# 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.
import HT16K33
# Digit value to bitmask mapping:
DIGIT_VALUES = {
' ': 0b0000000000000000,
'!': 0b0000000000000110,
'"': 0b0000001000100000,
'#': 0b0001001011001110,
'$': 0b0001001011101101,
'%': 0b0000110000100100,
'&': 0b0010001101011101,
'\'': 0b0000010000000000,
'(': 0b0010010000000000,
')': 0b0000100100000000,
'*': 0b0011111111000000,
'+': 0b0001001011000000,
',': 0b0000100000000000,
'-': 0b0000000011000000,
'.': 0b0000000000000000,
'/': 0b0000110000000000,
'0': 0b0000110000111111,
'1': 0b0000000000000110,
'2': 0b0000000011011011,
'3': 0b0000000010001111,
'4': 0b0000000011100110,
'5': 0b0010000001101001,
'6': 0b0000000011111101,
'7': 0b0000000000000111,
'8': 0b0000000011111111,
'9': 0b0000000011101111,
':': 0b0001001000000000,
';': 0b0000101000000000,
'<': 0b0010010000000000,
'=': 0b0000000011001000,
'>': 0b0000100100000000,
'?': 0b0001000010000011,
'@': 0b0000001010111011,
'A': 0b0000000011110111,
'B': 0b0001001010001111,
'C': 0b0000000000111001,
'D': 0b0001001000001111,
'E': 0b0000000011111001,
'F': 0b0000000001110001,
'G': 0b0000000010111101,
'H': 0b0000000011110110,
'I': 0b0001001000000000,
'J': 0b0000000000011110,
'K': 0b0010010001110000,
'L': 0b0000000000111000,
'M': 0b0000010100110110,
'N': 0b0010000100110110,
'O': 0b0000000000111111,
'P': 0b0000000011110011,
'Q': 0b0010000000111111,
'R': 0b0010000011110011,
'S': 0b0000000011101101,
'T': 0b0001001000000001,
'U': 0b0000000000111110,
'V': 0b0000110000110000,
'W': 0b0010100000110110,
'X': 0b0010110100000000,
'Y': 0b0001010100000000,
'Z': 0b0000110000001001,
'[': 0b0000000000111001,
'\\': 0b0010000100000000,
']': 0b0000000000001111,
'^': 0b0000110000000011,
'_': 0b0000000000001000,
'`': 0b0000000100000000,
'a': 0b0001000001011000,
'b': 0b0010000001111000,
'c': 0b0000000011011000,
'd': 0b0000100010001110,
'e': 0b0000100001011000,
'f': 0b0000000001110001,
'g': 0b0000010010001110,
'h': 0b0001000001110000,
'i': 0b0001000000000000,
'j': 0b0000000000001110,
'k': 0b0011011000000000,
'l': 0b0000000000110000,
'm': 0b0001000011010100,
'n': 0b0001000001010000,
'o': 0b0000000011011100,
'p': 0b0000000101110000,
'q': 0b0000010010000110,
'r': 0b0000000001010000,
's': 0b0010000010001000,
't': 0b0000000001111000,
'u': 0b0000000000011100,
'v': 0b0010000000000100,
'w': 0b0010100000010100,
'x': 0b0010100011000000,
'y': 0b0010000000001100,
'z': 0b0000100001001000,
'{': 0b0000100101001001,
'|': 0b0001001000000000,
'}': 0b0010010010001001,
'~': 0b0000010100100000
}
class AlphaNum4(HT16K33.HT16K33):
"""Alphanumeric 14 segment LED backpack display."""
def __init__(self, **kwargs):
"""Initialize display. All arguments will be passed to the HT16K33 class
initializer, including optional I2C address and bus number parameters.
"""
super(AlphaNum4, self).__init__(**kwargs)
def set_digit_raw(self, pos, bitmask):
"""Set digit at position to raw bitmask value. Position should be a value
of 0 to 3 with 0 being the left most digit on the display."""
if pos < 0 or pos > 3:
# Ignore out of bounds digits.
return
# Set the digit bitmask value at the appropriate position.
# Also set bit 7 (decimal point) if decimal is True.
self.buffer[pos*2] = bitmask & 0xFF
self.buffer[pos*2+1] = (bitmask >> 8) & 0xFF
def set_decimal(self, pos, decimal):
"""Turn decimal point on or off at provided position. Position should be
a value 0 to 3 with 0 being the left most digit on the display. Decimal
should be True to turn on the decimal point and False to turn it off.
"""
if pos < 0 or pos > 3:
# Ignore out of bounds digits.
return
# Set bit 14 (decimal point) based on provided value.
if decimal:
self.buffer[pos*2+1] |= (1 << 6)
else:
self.buffer[pos*2+1] &= ~(1 << 6)
def set_digit(self, pos, digit, decimal=False):
"""Set digit at position to provided value. Position should be a value
of 0 to 3 with 0 being the left most digit on the display. Digit should
be any ASCII value 32-127 (printable ASCII).
"""
self.set_digit_raw(pos, DIGIT_VALUES.get(str(digit), 0x00))
if decimal:
self.set_decimal(pos, True)
def print_str(self, value, justify_right=True):
"""Print a 4 character long string of values to the display. Characters
in the string should be any ASCII value 32 to 127 (printable ASCII).
"""
# Calculcate starting position of digits based on justification.
pos = (4-len(value)) if justify_right else 0
# Go through each character and print it on the display.
for i, ch in enumerate(value):
self.set_digit(i, ch)
def print_number_str(self, value, justify_right=True):
"""Print a 4 character long string of numeric values to the display. This
function is similar to print_str but will interpret periods not as
characters but as decimal points associated with the previous character.
"""
# Calculate length of value without decimals.
length = len(value.translate(None, '.'))
# Error if value without decimals is longer than 4 characters.
if length > 4:
self.print_str('----')
return
# Calculcate starting position of digits based on justification.
pos = (4-length) if justify_right else 0
# Go through each character and print it on the display.
for i, ch in enumerate(value):
if ch == '.':
# Print decimal points on the previous digit.
self.set_decimal(pos-1, True)
else:
self.set_digit(pos, ch)
pos += 1
def print_float(self, value, decimal_digits=2, justify_right=True):
"""Print a numeric value to the display. If value is negative
it will be printed with a leading minus sign. Decimal digits is the
desired number of digits after the decimal point.
"""
format_string = '{{0:0.{0}F}}'.format(decimal_digits)
self.print_number_str(format_string.format(value), justify_right)
def print_hex(self, value, justify_right=True):
"""Print a numeric value in hexadecimal. Value should be from 0 to FFFF.
"""
if value < 0 or value > 0xFFFF:
# Ignore out of range values.
return
self.print_str('{0:X}'.format(value), justify_right)

View file

@ -0,0 +1,57 @@
# Copyright (c) 2014 Adafruit Industries
# Author: Tony DiCola
#
# 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.
import HT16K33
# Color values as convenient globals.
# This is a bitmask value where the first bit is green, and the second bit is
# red. If both bits are set the color is yellow (red + green light).
OFF = 0
GREEN = 1
RED = 2
YELLOW = 3
class BicolorBargraph24(HT16K33.HT16K33):
"""Bi-color 24 segment bar graph LED backpack display."""
def __init__(self, **kwargs):
"""Initialize display. All arguments will be passed to the HT16K33 class
initializer, including optional I2C address and bus number parameters.
"""
super(BicolorBargraph24, self).__init__(**kwargs)
def set_bar(self, bar, value):
"""Set bar to desired color. Bar should be a value of 0 to 23, and value
should be OFF, GREEN, RED, or YELLOW.
"""
if bar < 0 or bar > 23:
# Ignore out of bounds bars.
return
# Compute cathode and anode value.
c = (bar if bar < 12 else bar - 12) / 4
a = bar % 4
if bar >= 12:
a += 4
# Set green LED based on 1st bit in value.
self.set_led(c*16+a+8, 1 if value & GREEN > 0 else 0)
# Set red LED based on 2nd bit in value.
self.set_led(c*16+a, 1 if value & RED > 0 else 0)

View file

@ -0,0 +1,52 @@
# Copyright (c) 2014 Adafruit Industries
# Author: Tony DiCola
#
# 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.
import HT16K33
# Color values as convenient globals.
# This is a bitmask value where the first bit is green, and the second bit is
# red. If both bits are set the color is yellow (red + green light).
OFF = 0
GREEN = 1
RED = 2
YELLOW = 3
class BicolorMatrix8x8(HT16K33.HT16K33):
"""Bi-color 8x8 matrix LED backpack display."""
def __init__(self, **kwargs):
"""Initialize display. All arguments will be passed to the HT16K33 class
initializer, including optional I2C address and bus number parameters.
"""
super(BicolorMatrix8x8, self).__init__(**kwargs)
def set_pixel(self, x, y, value):
"""Set pixel at position x, y to the given value. X and Y should be values
of 0 to 8. Value should be OFF, GREEN, RED, or YELLOW.
"""
if x < 0 or x > 7 or y < 0 or y > 7:
# Ignore out of bounds pixels.
return
# Set green LED based on 1st bit in value.
self.set_led(y*16+x, 1 if value & GREEN > 0 else 0)
# Set red LED based on 2nd bit in value.
self.set_led(y*16+x+8, 1 if value & RED > 0 else 0)

View file

@ -0,0 +1,98 @@
# Copyright (c) 2014 Adafruit Industries
# Author: Tony DiCola
#
# 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.
import Adafruit_GPIO.I2C as I2C
# Constants
DEFAULT_ADDRESS = 0x70
HT16K33_BLINK_CMD = 0x80
HT16K33_BLINK_DISPLAYON = 0x01
HT16K33_BLINK_OFF = 0x00
HT16K33_BLINK_2HZ = 0x02
HT16K33_BLINK_1HZ = 0x04
HT16K33_BLINK_HALFHZ = 0x06
HT16K33_SYSTEM_SETUP = 0x20
HT16K33_OSCILLATOR = 0x01
HT16K33_CMD_BRIGHTNESS = 0xE0
class HT16K33(object):
"""Driver for interfacing with a Holtek HT16K33 16x8 LED driver."""
def __init__(self, address=DEFAULT_ADDRESS, busnum=I2C.get_default_bus()):
"""Create an HT16K33 driver for devie on the specified I2C address
(defaults to 0x70) and I2C bus (defaults to platform specific bus).
"""
self._i2c = I2C.Device(address, busnum)
self.buffer = bytearray([0]*16)
def begin(self):
"""Initialize driver with LEDs enabled and all turned off."""
# Turn on the oscillator.
self._i2c.writeList(HT16K33_SYSTEM_SETUP | HT16K33_OSCILLATOR, [])
# Turn display on with no blinking.
self.set_blink(HT16K33_BLINK_OFF)
# Set display to full brightness.
self.set_brightness(15)
def set_blink(self, frequency):
"""Blink display at specified frequency. Note that frequency must be a
value allowed by the HT16K33, specifically one of: HT16K33_BLINK_OFF,
HT16K33_BLINK_2HZ, HT16K33_BLINK_1HZ, or HT16K33_BLINK_HALFHZ.
"""
if frequency not in [HT16K33_BLINK_OFF, HT16K33_BLINK_2HZ,
HT16K33_BLINK_1HZ, HT16K33_BLINK_HALFHZ]:
raise ValueError('Frequency must be one of HT16K33_BLINK_OFF, HT16K33_BLINK_2HZ, HT16K33_BLINK_1HZ, or HT16K33_BLINK_HALFHZ.')
self._i2c.writeList(HT16K33_BLINK_CMD | HT16K33_BLINK_DISPLAYON | frequency, [])
def set_brightness(self, brightness):
"""Set brightness of entire display to specified value (16 levels, from
0 to 15).
"""
if brightness < 0 or brightness > 15:
raise ValueError('Brightness must be a value of 0 to 15.')
self._i2c.writeList(HT16K33_CMD_BRIGHTNESS | brightness, [])
def set_led(self, led, value):
"""Sets specified LED (value of 0 to 127) to the specified value, 0/False
for off and 1 (or any True/non-zero value) for on.
"""
if led < 0 or led > 127:
raise ValueError('LED must be value of 0 to 127.')
# Calculate position in byte buffer and bit offset of desired LED.
pos = led / 8
offset = led % 8
if not value:
# Turn off the specified LED (set bit to zero).
self.buffer[pos] &= ~(1 << offset)
else:
# Turn on the speciried LED (set bit to one).
self.buffer[pos] |= (1 << offset)
def write_display(self):
"""Write display buffer to display hardware."""
for i, value in enumerate(self.buffer):
self._i2c.write8(i, value)
def clear(self):
"""Clear contents of display buffer."""
for i, value in enumerate(self.buffer):
self.buffer[i] = 0

View file

@ -0,0 +1,40 @@
# Copyright (c) 2014 Adafruit Industries
# Author: Tony DiCola
#
# 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.
import HT16K33
class Matrix8x8(HT16K33.HT16K33):
"""Single color 8x8 matrix LED backpack display."""
def __init__(self, **kwargs):
"""Initialize display. All arguments will be passed to the HT16K33 class
initializer, including optional I2C address and bus number parameters.
"""
super(Matrix8x8, self).__init__(**kwargs)
def set_pixel(self, x, y, value):
"""Set pixel at position x, y to the given value. X and Y should be values
of 0 to 8. Value should be 0 for off and non-zero for on.
"""
if x < 0 or x > 7 or y < 0 or y > 7:
# Ignore out of bounds pixels.
return
self.set_led(y*16+((x+7)%8), value)

View file

@ -0,0 +1,136 @@
# Copyright (c) 2014 Adafruit Industries
# Author: Tony DiCola
#
# 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.
import HT16K33
# Digit value to bitmask mapping:
DIGIT_VALUES = {
' ': 0x00,
'-': 0x40,
'0': 0x3F,
'1': 0x06,
'2': 0x5B,
'3': 0x4F,
'4': 0x66,
'5': 0x6D,
'6': 0x7D,
'7': 0x07,
'8': 0x7F,
'9': 0x6F,
'A': 0x77,
'B': 0x7C,
'C': 0x39,
'D': 0x5E,
'E': 0x79,
'F': 0x71
}
class SevenSegment(HT16K33.HT16K33):
"""Seven segment LED backpack display."""
def __init__(self, **kwargs):
"""Initialize display. All arguments will be passed to the HT16K33 class
initializer, including optional I2C address and bus number parameters.
"""
super(SevenSegment, self).__init__(**kwargs)
def set_digit_raw(self, pos, bitmask):
"""Set digit at position to raw bitmask value. Position should be a value
of 0 to 3 with 0 being the left most digit on the display."""
if pos < 0 or pos > 3:
# Ignore out of bounds digits.
return
# Jump past the colon at position 2 by adding a conditional offset.
offset = 0 if pos < 2 else 1
# Set the digit bitmask value at the appropriate position.
self.buffer[(pos+offset)*2] = bitmask & 0xFF
def set_decimal(self, pos, decimal):
"""Turn decimal point on or off at provided position. Position should be
a value 0 to 3 with 0 being the left most digit on the display. Decimal
should be True to turn on the decimal point and False to turn it off.
"""
if pos < 0 or pos > 3:
# Ignore out of bounds digits.
return
# Jump past the colon at position 2 by adding a conditional offset.
offset = 0 if pos < 2 else 1
# Set bit 7 (decimal point) based on provided value.
if decimal:
self.buffer[(pos+offset)*2] |= (1 << 7)
else:
self.buffer[(pos+offset)*2] &= ~(1 << 7)
def set_digit(self, pos, digit, decimal=False):
"""Set digit at position to provided value. Position should be a value
of 0 to 3 with 0 being the left most digit on the display. Digit should
be a number 0-9, character A-F, space (all LEDs off), or dash (-).
"""
self.set_digit_raw(pos, DIGIT_VALUES.get(str(digit).upper(), 0x00))
if decimal:
self.set_decimal(pos, True)
def set_colon(self, show_colon):
"""Turn the colon on with show colon True, or off with show colon False."""
if show_colon:
self.buffer[2] = 0x02
else:
self.buffer[2] = 0x00
def print_number_str(self, value, justify_right=True):
"""Print a 4 character long string of numeric values to the display.
Characters in the string should be any supported character by set_digit,
or a decimal point. Decimal point characters will be associated with
the previous character.
"""
# Calculate length of value without decimals.
length = len(value.translate(None, '.'))
# Error if value without decimals is longer than 4 characters.
if length > 4:
self.print_number_str('----')
return
# Calculcate starting position of digits based on justification.
pos = (4-length) if justify_right else 0
# Go through each character and print it on the display.
for i, ch in enumerate(value):
if ch == '.':
# Print decimal points on the previous digit.
self.set_decimal(pos-1, True)
else:
self.set_digit(pos, ch)
pos += 1
def print_float(self, value, decimal_digits=2, justify_right=True):
"""Print a numeric value to the display. If value is negative
it will be printed with a leading minus sign. Decimal digits is the
desired number of digits after the decimal point.
"""
format_string = '{{0:0.{0}F}}'.format(decimal_digits)
self.print_number_str(format_string.format(value), justify_right)
def print_hex(self, value, justify_right=True):
"""Print a numeric value in hexadecimal. Value should be from 0 to FFFF.
"""
if value < 0 or value > 0xFFFF:
# Ignore out of range values.
return
self.print_number_str('{0:X}'.format(value), justify_right)

View file

View file

@ -1,4 +1,27 @@
Adafruit_Python_LED_Backpack
Adafruit Python LED Backpack
============================
Python library for controlling LED backpack displays such as 8x8 matrices, bar graphs, and 7/14-segment displays on a Raspberry Pi or BeagleBone Black.
Designed specifically to work with the Adafruit LED backpack displays ----> https://learn.adafruit.com/adafruit-led-backpack/overview
For all platforms (Raspberry Pi and Beaglebone Black) make sure your system is able to compile Python extensions. On Raspbian or Beaglebone Black's Debian/Ubuntu image you can ensure your system is ready by executing:
````
apt-get update
sudo apt-get install build-essential python-dev
````
Install the library by downloading with the download link on the right, unzipping the archive, and executing:
````
sudo python setup.py install
````
See example of usage in the examples folder.
Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit!
Written by Tony DiCola for Adafruit Industries.
MIT license, all text above must be included in any redistribution

View file

@ -0,0 +1,56 @@
# Copyright (c) 2014 Adafruit Industries
# Author: Tony DiCola
#
# 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.
import time
from Adafruit_LED_Backpack import AlphaNum4
# Create display instance on default I2C address (0x70) and bus number.
display = AlphaNum4.AlphaNum4()
# Alternatively, create a display with a specific I2C address and/or bus.
# display = AlphaNum4.AlphaNum4(address=0x74, bus=1)
# Initialize the display. Must be called once before using the display.
display.begin()
# Scroll a message across the display
message = 'This is an example of the 4 character alpha-numeric display. THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG? the quick brown fox jumps over the lazy dog!'
pos = 0
print 'Press Ctrl-C to quit.'
while True:
# Clear the display buffer.
display.clear()
# Print a 4 character string to the display buffer.
display.print_str(message[pos:pos+4])
# Write the display buffer to the hardware. This must be called to
# update the actual display LEDs.
display.write_display()
# Increment position. Wrap back to 0 when the end is reached.
pos += 1
if pos > len(message)-4:
pos = 0
# Delay for half a second.
time.sleep(0.5)
# Note that the alphanumeric display has the same number printing functions
# as the 7 segment display. See the sevensegment_test.py example for good
# examples of these functions.

View file

@ -0,0 +1,56 @@
# Copyright (c) 2014 Adafruit Industries
# Author: Tony DiCola
#
# 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.
import time
from Adafruit_LED_Backpack import BicolorBargraph24
# Create display instance on default I2C address (0x70) and bus number.
display = BicolorBargraph24.BicolorBargraph24()
# Alternatively, create a display with a specific I2C address and/or bus.
# display = BicolorBargraph24.BicolorBargraph24(address=0x74, bus=1)
# Initialize the display. Must be called once before using the display.
display.begin()
# Run through all bars and colors at different brightness levels.
print 'Press Ctrl-C to quit.'
brightness = 15
while True:
# Set display brightness (15 is max, 0 is min).
display.set_brightness(brightness)
for i in range(24):
# Clear the display buffer.
display.clear()
# Light up 3 bars, each a different color and position.
display.set_bar(i, BicolorBargraph24.RED)
display.set_bar(i+1, BicolorBargraph24.GREEN)
display.set_bar(i+2, BicolorBargraph24.YELLOW)
# Write the display buffer to the hardware. This must be called to
# update the actual display LEDs.
display.write_display()
# Delay for half a second.
time.sleep(0.5)
# Decrease brightness, wrapping back to 15 if necessary.
brightness -= 1
if brightness == 0:
brightness = 15

View file

@ -0,0 +1,51 @@
# Copyright (c) 2014 Adafruit Industries
# Author: Tony DiCola
#
# 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.
import time
from Adafruit_LED_Backpack import BicolorMatrix8x8
# Create display instance on default I2C address (0x70) and bus number.
display = BicolorMatrix8x8.BicolorMatrix8x8()
# Alternatively, create a display with a specific I2C address and/or bus.
# display = Matrix8x8.Matrix8x8(address=0x74, bus=1)
# Initialize the display. Must be called once before using the display.
display.begin()
# Run through each color and pixel.
print 'Press Ctrl-C to quit.'
while True:
# Iterate through all colors.
for c in [BicolorMatrix8x8.RED, BicolorMatrix8x8.GREEN, BicolorMatrix8x8.YELLOW]:
# Iterate through all positions x and y.
for x in range(8):
for y in range(8):
# Clear the display buffer.
display.clear()
# Set pixel at position i, j to appropriate color.
display.set_pixel(x, y, c)
# Write the display buffer to the hardware. This must be called to
# update the actual display LEDs.
display.write_display()
# Delay for a quarter second.
time.sleep(0.25)

View file

@ -0,0 +1,49 @@
# Copyright (c) 2014 Adafruit Industries
# Author: Tony DiCola
#
# 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.
import time
from Adafruit_LED_Backpack import Matrix8x8
# Create display instance on default I2C address (0x70) and bus number.
display = Matrix8x8.Matrix8x8(address=0x71)
# Alternatively, create a display with a specific I2C address and/or bus.
# display = Matrix8x8.Matrix8x8(address=0x74, bus=1)
# Initialize the display. Must be called once before using the display.
display.begin()
# Run through each pixel individually and turn it on.
print 'Press Ctrl-C to quit.'
while True:
for x in range(8):
for y in range(8):
# Clear the display buffer.
display.clear()
# Set pixel at position i, j to on. To turn off a pixel set
# the last parameter to 0.
display.set_pixel(x, y, 1)
# Write the display buffer to the hardware. This must be called to
# update the actual display LEDs.
display.write_display()
# Delay for half a second.
time.sleep(0.5)

View file

@ -0,0 +1,67 @@
# Copyright (c) 2014 Adafruit Industries
# Author: Tony DiCola
#
# 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.
import time
from Adafruit_LED_Backpack import SevenSegment
# Create display instance on default I2C address (0x70) and bus number.
display = SevenSegment.SevenSegment()
# Alternatively, create a display with a specific I2C address and/or bus.
# display = SevenSegment.SevenSegment(address=0x74, bus=1)
# Initialize the display. Must be called once before using the display.
display.begin()
# Run through different number printing examples.
print 'Press Ctrl-C to quit.'
numbers = [0.0, 1.0, -1.0, 0.55, -0.55, 10.23, -10.2, 100.5, -100.5]
while True:
# Print floating point values with default 2 digit precision.
for i in numbers:
# Clear the display buffer.
display.clear()
# Print a floating point number to the display.
display.print_float(i)
# Write the display buffer to the hardware. This must be called to
# update the actual display LEDs.
display.write_display()
# Delay for a second.
time.sleep(1.0)
# Print the same numbers with 1 digit precision.
for i in numbers:
display.clear()
display.print_float(i, decimal_digits=1)
display.write_display()
time.sleep(1.0)
# Print the same numbers with no decimal digits and left justified.
for i in numbers:
display.clear()
display.print_float(i, decimal_digits=0, justify_right=False)
display.write_display()
time.sleep(1.0)
# Run through some hex digits.
for i in range(0xFF):
display.clear()
display.print_hex(i)
display.write_display()
time.sleep(0.5)

332
ez_setup.py Normal file
View file

@ -0,0 +1,332 @@
#!/usr/bin/env python
"""Bootstrap setuptools installation
To use setuptools in your package's setup.py, include this
file in the same directory and add this to the top of your setup.py::
from ez_setup import use_setuptools
use_setuptools()
To require a specific version of setuptools, set a download
mirror, or use an alternate download directory, simply supply
the appropriate options to ``use_setuptools()``.
This file can also be run as a script to install or upgrade setuptools.
"""
import os
import shutil
import sys
import tempfile
import zipfile
import optparse
import subprocess
import platform
import textwrap
import contextlib
from distutils import log
try:
from site import USER_SITE
except ImportError:
USER_SITE = None
DEFAULT_VERSION = "3.5.1"
DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/"
def _python_cmd(*args):
"""
Return True if the command succeeded.
"""
args = (sys.executable,) + args
return subprocess.call(args) == 0
def _install(archive_filename, install_args=()):
with archive_context(archive_filename):
# installing
log.warn('Installing Setuptools')
if not _python_cmd('setup.py', 'install', *install_args):
log.warn('Something went wrong during the installation.')
log.warn('See the error message above.')
# exitcode will be 2
return 2
def _build_egg(egg, archive_filename, to_dir):
with archive_context(archive_filename):
# building an egg
log.warn('Building a Setuptools egg in %s', to_dir)
_python_cmd('setup.py', '-q', 'bdist_egg', '--dist-dir', to_dir)
# returning the result
log.warn(egg)
if not os.path.exists(egg):
raise IOError('Could not build the egg.')
def get_zip_class():
"""
Supplement ZipFile class to support context manager for Python 2.6
"""
class ContextualZipFile(zipfile.ZipFile):
def __enter__(self):
return self
def __exit__(self, type, value, traceback):
self.close
return zipfile.ZipFile if hasattr(zipfile.ZipFile, '__exit__') else \
ContextualZipFile
@contextlib.contextmanager
def archive_context(filename):
# extracting the archive
tmpdir = tempfile.mkdtemp()
log.warn('Extracting in %s', tmpdir)
old_wd = os.getcwd()
try:
os.chdir(tmpdir)
with get_zip_class()(filename) as archive:
archive.extractall()
# going in the directory
subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
os.chdir(subdir)
log.warn('Now working in %s', subdir)
yield
finally:
os.chdir(old_wd)
shutil.rmtree(tmpdir)
def _do_download(version, download_base, to_dir, download_delay):
egg = os.path.join(to_dir, 'setuptools-%s-py%d.%d.egg'
% (version, sys.version_info[0], sys.version_info[1]))
if not os.path.exists(egg):
archive = download_setuptools(version, download_base,
to_dir, download_delay)
_build_egg(egg, archive, to_dir)
sys.path.insert(0, egg)
# Remove previously-imported pkg_resources if present (see
# https://bitbucket.org/pypa/setuptools/pull-request/7/ for details).
if 'pkg_resources' in sys.modules:
del sys.modules['pkg_resources']
import setuptools
setuptools.bootstrap_install_from = egg
def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
to_dir=os.curdir, download_delay=15):
to_dir = os.path.abspath(to_dir)
rep_modules = 'pkg_resources', 'setuptools'
imported = set(sys.modules).intersection(rep_modules)
try:
import pkg_resources
except ImportError:
return _do_download(version, download_base, to_dir, download_delay)
try:
pkg_resources.require("setuptools>=" + version)
return
except pkg_resources.DistributionNotFound:
return _do_download(version, download_base, to_dir, download_delay)
except pkg_resources.VersionConflict as VC_err:
if imported:
msg = textwrap.dedent("""
The required version of setuptools (>={version}) is not available,
and can't be installed while this script is running. Please
install a more recent version first, using
'easy_install -U setuptools'.
(Currently using {VC_err.args[0]!r})
""").format(VC_err=VC_err, version=version)
sys.stderr.write(msg)
sys.exit(2)
# otherwise, reload ok
del pkg_resources, sys.modules['pkg_resources']
return _do_download(version, download_base, to_dir, download_delay)
def _clean_check(cmd, target):
"""
Run the command to download target. If the command fails, clean up before
re-raising the error.
"""
try:
subprocess.check_call(cmd)
except subprocess.CalledProcessError:
if os.access(target, os.F_OK):
os.unlink(target)
raise
def download_file_powershell(url, target):
"""
Download the file at url to target using Powershell (which will validate
trust). Raise an exception if the command cannot complete.
"""
target = os.path.abspath(target)
cmd = [
'powershell',
'-Command',
"(new-object System.Net.WebClient).DownloadFile(%(url)r, %(target)r)" % vars(),
]
_clean_check(cmd, target)
def has_powershell():
if platform.system() != 'Windows':
return False
cmd = ['powershell', '-Command', 'echo test']
devnull = open(os.path.devnull, 'wb')
try:
try:
subprocess.check_call(cmd, stdout=devnull, stderr=devnull)
except Exception:
return False
finally:
devnull.close()
return True
download_file_powershell.viable = has_powershell
def download_file_curl(url, target):
cmd = ['curl', url, '--silent', '--output', target]
_clean_check(cmd, target)
def has_curl():
cmd = ['curl', '--version']
devnull = open(os.path.devnull, 'wb')
try:
try:
subprocess.check_call(cmd, stdout=devnull, stderr=devnull)
except Exception:
return False
finally:
devnull.close()
return True
download_file_curl.viable = has_curl
def download_file_wget(url, target):
cmd = ['wget', url, '--quiet', '--output-document', target]
_clean_check(cmd, target)
def has_wget():
cmd = ['wget', '--version']
devnull = open(os.path.devnull, 'wb')
try:
try:
subprocess.check_call(cmd, stdout=devnull, stderr=devnull)
except Exception:
return False
finally:
devnull.close()
return True
download_file_wget.viable = has_wget
def download_file_insecure(url, target):
"""
Use Python to download the file, even though it cannot authenticate the
connection.
"""
try:
from urllib.request import urlopen
except ImportError:
from urllib2 import urlopen
src = dst = None
try:
src = urlopen(url)
# Read/write all in one block, so we don't create a corrupt file
# if the download is interrupted.
data = src.read()
dst = open(target, "wb")
dst.write(data)
finally:
if src:
src.close()
if dst:
dst.close()
download_file_insecure.viable = lambda: True
def get_best_downloader():
downloaders = [
download_file_powershell,
download_file_curl,
download_file_wget,
download_file_insecure,
]
for dl in downloaders:
if dl.viable():
return dl
def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
to_dir=os.curdir, delay=15, downloader_factory=get_best_downloader):
"""
Download setuptools from a specified location and return its filename
`version` should be a valid setuptools version number that is available
as an egg for download under the `download_base` URL (which should end
with a '/'). `to_dir` is the directory where the egg will be downloaded.
`delay` is the number of seconds to pause before an actual download
attempt.
``downloader_factory`` should be a function taking no arguments and
returning a function for downloading a URL to a target.
"""
# making sure we use the absolute path
to_dir = os.path.abspath(to_dir)
zip_name = "setuptools-%s.zip" % version
url = download_base + zip_name
saveto = os.path.join(to_dir, zip_name)
if not os.path.exists(saveto): # Avoid repeated downloads
log.warn("Downloading %s", url)
downloader = downloader_factory()
downloader(url, saveto)
return os.path.realpath(saveto)
def _build_install_args(options):
"""
Build the arguments to 'python setup.py install' on the setuptools package
"""
return ['--user'] if options.user_install else []
def _parse_args():
"""
Parse the command line for options
"""
parser = optparse.OptionParser()
parser.add_option(
'--user', dest='user_install', action='store_true', default=False,
help='install in user site package (requires Python 2.6 or later)')
parser.add_option(
'--download-base', dest='download_base', metavar="URL",
default=DEFAULT_URL,
help='alternative URL from where to download the setuptools package')
parser.add_option(
'--insecure', dest='downloader_factory', action='store_const',
const=lambda: download_file_insecure, default=get_best_downloader,
help='Use internal, non-validating downloader'
)
parser.add_option(
'--version', help="Specify which version to download",
default=DEFAULT_VERSION,
)
options, args = parser.parse_args()
# positional arguments are ignored
return options
def main():
"""Install or upgrade setuptools and EasyInstall"""
options = _parse_args()
archive = download_setuptools(
version=options.version,
download_base=options.download_base,
downloader_factory=options.downloader_factory,
)
return _install(archive, _build_install_args(options))
if __name__ == '__main__':
sys.exit(main())

14
setup.py Normal file
View file

@ -0,0 +1,14 @@
from ez_setup import use_setuptools
use_setuptools()
from setuptools import setup, find_packages
setup(name = 'Adafruit_LED_Backpack',
version = '1.0.0',
author = 'Tony DiCola',
author_email = 'tdicola@adafruit.com',
description = 'Library to control LED backpack displays such as 8x8 single and bi-color matrices, bargraphs, 7 segment, and 14 segment displays.',
license = 'MIT',
url = 'https://github.com/adafruit/Adafruit_Python_LED_Backpack/',
dependency_links = ['https://github.com/adafruit/Adafruit_Python_GPIO/tarball/master#egg=Adafruit-GPIO-0.3.0'],
install_requires = ['Adafruit-GPIO>=0.3.0'],
packages = find_packages())