Skip to content

Commit 12e137a

Browse files
committed
adds ssd1306 driver
1 parent 256a27a commit 12e137a

File tree

5 files changed

+257
-0
lines changed

5 files changed

+257
-0
lines changed
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
from micropython import const
2+
3+
_SET_CONTRAST = const(0x81)
4+
_SET_ENTIRE_ON = const(0xA4)
5+
_SET_NORM_INV = const(0xA6)
6+
_SET_DISP = const()
7+
_DISP_OFF = const(0xAE)
8+
_DISP_ON = const(0xAF)
9+
_SET_MEM_ADDR = const(0x20)
10+
_SET_COL_ADDR = const(0x21)
11+
_SET_PAGE_ADDR = const(0x22)
12+
_SET_DISP_START_LINE = const(0x40)
13+
_SET_SEG_REMAP = const(0xA0)
14+
_SET_MUX_RATIO = const(0xA8)
15+
_SET_COM_OUT_DIR = const(0xC0)
16+
_SET_DISP_OFFSET = const(0xD3)
17+
_SET_COM_PIN_CFG = const(0xDA)
18+
_SET_DISP_CLK_DIV = const(0xD5)
19+
_SET_PRECHARGE = const(0xD9)
20+
_SET_VCOM_DESEL = const(0xDB)
21+
_SET_CHARGE_PUMP = const(0x8D)
22+
23+
24+
def init(self):
25+
param_buf = bytearray(1)
26+
param_mv = bytearray(param_buf)
27+
28+
self.set_params(_DISP_OFF)
29+
30+
param_buf[0] = 0x00
31+
self.set_params(_SET_MEM_ADDR, param_mv[:1])
32+
33+
self.set_params(_SET_DISP_START_LINE | 0x00)
34+
35+
self.set_params(_SET_SEG_REMAP | 0x01)
36+
37+
param_buf[0] = self.height - 1
38+
self.set_params(_SET_MUX_RATIO, param_mv[:1])
39+
40+
self.set_params(_SET_COM_OUT_DIR | 0x08)
41+
42+
param_buf[0] = 0x00
43+
self.set_params(_SET_DISP_OFFSET, param_mv[:1])
44+
45+
if self.width > 2 * self.height:
46+
param_buf[0] = 0x02
47+
else:
48+
param_buf[0] = 0x12
49+
self.set_params(_SET_COM_PIN_CFG, param_mv[:1])
50+
51+
param_buf[0] = 0x80
52+
self.set_params(_SET_DISP_CLK_DIV, param_mv[:1])
53+
54+
if self._power_pin is not None:
55+
param_buf[0] = 0x22
56+
else:
57+
param_buf[0] = 0xF1
58+
59+
self.set_params(_SET_PRECHARGE, param_mv[:1])
60+
61+
param_buf[0] = 0x30
62+
self.set_params(_SET_VCOM_DESEL, param_mv[:1])
63+
64+
param_buf[0] = 0xFF
65+
self.set_params(_SET_CONTRAST, param_mv[:1])
66+
67+
self.set_params(_SET_ENTIRE_ON)
68+
69+
self.set_params(_SET_NORM_INV)
70+
71+
if self._power_pin is not None:
72+
param_buf[0] = 0x10
73+
else:
74+
param_buf[0] = 0x14
75+
self.set_params(_SET_CHARGE_PUMP, param_mv[:1])
76+
77+
self.set_params(_DISP_ON)
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
from micropython import const # NOQA
2+
import display_driver_framework
3+
4+
import lcd_bus
5+
import gc
6+
import lvgl as lv
7+
8+
9+
STATE_HIGH = display_driver_framework.STATE_HIGH
10+
STATE_LOW = display_driver_framework.STATE_LOW
11+
STATE_PWM = display_driver_framework.STATE_PWM
12+
13+
_SET_CONTRAST = const(0x81)
14+
_SET_NORM_INV = const(0xA6)
15+
_SET_DISP = const()
16+
_DISP_OFF = const(0xAE)
17+
_DISP_ON = const(0xAF)
18+
_SET_COL_ADDR = const(0x21)
19+
_SET_PAGE_ADDR = const(0x22)
20+
21+
22+
class SSD1306(display_driver_framework.DisplayDriver):
23+
24+
def __init__(
25+
self,
26+
data_bus,
27+
display_width,
28+
display_height,
29+
frame_buffer1=None,
30+
frame_buffer2=None,
31+
reset_pin=None,
32+
reset_state=STATE_HIGH,
33+
power_pin=None,
34+
backlight_pin=None,
35+
backlight_on_state=STATE_HIGH,
36+
offset_x=0,
37+
offset_y=0,
38+
color_space=lv.COLOR_FORMAT.RGB888, # NOQA
39+
rgb565_byte_swap=False
40+
):
41+
42+
if not isinstance(data_bus, (lcd_bus.SPIBus, lcd_bus.I2CBus)):
43+
raise ValueError('Only SPI and I2C lcd busses allowed')
44+
45+
buf_size = int(
46+
display_width *
47+
display_height *
48+
lv.color_format_get_size(color_space)
49+
)
50+
51+
if frame_buffer1 is None:
52+
53+
gc.collect()
54+
55+
for flags in (
56+
lcd_bus.MEMORY_INTERNAL | lcd_bus.MEMORY_DMA,
57+
lcd_bus.MEMORY_SPIRAM | lcd_bus.MEMORY_DMA,
58+
lcd_bus.MEMORY_INTERNAL,
59+
lcd_bus.MEMORY_SPIRAM
60+
):
61+
try:
62+
frame_buffer1 = (
63+
data_bus.allocate_framebuffer(buf_size, flags)
64+
)
65+
66+
if (flags | lcd_bus.MEMORY_DMA) == flags:
67+
frame_buffer2 = (
68+
data_bus.allocate_framebuffer(buf_size, flags)
69+
)
70+
71+
break
72+
except MemoryError:
73+
frame_buffer1 = data_bus.free_framebuffer(frame_buffer1)
74+
75+
if frame_buffer1 is None:
76+
raise MemoryError(
77+
f'Unable to allocate memory for frame buffer ({buf_size})'
78+
# NOQA
79+
)
80+
81+
self._pages = int(display_height // 8)
82+
83+
if len(frame_buffer1) != buf_size:
84+
raise ValueError(f'Framebuffer is too small ({buf_size}')
85+
86+
super().__init__(
87+
data_bus=data_bus,
88+
display_width=display_width,
89+
display_height=display_height,
90+
frame_buffer1=frame_buffer1,
91+
frame_buffer2=frame_buffer2,
92+
reset_pin=reset_pin,
93+
reset_state=reset_state,
94+
power_pin=None,
95+
backlight_pin=backlight_pin,
96+
backlight_on_state=backlight_on_state,
97+
offset_x=offset_x,
98+
offset_y=offset_y,
99+
color_byte_order=display_driver_framework.BYTE_ORDER_RGB,
100+
color_space=color_space, # NOQA
101+
rgb565_byte_swap=rgb565_byte_swap,
102+
_cmd_bits=8,
103+
_param_bits=8,
104+
_init_bus=True
105+
)
106+
107+
self._power_pin = power_pin
108+
109+
def set_constrast(self, value):
110+
self._param_buf[0] = value & 0xFF
111+
self.set_params(_SET_CONTRAST, self._param_mv[:1])
112+
113+
def set_color_inversion(self, value):
114+
self.set_params(_SET_NORM_INV | (int(bool(value)) & 1))
115+
116+
def get_power(self):
117+
return self._power
118+
119+
def set_power(self, value):
120+
self._power = bool(value)
121+
122+
if self._power:
123+
self.set_params(_DISP_ON)
124+
else:
125+
self.set_params(_DISP_OFF)
126+
127+
def _flush_cb(self, _, area, color_p):
128+
129+
x1 = 0
130+
x2 = self.display_width - 1
131+
132+
if self.display_width == 64:
133+
# displays with width of 64 pixels are shifted by 32
134+
x1 += 32
135+
x2 += 32
136+
137+
y1 = 0
138+
y2 = self._pages - 1
139+
140+
self._param_buf[0] = x1
141+
self._param_buf[1] = x2
142+
self.set_params(_SET_COL_ADDR, self._param_mv[:2])
143+
144+
self._param_buf[0] = y1
145+
self._param_buf[1] = y2
146+
self.set_params(_SET_PAGE_ADDR, self._param_mv[:2])
147+
148+
size = (
149+
(area.x2 - area.x1 + 1) *
150+
(area.y2 - area.y1 + 1) *
151+
lv.color_format_get_size(self._color_space)
152+
)
153+
154+
# we have to use the __dereference__ method because this method is
155+
# what converts from the C_Array object the binding passes into a
156+
# memoryview object that can be passed to the bus drivers
157+
data_view = color_p.__dereference__(size)
158+
self._data_bus.tx_color(0, data_view, x1, y1, x2, y2, self._rotation, self._disp_drv.flush_is_last())

api_drivers/common_api_drivers/display/ssd1351/ssd1351.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,13 @@
66
_PASET = const(0x75)
77
_RAMWR = const(0x5C)
88

9+
STATE_HIGH = display_driver_framework.STATE_HIGH
10+
STATE_LOW = display_driver_framework.STATE_LOW
11+
STATE_PWM = display_driver_framework.STATE_PWM
12+
13+
BYTE_ORDER_RGB = display_driver_framework.BYTE_ORDER_RGB
14+
BYTE_ORDER_BGR = display_driver_framework.BYTE_ORDER_BGR
15+
916

1017
class SSD1351(display_driver_framework.DisplayDriver):
1118
_INVOFF = 0xA6

api_drivers/common_api_drivers/display/ssd1963/ssd1963.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,13 @@
66
TYPE_800ALT = 3
77
TYPE_800BD = 4
88

9+
STATE_HIGH = display_driver_framework.STATE_HIGH
10+
STATE_LOW = display_driver_framework.STATE_LOW
11+
STATE_PWM = display_driver_framework.STATE_PWM
12+
13+
BYTE_ORDER_RGB = display_driver_framework.BYTE_ORDER_RGB
14+
BYTE_ORDER_BGR = display_driver_framework.BYTE_ORDER_BGR
15+
916

1017
class SSD1963(display_driver_framework.DisplayDriver):
1118
pass
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
import display_driver_framework
22

33

4+
STATE_HIGH = display_driver_framework.STATE_HIGH
5+
STATE_LOW = display_driver_framework.STATE_LOW
6+
STATE_PWM = display_driver_framework.STATE_PWM
7+
8+
BYTE_ORDER_RGB = display_driver_framework.BYTE_ORDER_RGB
9+
BYTE_ORDER_BGR = display_driver_framework.BYTE_ORDER_BGR
10+
11+
412
class ST7565(display_driver_framework.DisplayDriver):
513
pass

0 commit comments

Comments
 (0)