diff --git a/gfxlcd/demos/ili.py b/gfxlcd/demos/ili9325.py similarity index 100% rename from gfxlcd/demos/ili.py rename to gfxlcd/demos/ili9325.py diff --git a/gfxlcd/demos/ili_2.py b/gfxlcd/demos/ili9325_2.py similarity index 100% rename from gfxlcd/demos/ili_2.py rename to gfxlcd/demos/ili9325_2.py diff --git a/gfxlcd/demos/ili_image.py b/gfxlcd/demos/ili9325_image.py similarity index 100% rename from gfxlcd/demos/ili_image.py rename to gfxlcd/demos/ili9325_image.py diff --git a/gfxlcd/demos/ili9486.py b/gfxlcd/demos/ili9486.py new file mode 100644 index 0000000..58a531e --- /dev/null +++ b/gfxlcd/demos/ili9486.py @@ -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() diff --git a/gfxlcd/demos/ili9486_image.py b/gfxlcd/demos/ili9486_image.py new file mode 100644 index 0000000..5c957fd --- /dev/null +++ b/gfxlcd/demos/ili9486_image.py @@ -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) diff --git a/gfxlcd/drawing/area.py b/gfxlcd/drawing/area.py index 48bd8eb..418a84b 100644 --- a/gfxlcd/drawing/area.py +++ b/gfxlcd/drawing/area.py @@ -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) diff --git a/gfxlcd/driver/ad7843/ad7843.py b/gfxlcd/driver/ad7843/ad7843.py index 7e9e56b..6e107fe 100644 --- a/gfxlcd/driver/ad7843/ad7843.py +++ b/gfxlcd/driver/ad7843/ad7843.py @@ -4,7 +4,7 @@ import RPi.GPIO class AD7843(object): """AD7843 class""" - def __init__(self, width, height, int_pin=None, callback=None, spi=0, speed=2000000): + 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() @@ -17,6 +17,7 @@ class AD7843(object): 'ratio_x': 14.35, 'ratio_y': 10.59 } + self.cs_pin = cs_pin self.int_pin = int_pin self.callback = callback self.bouncetime = 500 @@ -28,6 +29,9 @@ class AD7843(object): 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""" @@ -39,7 +43,11 @@ class AD7843(object): 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""" diff --git a/gfxlcd/driver/ili9325/gpio.py b/gfxlcd/driver/ili9325/gpio.py index 9d06f5d..4d26d80 100644 --- a/gfxlcd/driver/ili9325/gpio.py +++ b/gfxlcd/driver/ili9325/gpio.py @@ -34,6 +34,12 @@ class GPIO(Driver): 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']: diff --git a/gfxlcd/driver/ili9325/ili9325.py b/gfxlcd/driver/ili9325/ili9325.py index b260f01..27562b5 100644 --- a/gfxlcd/driver/ili9325/ili9325.py +++ b/gfxlcd/driver/ili9325/ili9325.py @@ -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) diff --git a/gfxlcd/driver/ili9486/__init__.py b/gfxlcd/driver/ili9486/__init__.py new file mode 100644 index 0000000..7a53ea9 --- /dev/null +++ b/gfxlcd/driver/ili9486/__init__.py @@ -0,0 +1,2 @@ +"""driver/ili9486 module""" +__author__ = 'Bartosz Kosciow' diff --git a/gfxlcd/driver/ili9486/ili9486.py b/gfxlcd/driver/ili9486/ili9486.py new file mode 100644 index 0000000..58ed1c3 --- /dev/null +++ b/gfxlcd/driver/ili9486/ili9486.py @@ -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) diff --git a/gfxlcd/driver/ili9486/spi.py b/gfxlcd/driver/ili9486/spi.py new file mode 100644 index 0000000..fab722c --- /dev/null +++ b/gfxlcd/driver/ili9486/spi.py @@ -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) diff --git a/gfxlcd/driver/nju6450/nju6450.py b/gfxlcd/driver/nju6450/nju6450.py index 200ed15..a99c77e 100644 --- a/gfxlcd/driver/nju6450/nju6450.py +++ b/gfxlcd/driver/nju6450/nju6450.py @@ -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""" diff --git a/gfxlcd/driver/ssd1306/ssd1306.py b/gfxlcd/driver/ssd1306/ssd1306.py index 4b595a1..dfe6078 100644 --- a/gfxlcd/driver/ssd1306/ssd1306.py +++ b/gfxlcd/driver/ssd1306/ssd1306.py @@ -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"""