Skip to content
This repository was archived by the owner on Dec 16, 2018. It is now read-only.

Commit fef0b92

Browse files
author
Radomir Dopieralski
committed
Add initial set of display drivers
0 parents  commit fef0b92

File tree

7 files changed

+536
-0
lines changed

7 files changed

+536
-0
lines changed

display.py

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
import time
2+
import ustruct
3+
4+
5+
def color565(r, g, b):
6+
return (r & 0xf8) << 8 | (g & 0xfc) << 3 | b >> 3
7+
8+
9+
class DummyPin:
10+
"""A fake gpio pin for when you want to skip pins."""
11+
def init(self, *args, **kwargs):
12+
pass
13+
14+
def low(self):
15+
pass
16+
17+
def high(self):
18+
pass
19+
20+
21+
class Display:
22+
_PAGE_SET = None
23+
_COLUMN_SET = None
24+
_RAM_WRITE = None
25+
_RAM_READ = None
26+
_INIT = ()
27+
_ENCODE_PIXEL = ">H"
28+
_ENCODE_POS = ">HH"
29+
_DECODE_PIXEL = ">BBB"
30+
31+
def __init__(self, width, height):
32+
self.width = width
33+
self.height = height
34+
self.init()
35+
36+
def init(self):
37+
"""Run the initialization commands."""
38+
for command, data in self._INIT:
39+
self._write(command, data)
40+
41+
def _block(self, x0, y0, x1, y1, data=None):
42+
"""Read or write a block of data."""
43+
self._write(self._COLUMN_SET, self._encode_pos(x0, x1))
44+
self._write(self._PAGE_SET, self._encode_pos(y0, y1))
45+
if data is None:
46+
size = ustruct.calcsize(self._DECODE_PIXEL)
47+
return self._read(self._RAM_READ,
48+
(x1 - x0 + 1) * (y1 - y0 + 1) * size)
49+
self._write(self._RAM_WRITE, data)
50+
51+
def _encode_pos(self, a, b):
52+
"""Encode a postion into bytes."""
53+
return ustruct.pack(self._ENCODE_POS, a, b)
54+
55+
def _encode_pixel(self, color):
56+
"""Encode a pixel color into bytes."""
57+
return ustruct.pack(self._ENCODE_PIXEL, color)
58+
59+
def _decode_pixel(self, data):
60+
"""Decode bytes into a pixel color."""
61+
return color565(*ustruct.unpack(self._DECODE_PIXEL, data))
62+
63+
def pixel(self, x, y, color=None):
64+
"""Read or write a pixel."""
65+
if color is None:
66+
return self._decode_pixel(self._block(x, y, x, y))
67+
if not 0 <= x < self.width or not 0 <= y < self.height:
68+
return
69+
self._block(x, y, x, y, self._encode_pixel(color))
70+
71+
def fill_rectangle(self, x, y, w, h, color):
72+
"""Draw a filled rectangle."""
73+
x = min(self.width - 1, max(0, x))
74+
y = min(self.height - 1, max(0, y))
75+
w = min(self.width - x, max(1, w))
76+
h = min(self.height - y, max(1, h))
77+
self._block(x, y, x + w - 1, y + h - 1, b'')
78+
chunks, rest = divmod(w * h, 512)
79+
pixel = self._encode_pixel(color)
80+
if chunks:
81+
data = pixel * 512
82+
for count in range(chunks):
83+
self._write(None, data)
84+
self._write(None, pixel * rest)
85+
86+
def fill(self, color=0):
87+
"""Fill whole screen."""
88+
self.fill_rectangle(0, 0, self.width, self.height, color)
89+
90+
def hline(self, x, y, width, color):
91+
"""Draw a horizontal line."""
92+
self.fill_rectangle(x, y, width, 1, color)
93+
94+
def vline(self, x, y, height, color):
95+
"""Draw a vertical line."""
96+
self.fill_rectangle(x, y, 1, height, color)
97+
98+
99+
class DisplaySPI(Display):
100+
def __init__(self, spi, dc, cs, rst=None, width=1, height=1):
101+
self.spi = spi
102+
self.cs = cs
103+
self.dc = dc
104+
self.rst = rst
105+
self.cs.init(self.cs.OUT, value=1)
106+
self.dc.init(self.dc.OUT, value=0)
107+
if self.rst:
108+
self.rst.init(self.rst.OUT, value=0)
109+
self.reset()
110+
super().__init__(width, height)
111+
112+
def reset(self):
113+
self.rst.low()
114+
time.sleep_ms(50)
115+
self.rst.high()
116+
time.sleep_ms(50)
117+
118+
def _write(self, command=None, data=None):
119+
if command is not None:
120+
self.dc.low()
121+
self.cs.low()
122+
self.spi.write(bytearray([command]))
123+
self.cs.high()
124+
if data is not None:
125+
self.dc.high()
126+
self.cs.low()
127+
self.spi.write(data)
128+
self.cs.high()
129+
130+
def _read(self, command=None, count=0):
131+
self.dc.low()
132+
self.cs.low()
133+
if command is not None:
134+
self.spi.write(bytearray([command]))
135+
if count:
136+
data = self.spi.read(count)
137+
self.cs.high()
138+
return data
139+

