1from micropython import const 2import utime 3import framebuf 4from driver import SPI 5from driver import GPIO 6 7# register definitions 8SET_SCAN_DIR = const(0xc0) 9LOW_COLUMN_ADDRESS = const(0x00) 10HIGH_COLUMN_ADDRESS = const(0x10) 11SET_PAGE_ADDRESS = const(0xB0) 12SET_CONTRAST = const(0x81) 13SET_ENTIRE_ON = const(0xa4) 14SET_NORM_INV = const(0xa6) 15SET_DISP = const(0xae) 16SET_MEM_ADDR = const(0x20) 17SET_COL_ADDR = const(0x21) 18SET_PAGE_ADDR = const(0x22) 19SET_DISP_START_LINE = const(0x40) 20SET_SEG_REMAP = const(0xa0) 21SET_MUX_RATIO = const(0xa8) 22SET_COM_OUT_DIR = const(0xc0) 23SET_DISP_OFFSET = const(0xd3) 24SET_COM_PIN_CFG = const(0xda) 25SET_DISP_CLK_DIV = const(0xd5) 26SET_PRECHARGE = const(0xd9) 27SET_VCOM_DESEL = const(0xdb) 28SET_CHARGE_PUMP = const(0x8d) 29 30 31class SH1106: 32 def __init__(self, width, height): 33 self.width = width 34 self.height = height 35 self.pages = self.height // 8 36 self.buffer = bytearray(self.pages * self.width) 37 fb = framebuf.FrameBuffer( 38 self.buffer, self.width, self.height, framebuf.MVLSB) 39 self.framebuf = fb 40# set shortcuts for the methods of framebuf 41 self.fill = fb.fill 42 self.fill_rect = fb.fill_rect 43 self.hline = fb.hline 44 self.vline = fb.vline 45 self.line = fb.line 46 self.rect = fb.rect 47 self.pixel = fb.pixel 48 self.scroll = fb.scroll 49 self.text = fb.text 50 self.blit = fb.blit 51 52 # print("init done") 53 54 self.init_display() 55 56 def init_display(self): 57 self.reset() 58 for cmd in ( 59 SET_DISP | 0x00, # 关闭显示 60 SET_DISP_CLK_DIV, 0x80, # 设置时钟分频因子 61 SET_MUX_RATIO, self.height - 1, # 设置驱动路数 路数默认0x3F(1/64) 62 SET_DISP_OFFSET, 0x00, # 设置显示偏移 偏移默认为0 63 SET_DISP_START_LINE | 0x00, # 设置显示开始行[5:0] 64 SET_CHARGE_PUMP, 0x14, # 电荷泵设置 bit2,开启/关闭 65 # 设置内存地址模式 [1:0],00,列地址模式;01,行地址模式;10,页地址模式;默认10; 66 SET_MEM_ADDR, 0x02, 67 SET_SEG_REMAP | 0x01, # 段重定义设置,bit0:0,0->0;1,0->127; 68 # 设置COM扫描方向;bit3:0,普通模式;1,重定义模式 COM[N-1]->COM0;N:驱动路数 69 SET_COM_OUT_DIR | 0x08, 70 SET_COM_PIN_CFG, 0x12, # 设置COM硬件引脚配置 [5:4]配置 71 SET_PRECHARGE, 0xf1, # 设置预充电周期 [3:0],PHASE 1;[7:4],PHASE 2; 72 # 设置VCOMH 电压倍率 [6:4] 000,0.65*vcc;001,0.77*vcc;011,0.83*vcc; 73 SET_VCOM_DESEL, 0x30, 74 SET_CONTRAST, 0xff, # 对比度设置 默认0x7F(范围1~255,越大越亮) 75 SET_ENTIRE_ON, # 全局显示开启;bit0:1,开启;0,关闭;(白屏/黑屏) 76 SET_NORM_INV, # 设置显示方式;bit0:1,反相显示;0,正常显示 77 SET_DISP | 0x01): # 开启显示 78 self.write_cmd(cmd) 79 self.fill(1) 80 self.show() 81 82 def poweroff(self): 83 self.write_cmd(SET_DISP | 0x00) 84 85 def poweron(self): 86 self.write_cmd(SET_DISP | 0x01) 87 88 def rotate(self, flag, update=True): 89 if flag: 90 self.write_cmd(SET_SEG_REMAP | 0x01) # mirror display vertically 91 self.write_cmd(SET_SCAN_DIR | 0x08) # mirror display hor. 92 else: 93 self.write_cmd(SET_SEG_REMAP | 0x00) 94 self.write_cmd(SET_SCAN_DIR | 0x00) 95 if update: 96 self.show() 97 98 def sleep(self, value): 99 self.write_cmd(SET_DISP | (not value)) 100 101 def contrast(self, contrast): 102 self.write_cmd(SET_CONTRAST) 103 self.write_cmd(contrast) 104 105 def invert(self, invert): 106 self.write_cmd(SET_NORM_INV | (invert & 1)) 107 108 def show(self): 109 for page in range(self.height // 8): 110 self.write_cmd(SET_PAGE_ADDRESS | page) 111 self.write_cmd(LOW_COLUMN_ADDRESS) 112 self.write_cmd(HIGH_COLUMN_ADDRESS) 113 page_buffer = bytearray(self.width) 114 for i in range(self.width): 115 page_buffer[i] = self.buffer[self.width * page + i] 116 self.write_data(page_buffer) 117 118 def set_buffer(self, buffer): 119 for i in range(len(buffer)): 120 self.buffer[i] = buffer[i] 121 122 def draw_XBM(self, x, y, w, h, bitmap): 123 x_byte = (w//8) + (w % 8 != 0) 124 for nbyte in range(len(bitmap)): 125 for bit in range(8): 126 if(bitmap[nbyte] & (0b10000000 >> bit)): 127 p_x = (nbyte % x_byte)*8+bit 128 p_y = nbyte//x_byte 129 self.pixel(x + p_x, y + p_y, 1) 130 131 # 以屏幕GRAM的原始制式去填充Buffer 132 def draw_buffer(self, x, y, w, h, bitmap): 133 y_byte = (h//8) + (h % 8 != 0) 134 for nbyte in range(len(bitmap)): 135 for bit in range(8): 136 if(bitmap[nbyte] & (1 << bit)): 137 p_y = (nbyte % y_byte)*8+bit 138 p_x = nbyte//y_byte 139 self.pixel(x + p_x, y + p_y, 1) 140 141 def fill_rect(self, x, y, w, h, c): 142 self.fill_rect(x, y, w, h, c) 143 144 def fill_circle(self, x0, y0, r, c): 145 x = 0 146 y = r 147 deltax = 3 148 deltay = 2 - r - r 149 d = 1 - r 150 #print(x) 151 #print(y) 152 #print(deltax) 153 #print(deltay) 154 #print(d) 155 self.pixel(x + x0, y + y0, c) 156 self.pixel(x + x0, -y + y0, c) 157 for i in range(-r + x0, r + x0): 158 self.pixel(i, y0, c) 159 while x < y: 160 if d < 0: 161 d += deltax 162 deltax += 2 163 x = x +1 164 else: 165 d += (deltax + deltay) 166 deltax += 2 167 deltay += 2 168 x = x +1 169 y = y -1 170 for i in range(-x + x0, x + x0): 171 self.pixel(i, -y + y0, c) 172 self.pixel(i, y + y0, c) 173 for i in range(-y + x0, y + x0): 174 self.pixel(i, -x + y0, c) 175 self.pixel(i, x + y0, c) 176 177 def draw_circle(self, x0, y0, r, w, c): 178 self.fill_circle(x0, y0, r, c) 179 self.fill_circle(x0, y0, r -w, 0) 180 181 def reset(self, res): 182 if res is not None: 183 res.write(1) 184 utime.sleep_ms(1) 185 res.write(0) 186 utime.sleep_ms(20) 187 res.write(1) 188 utime.sleep_ms(20) 189 190 191class SH1106_I2C(SH1106): 192 def __init__(self, width, height, i2c, res=None, addr=0x3c): 193 self.i2c = i2c 194 self.addr = addr 195 self.res = res 196 self.temp = bytearray(2) 197 super().__init__(width, height) 198 199 def write_cmd(self, cmd): 200 self.temp[0] = 0x80 # Co=1, D/C#=0 201 self.temp[1] = cmd 202 self.i2c.write(self.temp) 203 204 def write_data(self, buf): 205 send_buf = bytearray(1 + len(buf)) 206 send_buf[0] = 0x40 207 for i in range(len(buf)): 208 send_buf[i+1] = buf[i] 209 print(send_buf) 210 self.i2c.write(send_buf) 211 212 def reset(self): 213 super().reset(self.res) 214 215class SH1106_SPI(SH1106): 216 def __init__(self, width, height, spi, dc, res=None, cs=None): 217 self.spi = spi 218 self.dc = dc 219 self.res = res 220 self.cs = cs 221 super().__init__(width, height) 222 223 def write_cmd(self, cmd): 224 if self.cs is not None: 225 self.cs.write(1) 226 self.dc.write(0) 227 self.cs.write(0) 228 self.spi.write(bytearray([cmd])) 229 self.cs.write(1) 230 else: 231 self.dc.write(0) 232 self.spi.write(bytearray([cmd])) 233 234 def write_data(self, buf): 235 if self.cs is not None: 236 self.cs.write(1) 237 self.dc.write(1) 238 self.cs.write(0) 239 self.spi.write(buf) 240 self.cs.write(1) 241 else: 242 self.dc.write(1) 243 self.spi.write(buf) 244 245 def reset(self): 246 super().reset(self.res) 247