From 5c7fca57d7242d268ccf4438e049af1c28a846ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20Ko=C5=9Bci=C3=B3w?= Date: Sun, 4 Jun 2017 21:00:13 +0200 Subject: [PATCH 1/2] rotate ssd --- gfxlcd/demos/assets/20x20.png | Bin 0 -> 396 bytes gfxlcd/demos/ssd_3.py | 60 +++++++++++++++++++++++++++++++ gfxlcd/demos/ssd_image_1.py | 19 ++++++++++ gfxlcd/drawing/page.py | 8 ++++- gfxlcd/drawing/pixel.py | 5 +-- gfxlcd/driver/ssd1306/ssd1306.py | 41 +++++++++++++++++---- gfxlcd/tests/test_chip.py | 31 ++++++++++++++++ 7 files changed, 154 insertions(+), 10 deletions(-) create mode 100644 gfxlcd/demos/assets/20x20.png create mode 100644 gfxlcd/demos/ssd_3.py create mode 100644 gfxlcd/demos/ssd_image_1.py create mode 100644 gfxlcd/tests/test_chip.py diff --git a/gfxlcd/demos/assets/20x20.png b/gfxlcd/demos/assets/20x20.png new file mode 100644 index 0000000000000000000000000000000000000000..e6ff3f54b3c81863f15b819a6c2c621bea93f003 GIT binary patch literal 396 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VV{wqX6T`Z5GB1G~mUKs7M+SzC z{oH>NS%G}c0*}aI1_r*vAk26?e?qM z&(O>zbNyGKqCcK4jv*HQOQ)RVI%FWw<~{v;y|Mm1)gCf9>4`!{5@{B@0-X1z`^>;s?uKQD!Bp2JJlz1Ds1&Y8e>-(=zmnbe1?R^2L| z$2Tv7C0t%)g-zy+hR*?y1j6)sxI-??K78UktG+y|)(yKNv8w;Eyz5;{4qnJ%o7}(X zq#29&ju!J7InoE4kGJ035G@msbTqQ~;_alPC#Gf0y}oSHKUW*SrzaP;zb~rtkL)gf z@FCn;ZyS%WL$vC4SD_t#X3C3`yT9FyxMs6!S*BT_bC67Y$@0Yutgf!f_c)czlTvSP nb2ac9*X5(}5vB(Z)iU~Bw0qpTaQzElI52p+`njxgN@xNA8Je4w literal 0 HcmV?d00001 diff --git a/gfxlcd/demos/ssd_3.py b/gfxlcd/demos/ssd_3.py new file mode 100644 index 0000000..379dbd7 --- /dev/null +++ b/gfxlcd/demos/ssd_3.py @@ -0,0 +1,60 @@ +import RPi.GPIO +import sys +import random +sys.path.append("../../") +from gfxlcd.driver.ssd1306.spi import SPI +from gfxlcd.driver.ssd1306.ssd1306 import SSD1306 +RPi.GPIO.setmode(RPi.GPIO.BCM) + + +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.rotation = 90 +lcd_oled.init() +lcd_oled.auto_flush = False + +x, y = lcd_oled.width // 2, lcd_oled.height // 2 +lcd_oled.draw_circle(x, y, 31) +lcd_oled.draw_circle(x-12, y-10, 7) +lcd_oled.draw_circle(x+12, y-10, 7) +lcd_oled.draw_arc(x, y, 20, 45, 135) +lcd_oled.draw_line(x, y-5, x-4, y+6) +lcd_oled.draw_line(x, y-5, x+4, y+6) +lcd_oled.draw_arc(x, y+3, 5, 45, 135) + +lcd_oled.fill_rect(0, 0, 10, 10) + +lcd_oled.flush(True) diff --git a/gfxlcd/demos/ssd_image_1.py b/gfxlcd/demos/ssd_image_1.py new file mode 100644 index 0000000..e60b503 --- /dev/null +++ b/gfxlcd/demos/ssd_image_1.py @@ -0,0 +1,19 @@ +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.rotation = 270 +lcd_oled.init() +lcd_oled.auto_flush = False + +image_file = Image.open("assets/20x20.png") +lcd_oled.threshold = 0 + +lcd_oled.draw_image(10, 0, image_file) + +lcd_oled.flush(True) diff --git a/gfxlcd/drawing/page.py b/gfxlcd/drawing/page.py index 0e7f54e..883c53f 100644 --- a/gfxlcd/drawing/page.py +++ b/gfxlcd/drawing/page.py @@ -11,10 +11,16 @@ class Page(Pixel, metaclass=abc.ABCMeta): def init(self): """init page""" - self.buffer = [[0] * (self.height // 8) for x in range(self.width)] + #self.rotate = rotate + if self.rotation == 0 or self.rotation == 180: + self.buffer = [[0] * (self.height // 8) for x in range(self.width)] + else: + self.buffer = [[0] * (self.width // 8) for x in range(self.height)] def draw_pixel(self, pos_x, pos_y): """draw a pixel at x,y""" + if self.rotation == 90 or self.rotation == 270: + pos_x, pos_y = pos_y, pos_x self.buffer[pos_x][pos_y//8] |= 1 << (pos_y % 8) self.flush() diff --git a/gfxlcd/drawing/pixel.py b/gfxlcd/drawing/pixel.py index e54f6cc..7157f21 100644 --- a/gfxlcd/drawing/pixel.py +++ b/gfxlcd/drawing/pixel.py @@ -6,6 +6,7 @@ class Pixel(object): """Pixel class""" def __init__(self, driver): self.driver = driver + self.rotation = 0 self.options['color'] = { 'R': 255, 'G': 255, 'B': 255 } @@ -36,11 +37,11 @@ class Pixel(object): self.options['transparency_color'] = transparency_color def draw_pixel(self, pos_x, pos_y): - """dummy fuction""" + """dummy function""" pass def draw_line(self, pos_x1, pos_y1, pos_x2, pos_y2): - """dummy fuction""" + """dummy function""" pass def draw_rect(self, pos_x1, pos_y1, pos_x2, pos_y2): diff --git a/gfxlcd/driver/ssd1306/ssd1306.py b/gfxlcd/driver/ssd1306/ssd1306.py index dfe6078..148066c 100644 --- a/gfxlcd/driver/ssd1306/ssd1306.py +++ b/gfxlcd/driver/ssd1306/ssd1306.py @@ -5,6 +5,25 @@ from gfxlcd.abstract.chip import Chip class SSD1306(Page, Chip): """Class for an LCD with SSD306 chip""" + rotations = { + 0: { + 'sgmt': 0xa1, + 'com': 0xc8 + }, + 90: { + 'sgmt': 0xa0, + 'com': 0xc8 + }, + 180: { + 'sgmt': 0xa0, + 'com': 0xc0 + }, + 270: { + 'sgmt': 0xa1, + 'com': 0xc0 + } + } + def __init__(self, width, height, driver, auto_flush=True): Chip.__init__(self, width, height, driver, auto_flush) Page.__init__(self, driver) @@ -13,7 +32,7 @@ class SSD1306(Page, Chip): def init(self): """inits a device""" self.driver.init() - Page.init(self) + Page.init(self)#, self.rotate) Chip.init(self) self.driver.reset() self.driver.cmd(0xae) # turn off panel @@ -27,8 +46,12 @@ class SSD1306(Page, Chip): 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, a1 = segment 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) + # a0/a1, a1 = segment 127 to 0, a0:0 to seg127 + self.driver.cmd(self.rotations[self.rotation]['sgmt']) + + # c8/c0 set com(N-1)to com0 c0:com0 to com(N-1) + self.driver.cmd(self.rotations[self.rotation]['com']) + self.driver.cmd(0xa6) # set normal display, a6 - normal, a7 - inverted self.driver.cmd(0xa8) # set multiplex ratio(16to63) @@ -66,15 +89,19 @@ class SSD1306(Page, Chip): :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): + if self.rotation == 0 or self.rotation == 180: + height, width = self.height, self.width + else: + width, height = self.height, self.width + for j in range(0, height//8): + self.set_area(0, j, width-1, j+1) + for i in range(0, width): self.driver.data(self.get_page_value(i, j)) def set_area(self, pos_x1, pos_y1, pos_x2, pos_y2): """set area to work on""" + self.driver.cmd(0x22) self.driver.cmd(0xb0 + pos_y1) self.driver.cmd(0xb0 + pos_y2) diff --git a/gfxlcd/tests/test_chip.py b/gfxlcd/tests/test_chip.py new file mode 100644 index 0000000..f8cf838 --- /dev/null +++ b/gfxlcd/tests/test_chip.py @@ -0,0 +1,31 @@ +__author__ = 'kosci' + +import sys +from nose.tools import assert_equal +sys.path.append("../../") +from gfxlcd.driver.null.null_page import NullPage + + +class TestChip(object): + def setUp(self): + self.lcd = NullPage(10, 16, None, False) + + def test_rotate_by_0(self): + self.lcd.rotation = 0 + assert_equal(10, self.lcd.width) + assert_equal(16, self.lcd.height) + + def test_rotate_by_90(self): + self.lcd.rotation = 90 + assert_equal(16, self.lcd.width) + assert_equal(10, self.lcd.height) + + def test_rotate_by_180(self): + self.lcd.rotation = 180 + assert_equal(10, self.lcd.width) + assert_equal(16, self.lcd.height) + + def test_rotate_by_270(self): + self.lcd.rotation = 270 + assert_equal(16, self.lcd.width) + assert_equal(10, self.lcd.height) From 578ae67c4469d6d8b1daf52e636082d6f223be9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20Ko=C5=9Bci=C3=B3w?= Date: Mon, 5 Jun 2017 17:49:07 +0200 Subject: [PATCH 2/2] rotate nju --- gfxlcd/demos/nju_3.py | 26 ++++++++++++++++++++ gfxlcd/demos/nju_image_1.py | 19 +++++++++++++++ gfxlcd/demos/ssd_3.py | 35 --------------------------- gfxlcd/drawing/page.py | 3 --- gfxlcd/driver/nju6450/nju6450.py | 41 ++++++++++++++++++++++++++++---- gfxlcd/driver/ssd1306/ssd1306.py | 7 +++++- 6 files changed, 87 insertions(+), 44 deletions(-) create mode 100644 gfxlcd/demos/nju_3.py create mode 100644 gfxlcd/demos/nju_image_1.py diff --git a/gfxlcd/demos/nju_3.py b/gfxlcd/demos/nju_3.py new file mode 100644 index 0000000..38762bd --- /dev/null +++ b/gfxlcd/demos/nju_3.py @@ -0,0 +1,26 @@ +import RPi.GPIO +import sys +sys.path.append("../../") +from gfxlcd.driver.nju6450.gpio import GPIO +from gfxlcd.driver.nju6450.nju6450 import NJU6450 +RPi.GPIO.setmode(RPi.GPIO.BCM) + +lcd = NJU6450(122, 32, GPIO()) +lcd.rotation = 270 +lcd.init() +lcd.auto_flush = False + +x, y = lcd.width // 2, lcd.height // 2 + +lcd.draw_pixel(3,1) +lcd.draw_circle(x, y, 15) +lcd.draw_circle(x-7, y-5, 3) +lcd.draw_circle(x+7, y-5, 3) +lcd.draw_arc(x, y, 10, 45, 135) +lcd.draw_line(x, y-3, x-3, y+2) +lcd.draw_line(x, y-3, x+3, y+2) +lcd.draw_arc(x, y, 3, 45, 135) + +lcd.fill_rect(0, 0, 5, 10) + +lcd.flush(True) diff --git a/gfxlcd/demos/nju_image_1.py b/gfxlcd/demos/nju_image_1.py new file mode 100644 index 0000000..c7a7f1f --- /dev/null +++ b/gfxlcd/demos/nju_image_1.py @@ -0,0 +1,19 @@ +import RPi.GPIO +import sys +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.rotation = 90 +lcd_nju.init() +lcd_nju.auto_flush = False + +image_file = Image.open("assets/20x20.png") +lcd_nju.threshold = 0 + +lcd_nju.draw_image(10, 0, image_file) + +lcd_nju.flush(True) diff --git a/gfxlcd/demos/ssd_3.py b/gfxlcd/demos/ssd_3.py index 379dbd7..8fbb777 100644 --- a/gfxlcd/demos/ssd_3.py +++ b/gfxlcd/demos/ssd_3.py @@ -6,41 +6,6 @@ from gfxlcd.driver.ssd1306.spi import SPI from gfxlcd.driver.ssd1306.ssd1306 import SSD1306 RPi.GPIO.setmode(RPi.GPIO.BCM) - -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.rotation = 90 lcd_oled.init() diff --git a/gfxlcd/drawing/page.py b/gfxlcd/drawing/page.py index 883c53f..0dd964c 100644 --- a/gfxlcd/drawing/page.py +++ b/gfxlcd/drawing/page.py @@ -11,7 +11,6 @@ class Page(Pixel, metaclass=abc.ABCMeta): def init(self): """init page""" - #self.rotate = rotate if self.rotation == 0 or self.rotation == 180: self.buffer = [[0] * (self.height // 8) for x in range(self.width)] else: @@ -19,8 +18,6 @@ class Page(Pixel, metaclass=abc.ABCMeta): def draw_pixel(self, pos_x, pos_y): """draw a pixel at x,y""" - if self.rotation == 90 or self.rotation == 270: - pos_x, pos_y = pos_y, pos_x self.buffer[pos_x][pos_y//8] |= 1 << (pos_y % 8) self.flush() diff --git a/gfxlcd/driver/nju6450/nju6450.py b/gfxlcd/driver/nju6450/nju6450.py index a99c77e..5b66a6b 100644 --- a/gfxlcd/driver/nju6450/nju6450.py +++ b/gfxlcd/driver/nju6450/nju6450.py @@ -24,12 +24,16 @@ class NJU6450(Page, Chip): def set_xy(self, pos_x, pos_y): """set xy pos""" - if pos_x < self.width/2: + if self.rotation == 0 or self.rotation == 180: + width = self.width + else: + width = self.height + if pos_x < width//2: self.driver.cmd(0xB8 | pos_y, 0) self.driver.cmd(0x00 | pos_x, 0) else: self.driver.cmd(0xB8 | pos_y, 1) - self.driver.cmd(0x00 | (pos_x - self.width//2), 1) + self.driver.cmd(0x00 | (pos_x - width//2), 1) def _converted_background_color(self): """convert RGB background to available color""" @@ -46,10 +50,37 @@ class NJU6450(Page, Chip): force = self.options['auto_flush'] if force: - for j in range(0, self.height//8): - for i in range(0, self.width): + if self.rotation == 0 or self.rotation == 180: + height, width = self.height, self.width + else: + width, height = self.height, self.width + for j in range(0, height//8): + for i in range(0, width): self.set_xy(i, j) - if i < self.width/2: + if i < width//2: self.driver.data(self.get_page_value(i, j), 0) else: self.driver.data(self.get_page_value(i, j), 1) + + def draw_pixel(self, pos_x, pos_y): + """draw a pixel at x,y""" + if self.rotation == 90: + pos_x, pos_y = self.height - pos_y - 1, pos_x + if self.rotation == 180: + pos_x, pos_y = self.width - pos_x - 1, self.height - pos_y - 1 + if self.rotation == 270: + pos_x, pos_y = pos_y, self.width - pos_x - 1 + Page.draw_pixel(self, pos_x, pos_y) + + def fill_rect(self, pos_x1, pos_y1, pos_x2, pos_y2): + """draw a filled rectangle""" + if self.rotation == 90: + pos_x1, pos_y1 = self.height - pos_y1 - 1, pos_x1 + pos_x2, pos_y2 = self.height - pos_y2 - 1, pos_x2 + if self.rotation == 180: + pos_x1, pos_y1 = self.width - pos_x1 - 1, self.height - pos_y1 - 1 + pos_x2, pos_y2 = self.width - pos_x2 - 1, self.height - pos_y2 - 1 + if self.rotation == 270: + pos_x1, pos_y1 = pos_y1 , self.width - pos_x1 - 1 + pos_x2, pos_y2 = pos_y2 , self.width - pos_x2 - 1 + Page.fill_rect(self, pos_x1, pos_y1, pos_x2, pos_y2) diff --git a/gfxlcd/driver/ssd1306/ssd1306.py b/gfxlcd/driver/ssd1306/ssd1306.py index 148066c..d756e7e 100644 --- a/gfxlcd/driver/ssd1306/ssd1306.py +++ b/gfxlcd/driver/ssd1306/ssd1306.py @@ -101,10 +101,15 @@ class SSD1306(Page, Chip): def set_area(self, pos_x1, pos_y1, pos_x2, pos_y2): """set area to work on""" - self.driver.cmd(0x22) self.driver.cmd(0xb0 + pos_y1) self.driver.cmd(0xb0 + pos_y2) self.driver.cmd(0x21) self.driver.cmd(pos_x1) self.driver.cmd(pos_x2) + + def draw_pixel(self, pos_x, pos_y): + """draw a pixel at x,y""" + if self.rotation == 90 or self.rotation == 270: + pos_x, pos_y = pos_y, pos_x + Page.draw_pixel(self, pos_x, pos_y)