Merge pull request #5 from bkosciow/pins

Pins
This commit is contained in:
Bartosz 2017-05-21 12:50:05 +02:00 committed by GitHub
commit f1bec0da5c
31 changed files with 761 additions and 37 deletions

View File

@ -1,2 +1,6 @@
0.2.1
- CS & LED pin do ILI drv
0.2.0
- add AD7843 touch panel driver
0.1.0
- extract library from Doton project

View File

@ -99,3 +99,8 @@ class Chip(metaclass=abc.ABCMeta):
def fill_rect(self, pos_x1, pos_y1, pos_x2, pos_y2):
"""draw a filled rectangle"""
pass
@abc.abstractmethod
def draw_image(self, pos_x, pos_y, image):
"""draw a PIL image"""
pass

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

View File

@ -31,6 +31,8 @@ def draw_net(o):
drv = GPIO()
drv.pins['LED'] = 6
drv.pins['CS'] = 18
o = ILI9325(240, 320, drv)
o.init()

View File

@ -37,14 +37,12 @@ def draw_net(o):
o.draw_line(0, s, o.width-1, s)
s += 10
lcd_tft = ILI9325(240, 320, ILIGPIO())
drv = ILIGPIO()
drv.pins['LED'] = 6
drv.pins['CS'] = 18
lcd_tft = ILI9325(240, 320, drv)
lcd_tft.init()
# bypass of missing +3v line to power backlight
LED = 6
RPi.GPIO.setup(LED, RPi.GPIO.OUT)
RPi.GPIO.output(LED, 1)
lcd_tft.background_color = (255, 255, 255)
lcd_tft.fill_rect(0, 0, 240, 320)
lcd_tft.color = (0, 255, 1)

View File

@ -0,0 +1,22 @@
import RPi.GPIO
import sys
from PIL import Image
sys.path.append("../../")
from gfxlcd.driver.ili9325.gpio import GPIO as ILIGPIO
from gfxlcd.driver.ili9325.ili9325 import ILI9325
RPi.GPIO.setmode(RPi.GPIO.BCM)
drv = ILIGPIO()
drv.pins['LED'] = 6
drv.pins['CS'] = 18
lcd_tft = ILI9325(240, 320, drv)
lcd_tft.init()
image_file = Image.open("assets/japan_temple_240x320.jpg")
lcd_tft.draw_image(0, 0, image_file)
numbers_image = Image.open("assets/dsp2017_101_64.png")
lcd_tft.transparency_color = (0, 0, 0)
lcd_tft.draw_image(10, 10, numbers_image)

76
gfxlcd/demos/ili9486.py Normal file
View File

@ -0,0 +1,76 @@
import sys
sys.path.append("../../")
from gfxlcd.driver.ili9486.spi import SPI
from gfxlcd.driver.ili9486.ili9486 import ILI9486
import RPi.GPIO
RPi.GPIO.setmode(RPi.GPIO.BCM)
import random
def hole(x, y):
o.draw_pixel(x+1, y)
o.draw_pixel(x+2, y)
o.draw_pixel(x+3, y)
o.draw_pixel(x+1, y + 4)
o.draw_pixel(x+2, y + 4)
o.draw_pixel(x+3, y + 4)
o.draw_pixel(x, y + 1)
o.draw_pixel(x+4, y + 1)
o.draw_pixel(x, y + 2)
o.draw_pixel(x+4, y + 2)
o.draw_pixel(x, y + 3)
o.draw_pixel(x+4, y + 3)
def draw_net(o):
s = 0
while s < o.width-1:
o.draw_line(s, 0, s, o.height-1)
s += 10
s = 0
while s < o.height-1:
o.draw_line(0, s, o.width-1, s)
s += 10
drv = SPI()
o = ILI9486(320, 480, drv)
print("init")
o.init()
# o.driver.reset()
# exit()
o.color = (255, 255, 255)
o.background_color = (0, 0, 0)
o.fill_rect(10, 150, 205, 205)
# exit()
# for _ in range(0, 50):
# hole(random.randint(2,o.width-3), random.randint(2,o.height-3))
# draw_net(o)
print("draw")
o.color = (10, 230, 200)
o.draw_circle(60, 15, 15)
o.color = (0, 250, 20)
o.draw_circle(53, 10, 3)
o.draw_circle(67, 10, 3)
o.color = (250, 150, 20)
o.draw_arc(60, 15, 10, 45, 135)
o.color = (10, 230, 200)
o.draw_line(60, 12, 57, 17)
o.draw_line(60, 12, 63, 17)
o.draw_arc(60, 15, 3, 45, 135)
o.background_color = (200, 0, 120)
o.fill_rect(2, 2, 42, 29)
o.background_color = (20, 200, 120)
o.fill_rect(119, 2, 109, 12)
o.fill_rect(119, 17, 109, 19)
o.background_color = (255, 255, 255)
o.fill_rect(77, 6, 105, 16)
o.background_color = (255, 0, 0)
o.fill_rect(77, 16, 105, 25)
print("end")
# o.driver.reset()

