Python 3 support tweaks, support for pillow library.

This commit is contained in:
Tony DiCola
2016-04-14 23:02:27 +00:00
parent 46228668bd
commit cf0b00d7c3
6 changed files with 334 additions and 323 deletions
+273 -272
View File
@@ -18,6 +18,7 @@
# 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 __future__ import division
import logging
import time
@@ -26,7 +27,7 @@ import Adafruit_GPIO.SPI as SPI
# Constants
SSD1306_I2C_ADDRESS = 0x3C # 011110+SA0+RW - 0x3C or 0x3D
SSD1306_I2C_ADDRESS = 0x3C # 011110+SA0+RW - 0x3C or 0x3D
SSD1306_SETCONTRAST = 0x81
SSD1306_DISPLAYALLON_RESUME = 0xA4
SSD1306_DISPLAYALLON = 0xA5
@@ -64,296 +65,296 @@ SSD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL = 0x2A
class SSD1306Base(object):
"""Base class for SSD1306-based OLED displays. Implementors should subclass
and provide an implementation for the _initialize function.
"""
"""Base class for SSD1306-based OLED displays. Implementors should subclass
and provide an implementation for the _initialize function.
"""
def __init__(self, width, height, rst, dc=None, sclk=None, din=None, cs=None,
gpio=None, spi=None, i2c_bus=None, i2c_address=SSD1306_I2C_ADDRESS,
i2c=None):
self._log = logging.getLogger('Adafruit_SSD1306.SSD1306Base')
self._spi = None
self._i2c = None
self.width = width
self.height = height
self._pages = height/8
self._buffer = [0]*(width*self._pages)
# Default to platform GPIO if not provided.
self._gpio = gpio
if self._gpio is None:
self._gpio = GPIO.get_platform_gpio()
# Setup reset pin.
self._rst = rst
self._gpio.setup(self._rst, GPIO.OUT)
# Handle hardware SPI
if spi is not None:
self._log.debug('Using hardware SPI')
self._spi = spi
self._spi.set_clock_hz(8000000)
# Handle software SPI
elif sclk is not None and din is not None and cs is not None:
self._log.debug('Using software SPI')
self._spi = SPI.BitBang(self._gpio, sclk, din, None, cs)
# Handle hardware I2C
elif i2c is not None:
self._log.debug('Using hardware I2C with custom I2C provider.')
self._i2c = i2c.get_i2c_device(i2c_address)
else:
self._log.debug('Using hardware I2C with platform I2C provider.')
import Adafruit_GPIO.I2C as I2C
if i2c_bus is None:
self._i2c = I2C.get_i2c_device(i2c_address)
else:
self._i2c = I2C.get_i2c_device(i2c_address, busnum=i2c_bus)
# Initialize DC pin if using SPI.
if self._spi is not None:
if dc is None:
raise ValueError('DC pin must be provided when using SPI.')
self._dc = dc
self._gpio.setup(self._dc, GPIO.OUT)
def _initialize(self):
raise NotImplementedError
def __init__(self, width, height, rst, dc=None, sclk=None, din=None, cs=None,
gpio=None, spi=None, i2c_bus=None, i2c_address=SSD1306_I2C_ADDRESS,
i2c=None):
self._log = logging.getLogger('Adafruit_SSD1306.SSD1306Base')
self._spi = None
self._i2c = None
self.width = width
self.height = height
self._pages = height//8
self._buffer = [0]*(width*self._pages)
# Default to platform GPIO if not provided.
self._gpio = gpio
if self._gpio is None:
self._gpio = GPIO.get_platform_gpio()
# Setup reset pin.
self._rst = rst
self._gpio.setup(self._rst, GPIO.OUT)
# Handle hardware SPI
if spi is not None:
self._log.debug('Using hardware SPI')
self._spi = spi
self._spi.set_clock_hz(8000000)
# Handle software SPI
elif sclk is not None and din is not None and cs is not None:
self._log.debug('Using software SPI')
self._spi = SPI.BitBang(self._gpio, sclk, din, None, cs)
# Handle hardware I2C
elif i2c is not None:
self._log.debug('Using hardware I2C with custom I2C provider.')
self._i2c = i2c.get_i2c_device(i2c_address)
else:
self._log.debug('Using hardware I2C with platform I2C provider.')
import Adafruit_GPIO.I2C as I2C
if i2c_bus is None:
self._i2c = I2C.get_i2c_device(i2c_address)
else:
self._i2c = I2C.get_i2c_device(i2c_address, busnum=i2c_bus)
# Initialize DC pin if using SPI.
if self._spi is not None:
if dc is None:
raise ValueError('DC pin must be provided when using SPI.')
self._dc = dc
self._gpio.setup(self._dc, GPIO.OUT)
def command(self, c):
"""Send command byte to display."""
if self._spi is not None:
# SPI write.
self._gpio.set_low(self._dc)
self._spi.write([c])
else:
# I2C write.
control = 0x00 # Co = 0, DC = 0
self._i2c.write8(control, c)
def _initialize(self):
raise NotImplementedError
def data(self, c):
"""Send byte of data to display."""
if self._spi is not None:
# SPI write.
self._gpio.set_high(self._dc)
self._spi.write([c])
else:
# I2C write.
control = 0x40 # Co = 0, DC = 0
self._i2c.write8(control, c)
def command(self, c):
"""Send command byte to display."""
if self._spi is not None:
# SPI write.
self._gpio.set_low(self._dc)
self._spi.write([c])
else:
# I2C write.
control = 0x00 # Co = 0, DC = 0
self._i2c.write8(control, c)
def begin(self, vccstate=SSD1306_SWITCHCAPVCC):
"""Initialize display."""
# Save vcc state.
self._vccstate = vccstate
# Reset and initialize display.
self.reset()
self._initialize()
# Turn on the display.
self.command(SSD1306_DISPLAYON)
def data(self, c):
"""Send byte of data to display."""
if self._spi is not None:
# SPI write.
self._gpio.set_high(self._dc)
self._spi.write([c])
else:
# I2C write.
control = 0x40 # Co = 0, DC = 0
self._i2c.write8(control, c)
def reset(self):
"""Reset the display."""
# Set reset high for a millisecond.
self._gpio.set_high(self._rst)
time.sleep(0.001)
# Set reset low for 10 milliseconds.
self._gpio.set_low(self._rst)
time.sleep(0.010)
# Set reset high again.
self._gpio.set_high(self._rst)
def begin(self, vccstate=SSD1306_SWITCHCAPVCC):
"""Initialize display."""
# Save vcc state.
self._vccstate = vccstate
# Reset and initialize display.
self.reset()
self._initialize()
# Turn on the display.
self.command(SSD1306_DISPLAYON)
def display(self):
"""Write display buffer to physical display."""
self.command(SSD1306_COLUMNADDR)
self.command(0) # Column start address. (0 = reset)
self.command(self.width-1) # Column end address.
self.command(SSD1306_PAGEADDR)
self.command(0) # Page start address. (0 = reset)
self.command(self._pages-1) # Page end address.
# Write buffer data.
if self._spi is not None:
# Set DC high for data.
self._gpio.set_high(self._dc)
# Write buffer.
self._spi.write(self._buffer)
else:
for i in range(0, len(self._buffer), 16):
control = 0x40 # Co = 0, DC = 0
self._i2c.writeList(control, self._buffer[i:i+16])
def reset(self):
"""Reset the display."""
# Set reset high for a millisecond.
self._gpio.set_high(self._rst)
time.sleep(0.001)
# Set reset low for 10 milliseconds.
self._gpio.set_low(self._rst)
time.sleep(0.010)
# Set reset high again.
self._gpio.set_high(self._rst)
def image(self, image):
"""Set buffer to value of Python Imaging Library image. The image should
be in 1 bit mode and a size equal to the display size.
"""
if image.mode != '1':
raise ValueError('Image must be in mode 1.')
imwidth, imheight = image.size
if imwidth != self.width or imheight != self.height:
raise ValueError('Image must be same dimensions as display ({0}x{1}).' \
.format(self.width, self.height))
# Grab all the pixels from the image, faster than getpixel.
pix = image.load()
# Iterate through the memory pages
index = 0
for page in range(self._pages):
# Iterate through all x axis columns.
for x in range(self.width):
# Set the bits for the column of pixels at the current position.
bits = 0
# Don't use range here as it's a bit slow
for bit in [0, 1, 2, 3, 4, 5, 6, 7]:
bits = bits << 1
bits |= 0 if pix[(x, page*8+7-bit)] == 0 else 1
# Update buffer byte and increment to next byte.
self._buffer[index] = bits
index += 1
def display(self):
"""Write display buffer to physical display."""
self.command(SSD1306_COLUMNADDR)
self.command(0) # Column start address. (0 = reset)
self.command(self.width-1) # Column end address.
self.command(SSD1306_PAGEADDR)
self.command(0) # Page start address. (0 = reset)
self.command(self._pages-1) # Page end address.
# Write buffer data.
if self._spi is not None:
# Set DC high for data.
self._gpio.set_high(self._dc)
# Write buffer.
self._spi.write(self._buffer)
else:
for i in range(0, len(self._buffer), 16):
control = 0x40 # Co = 0, DC = 0
self._i2c.writeList(control, self._buffer[i:i+16])
def clear(self):
"""Clear contents of image buffer."""
self._buffer = [0]*(self.width*self._pages)
def image(self, image):
"""Set buffer to value of Python Imaging Library image. The image should
be in 1 bit mode and a size equal to the display size.
"""
if image.mode != '1':
raise ValueError('Image must be in mode 1.')
imwidth, imheight = image.size
if imwidth != self.width or imheight != self.height:
raise ValueError('Image must be same dimensions as display ({0}x{1}).' \
.format(self.width, self.height))
# Grab all the pixels from the image, faster than getpixel.
pix = image.load()
# Iterate through the memory pages
index = 0
for page in range(self._pages):
# Iterate through all x axis columns.
for x in range(self.width):
# Set the bits for the column of pixels at the current position.
bits = 0
# Don't use range here as it's a bit slow
for bit in [0, 1, 2, 3, 4, 5, 6, 7]:
bits = bits << 1
bits |= 0 if pix[(x, page*8+7-bit)] == 0 else 1
# Update buffer byte and increment to next byte.
self._buffer[index] = bits
index += 1
def set_contrast(self, contrast):
"""Sets the contrast of the display. Contrast should be a value between
0 and 255."""
if contrast < 0 or contrast > 255:
raise ValueError('Contrast must be a value from 0 to 255 (inclusive).')
self.command(SSD1306_SETCONTRAST)
self.command(contrast)
def clear(self):
"""Clear contents of image buffer."""
self._buffer = [0]*(self.width*self._pages)
def dim(self, dim):
"""Adjusts contrast to dim the display if dim is True, otherwise sets the
contrast to normal brightness if dim is False.
"""
# Assume dim display.
contrast = 0
# Adjust contrast based on VCC if not dimming.
if not dim:
if self._vccstate == SSD1306_EXTERNALVCC:
contrast = 0x9F
else:
contrast = 0xCF
def set_contrast(self, contrast):
"""Sets the contrast of the display. Contrast should be a value between
0 and 255."""
if contrast < 0 or contrast > 255:
raise ValueError('Contrast must be a value from 0 to 255 (inclusive).')
self.command(SSD1306_SETCONTRAST)
self.command(contrast)
def dim(self, dim):
"""Adjusts contrast to dim the display if dim is True, otherwise sets the
contrast to normal brightness if dim is False.
"""
# Assume dim display.
contrast = 0
# Adjust contrast based on VCC if not dimming.
if not dim:
if self._vccstate == SSD1306_EXTERNALVCC:
contrast = 0x9F
else:
contrast = 0xCF
class SSD1306_128_64(SSD1306Base):
def __init__(self, rst, dc=None, sclk=None, din=None, cs=None, gpio=None,
spi=None, i2c_bus=None, i2c_address=SSD1306_I2C_ADDRESS,
i2c=None):
# Call base class constructor.
super(SSD1306_128_64, self).__init__(128, 64, rst, dc, sclk, din, cs,
gpio, spi, i2c_bus, i2c_address, i2c)
def __init__(self, rst, dc=None, sclk=None, din=None, cs=None, gpio=None,
spi=None, i2c_bus=None, i2c_address=SSD1306_I2C_ADDRESS,
i2c=None):
# Call base class constructor.
super(SSD1306_128_64, self).__init__(128, 64, rst, dc, sclk, din, cs,
gpio, spi, i2c_bus, i2c_address, i2c)
def _initialize(self):
# 128x64 pixel specific initialization.
self.command(SSD1306_DISPLAYOFF) # 0xAE
self.command(SSD1306_SETDISPLAYCLOCKDIV) # 0xD5
self.command(0x80) # the suggested ratio 0x80
self.command(SSD1306_SETMULTIPLEX) # 0xA8
self.command(0x3F)
self.command(SSD1306_SETDISPLAYOFFSET) # 0xD3
self.command(0x0) # no offset
self.command(SSD1306_SETSTARTLINE | 0x0) # line #0
self.command(SSD1306_CHARGEPUMP) # 0x8D
if self._vccstate == SSD1306_EXTERNALVCC:
self.command(0x10)
else:
self.command(0x14)
self.command(SSD1306_MEMORYMODE) # 0x20
self.command(0x00) # 0x0 act like ks0108
self.command(SSD1306_SEGREMAP | 0x1)
self.command(SSD1306_COMSCANDEC)
self.command(SSD1306_SETCOMPINS) # 0xDA
self.command(0x12)
self.command(SSD1306_SETCONTRAST) # 0x81
if self._vccstate == SSD1306_EXTERNALVCC:
self.command(0x9F)
else:
self.command(0xCF)
self.command(SSD1306_SETPRECHARGE) # 0xd9
if self._vccstate == SSD1306_EXTERNALVCC:
self.command(0x22)
else:
self.command(0xF1)
self.command(SSD1306_SETVCOMDETECT) # 0xDB
self.command(0x40)
self.command(SSD1306_DISPLAYALLON_RESUME) # 0xA4
self.command(SSD1306_NORMALDISPLAY) # 0xA6
def _initialize(self):
# 128x64 pixel specific initialization.
self.command(SSD1306_DISPLAYOFF) # 0xAE
self.command(SSD1306_SETDISPLAYCLOCKDIV) # 0xD5
self.command(0x80) # the suggested ratio 0x80
self.command(SSD1306_SETMULTIPLEX) # 0xA8
self.command(0x3F)
self.command(SSD1306_SETDISPLAYOFFSET) # 0xD3
self.command(0x0) # no offset
self.command(SSD1306_SETSTARTLINE | 0x0) # line #0
self.command(SSD1306_CHARGEPUMP) # 0x8D
if self._vccstate == SSD1306_EXTERNALVCC:
self.command(0x10)
else:
self.command(0x14)
self.command(SSD1306_MEMORYMODE) # 0x20
self.command(0x00) # 0x0 act like ks0108
self.command(SSD1306_SEGREMAP | 0x1)
self.command(SSD1306_COMSCANDEC)
self.command(SSD1306_SETCOMPINS) # 0xDA
self.command(0x12)
self.command(SSD1306_SETCONTRAST) # 0x81
if self._vccstate == SSD1306_EXTERNALVCC:
self.command(0x9F)
else:
self.command(0xCF)
self.command(SSD1306_SETPRECHARGE) # 0xd9
if self._vccstate == SSD1306_EXTERNALVCC:
self.command(0x22)
else:
self.command(0xF1)
self.command(SSD1306_SETVCOMDETECT) # 0xDB
self.command(0x40)
self.command(SSD1306_DISPLAYALLON_RESUME) # 0xA4
self.command(SSD1306_NORMALDISPLAY) # 0xA6
class SSD1306_128_32(SSD1306Base):
def __init__(self, rst, dc=None, sclk=None, din=None, cs=None, gpio=None,
spi=None, i2c_bus=None, i2c_address=SSD1306_I2C_ADDRESS,
i2c=None):
# Call base class constructor.
super(SSD1306_128_32, self).__init__(128, 32, rst, dc, sclk, din, cs,
gpio, spi, i2c_bus, i2c_address, i2c)
def __init__(self, rst, dc=None, sclk=None, din=None, cs=None, gpio=None,
spi=None, i2c_bus=None, i2c_address=SSD1306_I2C_ADDRESS,
i2c=None):
# Call base class constructor.
super(SSD1306_128_32, self).__init__(128, 32, rst, dc, sclk, din, cs,
gpio, spi, i2c_bus, i2c_address, i2c)
def _initialize(self):
# 128x32 pixel specific initialization.
self.command(SSD1306_DISPLAYOFF) # 0xAE
self.command(SSD1306_SETDISPLAYCLOCKDIV) # 0xD5
self.command(0x80) # the suggested ratio 0x80
self.command(SSD1306_SETMULTIPLEX) # 0xA8
self.command(0x1F)
self.command(SSD1306_SETDISPLAYOFFSET) # 0xD3
self.command(0x0) # no offset
self.command(SSD1306_SETSTARTLINE | 0x0) # line #0
self.command(SSD1306_CHARGEPUMP) # 0x8D
if self._vccstate == SSD1306_EXTERNALVCC:
self.command(0x10)
else:
self.command(0x14)
self.command(SSD1306_MEMORYMODE) # 0x20
self.command(0x00) # 0x0 act like ks0108
self.command(SSD1306_SEGREMAP | 0x1)
self.command(SSD1306_COMSCANDEC)
self.command(SSD1306_SETCOMPINS) # 0xDA
self.command(0x02)
self.command(SSD1306_SETCONTRAST) # 0x81
self.command(0x8F)
self.command(SSD1306_SETPRECHARGE) # 0xd9
if self._vccstate == SSD1306_EXTERNALVCC:
self.command(0x22)
else:
self.command(0xF1)
self.command(SSD1306_SETVCOMDETECT) # 0xDB
self.command(0x40)
self.command(SSD1306_DISPLAYALLON_RESUME) # 0xA4
self.command(SSD1306_NORMALDISPLAY) # 0xA6
def _initialize(self):
# 128x32 pixel specific initialization.
self.command(SSD1306_DISPLAYOFF) # 0xAE
self.command(SSD1306_SETDISPLAYCLOCKDIV) # 0xD5
self.command(0x80) # the suggested ratio 0x80
self.command(SSD1306_SETMULTIPLEX) # 0xA8
self.command(0x1F)
self.command(SSD1306_SETDISPLAYOFFSET) # 0xD3
self.command(0x0) # no offset
self.command(SSD1306_SETSTARTLINE | 0x0) # line #0
self.command(SSD1306_CHARGEPUMP) # 0x8D
if self._vccstate == SSD1306_EXTERNALVCC:
self.command(0x10)
else:
self.command(0x14)
self.command(SSD1306_MEMORYMODE) # 0x20
self.command(0x00) # 0x0 act like ks0108
self.command(SSD1306_SEGREMAP | 0x1)
self.command(SSD1306_COMSCANDEC)
self.command(SSD1306_SETCOMPINS) # 0xDA
self.command(0x02)
self.command(SSD1306_SETCONTRAST) # 0x81
self.command(0x8F)
self.command(SSD1306_SETPRECHARGE) # 0xd9
if self._vccstate == SSD1306_EXTERNALVCC:
self.command(0x22)
else:
self.command(0xF1)
self.command(SSD1306_SETVCOMDETECT) # 0xDB
self.command(0x40)
self.command(SSD1306_DISPLAYALLON_RESUME) # 0xA4
self.command(SSD1306_NORMALDISPLAY) # 0xA6
class SSD1306_96_16(SSD1306Base):
def __init__(self, rst, dc=None, sclk=None, din=None, cs=None, gpio=None,
spi=None, i2c_bus=None, i2c_address=SSD1306_I2C_ADDRESS,
i2c=None):
# Call base class constructor.
super(SSD1306_96_16, self).__init__(96, 16, rst, dc, sclk, din, cs,
gpio, spi, i2c_bus, i2c_address, i2c)
def __init__(self, rst, dc=None, sclk=None, din=None, cs=None, gpio=None,
spi=None, i2c_bus=None, i2c_address=SSD1306_I2C_ADDRESS,
i2c=None):
# Call base class constructor.
super(SSD1306_96_16, self).__init__(96, 16, rst, dc, sclk, din, cs,
gpio, spi, i2c_bus, i2c_address, i2c)
def _initialize(self):
# 128x32 pixel specific initialization.
self.command(SSD1306_DISPLAYOFF) # 0xAE
self.command(SSD1306_SETDISPLAYCLOCKDIV) # 0xD5
self.command(0x60) # the suggested ratio 0x60
self.command(SSD1306_SETMULTIPLEX) # 0xA8
self.command(0x0F)
self.command(SSD1306_SETDISPLAYOFFSET) # 0xD3
self.command(0x0) # no offset
self.command(SSD1306_SETSTARTLINE | 0x0) # line #0
self.command(SSD1306_CHARGEPUMP) # 0x8D
if self._vccstate == SSD1306_EXTERNALVCC:
self.command(0x10)
else:
self.command(0x14)
self.command(SSD1306_MEMORYMODE) # 0x20
self.command(0x00) # 0x0 act like ks0108
self.command(SSD1306_SEGREMAP | 0x1)
self.command(SSD1306_COMSCANDEC)
self.command(SSD1306_SETCOMPINS) # 0xDA
self.command(0x02)
self.command(SSD1306_SETCONTRAST) # 0x81
self.command(0x8F)
self.command(SSD1306_SETPRECHARGE) # 0xd9
if self._vccstate == SSD1306_EXTERNALVCC:
self.command(0x22)
else:
self.command(0xF1)
self.command(SSD1306_SETVCOMDETECT) # 0xDB
self.command(0x40)
self.command(SSD1306_DISPLAYALLON_RESUME) # 0xA4
self.command(SSD1306_NORMALDISPLAY) # 0xA6
def _initialize(self):
# 128x32 pixel specific initialization.
self.command(SSD1306_DISPLAYOFF) # 0xAE
self.command(SSD1306_SETDISPLAYCLOCKDIV) # 0xD5
self.command(0x60) # the suggested ratio 0x60
self.command(SSD1306_SETMULTIPLEX) # 0xA8
self.command(0x0F)
self.command(SSD1306_SETDISPLAYOFFSET) # 0xD3
self.command(0x0) # no offset
self.command(SSD1306_SETSTARTLINE | 0x0) # line #0
self.command(SSD1306_CHARGEPUMP) # 0x8D
if self._vccstate == SSD1306_EXTERNALVCC:
self.command(0x10)
else:
self.command(0x14)
self.command(SSD1306_MEMORYMODE) # 0x20
self.command(0x00) # 0x0 act like ks0108
self.command(SSD1306_SEGREMAP | 0x1)
self.command(SSD1306_COMSCANDEC)
self.command(SSD1306_SETCOMPINS) # 0xDA
self.command(0x02)
self.command(SSD1306_SETCONTRAST) # 0x81
self.command(0x8F)
self.command(SSD1306_SETPRECHARGE) # 0xd9
if self._vccstate == SSD1306_EXTERNALVCC:
self.command(0x22)
else:
self.command(0xF1)
self.command(SSD1306_SETVCOMDETECT) # 0xDB
self.command(0x40)
self.command(SSD1306_DISPLAYALLON_RESUME) # 0xA4
self.command(SSD1306_NORMALDISPLAY) # 0xA6
+1 -1
View File
@@ -1 +1 @@
from SSD1306 import *
from .SSD1306 import *
+34 -34
View File
@@ -24,9 +24,9 @@ import time
import Adafruit_GPIO.SPI as SPI
import Adafruit_SSD1306
import Image
import ImageFont
import ImageDraw
from PIL import Image
from PIL import ImageFont
from PIL import ImageDraw
# Raspberry Pi pin configuration:
@@ -91,36 +91,36 @@ velocity = -2
startpos = width
# Animate text moving in sine wave.
print 'Press Ctrl-C to quit.'
print('Press Ctrl-C to quit.')
pos = startpos
while True:
# Clear image buffer by drawing a black filled box.
draw.rectangle((0,0,width,height), outline=0, fill=0)
# Enumerate characters and draw them offset vertically based on a sine wave.
x = pos
for i, c in enumerate(text):
# Stop drawing if off the right side of screen.
if x > width:
break
# Calculate width but skip drawing if off the left side of screen.
if x < -10:
char_width, char_height = draw.textsize(c, font=font)
x += char_width
continue
# Calculate offset from sine wave.
y = offset+math.floor(amplitude*math.sin(x/float(width)*2.0*math.pi))
# Draw text.
draw.text((x, y), c, font=font, fill=255)
# Increment x position based on chacacter width.
char_width, char_height = draw.textsize(c, font=font)
x += char_width
# Draw the image buffer.
disp.image(image)
disp.display()
# Move position for next frame.
pos += velocity
# Start over if text has scrolled completely off left side of screen.
if pos < -maxwidth:
pos = startpos
# Pause briefly before drawing next frame.
time.sleep(0.1)
# Clear image buffer by drawing a black filled box.
draw.rectangle((0,0,width,height), outline=0, fill=0)
# Enumerate characters and draw them offset vertically based on a sine wave.
x = pos
for i, c in enumerate(text):
# Stop drawing if off the right side of screen.
if x > width:
break
# Calculate width but skip drawing if off the left side of screen.
if x < -10:
char_width, char_height = draw.textsize(c, font=font)
x += char_width
continue
# Calculate offset from sine wave.
y = offset+math.floor(amplitude*math.sin(x/float(width)*2.0*math.pi))
# Draw text.
draw.text((x, y), c, font=font, fill=255)
# Increment x position based on chacacter width.
char_width, char_height = draw.textsize(c, font=font)
x += char_width
# Draw the image buffer.
disp.image(image)
disp.display()
# Move position for next frame.
pos += velocity
# Start over if text has scrolled completely off left side of screen.
if pos < -maxwidth:
pos = startpos
# Pause briefly before drawing next frame.
time.sleep(0.1)
+3 -3
View File
@@ -23,7 +23,7 @@ import time
import Adafruit_GPIO.SPI as SPI
import Adafruit_SSD1306
import Image
from PIL import Image
# Raspberry Pi pin configuration:
@@ -61,9 +61,9 @@ disp.display()
# Load image based on OLED display height. Note that image is converted to 1 bit color.
if disp.height == 64:
image = Image.open('happycat_oled_64.ppm').convert('1')
image = Image.open('happycat_oled_64.ppm').convert('1')
else:
image = Image.open('happycat_oled_32.ppm').convert('1')
image = Image.open('happycat_oled_32.ppm').convert('1')
# Alternatively load a different format image, resize it, and convert to 1 bit color.
#image = Image.open('happycat.png').resize((disp.width, disp.height), Image.ANTIALIAS).convert('1')
+3 -3
View File
@@ -23,9 +23,9 @@ import time
import Adafruit_GPIO.SPI as SPI
import Adafruit_SSD1306
import Image
import ImageDraw
import ImageFont
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont
# Raspberry Pi pin configuration:
+20 -10
View File
@@ -2,13 +2,23 @@ from ez_setup import use_setuptools
use_setuptools()
from setuptools import setup, find_packages
setup(name = 'Adafruit_SSD1306',
version = '1.5.0',
author = 'Tony DiCola',
author_email = 'tdicola@adafruit.com',
description = 'Python library to use SSD1306-based 128x64 or 128x32 pixel OLED displays with a Raspberry Pi or Beaglebone Black.',
license = 'MIT',
url = 'https://github.com/adafruit/Adafruit_Python_SSD1306/',
dependency_links = ['https://github.com/adafruit/Adafruit_Python_GPIO/tarball/master#egg=Adafruit-GPIO-0.6.5'],
install_requires = ['Adafruit-GPIO>=0.6.5'],
packages = find_packages())
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 :: System :: Hardware']
setup(name = 'Adafruit_SSD1306',
version = '1.6.0',
author = 'Tony DiCola',
author_email = 'tdicola@adafruit.com',
description = 'Python library to use SSD1306-based 128x64 or 128x32 pixel OLED displays with a Raspberry Pi or Beaglebone Black.',
license = 'MIT',
classifiers = classifiers,
url = 'https://github.com/adafruit/Adafruit_Python_SSD1306/',
dependency_links = ['https://github.com/adafruit/Adafruit_Python_GPIO/tarball/master#egg=Adafruit-GPIO-0.6.5'],
install_requires = ['Adafruit-GPIO>=0.6.5'],
packages = find_packages())