-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdisplay.py
115 lines (100 loc) · 3.88 KB
/
display.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
from driver import SSD1306
from utilities import Indexable
from pyb import delay
from context import *
class OLED(object):
def __init__(self, prot):
self.driver = SSD1306(prot)
self.width = SSD1306.COLUMN_NUM
self.height = SSD1306.PAGE_NUM * 8
# buffer[页][列]
self.__buffer = [[0 for _ in range(SSD1306.COLUMN_NUM)] for _ in range(SSD1306.PAGE_NUM)]
self.__flag_modified = [[False for _ in range(SSD1306.COLUMN_NUM)] for _ in range(SSD1306.PAGE_NUM)]
self.__flag_page = [-1 for _ in range(SSD1306.COLUMN_NUM * SSD1306.PAGE_NUM)]
self.__flag_column = [-1 for _ in range(SSD1306.COLUMN_NUM * SSD1306.PAGE_NUM)]
self.__fpos = 0
self.__context = Context(exit_func=self.__session_exit)
@property
def session(self):
return self.__context
def __session_exit(self):
if self.__context.nest_count == 0:
self.submit()
def init(self):
self.driver.display_on = False # 默认
self.driver.address_column = 0 # 默认
self.driver.hardware_start_line = 0 # 默认
self.driver.address_page = 0 # 默认
self.driver.contrast = 0xff # 可默认
self.driver.hardware_segment_remap = True
self.driver.display_inverse = False # 默认
self.driver.hardware_multiplex_ratio = 64 # 默认
self.driver.hardware_com_scan_dir = SSD1306.COM_SCAN_DIR_REMAPPED
self.driver.hardware_vertical_offset = 0 # 默认
self.driver.timing_clockdiv_and_oscfreq = SSD1306.CLOCKDIV_AND_OSCFREQ_MAX_FPS
self.driver.timing_precharge_period = (1, 15)
self.driver.hardware_com_pin_config = (SSD1306.HARDWARE_COM_PIN_MODE_ALTERNATIVE, False) # 默认
self.driver.timing_vcomh_deselect_level = SSD1306.TIMING_VCOMH_DESELECT_LEVEL_83_PERCENT_VCC
self.driver.charge_pump_enable = True
self.driver.display_on = True
# fast_mode 记录那些不为黑色的列
def clear(self, color=False, fast_mode=False):
for y in range(64):
for x in range(128):
self.__draw_point(x, y, color, auto_submit=False, force_refresh=True)
self.submit()
# color: True for white, False for black
def __draw_point(self, x, y, color=True, *, auto_submit=True, force_refresh=False):
page = y // 8
column = x
bit_pos = y % 8
changed = False
if color:
if self.__buffer[page][column] & (1 << bit_pos) == 0:
self.__buffer[page][column] |= 1 << bit_pos
changed = True
else:
if self.__buffer[page][column] & (1 << bit_pos) != 0:
self.__buffer[page][column] &= ~(1 << bit_pos)
changed = True
if (force_refresh or changed) and not self.__flag_modified[page][column]:
self.__flag_modified[page][column] = True
self.__flag_page[self.__fpos] = page
self.__flag_column[self.__fpos] = column
self.__fpos += 1
if auto_submit:
self.submit()
def draw_column(self, page, column, data):
if self.__buffer[page][column] != data:
self.__buffer[page][column] = data
self.__flag_modified[page][column] = True
self.__flag_page[self.__fpos] = page
self.__flag_column[self.__fpos] = column
self.__fpos += 1
def __getitem__(self, item):
def getter(key):
page = key // 8
column = item
bit_pos = key % 8
return bool(self.__buffer[page][column] & (1 << bit_pos))
def setter(key, value):
self.__draw_point(item, key, value, auto_submit=self.__context.nest_count == 0)
return Indexable(getter, setter)
def submit(self):
prev_page = None
prev_column = None
for i in range(self.__fpos):
page = self.__flag_page[i]
column = self.__flag_column[i]
self.__flag_modified[page][column] = False
assign_addr = True
if prev_page is not None and prev_column is not None:
if prev_page == page and prev_column + 1 == column:
assign_addr = False
if assign_addr:
self.driver.address_page = page
self.driver.address_column = column
prev_page, prev_column = page, column
self.driver.ram = self.__buffer[page][column]
self.__fpos = 0
pass