hx8353.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
from display import DisplaySPI, color565
2+
3+
_SWRESET = const(0x01)
4+
_NORON = const(0x13)
5+
_INVOFF = const(0x20)
6+
_INVON = const(0x21)
7+
_DISPOFF = const(0x28)
8+
_DISPON = const(0x29)
9+
_CASET = const(0x2a)
10+
_PASET = const(0x2b)
11+
_RAMWR = const(0x2c)
12+
_RAMRD = const(0x2e)
13+
_MADCTL = const(0x36)
14+
_COLMOD = const(0x3a)
15+
16+
class HX8353(DisplaySPI):
17+
"""
18+
A simple driver for the ST7735-based displays.
19+
20+
>>> from machine import Pin, SPI
21+
>>> import hx8353
22+
>>> spi = SPI(0)
23+
>>> display = hx8353.HX8383(spi, dc=Pin(0), cs=Pin(15), rst=Pin(16))
24+
>>> display.fill(0x7521)
25+
>>> display.pixel(64, 64, 0)
26+
27+
"""
28+
_COLUMN_SET = _CASET
29+
_PAGE_SET = _PASET
30+
_RAM_WRITE = _RAMWR
31+
_RAM_READ = _RAMRD
32+
_INIT = (
33+
(_SWRESET, None),
34+
(_DISPON, None),
35+
)
36+
_ENCODE_PIXEL = ">H"
37+
_ENCODE_POS = ">HH"
38+
39+
def __init__(self, spi, dc, cs, rst=None, width=128, height=128):
40+
super().__init__(spi, dc, cs, rst, width, height)