View File

@ -0,0 +1,19 @@
import RPi.GPIO
import sys
from PIL import Image
sys.path.append("../../")
from gfxlcd.driver.ili9486.spi import SPI
from gfxlcd.driver.ili9486.ili9486 import ILI9486
RPi.GPIO.setmode(RPi.GPIO.BCM)
drv = SPI()
lcd_tft = ILI9486(320, 480, drv)
lcd_tft.init()
image_file = Image.open("assets/japan_temple_240x320.jpg")
lcd_tft.draw_image(0, 0, image_file)
numbers_image = Image.open("assets/dsp2017_101_64.png")
lcd_tft.transparency_color = (0, 0, 0)
lcd_tft.draw_image(10, 10, numbers_image)

20
gfxlcd/demos/nju_image.py Normal file
View File

@ -0,0 +1,20 @@
import RPi.GPIO
import sys
import random
from PIL import Image
sys.path.append("../../")
from gfxlcd.driver.nju6450.gpio import GPIO
from gfxlcd.driver.nju6450.nju6450 import NJU6450
RPi.GPIO.setmode(RPi.GPIO.BCM)
lcd_nju = NJU6450(122, 32, GPIO())
lcd_nju.init()
lcd_nju.auto_flush = False
image_file = Image.open("assets/dsp2017_122_29.png")
# lcd_nju.threshold = 50
# lcd_nju.transparency_color = [110, 57]
lcd_nju.draw_image(0, 0, image_file)
lcd_nju.flush(True)

23
gfxlcd/demos/ssd_image.py Normal file
View File

@ -0,0 +1,23 @@
import RPi.GPIO
import sys
from PIL import Image
sys.path.append("../../")
from gfxlcd.driver.ssd1306.spi import SPI
from gfxlcd.driver.ssd1306.ssd1306 import SSD1306
RPi.GPIO.setmode(RPi.GPIO.BCM)
lcd_oled = SSD1306(128, 64, SPI())
lcd_oled.init()
lcd_oled.auto_flush = False
image_file = Image.open("assets/dsp2017_101_64.png")
lcd_oled.threshold = 50
lcd_oled.threshold = 0
# lcd_oled.transparency_color = [110, 57] #110 #[110, 57]
# lcd_oled.threshold = 255
lcd_oled.draw_image(10, 0, image_file)
lcd_oled.flush(True)

29
gfxlcd/demos/touch.py Normal file
View File

@ -0,0 +1,29 @@
import RPi.GPIO
import sys
import time
sys.path.append("../../")
from gfxlcd.driver.ili9325.gpio import GPIO as ILIGPIO
from gfxlcd.driver.ili9325.ili9325 import ILI9325
from gfxlcd.driver.ad7843.ad7843 import AD7843
RPi.GPIO.setmode(RPi.GPIO.BCM)
lcd_tft = ILI9325(240, 320, ILIGPIO())
lcd_tft.init()
def callback(position):
print('(x,y)', position)
touch = AD7843(240, 320, 26, callback)
touch.init()
while True:
try:
time.sleep(1)
except KeyboardInterrupt:
touch.close()
# RPi.GPIO.cleanup()

