init afer lib extraction from Doton project
This commit is contained in:
commit
95f2b8c7c9
18
.gitignore
vendored
Normal file
18
.gitignore
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
.idea
|
||||
.vs
|
||||
*.pyproj
|
||||
*.sln
|
||||
*.pyc
|
||||
*.pyo
|
||||
*.bak
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
build/
|
||||
dist/
|
||||
sdist/
|
||||
*.egg-info/
|
||||
*.egg
|
||||
.python-version
|
||||
__pycache__/
|
||||
.tox
|
3
.pylintrc
Normal file
3
.pylintrc
Normal file
@ -0,0 +1,3 @@
|
||||
[REPORTS]
|
||||
reports=yes
|
||||
msg-template={path}:{line}: [{msg_id}({symbol}), {obj}] {msg}
|
2
CHANGELOG.txt
Normal file
2
CHANGELOG.txt
Normal file
@ -0,0 +1,2 @@
|
||||
0.1.0
|
||||
- extract library from Doton project
|
3
CONTRIBUTORS.txt
Normal file
3
CONTRIBUTORS.txt
Normal file
@ -0,0 +1,3 @@
|
||||
List of contributors:
|
||||
|
||||
- Bartosz Kościów - kosci1@gmail.com
|
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
Copyright (c) 2017 Bartosz Kościów <kosci1@gmail.com>
|
||||
|
||||
The MIT License
|
||||
|
||||
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.
|
5
MANIFEST.in
Normal file
5
MANIFEST.in
Normal file
@ -0,0 +1,5 @@
|
||||
include CONTRIBUTORS.txt
|
||||
include LICENSE
|
||||
include readme.md
|
||||
include CHANGELOG.txt
|
||||
|
1
gfxlcd/__init__.py
Normal file
1
gfxlcd/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
__author__ = 'kosci'
|
1
gfxlcd/abstract/__init__.py
Normal file
1
gfxlcd/abstract/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
__author__ = 'kosci'
|
95
gfxlcd/abstract/chip.py
Normal file
95
gfxlcd/abstract/chip.py
Normal file
@ -0,0 +1,95 @@
|
||||
import abc
|
||||
|
||||
|
||||
class Chip(metaclass=abc.ABCMeta):
|
||||
def __init__(self, width, height, driver, auto_flush):
|
||||
self.options = {}
|
||||
self._width = width
|
||||
self._height = height
|
||||
self.driver = driver
|
||||
self.options['auto_flush'] = auto_flush
|
||||
|
||||
@property
|
||||
def width(self):
|
||||
"""get width"""
|
||||
return self._width
|
||||
|
||||
@property
|
||||
def height(self):
|
||||
"""get height"""
|
||||
return self._height
|
||||
|
||||
@abc.abstractmethod
|
||||
def _converted_background_color(self):
|
||||
"""convert RGB background to available color"""
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def _converted_color(self):
|
||||
"""convert RGB color to available color"""
|
||||
pass
|
||||
|
||||
@property
|
||||
def color(self):
|
||||
return self.options['color']
|
||||
|
||||
@color.setter
|
||||
def color(self, rgb):
|
||||
self.options['color'] = {
|
||||
'R': rgb[0], 'G': rgb[1], 'B': rgb[2]
|
||||
}
|
||||
|
||||
@property
|
||||
def background_color(self):
|
||||
return self.options['background_color']
|
||||
|
||||
@background_color.setter
|
||||
def background_color(self, rgb):
|
||||
self.options['background_color'] = {
|
||||
'R': rgb[0], 'G': rgb[1], 'B': rgb[2]
|
||||
}
|
||||
|
||||
@property
|
||||
def auto_flush(self):
|
||||
"""get auto_flush"""
|
||||
return self.options['auto_flush']
|
||||
|
||||
@auto_flush.setter
|
||||
def auto_flush(self, value):
|
||||
"""set auto_flush"""
|
||||
self.options['auto_flush'] = bool(value)
|
||||
|
||||
@abc.abstractmethod
|
||||
def init(self):
|
||||
"""init a chipset"""
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def draw_pixel(self, x, y):
|
||||
"""draw a pixel at x,y"""
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def draw_line(self, x1, y1, x2, y2):
|
||||
"""draw a line from point x1,y1 to x2,y2"""
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def draw_rect(self, x1, y1, x2, y2):
|
||||
"""draw a rectangle"""
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def draw_circle(self, x, y, r):
|
||||
"""draw a circle"""
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def draw_arc(self, x, y, radius, start, end):
|
||||
"""draw an arc"""
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def fill_rect(self, x1, y1, x2, y2):
|
||||
"""draw a filled rectangle"""
|
||||
pass
|
23
gfxlcd/abstract/driver.py
Normal file
23
gfxlcd/abstract/driver.py
Normal file
@ -0,0 +1,23 @@
|
||||
import abc
|
||||
|
||||
|
||||
class Driver(metaclass=abc.ABCMeta):
|
||||
@abc.abstractmethod
|
||||
def init(self):
|
||||
"""initialize a device"""
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def reset(self):
|
||||
"""resets a device"""
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def cmd(self, data, enable):
|
||||
"""sends command to device"""
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def data(self, data, enable):
|
||||
"""sends data to device"""
|
||||
pass
|
62
gfxlcd/demos/ili.py
Normal file
62
gfxlcd/demos/ili.py
Normal file
@ -0,0 +1,62 @@
|
||||
import sys
|
||||
sys.path.append("../../")
|
||||
from gfxlcd.driver.ili9325.gpio import GPIO
|
||||
from gfxlcd.driver.ili9325.ili9325 import ILI9325
|
||||
|
||||
|
||||
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 = GPIO()
|
||||
o = ILI9325(240, 320, drv)
|
||||
|
||||
o.init()
|
||||
# for _ in range(0, 50):
|
||||
# hole(random.randint(2,o.width-3), random.randint(2,o.height-3))
|
||||
#
|
||||
# draw_net(o)
|
||||
|
||||
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)
|
98
gfxlcd/demos/ili_2.py
Normal file
98
gfxlcd/demos/ili_2.py
Normal file
@ -0,0 +1,98 @@
|
||||
import RPi.GPIO
|
||||
import sys
|
||||
RPi.GPIO.setmode(RPi.GPIO.BCM)
|
||||
sys.path.append("../../")
|
||||
from gfxlcd.driver.ili9325.gpio import GPIO as ILIGPIO
|
||||
from gfxlcd.driver.ili9325.ili9325 import ILI9325
|
||||
import random
|
||||
|
||||
|
||||
def hole(o, 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_points(o):
|
||||
for _ in range(0, 50):
|
||||
hole(o, random.randint(2,o.width - 10), random.randint(2,o.height-10))
|
||||
|
||||
|
||||
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
|
||||
|
||||
lcd_tft = ILI9325(240, 320, ILIGPIO())
|
||||
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)
|
||||
lcd_tft.draw_circle(79, 99, 40)
|
||||
lcd_tft.draw_circle(60, 80, 7)
|
||||
lcd_tft.draw_circle(100, 80, 7)
|
||||
|
||||
lcd_tft.draw_line(79, 90, 70, 100)
|
||||
lcd_tft.draw_line(79, 90, 88, 100)
|
||||
lcd_tft.draw_arc(79, 91, 12, 45, 135)
|
||||
|
||||
lcd_tft.color = (255, 0, 0)
|
||||
lcd_tft.draw_arc(79, 90, 40, 45, 135)
|
||||
lcd_tft.draw_line(51, 117, 105, 117)
|
||||
|
||||
lcd_tft.background_color = (255, 127, 127)
|
||||
lcd_tft.fill_rect(75, 140, 83, 220)
|
||||
lcd_tft.draw_line(75, 220, 65, 280)
|
||||
lcd_tft.draw_line(83, 220, 93, 280)
|
||||
lcd_tft.draw_line(83, 150, 130, 150)
|
||||
|
||||
lcd_tft.background_color = (0, 255, 0)
|
||||
lcd_tft.fill_rect(0, 0, 122, 32)
|
||||
lcd_tft.color = (0, 0, 0)
|
||||
lcd_tft.background_color = (0, 0, 0)
|
||||
lcd_tft.draw_circle(60, 15, 15)
|
||||
lcd_tft.draw_circle(53, 10, 3)
|
||||
lcd_tft.draw_circle(67, 10, 3)
|
||||
lcd_tft.draw_arc(60, 15, 10, 45, 135)
|
||||
lcd_tft.draw_line(60, 12, 57, 17)
|
||||
lcd_tft.draw_line(60, 12, 63, 17)
|
||||
lcd_tft.draw_arc(60, 15, 3, 45, 135)
|
||||
lcd_tft.fill_rect(2, 2, 42, 29)
|
||||
lcd_tft.fill_rect(119, 2, 109, 12)
|
||||
lcd_tft.fill_rect(119, 17, 109, 19)
|
||||
lcd_tft.draw_rect(77, 6, 105, 16)
|
||||
lcd_tft.fill_rect(77, 16, 105, 25)
|
||||
|
||||
lcd_tft.background_color = (0, 0, 0)
|
||||
lcd_tft.fill_rect(100, 200, 222, 264)
|
||||
lcd_tft.color = (43, 212, 255)
|
||||
lcd_tft.background_color = (43, 212, 255)
|
||||
lcd_tft.draw_circle(131, 232, 31)
|
||||
lcd_tft.draw_circle(119, 222, 7)
|
||||
lcd_tft.draw_circle(143, 222, 7)
|
||||
lcd_tft.draw_arc(131, 232, 20, 45, 135)
|
||||
lcd_tft.draw_line(131, 227, 127, 238)
|
||||
lcd_tft.draw_line(131, 227, 135, 238)
|
||||
lcd_tft.draw_arc(131, 235, 5, 45, 135)
|
||||
lcd_tft.fill_rect(195, 204, 205, 210)
|
||||
lcd_tft.draw_rect(180, 210, 220, 225)
|
||||
lcd_tft.fill_rect(180, 226, 220, 259)
|
31
gfxlcd/demos/nju.py
Normal file
31
gfxlcd/demos/nju.py
Normal file
@ -0,0 +1,31 @@
|
||||
import random
|
||||
from gfxlcd.driver.nju6450.gpio import GPIO
|
||||
from gfxlcd.driver.nju6450.nju6450 import NJU6450
|
||||
|
||||
|
||||
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)
|
||||
|
||||
drv = GPIO()
|
||||
o = NJU6450(122, 32, drv)
|
||||
|
||||
o.init()
|
||||
o.auto_flush = False
|
||||
for _ in range(0, 50):
|
||||
hole(random.randint(2, 115), random.randint(2, 25))
|
||||
hole(10, 10)
|
||||
hole(15, 13)
|
||||
hole(18, 23)
|
||||
hole(40, 10)
|
||||
o.flush(True)
|
60
gfxlcd/demos/nju_2.py
Normal file
60
gfxlcd/demos/nju_2.py
Normal file
@ -0,0 +1,60 @@
|
||||
import RPi.GPIO
|
||||
import sys
|
||||
RPi.GPIO.setmode(RPi.GPIO.BCM)
|
||||
sys.path.append("../../")
|
||||
from gfxlcd.driver.nju6450.gpio import GPIO
|
||||
from gfxlcd.driver.nju6450.nju6450 import NJU6450
|
||||
import random
|
||||
|
||||
|
||||
def hole(o, 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_points(o):
|
||||
for _ in range(0, 50):
|
||||
hole(o, random.randint(2,o.width - 10), random.randint(2,o.height-10))
|
||||
|
||||
|
||||
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
|
||||
|
||||
lcd_nju = NJU6450(122, 32, GPIO())
|
||||
lcd_nju.init()
|
||||
lcd_nju.auto_flush = False
|
||||
|
||||
|
||||
lcd_nju.draw_circle(60, 15, 15)
|
||||
lcd_nju.draw_circle(53, 10, 3)
|
||||
lcd_nju.draw_circle(67, 10, 3)
|
||||
lcd_nju.draw_arc(60, 15, 10, 45, 135)
|
||||
lcd_nju.draw_line(60, 12, 57, 17)
|
||||
lcd_nju.draw_line(60, 12, 63, 17)
|
||||
lcd_nju.draw_arc(60, 15, 3, 45, 135)
|
||||
|
||||
lcd_nju.fill_rect(2, 2, 42, 29)
|
||||
lcd_nju.fill_rect(119, 2, 109, 12)
|
||||
lcd_nju.fill_rect(119, 17, 109, 19)
|
||||
|
||||
lcd_nju.draw_rect(77, 6, 105, 16)
|
||||
lcd_nju.fill_rect(77, 16, 105, 25)
|
||||
|
||||
lcd_nju.flush(True)
|
90
gfxlcd/demos/ssd.py
Normal file
90
gfxlcd/demos/ssd.py
Normal file
@ -0,0 +1,90 @@
|
||||
import random
|
||||
from driver.ssd1306.spi import SPI
|
||||
from driver.ssd1306.ssd1306 import SSD1306
|
||||
|
||||
|
||||
|
||||
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)
|
||||
|
||||
drv = SPI()
|
||||
o = SSD1306(128, 64, drv)
|
||||
|
||||
o.init()
|
||||
o.auto_flush = False
|
||||
for _ in range(0, 50):
|
||||
hole(random.randint(2,120), random.randint(2,56))
|
||||
hole(10, 10)
|
||||
hole(15, 13)
|
||||
hole(18, 23)
|
||||
hole(40, 10)
|
||||
o.flush(True)
|
||||
# o.fill(0)
|
||||
#
|
||||
# o.fill(random.randint(0, 255))
|
||||
#
|
||||
# o.draw_pixels(2, 0, 128)
|
||||
# o.draw_pixels(3, 0, 128)
|
||||
# o.draw_pixels(7, 0, 128)
|
||||
# o.draw_pixels(8, 0, 128)
|
||||
# o.draw_pixels(1, 9, 7)
|
||||
# o.draw_pixels(9, 9, 7)
|
||||
# o.draw_pixels(2, 9, 8)
|
||||
# o.draw_pixels(3, 9, 16)
|
||||
# o.draw_pixels(4, 9, 33)
|
||||
# o.draw_pixels(5, 9, 66)
|
||||
# o.draw_pixels(6, 9, 33)
|
||||
# o.draw_pixels(7, 9, 16)
|
||||
# o.draw_pixels(8, 9, 8)
|
||||
#
|
||||
# o.draw_pixels(15, 9, 127)
|
||||
# o.draw_pixels(16, 9, 65)
|
||||
# o.draw_pixels(17, 9, 65)
|
||||
# o.draw_pixels(18, 9, 62)
|
||||
#
|
||||
# o.draw_pixels(20, 9, 38)
|
||||
# o.draw_pixels(21, 9, 73)
|
||||
# o.draw_pixels(22, 9, 73)
|
||||
# o.draw_pixels(23, 9, 50)
|
||||
#
|
||||
# o.draw_pixels(25, 9, 127)
|
||||
# o.draw_pixels(26, 9, 9)
|
||||
# o.draw_pixels(27, 9, 9)
|
||||
# o.draw_pixels(28, 9, 6)
|
||||
#
|
||||
# o.draw_pixels(30, 9, 98)
|
||||
# o.draw_pixels(31, 9, 81)
|
||||
# o.draw_pixels(32, 9, 73)
|
||||
# o.draw_pixels(33, 9, 70)
|
||||
#
|
||||
# o.draw_pixels(35, 9, 62)
|
||||
# o.draw_pixels(36, 9, 65)
|
||||
# o.draw_pixels(37, 9, 65)
|
||||
# o.draw_pixels(38, 9, 62)
|
||||
#
|
||||
# o.draw_pixels(40, 9, 4)
|
||||
# o.draw_pixels(41, 9, 2+64)
|
||||
# o.draw_pixels(42, 9, 127)
|
||||
# o.draw_pixels(43, 9, 64)
|
||||
#
|
||||
# o.draw_pixels(40, 9, 4)
|
||||
# o.draw_pixels(41, 9, 2+64)
|
||||
# o.draw_pixels(42, 9, 127)
|
||||
# o.draw_pixels(43, 9, 64)
|
||||
#
|
||||
# o.draw_pixels(45, 9, 97)
|
||||
# o.draw_pixels(46, 9, 25)
|
||||
# o.draw_pixels(47, 9, 5)
|
||||
# o.draw_pixels(48, 9, 3)
|
||||
|
56
gfxlcd/demos/ssd_2.py
Normal file
56
gfxlcd/demos/ssd_2.py
Normal file
@ -0,0 +1,56 @@
|
||||
import RPi.GPIO
|
||||
import sys
|
||||
RPi.GPIO.setmode(RPi.GPIO.BCM)
|
||||
sys.path.append("../../")
|
||||
from gfxlcd.driver.ssd1306.spi import SPI
|
||||
from gfxlcd.driver.ssd1306.ssd1306 import SSD1306
|
||||
import random
|
||||
|
||||
|
||||
def hole(o, 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_points(o):
|
||||
for _ in range(0, 50):
|
||||
hole(o, random.randint(2,o.width - 10), random.randint(2,o.height-10))
|
||||
|
||||
|
||||
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
|
||||
|
||||
lcd_oled = SSD1306(128, 64, SPI())
|
||||
lcd_oled.init()
|
||||
lcd_oled.auto_flush = False
|
||||
|
||||
lcd_oled.draw_circle(31, 32, 31)
|
||||
lcd_oled.draw_circle(19, 22, 7)
|
||||
lcd_oled.draw_circle(43, 22, 7)
|
||||
lcd_oled.draw_arc(31, 32, 20, 45, 135)
|
||||
lcd_oled.draw_line(31, 27, 27, 38)
|
||||
lcd_oled.draw_line(31, 27, 35, 38)
|
||||
lcd_oled.draw_arc(31, 35, 5, 45, 135)
|
||||
|
||||
lcd_oled.fill_rect(95, 4, 105, 10)
|
||||
lcd_oled.draw_rect(80, 10, 120, 25)
|
||||
lcd_oled.fill_rect(80, 26, 120, 59)
|
||||
|
||||
lcd_oled.flush(True)
|
1
gfxlcd/drawing/__init__.py
Normal file
1
gfxlcd/drawing/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
__author__ = 'kosci'
|
115
gfxlcd/drawing/area.py
Normal file
115
gfxlcd/drawing/area.py
Normal file
@ -0,0 +1,115 @@
|
||||
import itertools
|
||||
from gfxlcd.drawing.pixel import Pixel
|
||||
|
||||
|
||||
class Area(Pixel):
|
||||
"""Page drawing algorithm"""
|
||||
def __init__(self):
|
||||
Pixel.__init__(self)
|
||||
|
||||
def init(self):
|
||||
pass
|
||||
|
||||
def draw_pixel(self, x, y):
|
||||
"""draw one pixel"""
|
||||
self._set_area(x, y, x, y)
|
||||
self.driver.data(self._converted_color(), None)
|
||||
|
||||
def _set_area(self, x1, y1, x2, y2):
|
||||
"""select area to work with"""
|
||||
self.driver.cmd_data(0x0020, x1)
|
||||
self.driver.cmd_data(0x0021, y1)
|
||||
self.driver.cmd_data(0x0050, x1)
|
||||
self.driver.cmd_data(0x0052, y1)
|
||||
self.driver.cmd_data(0x0051, x2)
|
||||
self.driver.cmd_data(0x0053, y2)
|
||||
self.driver.cmd(0x0022, None)
|
||||
|
||||
|
||||
def _draw_vertical_line(self, x, y, length):
|
||||
"""draw vertical line"""
|
||||
self._set_area(x, y, x, y + length)
|
||||
color = self._converted_color()
|
||||
for _ in itertools.repeat(None, length):
|
||||
self.driver.data(color, None)
|
||||
|
||||
def _draw_horizontal_line(self, x, y, length):
|
||||
"""draw horizontal line"""
|
||||
self._set_area(x, y, x + length, y)
|
||||
color = self._converted_color()
|
||||
for _ in itertools.repeat(None, length):
|
||||
self.driver.data(color, None)
|
||||
|
||||
def _calculate_steps(self, length, step, required_length):
|
||||
"""calculate lineparts - helper"""
|
||||
steps = [length for _ in range(0, step)]
|
||||
if step * length < required_length:
|
||||
for idx in range(0, required_length - step * length):
|
||||
steps[idx] += 1
|
||||
|
||||
return steps
|
||||
|
||||
def draw_line(self, x1, y1, x2, y2):
|
||||
"""draw diagonal line"""
|
||||
width = abs(x2 - x1)
|
||||
height = abs(y2 - y1)
|
||||
if x1 == x2:
|
||||
steps = [height]
|
||||
horizontal = False
|
||||
offset_x = offset_y = 0
|
||||
elif y1 == y2:
|
||||
steps = [width]
|
||||
horizontal = True
|
||||
offset_x = offset_y = 0
|
||||
elif width > height:
|
||||
if x2 < x1:
|
||||
x1, x2 = x2, x1
|
||||
y1, y2 = y2, y1
|
||||
offset_y = 1 if y2 > y1 else -1
|
||||
offset_x = 1 if x2 > x1 else -1
|
||||
horizontal = True
|
||||
step = height
|
||||
length = width / step
|
||||
steps = self._calculate_steps(length, step, width)
|
||||
|
||||
else:
|
||||
if y2 < y1:
|
||||
x1, x2 = x2, x1
|
||||
y1, y2 = y2, y1
|
||||
offset_y = 1 if y2 > y1 else -1
|
||||
offset_x = 1 if x2 > x1 else -1
|
||||
horizontal = False
|
||||
step = width
|
||||
length = height / step
|
||||
steps = self._calculate_steps(length, step, height)
|
||||
|
||||
dy = 0
|
||||
dx = 0
|
||||
for idx, step in enumerate(steps):
|
||||
if horizontal:
|
||||
self._draw_horizontal_line(
|
||||
int(x1 + dx),
|
||||
int(y1 + (idx * offset_y)),
|
||||
int(step)
|
||||
)
|
||||
dx += step * offset_x
|
||||
else:
|
||||
self._draw_vertical_line(
|
||||
int(x1 + (idx * offset_x)),
|
||||
int(y1 + dy),
|
||||
int(step)
|
||||
)
|
||||
dy += step * offset_y
|
||||
|
||||
def fill_rect(self, x1, y1, x2, y2):
|
||||
"""fill an area"""
|
||||
size = (abs(x2 - x1) + 1) * (abs(y2 - y1) + 1)
|
||||
self._set_area(
|
||||
min(x1, x2),
|
||||
min(y1, y2),
|
||||
max(x1, x2),
|
||||
max(y1, y2)
|
||||
)
|
||||
color = self._converted_background_color()
|
||||
for _ in range(0, size):
|
||||
self.driver.data(color, None)
|
114
gfxlcd/drawing/page.py
Normal file
114
gfxlcd/drawing/page.py
Normal file
@ -0,0 +1,114 @@
|
||||
import abc
|
||||
from gfxlcd.drawing.pixel import Pixel
|
||||
|
||||
|
||||
class Page(Pixel, metaclass=abc.ABCMeta):
|
||||
"""Page drawing algorithm"""
|
||||
def __init__(self):
|
||||
Pixel.__init__(self)
|
||||
self.buffer = []
|
||||
|
||||
def init(self):
|
||||
"""init page"""
|
||||
self.buffer = [[0] * (self.height // 8) for x in range(self.width)]
|
||||
|
||||
def draw_pixel(self, x, y):
|
||||
"""draw a pixel at x,y"""
|
||||
self.buffer[x][y//8] |= 1 << (y % 8)
|
||||
self.flush()
|
||||
|
||||
def _calculate_steps(self, length, step, required_length):
|
||||
"""calculate lineparts - helper"""
|
||||
steps = [length for _ in range(0, step)]
|
||||
if step * length < required_length:
|
||||
for idx in range(0, required_length - step * length):
|
||||
steps[idx] += 1
|
||||
|
||||
return steps
|
||||
|
||||
def draw_line(self, x1, y1, x2, y2):
|
||||
"""draw diagonal line"""
|
||||
width = abs(x2 - x1)
|
||||
height = abs(y2 - y1)
|
||||
if x1 == x2:
|
||||
steps = [height]
|
||||
horizontal = False
|
||||
offset_x = offset_y = 0
|
||||
elif y1 == y2:
|
||||
steps = [width]
|
||||
horizontal = True
|
||||
offset_x = offset_y = 0
|
||||
elif width > height:
|
||||
if x2 < x1:
|
||||
x1, x2 = x2, x1
|
||||
y1, y2 = y2, y1
|
||||
offset_y = 1 if y2 > y1 else -1
|
||||
offset_x = 1 if x2 > x1 else -1
|
||||
horizontal = True
|
||||
step = height
|
||||
length = width / step
|
||||
steps = self._calculate_steps(length, step, width)
|
||||
|
||||
else:
|
||||
if y2 < y1:
|
||||
x1, x2 = x2, x1
|
||||
y1, y2 = y2, y1
|
||||
offset_y = 1 if y2 > y1 else -1
|
||||
offset_x = 1 if x2 > x1 else -1
|
||||
horizontal = False
|
||||
step = width
|
||||
length = height / step
|
||||
steps = self._calculate_steps(length, step, height)
|
||||
dy = 0
|
||||
dx = 0
|
||||
for idx, step in enumerate(steps):
|
||||
if horizontal:
|
||||
for appendix in range(int(step)+1):
|
||||
self.draw_pixel(
|
||||
int(x1 + dx + appendix),
|
||||
int(y1 + (idx * offset_y))
|
||||
)
|
||||
dx += step * offset_x
|
||||
else:
|
||||
for appendix in range(int(step)+1):
|
||||
self.draw_pixel(
|
||||
int(x1 + (idx * offset_x)),
|
||||
int(y1 + dy + appendix)
|
||||
)
|
||||
dy += step * offset_y
|
||||
|
||||
def fill_rect(self, x1, y1, x2, y2):
|
||||
"""draw a filled rectangle"""
|
||||
if y2 < y1:
|
||||
y1, y2 = y2, y1
|
||||
if x2 < x1:
|
||||
x1, x2 = x2, x1
|
||||
start_page = y1 // 8
|
||||
start_bit = y1 % 8
|
||||
end_page = y2 // 8
|
||||
end_bit = y2 % 8
|
||||
rows = []
|
||||
first_page = int(('0' * start_bit).rjust(8, '1'), 2)
|
||||
last_page = int('1' * (end_bit+1), 2)
|
||||
if start_page != end_page:
|
||||
rows.append(first_page)
|
||||
for _ in range(end_page - start_page - 1):
|
||||
rows.append(255)
|
||||
rows.append(last_page)
|
||||
else:
|
||||
rows.append(first_page & last_page)
|
||||
|
||||
page = start_page
|
||||
for v in rows:
|
||||
for x in range(x2-x1+1):
|
||||
self.buffer[x1+x][page] |= v
|
||||
page += 1
|
||||
|
||||
def get_page_value(self, column, page):
|
||||
"""returns value"""
|
||||
return self.buffer[column][page]
|
||||
|
||||
@abc.abstractmethod
|
||||
def flush(self, force=None):
|
||||
"""flush buffer to the screen"""
|
||||
pass
|
73
gfxlcd/drawing/pixel.py
Normal file
73
gfxlcd/drawing/pixel.py
Normal file
@ -0,0 +1,73 @@
|
||||
import math
|
||||
|
||||
|
||||
class Pixel(object):
|
||||
def __init__(self):
|
||||
self.options['color'] = {
|
||||
'R': 255, 'G': 255, 'B': 255
|
||||
}
|
||||
self.options['background_color'] = {
|
||||
'R': 0, 'G': 0, 'B': 0,
|
||||
}
|
||||
|
||||
def draw_rect(self, x1, y1, x2, y2):
|
||||
"""draw a rectangle"""
|
||||
self.draw_line(x1, y1, x2, y1)
|
||||
self.draw_line(x1, y2, x2, y2)
|
||||
self.draw_line(x1, y1, x1, y2)
|
||||
self.draw_line(x2, y1, x2, y2)
|
||||
|
||||
def draw_circle(self, x, y, radius):
|
||||
"""draw a circle"""
|
||||
err = 0
|
||||
offset_x = radius
|
||||
offset_y = 0
|
||||
while offset_x >= offset_y:
|
||||
self.draw_pixel(x + offset_x, y + offset_y)
|
||||
self.draw_pixel(x + offset_y, y + offset_x)
|
||||
self.draw_pixel(x - offset_y, y + offset_x)
|
||||
self.draw_pixel(x - offset_x, y + offset_y)
|
||||
self.draw_pixel(x - offset_x, y - offset_y)
|
||||
self.draw_pixel(x - offset_y, y - offset_x)
|
||||
self.draw_pixel(x + offset_y, y - offset_x)
|
||||
self.draw_pixel(x + offset_x, y - offset_y)
|
||||
if err <= 0:
|
||||
offset_y += 1
|
||||
err += 2*offset_y + 1
|
||||
else:
|
||||
offset_x -= 1
|
||||
err -= 2*offset_x + 1
|
||||
|
||||
def draw_arc(self, x, y, radius, start, end):
|
||||
"""draw an arc"""
|
||||
start = start * math.pi / 180
|
||||
end = end * math.pi / 180
|
||||
|
||||
err = 0
|
||||
offset_x = radius
|
||||
offset_y = 0
|
||||
while offset_x >= offset_y:
|
||||
if start <= math.atan2(offset_y, offset_x) <= end:
|
||||
self.draw_pixel(x + offset_x, y + offset_y)
|
||||
if start <= math.atan2(offset_x, offset_y) <= end:
|
||||
self.draw_pixel(x + offset_y, y + offset_x)
|
||||
if start <= math.atan2(offset_x, -offset_y) <= end:
|
||||
self.draw_pixel(x - offset_y, y + offset_x)
|
||||
if start <= math.atan2(offset_y, -offset_x) <= end:
|
||||
self.draw_pixel(x - offset_x, y + offset_y)
|
||||
|
||||
if start <= math.atan2(-offset_y, -offset_x) + 2*math.pi <= end:
|
||||
self.draw_pixel(x - offset_x, y - offset_y)
|
||||
if start <= math.atan2(-offset_x, -offset_y) + 2*math.pi <= end:
|
||||
self.draw_pixel(x - offset_y, y - offset_x)
|
||||
if start <= math.atan2(-offset_x, offset_y) + 2*math.pi <= end:
|
||||
self.draw_pixel(x + offset_y, y - offset_x)
|
||||
if start <= math.atan2(-offset_y, offset_x) + 2*math.pi <= end:
|
||||
self.draw_pixel(x + offset_x, y - offset_y)
|
||||
|
||||
if err <= 0:
|
||||
offset_y += 1
|
||||
err += 2*offset_y + 1
|
||||
else:
|
||||
offset_x -= 1
|
||||
err -= 2*offset_x + 1
|
1
gfxlcd/driver/__init__.py
Normal file
1
gfxlcd/driver/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
__author__ = 'kosci'
|
1
gfxlcd/driver/ili9325/__init__.py
Normal file
1
gfxlcd/driver/ili9325/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
__author__ = 'kosci'
|
72
gfxlcd/driver/ili9325/gpio.py
Normal file
72
gfxlcd/driver/ili9325/gpio.py
Normal file
@ -0,0 +1,72 @@
|
||||
import time
|
||||
import RPi.GPIO
|
||||
from gfxlcd.abstract.driver import Driver
|
||||
|
||||
RPi.GPIO.setmode(RPi.GPIO.BCM)
|
||||
|
||||
|
||||
class GPIO(Driver):
|
||||
def __init__(self):
|
||||
self.pins = {
|
||||
'RS': 27,
|
||||
'W': 17,
|
||||
'DB8': 22,
|
||||
'DB9': 23,
|
||||
'DB10': 24,
|
||||
'DB11': 5,
|
||||
'DB12': 12,
|
||||
'DB13': 16,
|
||||
'DB14': 20,
|
||||
'DB15': 21,
|
||||
'RST': 25,
|
||||
}
|
||||
self.data_pins = [
|
||||
'DB8', 'DB9', 'DB10', 'DB11', 'DB12', 'DB13', 'DB14', 'DB15',
|
||||
]
|
||||
|
||||
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)
|
||||
|
||||
def reset(self):
|
||||
"""reset a display"""
|
||||
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 _set_pins(self, bits):
|
||||
"""set rpi pins"""
|
||||
for pin in self.data_pins:
|
||||
value = bits & 0x01
|
||||
RPi.GPIO.output(self.pins[pin], value)
|
||||
bits >>= 1
|
||||
|
||||
def cmd(self, char, enable):
|
||||
"""send command to display"""
|
||||
RPi.GPIO.output(self.pins['RS'], 0)
|
||||
self.send(char, enable)
|
||||
|
||||
def send(self, char, enable):
|
||||
"""send 16bit as 2*8bit"""
|
||||
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)
|
||||
|
||||
def data(self, data, enable):
|
||||
"""send data to display"""
|
||||
RPi.GPIO.output(self.pins['RS'], 1)
|
||||
self.send(data, enable)
|
||||
|
||||
def cmd_data(self, cmd, data):
|
||||
RPi.GPIO.output(self.pins['RS'], 0)
|
||||
self.send(cmd, None)
|
||||
RPi.GPIO.output(self.pins['RS'], 1)
|
||||
self.send(data, None)
|
174
gfxlcd/driver/ili9325/ili9325.py
Normal file
174
gfxlcd/driver/ili9325/ili9325.py
Normal file
@ -0,0 +1,174 @@
|
||||
import time
|
||||
from gfxlcd.drawing.area import Area
|
||||
from gfxlcd.abstract.chip import Chip
|
||||
|
||||
|
||||
class ILI9325(Area, Chip):
|
||||
"""CLass for ILI9325 based LCD"""
|
||||
def __init__(self, width, height, driver):
|
||||
Chip.__init__(self, width, height, driver, True)
|
||||
Area.__init__(self)
|
||||
|
||||
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()
|
||||
|
||||
# ************* ILI9325C/D **********
|
||||
# set SS and SM bit
|
||||
self.driver.cmd(0x0001, None)
|
||||
self.driver.data(0x0100, 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)
|
||||
# Resize register
|
||||
self.driver.cmd(0x0004, None)
|
||||
self.driver.data(0x0000, None)
|
||||
# set the back porch and front porch
|
||||
self.driver.cmd(0x0008, None)
|
||||
self.driver.data(0x0207, None)
|
||||
# set non-display area refresh cycle ISC[3:0]
|
||||
self.driver.cmd(0x0009, None)
|
||||
self.driver.data(0x0000, None)
|
||||
# FMARK function
|
||||
self.driver.cmd(0x000A, None)
|
||||
self.driver.data(0x0000, None)
|
||||
# RGB interface setting
|
||||
self.driver.cmd(0x000C, None)
|
||||
self.driver.data(0x0000, None)
|
||||
# Frame marker Position
|
||||
self.driver.cmd(0x000D, None)
|
||||
self.driver.data(0x0000, None)
|
||||
# RGB interface polarity
|
||||
self.driver.cmd(0x000F, None)
|
||||
self.driver.data(0x0000, None)
|
||||
|
||||
# ************* Power On sequence ****************
|
||||
# SAP, BT[3:0], AP, DSTB, SLP, STB
|
||||
self.driver.cmd(0x0010, None)
|
||||
self.driver.data(0x0000, None)
|
||||
# DC1[2:0], DC0[2:0], VC[2:0]
|
||||
self.driver.cmd(0x0011, None)
|
||||
self.driver.data(0x0007, None)
|
||||
# VREG1OUT voltage
|
||||
self.driver.cmd(0x0012, None)
|
||||
self.driver.data(0x0000, None)
|
||||
# VDV[4:0] for VCOM amplitude
|
||||
self.driver.cmd(0x0013, None)
|
||||
self.driver.data(0x0000, None)
|
||||
self.driver.cmd(0x0007, None)
|
||||
self.driver.data(0x0001, None)
|
||||
time.sleep(0.2) # Dis-charge capacitor power voltage
|
||||
# SAP, BT[3:0], AP, DSTB, SLP, STB
|
||||
self.driver.cmd(0x0010, None)
|
||||
self.driver.data(0x1690, None)
|
||||
# Set DC1[2:0], DC0[2:0], VC[2:0]
|
||||
self.driver.cmd(0x0011, None)
|
||||
self.driver.data(0x0227, None)
|
||||
time.sleep(0.05)
|
||||
self.driver.cmd(0x0012, None)
|
||||
self.driver.data(0x000D, None)
|
||||
time.sleep(0.05)
|
||||
# VDV[4:0] for VCOM amplitude
|
||||
self.driver.cmd(0x0013, None)
|
||||
self.driver.data(0x1200, None)
|
||||
# 04 VCM[5:0] for VCOMH
|
||||
self.driver.cmd(0x0029, None)
|
||||
self.driver.data(0x000A, None)
|
||||
# Set Frame Rate
|
||||
self.driver.cmd(0x002B, None)
|
||||
self.driver.data(0x000D, None)
|
||||
time.sleep(0.05)
|
||||
# GRAM horizontal Address
|
||||
self.driver.cmd(0x0020, None)
|
||||
self.driver.data(0x0000, None)
|
||||
# GRAM Vertical Address
|
||||
self.driver.cmd(0x0021, None)
|
||||
self.driver.data(0x0000, None)
|
||||
|
||||
# ************* Adjust the Gamma Curve *************
|
||||
self.driver.cmd(0x0030, None)
|
||||
self.driver.data(0x0000, None)
|
||||
self.driver.cmd(0x0031, None)
|
||||
self.driver.data(0x0404, None)
|
||||
self.driver.cmd(0x0032, None)
|
||||
self.driver.data(0x0003, None)
|
||||
self.driver.cmd(0x0035, None)
|
||||
self.driver.data(0x0405, None)
|
||||
self.driver.cmd(0x0036, None)
|
||||
self.driver.data(0x0808, None)
|
||||
self.driver.cmd(0x0037, None)
|
||||
self.driver.data(0x0407, None)
|
||||
self.driver.cmd(0x0038, None)
|
||||
self.driver.data(0x0303, None)
|
||||
self.driver.cmd(0x0039, None)
|
||||
self.driver.data(0x0707, None)
|
||||
self.driver.cmd(0x003C, None)
|
||||
self.driver.data(0x0504, None)
|
||||
self.driver.cmd(0x003D, None)
|
||||
self.driver.data(0x0808, None)
|
||||
|
||||
# ************* Set GRAM area *************
|
||||
# Horizontal GRAM Start Address
|
||||
self.driver.cmd(0x0050, None)
|
||||
self.driver.data(0x0000, None)
|
||||
# Horizontal GRAM End Address
|
||||
self.driver.cmd(0x0051, None)
|
||||
self.driver.data(0x00EF, None)
|
||||
# Vertical GRAM Start Address
|
||||
self.driver.cmd(0x0052, None)
|
||||
self.driver.data(0x0000, None)
|
||||
# Vertical GRAM Start Address
|
||||
self.driver.cmd(0x0053, None)
|
||||
self.driver.data(0x013F, None)
|
||||
# Gate Scan Line
|
||||
self.driver.cmd(0x0060, None)
|
||||
self.driver.data(0xA700, None)
|
||||
# NDL, VLE, REV
|
||||
self.driver.cmd(0x0061, None)
|
||||
self.driver.data(0x0001, None)
|
||||
# set scrolling line
|
||||
self.driver.cmd(0x006A, None)
|
||||
self.driver.data(0x0000, None)
|
||||
|
||||
# ************* Partial Display Control *************
|
||||
self.driver.cmd(0x0080, None)
|
||||
self.driver.data(0x0000, None)
|
||||
self.driver.cmd(0x0081, None)
|
||||
self.driver.data(0x0000, None)
|
||||
self.driver.cmd(0x0082, None)
|
||||
self.driver.data(0x0000, None)
|
||||
self.driver.cmd(0x0083, None)
|
||||
self.driver.data(0x0000, None)
|
||||
self.driver.cmd(0x0084, None)
|
||||
self.driver.data(0x0000, None)
|
||||
self.driver.cmd(0x0085, None)
|
||||
self.driver.data(0x0000, None)
|
||||
|
||||
# ************* Panel Control *************
|
||||
self.driver.cmd(0x0090, None)
|
||||
self.driver.data(0x0010, None)
|
||||
self.driver.cmd(0x0092, None)
|
||||
self.driver.data(0x0000, None)
|
||||
# 262K color and display ON
|
||||
self.driver.cmd(0x0007, None)
|
||||
self.driver.data(0x0133, None)
|
1
gfxlcd/driver/nju6450/__init__.py
Normal file
1
gfxlcd/driver/nju6450/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
__author__ = 'kosci'
|
69
gfxlcd/driver/nju6450/gpio.py
Normal file
69
gfxlcd/driver/nju6450/gpio.py
Normal file
@ -0,0 +1,69 @@
|
||||
import time
|
||||
import RPi.GPIO
|
||||
from gfxlcd.abstract.driver import Driver
|
||||
|
||||
RPi.GPIO.setmode(RPi.GPIO.BCM)
|
||||
|
||||
|
||||
class GPIO(Driver):
|
||||
def __init__(self):
|
||||
self.pins = {
|
||||
'A0': 17,
|
||||
'E1': 22,
|
||||
'E2': 21,
|
||||
'D0': 23,
|
||||
'D1': 24,
|
||||
'D2': 25,
|
||||
'D3': 12,
|
||||
'D4': 16,
|
||||
'D5': 20,
|
||||
'D6': 26,
|
||||
'D7': 19,
|
||||
'RST': 5,
|
||||
}
|
||||
|
||||
self.data_pins = [
|
||||
'D0', 'D1', 'D2', 'D3', 'D4', 'D5', 'D6', 'D7'
|
||||
]
|
||||
|
||||
def init(self):
|
||||
"""init a device"""
|
||||
for pin in self.pins:
|
||||
RPi.GPIO.setup(self.pins[pin], RPi.GPIO.OUT)
|
||||
RPi.GPIO.output(self.pins[pin], 0)
|
||||
|
||||
def reset(self):
|
||||
"""resets a device"""
|
||||
RPi.GPIO.output(self.pins['RST'], 1)
|
||||
time.sleep(0.025)
|
||||
RPi.GPIO.output(self.pins['RST'], 0)
|
||||
time.sleep(0.025)
|
||||
RPi.GPIO.output(self.pins['RST'], 1)
|
||||
time.sleep(0.025)
|
||||
RPi.GPIO.output(self.pins['A0'], 0)
|
||||
RPi.GPIO.output(self.pins['E1'], 1)
|
||||
RPi.GPIO.output(self.pins['E2'], 1)
|
||||
|
||||
def cmd(self, char, enable):
|
||||
"""send command"""
|
||||
RPi.GPIO.output(self.pins['A0'], 0)
|
||||
self.send(char, enable)
|
||||
|
||||
def data(self, char, enable):
|
||||
"""send data"""
|
||||
RPi.GPIO.output(self.pins['A0'], 1)
|
||||
self.send(char, enable)
|
||||
|
||||
def send(self, data, enable):
|
||||
"""Write to gpio"""
|
||||
RPi.GPIO.output(self.pins['E1'], 0)
|
||||
RPi.GPIO.output(self.pins['E2'], 0)
|
||||
for i in self.data_pins:
|
||||
value = data & 0x01
|
||||
RPi.GPIO.output(self.pins[i], value)
|
||||
data >>= 1
|
||||
|
||||
RPi.GPIO.output(self.pins['E'+str(enable+1)], 1)
|
||||
time.sleep(0.00025)
|
||||
RPi.GPIO.output(self.pins['E1'], 0)
|
||||
RPi.GPIO.output(self.pins['E2'], 0)
|
53
gfxlcd/driver/nju6450/nju6450.py
Normal file
53
gfxlcd/driver/nju6450/nju6450.py
Normal file
@ -0,0 +1,53 @@
|
||||
from gfxlcd.drawing.page import Page
|
||||
from gfxlcd.abstract.chip import Chip
|
||||
|
||||
|
||||
class NJU6450(Page, Chip):
|
||||
"""Class for an LCD with NJU6450 chip"""
|
||||
def __init__(self, width, height, driver, auto_flush=True):
|
||||
Chip.__init__(self, width, height, driver, auto_flush)
|
||||
Page.__init__(self)
|
||||
|
||||
def init(self):
|
||||
"""initialize display"""
|
||||
self.driver.init()
|
||||
Page.init(self)
|
||||
Chip.init(self)
|
||||
self.driver.reset()
|
||||
|
||||
init_sequence = [0xae, 0xa4, 0xa9, 0xe2, 0xa0, 0xaf]
|
||||
for cmd in init_sequence:
|
||||
self.driver.cmd(cmd, 0)
|
||||
self.driver.cmd(cmd, 1)
|
||||
|
||||
def set_xy(self, x, y):
|
||||
"""set xy pos"""
|
||||
if x < self.width/2:
|
||||
self.driver.cmd(0xB8 | y, 0)
|
||||
self.driver.cmd(0x00 | x, 0)
|
||||
else:
|
||||
self.driver.cmd(0xB8 | y, 1)
|
||||
self.driver.cmd(0x00 | (x - self.width//2), 1)
|
||||
|
||||
def _converted_background_color(self):
|
||||
"""convert RGB background to available color"""
|
||||
return 1
|
||||
|
||||
def _converted_color(self):
|
||||
"""convert RGB color to available color"""
|
||||
return 1
|
||||
|
||||
def flush(self, force=None):
|
||||
"""flush buffer to device
|
||||
:force - boolean|None"""
|
||||
if force is None:
|
||||
force = self.options['auto_flush']
|
||||
|
||||
if force:
|
||||
for j in range(0, self.height//8):
|
||||
for i in range(0, self.width):
|
||||
self.set_xy(i, j)
|
||||
if i < self.width/2:
|
||||
self.driver.data(self.get_page_value(i, j), 0)
|
||||
else:
|
||||
self.driver.data(self.get_page_value(i, j), 1)
|
1
gfxlcd/driver/ssd1306/__init__.py
Normal file
1
gfxlcd/driver/ssd1306/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
__author__ = 'kosci'
|
49
gfxlcd/driver/ssd1306/spi.py
Normal file
49
gfxlcd/driver/ssd1306/spi.py
Normal file
@ -0,0 +1,49 @@
|
||||
import spidev
|
||||
import RPi.GPIO as GPIO
|
||||
|
||||
|
||||
GPIO.setmode(GPIO.BCM)
|
||||
import time
|
||||
from gfxlcd.abstract.driver import Driver
|
||||
|
||||
|
||||
class SPI(Driver):
|
||||
def __init__(self):
|
||||
self.pins = {
|
||||
'RST': 13,
|
||||
'DC': 6,
|
||||
}
|
||||
self.spi = None
|
||||
|
||||
def init(self):
|
||||
"""init sequence"""
|
||||
for pin in self.pins:
|
||||
GPIO.setup(self.pins[pin], GPIO.OUT)
|
||||
GPIO.output(self.pins[pin], 0)
|
||||
|
||||
spi = spidev.SpiDev()
|
||||
spi.open(0,0)
|
||||
spi.max_speed_hz = 8000000
|
||||
spi.mode = 0
|
||||
self.spi = spi
|
||||
|
||||
def reset(self):
|
||||
"""reset device"""
|
||||
GPIO.output(self.pins['RST'], 1)
|
||||
time.sleep(0.025)
|
||||
GPIO.output(self.pins['RST'], 0)
|
||||
time.sleep(0.025)
|
||||
GPIO.output(self.pins['RST'], 1)
|
||||
time.sleep(0.025)
|
||||
|
||||
def cmd(self, data, enable=None):
|
||||
"""send command to device"""
|
||||
GPIO.output(self.pins['DC'], 0)
|
||||
self.spi.xfer2([data])
|
||||
|
||||
def data(self, data, enable=None):
|
||||
"""send data to device"""
|
||||
GPIO.output(self.pins['DC'], 1)
|
||||
self.spi.xfer2([data])
|
||||
GPIO.output(self.pins['DC'], 0)
|
||||
|
80
gfxlcd/driver/ssd1306/ssd1306.py
Normal file
80
gfxlcd/driver/ssd1306/ssd1306.py
Normal file
@ -0,0 +1,80 @@
|
||||
from gfxlcd.drawing.page import Page
|
||||
from gfxlcd.abstract.chip import Chip
|
||||
|
||||
|
||||
class SSD1306(Page, Chip):
|
||||
"""Class for an LCD with SSD306 chip"""
|
||||
def __init__(self, width, height, driver, auto_flush=True):
|
||||
Chip.__init__(self, width, height, driver, auto_flush)
|
||||
Page.__init__(self)
|
||||
|
||||
def init(self):
|
||||
"""inits a device"""
|
||||
self.driver.init()
|
||||
Page.init(self)
|
||||
Chip.init(self)
|
||||
self.driver.reset()
|
||||
self.driver.cmd(0xae) # turn off panel
|
||||
self.driver.cmd(0x00) # set low column address
|
||||
self.driver.cmd(0x10) # set high column address
|
||||
self.driver.cmd(0x40) # set start line address
|
||||
|
||||
self.driver.cmd(0x20) # addr mode
|
||||
self.driver.cmd(0x02) # horizontal
|
||||
|
||||
self.driver.cmd(0xb0) # set page address
|
||||
self.driver.cmd(0x81) # set contrast control register
|
||||
self.driver.cmd(0xff)
|
||||
self.driver.cmd(0xa1) # a0/a1 set segment re-map 127 to 0 a0:0 to seg127
|
||||
self.driver.cmd(0xc8) # c8/c0 set com(N-1)to com0 c0:com0 to com(N-1)
|
||||
self.driver.cmd(0xa6) # set normal display, a6 - normal, a7 - inverted
|
||||
|
||||
self.driver.cmd(0xa8) # set multiplex ratio(16to63)
|
||||
self.driver.cmd(0x3f) # 1/64 duty
|
||||
|
||||
self.driver.cmd(0xd3) # set display offset
|
||||
self.driver.cmd(0x00) # not offset
|
||||
|
||||
self.driver.cmd(0xd5) # set display clock divide ratio/oscillator frequency
|
||||
self.driver.cmd(0x80) # set divide ratio
|
||||
|
||||
self.driver.cmd(0xd9) # set pre-charge period
|
||||
self.driver.cmd(0xf1)
|
||||
self.driver.cmd(0xda) # set com pins hardware configuration
|
||||
self.driver.cmd(0x12)
|
||||
|
||||
self.driver.cmd(0xdb) # set vcomh
|
||||
self.driver.cmd(0x40)
|
||||
|
||||
self.driver.cmd(0x8d) # charge pump
|
||||
self.driver.cmd(0x14) # enable charge pump
|
||||
self.driver.cmd(0xaf) # turn on panel
|
||||
|
||||
def _converted_background_color(self):
|
||||
"""convert RGB background to available color"""
|
||||
return 1
|
||||
|
||||
def _converted_color(self):
|
||||
"""convert RGB color to available color"""
|
||||
return 1
|
||||
|
||||
def flush(self, force=None):
|
||||
"""flush buffer to device
|
||||
:force - boolean|None"""
|
||||
if force is None:
|
||||
force = self.options['auto_flush']
|
||||
|
||||
if force:
|
||||
for j in range(0, self.height//8):
|
||||
self.set_area(0, j, self.width-1, j+1)
|
||||
for i in range(0, self.width):
|
||||
self.driver.data(self.get_page_value(i, j))
|
||||
|
||||
def set_area(self, x1, y1, x2, y2):
|
||||
"""set area to work on"""
|
||||
self.driver.cmd(0x22)
|
||||
self.driver.cmd(0xb0 + y1)
|
||||
self.driver.cmd(0xb0 + y2)
|
||||
self.driver.cmd(0x21)
|
||||
self.driver.cmd(x1)
|
||||
self.driver.cmd(x2)
|
183
readme.md
Normal file
183
readme.md
Normal file
@ -0,0 +1,183 @@
|
||||
What it is
|
||||
===
|
||||
|
||||
Library for graphical LCDs for Python on Raspberry Pi. Creates a united interface for supported devices
|
||||
|
||||
Supported:
|
||||
|
||||
- ili325 via GPIO
|
||||
- ssd1306 via SPI
|
||||
- nju6450 via GPIO
|
||||
|
||||
On NJU and SSD uses buffer to keep current content as help for page operations.
|
||||
|
||||
Wiring is below
|
||||
|
||||
|
||||
Initialization
|
||||
===
|
||||
##SSD1306
|
||||
### SPI
|
||||
|
||||
from driver.ssd1306.spi import SPI
|
||||
from driver.ssd1306.ssd1306 import SSD1306
|
||||
drv = SPI()
|
||||
o = SSD1306(128, 64, drv)
|
||||
o.init()
|
||||
|
||||
If you want to set your own pins:
|
||||
|
||||
drv = SPI()
|
||||
drv.pins = {
|
||||
'RST': 13,
|
||||
'DC': 6,
|
||||
}
|
||||
o = SSD1306(128, 64, drv)
|
||||
o.init()
|
||||
|
||||
##NJU6450
|
||||
### GPIO
|
||||
|
||||
from gfxlcd.driver.nju6450.gpio import GPIO
|
||||
from gfxlcd.driver.nju6450.nju6450 import NJU6450
|
||||
drv = GPIO()
|
||||
o = NJU6450(122, 32, drv)
|
||||
o.init()
|
||||
|
||||
Custom wiring:
|
||||
|
||||
from gfxlcd.driver.nju6450.gpio import GPIO
|
||||
from gfxlcd.driver.nju6450.nju6450 import NJU6450
|
||||
drv = GPIO()
|
||||
drv.pins = {
|
||||
'A0': 17,
|
||||
'E1': 22,
|
||||
'E2': 21,
|
||||
'D0': 23,
|
||||
'D1': 24,
|
||||
'D2': 25,
|
||||
'D3': 12,
|
||||
'D4': 16,
|
||||
'D5': 20,
|
||||
'D6': 26,
|
||||
'D7': 19,
|
||||
'RST': 5,
|
||||
}
|
||||
o = NJU6450(122, 32, drv)
|
||||
o.init()
|
||||
|
||||
##ILI9325
|
||||
### GPIO
|
||||
|
||||
from gfxlcd.driver.ili9325.gpio import GPIO
|
||||
from gfxlcd.driver.ili9325.ili9325 import ILI9325
|
||||
drv = GPIO()
|
||||
o = ILI9325(240, 320, drv)
|
||||
o.init()
|
||||
|
||||
Custom pins:
|
||||
|
||||
from gfxlcd.driver.ili9325.gpio import GPIO
|
||||
from gfxlcd.driver.ili9325.ili9325 import ILI9325
|
||||
drv = GPIO()
|
||||
drv.pins = {
|
||||
'RS': 27,
|
||||
'W': 17,
|
||||
'DB8': 22,
|
||||
'DB9': 23,
|
||||
'DB10': 24,
|
||||
'DB11': 5,
|
||||
'DB12': 12,
|
||||
'DB13': 16,
|
||||
'DB14': 20,
|
||||
'DB15': 21,
|
||||
'RST': 25,
|
||||
}
|
||||
o = ILI9325(240, 320, drv)
|
||||
o.init()
|
||||
|
||||
|
||||
Drawing functions
|
||||
===
|
||||
draw_pixel
|
||||
|
||||
draw_line
|
||||
|
||||
draw_rect
|
||||
|
||||
draw_circle
|
||||
|
||||
draw_arc
|
||||
|
||||
fill_rect
|
||||
|
||||
|
||||
Colours
|
||||
===
|
||||
lcd.color = (r, g, b)
|
||||
lcd.background_color = (r, g ,b)
|
||||
|
||||
|
||||
Wiring
|
||||
===
|
||||
|
||||
##SSD1306
|
||||
### SPI
|
||||
SPI wiring + 2 additional pins. Defaults:
|
||||
|
||||
LCD Raspberry Pi
|
||||
GND ----------- GND
|
||||
+3.3V ----------- +3.3V
|
||||
SCL ----------- G11
|
||||
SDA ----------- G10
|
||||
RST ----------- G13
|
||||
D/C ----------- G6
|
||||
|
||||
|
||||
##NJU6450
|
||||
### GPIO
|
||||
Default wiring:
|
||||
|
||||
LCD Raspberry Pi
|
||||
1 (Vss) ------- GND
|
||||
2 (Vdd) ------- +5V
|
||||
3 (V0) ---[-\-] 10k
|
||||
\--- GND
|
||||
4 (A0) ---------------------- G17
|
||||
5 (E1) ---------------------- G22
|
||||
6 (E2) ---------------------- G21
|
||||
7 (R/W) ------- GND
|
||||
8 (D0) ---------------------- G23
|
||||
9 (D1) ---------------------- G24
|
||||
10 (D2) ---------------------- G25
|
||||
11 (D3) ---------------------- G12
|
||||
12 (D4) ---------------------- G16
|
||||
13 (D5) ---------------------- G20
|
||||
14 (D6) ---------------------- G26
|
||||
15 (D7) ---------------------- G19
|
||||
16 (RST) ------- +5V
|
||||
17 (A) ------- +5V
|
||||
18 (K) ------- GND
|
||||
|
||||
##ILI9325
|
||||
### GPIO
|
||||
Default:
|
||||
|
||||
TFT Raspberry Pi 2B
|
||||
|
||||
GND ------------------------ GND
|
||||
Vcc ------------------------ 3.3
|
||||
RS ------------------------ G27 (data[H]/cmd[L])
|
||||
WR ------------------------ G17
|
||||
RD ------------------------ 3.3 (never read from screen)
|
||||
DB8 ------------------------ G22
|
||||
DB9 ------------------------ G23
|
||||
DB10 ------------------------ G24
|
||||
DB11 ------------------------ G5
|
||||
DB12 ------------------------ G12
|
||||
DB13 ------------------------ G16
|
||||
DB14 ------------------------ G20
|
||||
DB15 ------------------------ G21
|
||||
CS ------------------------ GND (always selected)
|
||||
REST ------------------------ G25
|
||||
LED_A ------------------------ 3.3
|
4
setup.cfg
Normal file
4
setup.cfg
Normal file
@ -0,0 +1,4 @@
|
||||
[bdist_wheel]
|
||||
universal = 1
|
||||
[metadata]
|
||||
description-file = readme.md
|
39
setup.py
Normal file
39
setup.py
Normal file
@ -0,0 +1,39 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""setup for GfxLCD package"""
|
||||
|
||||
import os
|
||||
from setuptools import setup, find_packages
|
||||
|
||||
|
||||
def read(*paths):
|
||||
"""Build a file path from *paths* and return the contents."""
|
||||
with open(os.path.join(*paths), 'r') as file_handler:
|
||||
return file_handler.read()
|
||||
|
||||
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'],
|
||||
long_description=(read('readme.md')),
|
||||
url='https://bitbucket.org/kosci/charlcd.git',
|
||||
license='MIT',
|
||||
author='Bartosz Kościów',
|
||||
author_email='kosci1@gmail.com',
|
||||
py_modules=['gfxlcd'],
|
||||
include_package_data=True,
|
||||
classifiers=[
|
||||
'Development Status :: 4 - Beta',
|
||||
'Environment :: Console',
|
||||
'Intended Audience :: Developers',
|
||||
'Natural Language :: English',
|
||||
'License :: OSI Approved :: MIT License',
|
||||
'Operating System :: OS Independent',
|
||||
'Programming Language :: Python',
|
||||
'Programming Language :: Python :: 3',
|
||||
'Topic :: Software Development :: Libraries :: Python Modules',
|
||||
'Topic :: Home Automation'
|
||||
],
|
||||
packages=find_packages(exclude=['tests*']),
|
||||
)
|
2
tests3
Normal file
2
tests3
Normal file
@ -0,0 +1,2 @@
|
||||
chmod 644 gfxlcd/tests/*.py
|
||||
python3 -m nose --with-specplugin
|
20
tox.ini
Normal file
20
tox.ini
Normal file
@ -0,0 +1,20 @@
|
||||
[tox]
|
||||
envlist = py35
|
||||
skipsdist = True
|
||||
[testenv]
|
||||
setenv = VIRTUAL_ENV={envdir}
|
||||
deps=
|
||||
nose
|
||||
mock
|
||||
future
|
||||
flake8
|
||||
pylint
|
||||
whitelist_externals = /bin/bash
|
||||
commands= nosetests --with-xunit --xunit-file=junit-{envname}.xml charlcd/tests
|
||||
rm flake8-{envname}.log
|
||||
/bin/bash -c "flake8 --output-file=flake8-{envname}.log gfxlcd || :"
|
||||
/bin/bash -c "pylint gfxlcd > pylint-{envname}.log || :"
|
||||
[flake8]
|
||||
show-source = True
|
||||
exclude = .git,.venv,.tox,dist,doc,build,*egg,*/tests/*
|
||||
|
Loading…
Reference in New Issue
Block a user