ili9341.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import ustruct
2+
from display import DisplaySPI, color565
3+
4+
5+
class ILI9341(DisplaySPI):
6+
"""
7+
A simple driver for the ILI9341/ILI9340-based displays.
8+
9+
10+
>>> import ili9341
11+
>>> from machine import Pin, SPI
12+
>>> spi = SPI(mosi=Pin(13), sck=Pin(14))
13+
>>> display = ili9341.ILI9341(spi, cs=Pin(15), dc=Pin(12), rst=Pin(16))
14+
>>> display.fill(ili9341.color565(0xff, 0x11, 0x22))
15+
>>> display.pixel(120, 160, 0)
16+
"""
17+
18+
_COLUMN_SET = 0x2a
19+
_PAGE_SET = 0x2b
20+
_RAM_WRITE = 0x2c
21+
_RAM_READ = 0x2e
22+
_INIT = (
23+
(0xef, b'\x03\x80\x02'),
24+
(0xcf, b'\x00\xc1\x30'),
25+
(0xed, b'\x64\x03\x12\x81'),
26+
(0xe8, b'\x85\x00\x78'),
27+
(0xcb, b'\x39\x2c\x00\x34\x02'),
28+
(0xf7, b'\x20'),
29+
(0xea, b'\x00\x00'),
30+
(0xc0, b'\x23'), # Power Control 1, VRH[5:0]
31+
(0xc1, b'\x10'), # Power Control 2, SAP[2:0], BT[3:0]
32+
(0xc5, b'\x3e\x28'), # VCM Control 1
33+
(0xc7, b'\x86'), # VCM Control 2
34+
(0x36, b'\x48'), # Memory Access Control
35+
(0x3a, b'\x55'), # Pixel Format
36+
(0xb1, b'\x00\x18'), # FRMCTR1
37+
(0xb6, b'\x08\x82\x27'), # Display Function Control
38+
(0xf2, b'\x00'), # 3Gamma Function Disable
39+
(0x26, b'\x01'), # Gamma Curve Selected
40+
(0xe0, # Set Gamma
41+
b'\x0f\x31\x2b\x0c\x0e\x08\x4e\xf1\x37\x07\x10\x03\x0e\x09\x00'),
42+
(0xe1, # Set Gamma
43+
b'\x00\x0e\x14\x03\x11\x07\x31\xc1\x48\x08\x0f\x0c\x31\x36\x0f'),
44+
(0x11, None),
45+
(0x29, None),
46+
)
47+
_ENCODE_PIXEL = ">H"
48+
_ENCODE_POS = ">HH"
49+
_DECODE_PIXEL = ">BBB"
50+
51+
def __init__(self, spi, dc, cs, rst=None, width=240, height=320):
52+
super().__init__(spi, dc, cs, rst, width, height)
53+
self._scroll = 0
54+
55+
def scroll(self, dy=None):
56+
if dy is None:
57+
return self._scroll
58+
self._scroll = (self._scroll + dy) % self.height
59+
self._write(0x37, ustruct.pack('>H', self._scroll))

s6d02a1.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
from display import DisplaySPI, color565
2+
3+
_SWRESET = const(0x01)
4+
_DISPON = const(0x29)
5+
_SLEEPOUT = const(0x11)
6+
_CASET = const(0x2a)
7+
_PASET = const(0x2b)
8+
_RAMWR = const(0x2c)
9+
_RAMRD = const(0x2e)
10+
_COLMOD = const(0x3a)
11+
_MADCTL = const(0x36)
12+
13+
class S6D02A1(DisplaySPI):
14+
"""
15+
A simple driver for the ST7735-based displays.
16+
17+
>>> from machine import Pin, SPI
18+
>>> import s6d02a1
19+
>>> spi = SPI(0, baudrate=40000000)
20+
>>> display = s6d02a1.S6D02A1(spi, dc=Pin(0), cs=Pin(15), rst=Pin(16))
21+
>>> display.fill(0x7521)
22+
>>> display.pixel(64, 64, 0)
23+
24+
"""
25+
_COLUMN_SET = _CASET
26+
_PAGE_SET = _PASET
27+
_RAM_WRITE = _RAMWR
28+
_RAM_READ = _RAMRD
29+
_INIT = (
30+
(_SWRESET, None),
31+
(_SLEEPOUT, None),
32+
(_MADCTL, b'\x10'), # bottom-top
33+
(_COLMOD, b'\x05'), # RGB565 pixel format
34+
(_DISPON, None),
35+
)
36+
_ENCODE_PIXEL = ">H"
37+
_ENCODE_POS = ">HH"
38+
39+
def __init__(self, spi, dc, cs, rst=None, width=128, height=160):
40+
super().__init__(spi, dc, cs, rst, width, height)

