123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215 |
- import gc
- from machine import I2C
- from lcd import color, constant, font
- class LCD(object):
- def __init__(self, dt=constant.I2C128x64, baud=constant.I2CBAUDRATE):
- self.__width = int(dt['width'] if 'width' in dt else 0)
- self.__height = int(dt['height'] if 'height' in dt else 0)
- self.__pages = int(self.__height / 8)
- self.__buff_size = int(self.__width * self.__height / 8)
- self.__buffer = [0] * self.__buff_size
- self.__i2c = I2C(0, I2C.MASTER, baudrate=baud)
-
- self.__write(constant.SSD1306_DISPLAYOFF)
- self.__write(constant.SSD1306_SETDISPLAYCLOCKDIV, 0x80)
- self.__write(constant.SSD1306_SETDISPLAYOFFSET, 0x0)
- self.__write(constant.SSD1306_SETSTARTLINE | 0x0)
- self.__write(constant.SSD1306_CHARGEPUMP, 0x14)
- self.__write(constant.SSD1306_MEMORYMODE, 0x00)
- self.__write(constant.SSD1306_COLUMNADDR, 0, self.__width - 1)
- self.__write(constant.SSD1306_PAGEADDR, 0, self.__pages - 1)
- self.__write(constant.SSD1306_SEGREMAP | 0x1)
- self.__write(constant.SSD1306_COMSCANDEC)
- self.__write(constant.SSD1306_SETPRECHARGE, 0xF1)
- self.__write(constant.SSD1306_SETVCOMDETECT, 0x40)
- self.__write(constant.SSD1306_DISPLAYALLON_RESUME)
- self.__write(constant.SSD1306_NORMALDISPLAY)
- if dt == constant.I2C128x32:
- self.__write(constant.SSD1306_SETMULTIPLEX, 0x1F)
- self.__write(constant.SSD1306_SETCOMPINS, 0x02)
- self.__write(constant.SSD1306_SETCONTRAST, 0x8F)
- elif dt == constant.I2C128x64:
- self.__write(constant.SSD1306_SETMULTIPLEX, 0x3F)
- self.__write(constant.SSD1306_SETCOMPINS, 0x12)
- self.__write(constant.SSD1306_SETCONTRAST, 0xCF)
- else:
- raise NotImplementedError
- self.display_clear(True)
- self.display_off()
- def __write(self, *args):
- b = [0]
- if len(args) == 1 and type(args[0]) == bytearray:
- b = args[0]
- else:
- b = bytearray(b + list(args))
- self.__i2c.writeto(constant.SSD1306_I2C_ADDRESS, b)
- gc.collect()
- def display_contrast(self, c):
- if c < 0 or c > 255:
- raise ValueError("Contrast must be between 0-255")
- self.__write(constant.SSD1306_SETCONTRAST, c)
- def display_off(self):
- self.__write(constant.SSD1306_DISPLAYOFF)
- def display_on(self):
- self.__write(constant.SSD1306_DISPLAYON)
- def display_clear(self, update=False):
- self.__buffer = [0] * self.__buff_size
- if update:
- self.display_update()
-
- def draw_px(self, x, y, clr=color.WHITE):
- pos = int(y / 8) * self.__width + x
- bm = (0x1 << (y % 8))
- bpos = self.__buffer[pos]
- self.__buffer[pos] = bpos | bm if clr == color.WHITE else bpos & (0xff ^ bm)
-
- def draw_line(self, x0, y0, x1, y1, clr=color.WHITE):
- if x0 == x1:
- self.__draw_v_line(x0, y0, abs(y1 - y0), clr)
- elif y0 == y1:
- self.__draw_h_line(x0, y0, abs(x1 - x0), clr)
- else:
- self.__draw_line(x0, y0, x1, y1, clr)
- def __draw_line(self, x0, y0, x1, y1, clr):
- steep = abs(y1 - y0) > abs(x1 - x0)
- if steep:
- x0, y0 = y0, x0
- x1, y1 = y1, x1
- if x0 > x1:
- x0, x1 = x1, x0
- y0, y1 = y1, y0
- dx = abs(x1 - x0)
- dy = abs(y1 - y0)
- err = dx / 2
- ystep = 1 if y0 < y1 else -1
- y = y0
- for x in range(x0, x1):
- if steep:
- self.draw_px(y, x, clr)
- else:
- self.draw_px(x, y, clr)
- err = err - dy
- if err < 0:
- y += ystep
- err += dx
- def __draw_v_line(self, x, y, h, clr):
- for y1 in range(y, y + h):
- self.draw_px(x, y1, clr)
- def __draw_h_line(self, x, y, w, clr):
- for x1 in range(x, x + w):
- self.draw_px(x1, y, clr)
- def __bresenham_plot(self, x, d1, y, d2, clr):
- self.draw_px(x + d1, y + d2)
- self.draw_px(x + d1, y - d2)
- self.draw_px(x - d1, y + d2)
- self.draw_px(x - d1, y - d2)
- self.draw_px(x + d2, y + d1)
- self.draw_px(x + d2, y - d1)
- self.draw_px(x - d2, y + d1)
- self.draw_px(x - d2, y - d1)
- def __bresenham_line(self, x, d1, y, d2, clr):
- self.__draw_v_line(x + d1, y - d2, 2 * d2, clr)
- self.__draw_v_line(x + d2, y - d1, 2 * d1, clr)
- self.__draw_v_line(x - d1, y - d2, 2 * d2, clr)
- self.__draw_v_line(x - d2, y - d1, 2 * d1, clr)
- def draw_circle(self, x0, y0, r, clr=color.WHITE):
- x = r
- y = 0
- err = 0
- while x >= y:
- self.__bresenham_plot(x0, x, y0, y, clr)
- if err <= 0:
- y += 1
- err += (2 * y) + 1
- else:
- x -= 1
- err -= (2 * x) + 1
- def draw_rect(self, x, y, w, h, clr=color.WHITE):
- self.__draw_h_line(x, y, w, clr)
- self.__draw_h_line(x, y + h, w, clr)
- self.__draw_v_line(x, y, h, clr)
- self.__draw_v_line(x + w, y, h, clr)
- def fill_circle(self, x0, y0, r, clr=color.WHITE):
- x = r
- y = 0
- err = 0
- while x >= y:
- self.__bresenham_line(x0, x, y0, y, clr)
- if err <= 0:
- y += 1
- err += (2 * y) + 1
- else:
- x -= 1
- err -= (2 * x) + 1
- def fill_rect(self, x, y, w, h, clr=color.WHITE):
- for i in range(x, x+w):
- self.__draw_v_line(i, y, h, clr)
- def fill_screen(self, clr=color.WHITE):
- self.fill_rect(0, 0, self.__width, self.__height, clr)
- def invert_colors(self):
- for i in range(0, len(self.__buffer)):
- self.__buffer[i] = ~self.__buffer[i]
- def draw_string(self, x, y, s, f=font.ASCII, clr=color.WHITE):
- mx = int(self.__width / (f['width'] + 1))
- my = int(self.__height / (f['height'] + 1))
- if x < 0 or (x + len(s)) > mx:
- raise ValueError("Out of X range")
- if y < 0 or y > my:
- raise ValueError("Out of Y range")
- pos = (self.__width) * y + ((f['width'] + 1) * x)
- for i in range(0, len(s)):
- c = 5 * (ord(s[i]) - 32)
- for p in range(0, f['width']):
- self.__buffer[pos + p] = f['value'][c + p]
- pos = pos + 6
- def display_text_mid_x(self, l, f=font.ASCII):
- mx = int(self.__width / (f['width'] + 1))
- return int((mx - l) / 2)
- def display_text_mid_y(self, f=font.ASCII):
- my = int(self.__height / (f['height'] + 1))
- return int(my / 2)
- def display_update(self):
- self.__write(constant.SSD1306_SETLOWCOLUMN)
- self.__write(constant.SSD1306_SETHIGHCOLUMN)
- self.__write(constant.SSD1306_SETSTARTLINE)
- line = [0] * 17
- line[0] = 0x40
- for i in range(0, len(self.__buffer), 16):
- for pos in range(0, 16):
- line[pos + 1] = self.__buffer[pos + i]
- self.__write(bytearray(line))
|