View File

@ -0,0 +1,32 @@
import RPi.GPIO
import sys
import time
sys.path.append("../../")
from gfxlcd.driver.ili9325.gpio import GPIO as ILIGPIO
from gfxlcd.driver.ili9325.ili9325 import ILI9325
from gfxlcd.driver.ad7843.ad7843 import AD7843
RPi.GPIO.setmode(RPi.GPIO.BCM)
lcd_tft = ILI9325(240, 320, ILIGPIO())
lcd_tft.init()
def callback(position):
print('(x,y)', position)
touch = AD7843(240, 320)
touch.init()
while True:
try:
time.sleep(0.05)
ret = touch.get_position()
if ret:
print(ret[0], ret[1])
except KeyboardInterrupt:
touch.close()
RPi.GPIO.cleanup()

View File

@ -18,22 +18,6 @@ class Area(Pixel):
self._set_area(pos_x, pos_y, pos_x, pos_y)
self.driver.data(self._converted_color(), None)
def _set_area(self, pos_x1, pos_y1, pos_x2, pos_y2):
"""select area to work with"""
self.driver.cmd(0x0020, None)
self.driver.data(pos_x1, None)
self.driver.cmd(0x0021, None)
self.driver.data(pos_y1, None)
self.driver.cmd(0x0050, None)
self.driver.data(pos_x1, None)
self.driver.cmd(0x0052, None)
self.driver.data(pos_y1, None)
self.driver.cmd(0x0051, None)
self.driver.data(pos_x2, None)
self.driver.cmd(0x0053, None)
self.driver.data(pos_y2, None)
self.driver.cmd(0x0022, None)
def _draw_vertical_line(self, pos_x, pos_y, length):
"""draw vertical line"""
self._set_area(pos_x, pos_y, pos_x, pos_y + length)
@ -121,3 +105,61 @@ class Area(Pixel):
color = self._converted_background_color()
for _ in range(0, size):
self.driver.data(color, None)
def draw_image(self, pos_x, pos_y, image):
"""draw a PIL image"""
image_file = image.convert('RGB')
width, height = image_file.size
self._set_area(
pos_x,
pos_y,
pos_x + width - 1,
pos_y + height - 1
)
row = 0
col = 0
area = None
temporary_area = None
for red, green, blue in list(image_file.getdata()):
if self._is_transparent((red, green, blue)):
area = (
pos_x,
pos_y + row + 1,
pos_x + width - 1,
pos_y + height - 1
)
temporary_area = (
pos_x + col + 1,
pos_y + row,
pos_x + width - 1,
pos_y + row
)
else:
if temporary_area is not None:
self._set_area(*temporary_area)
temporary_area = None
self.color = (red, green, blue)
self.driver.data(self._converted_color(), None)
col += 1
if col > width - 1:
col = 0
row += 1
if area is not None:
self._set_area(*area)
area = None
temporary_area = None
def _is_transparent(self, color):
"""check if color is a transparency color"""
if self.options['transparency_color'] is None:
return False
elif type(self.options['transparency_color'][0]) == int \
and color == self.options['transparency_color']:
return True
elif (type(self.options['transparency_color'][0]) == list or
type(self.options['transparency_color'][0]) == tuple) \
and color in self.options['transparency_color']:
return True
return False

View File