ssd1331.py

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
from display import DisplaySPI, color565
2+
3+
4+
_DRAWLINE = const(0x21)
5+
_DRAWRECT = const(0x22)
6+
_FILL = const(0x26)
7+
_PHASEPERIOD = const(0x12)
8+
_SETCOLUMN = const(0x15)
9+
_SETROW = const(0x75)
10+
_CONTRASTA = const(0x81)
11+
_CONTRASTB = const(0x82)
12+
_CONTRASTC = const(0x83)
13+
_MASTERCURRENT = const(0x87)
14+
_SETREMAP = const(0xA0)
15+
_STARTLINE = const(0xA1)
16+
_DISPLAYOFFSET = const(0xA2)
17+
_NORMALDISPLAY = const(0xA4)
18+
_DISPLAYALLON = const(0xA5)
19+
_DISPLAYALLOFF = const(0xA6)
20+
_INVERTDISPLAY = const(0xA7)
21+
_SETMULTIPLEX = const(0xA8)
22+
_SETMASTER = const(0xAD)
23+
_DISPLAYOFF = const(0xAE)
24+
_DISPLAYON = const(0xAF)
25+
_POWERMODE = const(0xB0)
26+
_PRECHARGE = const(0xB1)
27+
_CLOCKDIV = const(0xB3)
28+
_PRECHARGEA = const(0x8A)
29+
_PRECHARGEB = const(0x8B)
30+
_PRECHARGEC = const(0x8C)
31+
_PRECHARGELEVEL = const(0xBB)
32+
_VCOMH = const(0xBE)
33+
_LOCK = const(0xfd)
34+
35+
36+
class SSD1331(DisplaySPI):
37+
"""
38+
>>>
39+
from machine import Pin, HSPI
40+
import ssd1331
41+
#spi = SPI(mosi=Pin(13), sck=Pin(14), polarity=1, phase=1)
42+
spi = HSPI(polarity=1, phase=1)
43+
display = ssd1331.SSD1331(spi, dc=Pin(2), cs=Pin(15), rst=Pin(16))
44+
display.fill(0x7521)
45+
display.pixel(32, 32, 0)
46+
"""
47+
_COLUMN_SET = _SETCOLUMN
48+
_PAGE_SET = _SETROW
49+
_RAM_WRITE = None
50+
_RAM_READ = None
51+
_INIT = (
52+
(_DISPLAYOFF, b''),
53+
(_LOCK, b'\x0b'),
54+
(_SETREMAP, b'\x72'), # RGB Color
55+
(_STARTLINE, b'\x00'),
56+
(_DISPLAYOFFSET, b'\x00'),
57+
(_NORMALDISPLAY, b''),
58+
# (_FILL, b'\x01'),
59+
60+
# (_PHASEPERIOD, b'\x31'),
61+
# (_SETMULTIPLEX, b'\x3f'),
62+
# (_SETMASTER, b'\x8e'),
63+
# (_POWERMODE,b'\x0b'),
64+
# (_PRECHARGE, b'\x31'), #;//0x1F - 0x31
65+
# (_CLOCKDIV, b'\xf0'),
66+
# (_VCOMH, b'\x3e'), #;//0x3E - 0x3F
67+
# (_MASTERCURRENT, b'\x06'), # ;//0x06 - 0x0F
68+
# (_PRECHARGEA, b'\x64'),
69+
# (_PRECHARGEB, b'\x78'),
70+
# (_PRECHARGEC, b'\x64'),
71+
# (_PRECHARGELEVEL, b'\x3a'), # 0x3A - 0x00
72+
# (_CONTRASTA, b'\x91'), #//0xEF - 0x91
73+
# (_CONTRASTB, b'\x50'), #;//0x11 - 0x50
74+
# (_CONTRASTC, b'\x7d'), #;//0x48 - 0x7D
75+
(_DISPLAYON, b''),
76+
)
77+
_ENCODE_PIXEL = ">H"
78+
_ENCODE_POS = ">BB"
79+
80+
def __init__(self, spi, dc, cs, rst=None, width=96, height=64):
81+
super().__init__(spi, dc, cs, rst, width, height)

0 commit comments

Comments
 (0)