commit
f1bec0da5c
@ -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
|
||||
- extract library from Doton project
|
||||
|
@ -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
|
||||
|
BIN
gfxlcd/demos/assets/dsp2017_101_64.png
Normal file
BIN
gfxlcd/demos/assets/dsp2017_101_64.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.4 KiB |
BIN
gfxlcd/demos/assets/dsp2017_122_29.png
Normal file
BIN
gfxlcd/demos/assets/dsp2017_122_29.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.5 KiB |
BIN
gfxlcd/demos/assets/japan_temple_240x320.jpg
Normal file
BIN
gfxlcd/demos/assets/japan_temple_240x320.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 44 KiB |
BIN
gfxlcd/demos/assets/numbers.jpg
Normal file
BIN
gfxlcd/demos/assets/numbers.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.9 KiB |
@ -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()
|
@ -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)
|
22
gfxlcd/demos/ili9325_image.py
Normal file
22
gfxlcd/demos/ili9325_image.py
Normal 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
76
gfxlcd/demos/ili9486.py
Normal 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()
|
19
gfxlcd/demos/ili9486_image.py
Normal file
19
gfxlcd/demos/ili9486_image.py
Normal 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
20
gfxlcd/demos/nju_image.py
Normal 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
23
gfxlcd/demos/ssd_image.py
Normal 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
29
gfxlcd/demos/touch.py
Normal 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()
|
||||
|
32
gfxlcd/demos/touch_loop.py
Normal file
32
gfxlcd/demos/touch_loop.py
Normal 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()
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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"""
|
||||
|
2
gfxlcd/driver/ad7843/__init__.py
Normal file
2
gfxlcd/driver/ad7843/__init__.py
Normal file
@ -0,0 +1,2 @@
|
||||
"""driver/ad7843 module"""
|
||||
__author__ = 'Bartosz Kosciow'
|
89
gfxlcd/driver/ad7843/ad7843.py
Normal file
89
gfxlcd/driver/ad7843/ad7843.py
Normal 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()
|
||||
|
@ -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"""
|
||||
|
@ -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)
|
||||
|
2
gfxlcd/driver/ili9486/__init__.py
Normal file
2
gfxlcd/driver/ili9486/__init__.py
Normal file
@ -0,0 +1,2 @@
|
||||
"""driver/ili9486 module"""
|
||||
__author__ = 'Bartosz Kosciow'
|
126
gfxlcd/driver/ili9486/ili9486.py
Normal file
126
gfxlcd/driver/ili9486/ili9486.py
Normal 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)
|
65
gfxlcd/driver/ili9486/spi.py
Normal file
65
gfxlcd/driver/ili9486/spi.py
Normal 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)
|
@ -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"""
|
||||
|
@ -1,2 +1,2 @@
|
||||
"""driver/ssd1306 module"""
|
||||
__author__ = 'Bartosz Kosciow'
|
||||
__author__ = 'Bartosz Kosciow'
|
||||
|
@ -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"""
|
||||
|
61
readme.md
61
readme.md
@ -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,13 +119,60 @@ 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)
|
||||
|
8
setup.py
8
setup.py
@ -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',
|
||||
|
2
tox.ini
2
tox.ini
@ -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/*
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user