@ -113,3 +113,29 @@ class Page(Pixel, metaclass=abc.ABCMeta):
def flush(self, force=None):
"""flush buffer to the screen"""
pass
def draw_image(self, pos_x, pos_y, image):
"""draw a PIL image"""
image_file = image.convert('L')
width, height = image_file.size
offset_x = 0
offset_y = 0
for stream in list(image_file.getdata()):
if stream > self.options['threshold'] \
and not self._is_transparent(stream):
self.draw_pixel(pos_x + offset_x, pos_y + offset_y)
offset_x += 1
if offset_x > width - 1:
offset_x = 0
offset_y += 1
def _is_transparent(self, color):
"""check if color is a transparency color"""
if type(self.options['transparency_color']) == int \
and color == self.options['transparency_color']:
return True
elif type(self.options['transparency_color']) == list \
and color in self.options['transparency_color']:
return True
return False

View File

@ -12,6 +12,28 @@ class Pixel(object):
self.options['background_color'] = {
'R': 0, 'G': 0, 'B': 0,
}
self.options['threshold'] = 50
self.options['transparency_color'] = None
@property
def threshold(self):
"""get threshold for B&W conversion"""
return self.options['threshold']
@threshold.setter
def threshold(self, threshold):
"""set B&W threshold for conversion """
self.options['threshold'] = threshold
@property
def transparency_color(self):
"""get transparency color"""
return self.options['transparency_color']
@transparency_color.setter
def transparency_color(self, transparency_color):
"""set transparency color """
self.options['transparency_color'] = transparency_color
def draw_pixel(self, pos_x, pos_y):
"""dummy fuction"""

View File

@ -0,0 +1,2 @@
"""driver/ad7843 module"""
__author__ = 'Bartosz Kosciow'

View File

@ -0,0 +1,89 @@
import spidev # pylint: disable=I0011,F0401
import RPi.GPIO
class AD7843(object):
"""AD7843 class"""
def __init__(self, width, height, int_pin=None, callback=None, cs_pin=None, spi=0, speed=2000000):
self.width = width
self.height = height
self.spi = spidev.SpiDev()
self.spi.open(spi, 0)
self.spi.max_speed_hz = speed
self.spi.mode = 0
self.correction = {
'x': 364,
'y': 430,
'ratio_x': 14.35,
'ratio_y': 10.59
}
self.cs_pin = cs_pin
self.int_pin = int_pin
self.callback = callback
self.bouncetime = 500
def init(self):
"""some init functions"""
if self.int_pin:
RPi.GPIO.setup(self.int_pin, RPi.GPIO.IN)
RPi.GPIO.add_event_detect(
self.int_pin, RPi.GPIO.BOTH, callback=self._interrupt, bouncetime=self.bouncetime
)
if self.cs_pin:
RPi.GPIO.setup(self.cs_pin, RPi.GPIO.OUT)
RPi.GPIO.output(self.cs_pin, 1)
def get_x(self, value):
"""correct value to x"""
return self.width - int((value - self.correction['x']) / self.correction['ratio_x'])
def get_y(self, value):
"""correct value to y"""
return self.height - int((value - self.correction['y']) / self.correction['ratio_y'])
def _interrupt(self, channel):
"""call users callback"""
if self.cs_pin:
RPi.GPIO.output(self.cs_pin, 0)
self.callback(self.get_position())
if self.cs_pin:
RPi.GPIO.output(self.cs_pin, 1)
def get_position(self):
"""get touch coords"""
buffer = []
while len(buffer) < 20:
self.spi.xfer2([0xd0])
recvx = self.spi.readbytes(2)
self.spi.xfer2([0x90])
recvy = self.spi.readbytes(2)
tc_rx = recvx[0] << 5
tc_rx |= recvx[1] >> 3
tc_ry = recvy[0] << 5
tc_ry |= recvy[1] >> 3
pos_x = self.get_x(tc_rx)
pos_y = self.get_y(tc_ry)
if 0 <= pos_x <= self.width and 0 <= pos_y <= self.height:
buffer.append((pos_x, pos_y))
return self._calculate_avr(buffer)
def _calculate_avr(self, points):
"""calculate x,y by average"""
sum_x = 0
sum_y = 0
for point in points:
sum_x += point[0]
sum_y += point[1]
return int(sum_x / len(points)), int(sum_y / len(points))
def close(self):
"""close action"""
if self.int_pin:
RPi.GPIO.remove_event_detect(self.int_pin)
self.spi.close()

View File

@ -20,6 +20,8 @@ class GPIO(Driver):
'DB14': 20,
'DB15': 21,
'RST': 25,
'LED': None,
'CS': None
}
self.data_pins = [
'DB8', 'DB9', 'DB10', 'DB11', 'DB12', 'DB13', 'DB14', 'DB15',
@ -28,11 +30,22 @@ class GPIO(Driver):
def init(self):
"""initialize pins"""
for pin in self.pins:
RPi.GPIO.setup(self.pins[pin], RPi.GPIO.OUT)
RPi.GPIO.output(self.pins[pin], 0)
if self.pins[pin] is not None:
RPi.GPIO.setup(self.pins[pin], RPi.GPIO.OUT)
RPi.GPIO.output(self.pins[pin], 0)
if self.pins['LED']:
RPi.GPIO.output(self.pins['LED'], 1)
if self.pins['CS']:
RPi.GPIO.output(self.pins['CS'], 1)
def reset(self):
"""reset a display"""
if self.pins['LED']:
RPi.GPIO.output(self.pins['LED'], 1)
if self.pins['CS']:
RPi.GPIO.output(self.pins['CS'], 1)
RPi.GPIO.output(self.pins['RST'], 1)
time.sleep(0.005)
RPi.GPIO.output(self.pins['RST'], 0)
@ -54,12 +67,16 @@ class GPIO(Driver):
def send(self, char, enable):
"""send 16bit as 2*8bit"""
if self.pins['CS']:
RPi.GPIO.output(self.pins['CS'], 0)
self._set_pins(char >> 8)
RPi.GPIO.output(self.pins['W'], 0)
RPi.GPIO.output(self.pins['W'], 1)
self._set_pins(char)
RPi.GPIO.output(self.pins['W'], 0)
RPi.GPIO.output(self.pins['W'], 1)
if self.pins['CS']:
RPi.GPIO.output(self.pins['CS'], 1)
def data(self, data, enable):
"""send data to display"""

View File

@ -6,9 +6,33 @@ from gfxlcd.abstract.chip import Chip
class ILI9325(Area, Chip):
"""Class for ILI9325 based LCD"""
rotations = {
0: {
'output': 0x0100,
'mode': 0x1030,
'output2': 0xa700
},
90: {
'output': 0x0000,
'mode': 0x1038,
'output2': 0xa700
},
180: {
'output': 0x0000,
'mode': 0x1030,
'output2': 0x2700
},
270: {
'output': 0x0100,
'mode': 0x1038,
'output2': 0x2700
}
}
def __init__(self, width, height, driver):
Chip.__init__(self, width, height, driver, True)
Area.__init__(self, driver)
self.rotation = 0
def _converted_background_color(self):
"""color from 8-8-8 to 5-6-5"""
@ -36,13 +60,16 @@ class ILI9325(Area, Chip):
# ************* ILI9325C/D **********
# set SS and SM bit
self.driver.cmd(0x0001, None)
self.driver.data(0x0100, None)
self.driver.data(self.rotations[self.rotation]['output'], None)
# set 1 line inversion
self.driver.cmd(0x0002, None)
self.driver.data(0x0200, None)
# set GRAM write direction and BGR=1
self.driver.cmd(0x0003, None)
self.driver.data(0x1030, None)
self.driver.data(self.rotations[self.rotation]['mode'], None)
# Resize register
self.driver.cmd(0x0004, None)
self.driver.data(0x0000, None)
@ -145,7 +172,8 @@ class ILI9325(Area, Chip):
self.driver.data(0x013F, None)
# Gate Scan Line
self.driver.cmd(0x0060, None)
self.driver.data(0xA700, None)
self.driver.data(self.rotations[self.rotation]['output2'], None)
# NDL, VLE, REV
self.driver.cmd(0x0061, None)
self.driver.data(0x0001, None)
@ -175,3 +203,21 @@ class ILI9325(Area, Chip):
# 262K color and display ON
self.driver.cmd(0x0007, None)
self.driver.data(0x0133, None)
def _set_area(self, pos_x1, pos_y1, pos_x2, pos_y2):
"""select area to work with"""
if self.rotation == 90 or self.rotation == 270:
pos_x1, pos_y1, pos_x2, pos_y2 = pos_y1, pos_x1, pos_y2, pos_x2
self.driver.cmd(0x0020, None)
self.driver.data(pos_x1, None)
self.driver.cmd(0x0021, None)
self.driver.data(pos_y1, None)
self.driver.cmd(0x0050, None)
self.driver.data(pos_x1, None)
self.driver.cmd(0x0052, None)
self.driver.data(pos_y1, None)
self.driver.cmd(0x0051, None)
self.driver.data(pos_x2, None)
self.driver.cmd(0x0053, None)
self.driver.data(pos_y2, None)
self.driver.cmd(0x0022, None)

View File

@ -0,0 +1,2 @@
"""driver/ili9486 module"""
__author__ = 'Bartosz Kosciow'

View File

@ -0,0 +1,126 @@
"""ILI9486 chip driver"""
import time
from gfxlcd.drawing.area import Area
from gfxlcd.abstract.chip import Chip
class ILI9486(Area, Chip):
"""Class for ILI9486 based LCD"""
rotations = {0: 0x80, 90: 0xf0, 180: 0x40, 270: 0x20}
def __init__(self, width, height, driver):
Chip.__init__(self, width, height, driver, True)
Area.__init__(self, driver)
self.rotation = 0
def _converted_background_color(self):
"""color from 8-8-8 to 5-6-5"""
rgb = self.options['background_color']['R'] << 16 | \
self.options['background_color']['G'] << 8 | \
self.options['background_color']['B']
return ((rgb & 0x00f80000) >> 8) |\
((rgb & 0x0000fc00) >> 5) | ((rgb & 0x000000f8) >> 3)
def _converted_color(self):
"""color from 8-8-8 to 5-6-5"""
rgb = self.options['color']['R'] << 16 | \
self.options['color']['G'] << 8 | \
self.options['color']['B']
return ((rgb & 0x00f80000) >> 8) |\
((rgb & 0x0000fc00) >> 5) | ((rgb & 0x000000f8) >> 3)
def init(self):
"""init display"""
self.driver.init()
Area.init(self)
Chip.init(self)
self.driver.reset()
self.driver.cmd(0x0b, None)
self.driver.data(0x00, None)
self.driver.data(0x00, None)
self.driver.cmd(0x11, None)
self.driver.cmd(0x3a, None)
self.driver.data(0x55, None) #0x66
self.driver.cmd(0x36, None)
self.driver.data(self.rotations[self.rotation], None)
self.driver.cmd(0xc2, None)
self.driver.data(0x44, None)
self.driver.cmd(0xc5, None)
self.driver.data(0x00, None)
self.driver.data(0x00, None)
self.driver.data(0x00, None)
self.driver.data(0x00, None)
self.driver.cmd(0xe0, None)
self.driver.data(0x0F, None)
self.driver.data(0x1F, None)
self.driver.data(0x1C, None)
self.driver.data(0x0C, None)
self.driver.data(0x0F, None)
self.driver.data(0x08, None)
self.driver.data(0x48, None)
self.driver.data(0x98, None)
self.driver.data(0x37, None)
self.driver.data(0x0A, None)
self.driver.data(0x13, None)
self.driver.data(0x04, None)
self.driver.data(0x11, None)
self.driver.data(0x0D, None)
self.driver.data(0x00, None)
self.driver.cmd(0xe1, None)
self.driver.data(0x0F, None)
self.driver.data(0x32, None)
self.driver.data(0x2E, None)
self.driver.data(0x0B, None)
self.driver.data(0x0D, None)
self.driver.data(0x05, None)
self.driver.data(0x47, None)
self.driver.data(0x75, None)
self.driver.data(0x37, None)
self.driver.data(0x06, None)
self.driver.data(0x10, None)
self.driver.data(0x03, None)
self.driver.data(0x24, None)
self.driver.data(0x20, None)
self.driver.data(0x00, None)
self.driver.cmd(0xe2, None)
self.driver.data(0x0F, None)
self.driver.data(0x32, None)
self.driver.data(0x2E, None)
self.driver.data(0x0B, None)
self.driver.data(0x0D, None)
self.driver.data(0x05, None)
self.driver.data(0x47, None)
self.driver.data(0x75, None)
self.driver.data(0x37, None)
self.driver.data(0x06, None)
self.driver.data(0x10, None)
self.driver.data(0x03, None)
self.driver.data(0x24, None)
self.driver.data(0x20, None)
self.driver.data(0x00, None)
self.driver.cmd(0x11, None)
self.driver.cmd(0x29, None)
def _set_area(self, pos_x1, pos_y1, pos_x2, pos_y2):
"""select area to work with"""
self.driver.cmd(0x2a, None)
self.driver.data(pos_x1 >> 8, None)
self.driver.data(pos_x1 & 0xff, None)
self.driver.data(pos_x2 >> 8, None)
self.driver.data(pos_x2 & 0xff, None)
self.driver.cmd(0x2b, None)
self.driver.data(pos_y1 >> 8, None)
self.driver.data(pos_y1 & 0xff, None)
self.driver.data(pos_y2 >> 8, None)
self.driver.data(pos_y2 & 0xff, None)
self.driver.cmd(0x2c, None)

View File

@ -0,0 +1,65 @@
"""SPI communication driver"""
import time
import spidev
import RPi.GPIO # pylint: disable=I0011,F0401
from gfxlcd.abstract.driver import Driver
RPi.GPIO.setmode(RPi.GPIO.BCM)
class SPI(Driver):
"""SPI communication driver"""
def __init__(self, spi=0, speed=2000000):
self.pins = {
'CS': 8,
'RST': 25,
'RS': 24,
'LED': None
}
self.spi = spidev.SpiDev()
self.spi.open(spi, 0)
self.spi.max_speed_hz = speed
self.spi.mode = 0
def init(self):
"""initialize pins"""
for pin in self.pins:
if self.pins[pin] is not None:
RPi.GPIO.setup(self.pins[pin], RPi.GPIO.OUT)
RPi.GPIO.output(self.pins[pin], 0)
if self.pins['CS']:
RPi.GPIO.output(self.pins['CS'], 1)
if self.pins['LED']:
RPi.GPIO.output(self.pins['LED'], 1)
def reset(self):
"""reset a display"""
if self.pins['LED']:
RPi.GPIO.output(self.pins['LED'], 1)
if self.pins['CS']:
RPi.GPIO.output(self.pins['CS'], 1)
RPi.GPIO.output(self.pins['RST'], 1)
time.sleep(0.005)
RPi.GPIO.output(self.pins['RST'], 0)
time.sleep(0.005)
RPi.GPIO.output(self.pins['RST'], 1)
time.sleep(0.005)
def cmd(self, data, enable):
"""send command to display"""
RPi.GPIO.output(self.pins['RS'], 0)
if self.pins['CS']:
RPi.GPIO.output(self.pins['CS'], 0)
self.spi.xfer2([data])
if self.pins['CS']:
RPi.GPIO.output(self.pins['CS'], 1)
def data(self, data, enable):
"""send data to display"""
RPi.GPIO.output(self.pins['RS'], 1)
if self.pins['CS']:
RPi.GPIO.output(self.pins['CS'], 0)
self.spi.xfer2([data])
if self.pins['CS']:
RPi.GPIO.output(self.pins['CS'], 1)

View File

@ -8,6 +8,7 @@ class NJU6450(Page, Chip):
def __init__(self, width, height, driver, auto_flush=True):
Chip.__init__(self, width, height, driver, auto_flush)
Page.__init__(self, driver)
self.rotation = 0
def init(self):
"""initialize display"""

View File

@ -8,6 +8,7 @@ class SSD1306(Page, Chip):
def __init__(self, width, height, driver, auto_flush=True):
Chip.__init__(self, width, height, driver, auto_flush)
Page.__init__(self, driver)
self.rotation = 0
def init(self):
"""inits a device"""

View File

@ -9,12 +9,18 @@ Supported:
- ssd1306 via SPI
- nju6450 via GPIO
And for touch panels:
- ad7843 via SPI, uses irq or not
On NJU and SSD uses buffer to keep current content as help for page operations.
Wiring is below
Demos are in demos directory
Initialization
LCD initialization
===
## SSD1306
### SPI
@ -92,6 +98,8 @@ Custom pins:
'DB14': 20,
'DB15': 21,
'RST': 25,
'LED': None,
'CS': None
}
o = ILI9325(240, 320, drv)
o.init()
@ -111,12 +119,59 @@ draw_arc(x1, y1, radius, from_angle, to_angle
fill_rect(x1, y1, x2, y2)
draw_image(x, y, PIL.Image)
Colours
===
lcd.color = (r, g, b)
lcd.background_color = (r, g ,b)
lcd.threshold = 255 - for images a threshold between black and white (on monochrome)
lcd.transparency_color = [110, 57] #110 - color(s) that are skipped during drawing an image
Touch panels
===
## AD7843
Constructor:
AD7843(width, height, (T_INT), (callback))
Can be used with T_INT
def callback(position):
print('(x,y)', position)
touch = AD7843(240, 320, 26, callback)
touch.init()
or without:
touch = AD7843(240, 320)
touch.init()
while True:
try:
time.sleep(0.05)
ret = touch.get_position()
if ret:
print(ret[0], ret[1])
except KeyboardInterrupt:
touch.close()
There is no automatic calibration. It must be done manually.
self.correction = {
'x': 364,
'y': 430,
'ratio_x': 14.35,
'ratio_y': 10.59
}
Wiring
===
@ -178,6 +233,6 @@ Default:
DB13 ------------------------ G16
DB14 ------------------------ G20
DB15 ------------------------ G21
CS ------------------------ GND (always selected)
CS ------------------------ GND (always selected) (or connect to GPIO pin)
REST ------------------------ G25
LED_A ------------------------ 3.3
LED_A ------------------------ 3.3 (can be connected to GPIO pin)

View File

@ -13,11 +13,11 @@ def read(*paths):
setup(
name='gfxlcd',
version='0.1.0',
description='gfxlcd is a handler for grpahical lcds: ILI9328, SSD1306, NJU6450 @ Raspberry Pi.',
keywords=['gfxlcd', 'raspberry pi' ,'ili9328' ,'ssd1306', 'nju6450', 'lcd', 'graphical lcd'],
version='0.2.1',
description='gfxlcd is a handler for graphical lcds: ILI9328, SSD1306, NJU6450, touch panel: AD7843 @ Raspberry Pi.',
keywords=['gfxlcd', 'raspberry pi' ,'ili9328' ,'ssd1306', 'nju6450', 'lcd', 'graphical lcd', 'touch panel', 'ad7843'],
long_description=(read('readme.md')),
url='https://bitbucket.org/kosci/charlcd.git',
url='https://github.com/bkosciow/gfxlcd',
license='MIT',
author='Bartosz Kościów',
author_email='kosci1@gmail.com',

View File

@ -16,5 +16,5 @@ commands= nosetests --with-xunit --xunit-file=junit-{envname}.xml gfxlcd/tests
/bin/bash -c "pylint gfxlcd > pylint-{envname}.log || :"
[flake8]
show-source = True
exclude = .git,.venv,.tox,dist,doc,build,*egg,*/tests/*
exclude = .git,.venv,.tox,dist,doc,build,*egg,*/tests/*,*/demos/*