initial commit

master
alex 2026-03-05 22:40:23 +01:00
commit 247a92c519
8 changed files with 1518 additions and 0 deletions

19
colors.py 100644
View File

@ -0,0 +1,19 @@
def TFTColor(aR, aG, aB):
'''Create a 16 bit rgb value from the given R,G,B from 0-255.
This assumes rgb 565 layout and will be incorrect for bgr.'''
return ((aR & 0xF8) << 8) | ((aG & 0xFC) << 3) | (aB >> 3)
BLACK = 0
RED = TFTColor(0xFF, 0x00, 0x00)
MAROON = TFTColor(0x80, 0x00, 0x00)
GREEN = TFTColor(0x00, 0xFF, 0x00)
FOREST = TFTColor(0x00, 0x80, 0x80)
BLUE = TFTColor(0x00, 0x00, 0xFF)
NAVY = TFTColor(0x00, 0x00, 0x80)
CYAN = TFTColor(0x00, 0xFF, 0xFF)
YELLOW = TFTColor(0xFF, 0xFF, 0x00)
PURPLE = TFTColor(0xFF, 0x00, 0xFF)
WHITE = TFTColor(0xFF, 0xFF, 0xFF)
GRAY = TFTColor(0x80, 0x80, 0x80)

5
display.py 100644
View File

@ -0,0 +1,5 @@
class Display:
def __init__(self):
pass

43
main.py 100644
View File

@ -0,0 +1,43 @@
from machine import Pin, SPI
from st7735 import TFT
from colors import *
from page import Page
from widgets import *
spi = SPI(1, mosi=Pin(6), sck=Pin(4), baudrate=20000000, polarity=0, phase=0)
disp = TFT(spi, 0, 2, 1)
disp.initr()
disp.rgb(True)
disp.rotation(2)
page = Page(disp, b_color=WHITE)
lbl = Label("My Label", (10, 10), back_color=GREEN)
page.widgets.append(lbl)
chbox = Checkbox("My Checkbox", (10,30), f_color=MAROON, back_color=GREEN)
page.widgets.append(chbox)
chbox1 = Checkbox("My Checkbox", (10,50), checked=True, f_color=MAROON, back_color=GREEN)
page.widgets.append(chbox1)
rdbut = RadioButton("My RadioButton", (10,70), f_color=MAROON, back_color=GREEN)
page.widgets.append(rdbut)
rdbut1 = RadioButton("My RadioButton1", (10,90), checked=True, f_color=MAROON, back_color=GREEN)
page.widgets.append(rdbut1)
lbl1 = Label("Focus", (10, 110), back_color=GREEN)
lbl1.set_focus(True)
page.widgets.append(lbl1)
page.draw()
import time
time.sleep(2)
page2 = Page(disp, visible = False, b_color=0)
page2.widgets.append(Label("Hello 2. Screen", (10, 10),f_color=MAROON, back_color=WHITE))
lbl1.set_focus(False)
page.set_visible(False)
page2.set_visible(True)
page2.draw()

21
page.py 100644
View File

@ -0,0 +1,21 @@
from colors import *
class Page:
def __init__(self, display, visible = True, b_color=WHITE):
self.visible = visible
self.widgets = list()
self.display = display
self.b_color = b_color
def draw(self):
if self.visible:
self.display.fill(self.b_color)
for w in self.widgets:
w.draw(self.display)
def set_visible(self, visible):
self.visible = visible
def get_visible(self):
return self.visible

155
ssd1306.py 100644
View File

@ -0,0 +1,155 @@
# MicroPython SSD1306 OLED driver, I2C and SPI interfaces
from micropython import const
import framebuf
# register definitions
SET_CONTRAST = const(0x81)
SET_ENTIRE_ON = const(0xA4)
SET_NORM_INV = const(0xA6)
SET_DISP = const(0xAE)
SET_MEM_ADDR = const(0x20)
SET_COL_ADDR = const(0x21)
SET_PAGE_ADDR = const(0x22)
SET_DISP_START_LINE = const(0x40)
SET_SEG_REMAP = const(0xA0)
SET_MUX_RATIO = const(0xA8)
SET_COM_OUT_DIR = const(0xC0)
SET_DISP_OFFSET = const(0xD3)
SET_COM_PIN_CFG = const(0xDA)
SET_DISP_CLK_DIV = const(0xD5)
SET_PRECHARGE = const(0xD9)
SET_VCOM_DESEL = const(0xDB)
SET_CHARGE_PUMP = const(0x8D)
# Subclassing FrameBuffer provides support for graphics primitives
# http://docs.micropython.org/en/latest/pyboard/library/framebuf.html
class SSD1306(framebuf.FrameBuffer):
def __init__(self, width, height, external_vcc):
self.width = width
self.height = height
self.external_vcc = external_vcc
self.pages = self.height // 8
self.buffer = bytearray(self.pages * self.width)
super().__init__(self.buffer, self.width, self.height, framebuf.MONO_VLSB)
self.init_display()
def init_display(self):
for cmd in (
SET_DISP | 0x00, # off
# address setting
SET_MEM_ADDR,
0x00, # horizontal
# resolution and layout
SET_DISP_START_LINE | 0x00,
SET_SEG_REMAP | 0x01, # column addr 127 mapped to SEG0
SET_MUX_RATIO,
self.height - 1,
SET_COM_OUT_DIR | 0x08, # scan from COM[N] to COM0
SET_DISP_OFFSET,
0x00,
SET_COM_PIN_CFG,
0x02 if self.width > 2 * self.height else 0x12,
# timing and driving scheme
SET_DISP_CLK_DIV,
0x80,
SET_PRECHARGE,
0x22 if self.external_vcc else 0xF1,
SET_VCOM_DESEL,
0x30, # 0.83*Vcc
# display
SET_CONTRAST,
0xFF, # maximum
SET_ENTIRE_ON, # output follows RAM contents
SET_NORM_INV, # not inverted
# charge pump
SET_CHARGE_PUMP,
0x10 if self.external_vcc else 0x14,
SET_DISP | 0x01,
): # on
self.write_cmd(cmd)
self.fill(0)
self.show()
def poweroff(self):
self.write_cmd(SET_DISP | 0x00)
def poweron(self):
self.write_cmd(SET_DISP | 0x01)
def contrast(self, contrast):
self.write_cmd(SET_CONTRAST)
self.write_cmd(contrast)
def invert(self, invert):
self.write_cmd(SET_NORM_INV | (invert & 1))
def show(self):
x0 = 0
x1 = self.width - 1
if self.width == 64:
# displays with width of 64 pixels are shifted by 32
x0 += 32
x1 += 32
self.write_cmd(SET_COL_ADDR)
self.write_cmd(x0)
self.write_cmd(x1)
self.write_cmd(SET_PAGE_ADDR)
self.write_cmd(0)
self.write_cmd(self.pages - 1)
self.write_data(self.buffer)
class SSD1306_I2C(SSD1306):
def __init__(self, width, height, i2c, addr=0x3C, external_vcc=False):
self.i2c = i2c
self.addr = addr
self.temp = bytearray(2)
self.write_list = [b"\x40", None] # Co=0, D/C#=1
super().__init__(width, height, external_vcc)
def write_cmd(self, cmd):
self.temp[0] = 0x80 # Co=1, D/C#=0
self.temp[1] = cmd
self.i2c.writeto(self.addr, self.temp)
def write_data(self, buf):
self.write_list[1] = buf
self.i2c.writevto(self.addr, self.write_list)
class SSD1306_SPI(SSD1306):
def __init__(self, width, height, spi, dc, res, cs, external_vcc=False):
self.rate = 10 * 1024 * 1024
dc.init(dc.OUT, value=0)
res.init(res.OUT, value=0)
cs.init(cs.OUT, value=1)
self.spi = spi
self.dc = dc
self.res = res
self.cs = cs
import time
self.res(1)
time.sleep_ms(1)
self.res(0)
time.sleep_ms(10)
self.res(1)
super().__init__(width, height, external_vcc)
def write_cmd(self, cmd):
self.spi.init(baudrate=self.rate, polarity=0, phase=0)
self.cs(1)
self.dc(0)
self.cs(0)
self.spi.write(bytearray([cmd]))
self.cs(1)
def write_data(self, buf):
self.spi.init(baudrate=self.rate, polarity=0, phase=0)
self.cs(1)
self.dc(1)
self.cs(0)
self.spi.write(buf)
self.cs(1)

922
st7735.py 100644
View File

@ -0,0 +1,922 @@
# driver for Sainsmart 1.8" TFT display ST7735
# Translated by Guy Carver from the ST7735 sample code.
# Modirfied for micropython-esp32 by boochow
import machine
import time
from math import sqrt
from colors import *
# TFTRotations and TFTRGB are bits to set
# on MADCTL to control display rotation/color layout
# Looking at display with pins on top.
# 00 = upper left printing right
# 10 = does nothing (MADCTL_ML)
# 20 = upper left printing down (backwards) (Vertical flip)
# 40 = upper right printing left (backwards) (X Flip)
# 80 = lower left printing right (backwards) (Y Flip)
# 04 = (MADCTL_MH)
# 60 = 90 right rotation
# C0 = 180 right rotation
# A0 = 270 right rotation
TFTRotations = [0x00, 0x60, 0xC0, 0xA0]
TFTBGR = 0x08 # When set color is bgr else rgb.
TFTRGB = 0x00
# @micropython.native
def clamp(aValue, aMin, aMax):
return max(aMin, min(aMax, aValue))
# @micropython.native
def TFTColor(aR, aG, aB):
'''Create a 16 bit rgb value from the given R,G,B from 0-255.
This assumes rgb 565 layout and will be incorrect for bgr.'''
return ((aR & 0xF8) << 8) | ((aG & 0xFC) << 3) | (aB >> 3)
ScreenSize = (128, 160)
class TFT(object):
"""Sainsmart TFT 7735 display driver."""
NOP = 0x0
SWRESET = 0x01
RDDID = 0x04
RDDST = 0x09
SLPIN = 0x10
SLPOUT = 0x11
PTLON = 0x12
NORON = 0x13
INVOFF = 0x20
INVON = 0x21
DISPOFF = 0x28
DISPON = 0x29
CASET = 0x2A
RASET = 0x2B
RAMWR = 0x2C
RAMRD = 0x2E
VSCRDEF = 0x33
VSCSAD = 0x37
COLMOD = 0x3A
MADCTL = 0x36
FRMCTR1 = 0xB1
FRMCTR2 = 0xB2
FRMCTR3 = 0xB3
INVCTR = 0xB4
DISSET5 = 0xB6
PWCTR1 = 0xC0
PWCTR2 = 0xC1
PWCTR3 = 0xC2
PWCTR4 = 0xC3
PWCTR5 = 0xC4
VMCTR1 = 0xC5
RDID1 = 0xDA
RDID2 = 0xDB
RDID3 = 0xDC
RDID4 = 0xDD
PWCTR6 = 0xFC
GMCTRP1 = 0xE0
GMCTRN1 = 0xE1
@staticmethod
def color(aR, aG, aB):
'''Create a 565 rgb TFTColor value'''
return TFTColor(aR, aG, aB)
def __init__(self, spi, aDC, aReset, aCS):
"""aLoc SPI pin location is either 1 for 'X' or 2 for 'Y'.
aDC is the DC pin and aReset is the reset pin."""
self._size = ScreenSize
self._offset = bytearray([0, 0])
self.rotate = 0 # Vertical with top toward pins.
self._rgb = True # color order of rgb.
self.tfa = 0 # top fixed area
self.bfa = 0 # bottom fixed area
self.dc = machine.Pin(aDC, machine.Pin.OUT, machine.Pin.PULL_DOWN)
self.reset = machine.Pin(aReset, machine.Pin.OUT, machine.Pin.PULL_DOWN)
self.cs = machine.Pin(aCS, machine.Pin.OUT, machine.Pin.PULL_DOWN)
self.cs(1)
self.spi = spi
self.colorData = bytearray(2)
self.windowLocData = bytearray(4)
def size(self):
return self._size
# @micropython.native
def on(self, aTF=True):
'''Turn display on or off.'''
self._writecommand(TFT.DISPON if aTF else TFT.DISPOFF)
# @micropython.native
def invertcolor(self, aBool):
'''Invert the color data IE: Black = White.'''
self._writecommand(TFT.INVON if aBool else TFT.INVOFF)
# @micropython.native
def rgb(self, aTF=True):
'''True = rgb else bgr'''
self._rgb = aTF
self._setMADCTL()
# @micropython.native
def rotation(self, aRot):
'''0 - 3. Starts vertical with top toward pins and rotates 90 deg
clockwise each step.'''
if (0 <= aRot < 4):
rotchange = self.rotate ^ aRot
self.rotate = aRot
# If switching from vertical to horizontal swap x,y
# (indicated by bit 0 changing).
if (rotchange & 1):
self._size = (self._size[1], self._size[0])
self._setMADCTL()
# @micropython.native
def pixel(self, aPos, aColor):
'''Draw a pixel at the given position'''
if 0 <= aPos[0] < self._size[0] and 0 <= aPos[1] < self._size[1]:
self._setwindowpoint(aPos)
self._pushcolor(aColor)
# @micropython.native
def text(self, aPos, aString, aColor, aFont, aSize=1, nowrap=False):
'''Draw a text at the given position. If the string reaches the end of the
display it is wrapped to aPos[0] on the next line. aSize may be an integer
which will size the font uniformly on w,h or a or any type that may be
indexed with [0] or [1].'''
if aFont == None:
return
# Make a size either from single value or 2 elements.
if (type(aSize) == int) or (type(aSize) == float):
wh = (aSize, aSize)
else:
wh = aSize
px, py = aPos
width = wh[0] * aFont["Width"] + 1
for c in aString:
self.char((px, py), c, aColor, aFont, wh)
px += width
# We check > rather than >= to let the right (blank) edge of the
# character print off the right of the screen.
if px + width > self._size[0]:
if nowrap:
break
else:
py += aFont["Height"] * wh[1] + 1
px = aPos[0]
# @micropython.native
def char(self, aPos, aChar, aColor, aFont, aSizes):
'''Draw a character at the given position using the given font and color.
aSizes is a tuple with x, y as integer scales indicating the
# of pixels to draw for each pixel in the character.'''
if aFont == None:
return
startchar = aFont['Start']
endchar = aFont['End']
ci = ord(aChar)
if (startchar <= ci <= endchar):
fontw = aFont['Width']
fonth = aFont['Height']
ci = (ci - startchar) * fontw
charA = aFont["Data"][ci:ci + fontw]
px = aPos[0]
if aSizes[0] <= 1 and aSizes[1] <= 1:
buf = bytearray(2 * fonth * fontw)
for q in range(fontw):
c = charA[q]
for r in range(fonth):
if c & 0x01:
pos = 2 * (r * fontw + q)
buf[pos] = aColor >> 8
buf[pos + 1] = aColor & 0xff
c >>= 1
self.image(aPos[0], aPos[1], aPos[0] + fontw - 1, aPos[1] + fonth - 1, buf)
else:
for c in charA:
py = aPos[1]
for r in range(fonth):
if c & 0x01:
self.fillrect((px, py), aSizes, aColor)
py += aSizes[1]
c >>= 1
px += aSizes[0]
# @micropython.native
def line(self, aStart, aEnd, aColor):
'''Draws a line from aStart to aEnd in the given color. Vertical or horizontal
lines are forwarded to vline and hline.'''
if aStart[0] == aEnd[0]:
# Make sure we use the smallest y.
pnt = aEnd if (aEnd[1] < aStart[1]) else aStart
self.vline(pnt, abs(aEnd[1] - aStart[1]) + 1, aColor)
elif aStart[1] == aEnd[1]:
# Make sure we use the smallest x.
pnt = aEnd if aEnd[0] < aStart[0] else aStart
self.hline(pnt, abs(aEnd[0] - aStart[0]) + 1, aColor)
else:
px, py = aStart
ex, ey = aEnd
dx = ex - px
dy = ey - py
inx = 1 if dx > 0 else -1
iny = 1 if dy > 0 else -1
dx = abs(dx)
dy = abs(dy)
if (dx >= dy):
dy <<= 1
e = dy - dx
dx <<= 1
while (px != ex):
self.pixel((px, py), aColor)
if (e >= 0):
py += iny
e -= dx
e += dy
px += inx
else:
dx <<= 1
e = dx - dy
dy <<= 1
while (py != ey):
self.pixel((px, py), aColor)
if (e >= 0):
px += inx
e -= dy
e += dx
py += iny
# @micropython.native
def vline(self, aStart, aLen, aColor):
'''Draw a vertical line from aStart for aLen. aLen may be negative.'''
start = (clamp(aStart[0], 0, self._size[0]), clamp(aStart[1], 0, self._size[1]))
stop = (start[0], clamp(start[1] + aLen, 0, self._size[1]))
# Make sure smallest y 1st.
if (stop[1] < start[1]):
start, stop = stop, start
self._setwindowloc(start, stop)
self._setColor(aColor)
self._draw(aLen)
# @micropython.native
def hline(self, aStart, aLen, aColor):
'''Draw a horizontal line from aStart for aLen. aLen may be negative.'''
start = (clamp(aStart[0], 0, self._size[0]), clamp(aStart[1], 0, self._size[1]))
stop = (clamp(start[0] + aLen, 0, self._size[0]), start[1])
# Make sure smallest x 1st.
if (stop[0] < start[0]):
start, stop = stop, start
self._setwindowloc(start, stop)
self._setColor(aColor)
self._draw(aLen)
# @micropython.native
def rect(self, aStart, aSize, aColor):
'''Draw a hollow rectangle. aStart is the smallest coordinate corner
and aSize is a tuple indicating width, height.'''
self.hline(aStart, aSize[0], aColor)
self.hline((aStart[0], aStart[1] + aSize[1] - 1), aSize[0], aColor)
self.vline(aStart, aSize[1], aColor)
self.vline((aStart[0] + aSize[0] - 1, aStart[1]), aSize[1], aColor)
# @micropython.native
def fillrect(self, aStart, aSize, aColor):
'''Draw a filled rectangle. aStart is the smallest coordinate corner
and aSize is a tuple indicating width, height.'''
start = (clamp(aStart[0], 0, self._size[0]), clamp(aStart[1], 0, self._size[1]))
end = (clamp(start[0] + aSize[0] - 1, 0, self._size[0]), clamp(start[1] + aSize[1] - 1, 0, self._size[1]))
if (end[0] < start[0]):
tmp = end[0]
end = (start[0], end[1])
start = (tmp, start[1])
if (end[1] < start[1]):
tmp = end[1]
end = (end[0], start[1])
start = (start[0], tmp)
self._setwindowloc(start, end)
numPixels = (end[0] - start[0] + 1) * (end[1] - start[1] + 1)
self._setColor(aColor)
self._draw(numPixels)
# @micropython.native
def circle(self, aPos, aRadius, aColor):
'''Draw a hollow circle with the given radius and color with aPos as center.'''
self.colorData[0] = aColor >> 8
self.colorData[1] = aColor
xend = int(0.7071 * aRadius) + 1
rsq = aRadius * aRadius
for x in range(xend):
y = int(sqrt(rsq - x * x))
xp = aPos[0] + x
yp = aPos[1] + y
xn = aPos[0] - x
yn = aPos[1] - y
xyp = aPos[0] + y
yxp = aPos[1] + x
xyn = aPos[0] - y
yxn = aPos[1] - x
self._setwindowpoint((xp, yp))
self._writedata(self.colorData)
self._setwindowpoint((xp, yn))
self._writedata(self.colorData)
self._setwindowpoint((xn, yp))
self._writedata(self.colorData)
self._setwindowpoint((xn, yn))
self._writedata(self.colorData)
self._setwindowpoint((xyp, yxp))
self._writedata(self.colorData)
self._setwindowpoint((xyp, yxn))
self._writedata(self.colorData)
self._setwindowpoint((xyn, yxp))
self._writedata(self.colorData)
self._setwindowpoint((xyn, yxn))
self._writedata(self.colorData)
# @micropython.native
def fillcircle(self, aPos, aRadius, aColor):
'''Draw a filled circle with given radius and color with aPos as center'''
rsq = aRadius * aRadius
for x in range(aRadius):
y = int(sqrt(rsq - x * x))
y0 = aPos[1] - y
ey = y0 + y * 2
y0 = clamp(y0, 0, self._size[1])
ln = abs(ey - y0) + 1;
self.vline((aPos[0] + x, y0), ln, aColor)
self.vline((aPos[0] - x, y0), ln, aColor)
def fill(self, aColor=BLACK):
'''Fill screen with the given color.'''
self.fillrect((0, 0), self._size, aColor)
def image(self, x0, y0, x1, y1, data):
self._setwindowloc((x0, y0), (x1, y1))
self._writedata(data)
def setvscroll(self, tfa, bfa):
''' set vertical scroll area '''
self._writecommand(TFT.VSCRDEF)
data2 = bytearray([0, tfa])
self._writedata(data2)
data2[1] = 162 - tfa - bfa
self._writedata(data2)
data2[1] = bfa
self._writedata(data2)
self.tfa = tfa
self.bfa = bfa
def vscroll(self, value):
a = value + self.tfa
if (a + self.bfa > 162):
a = 162 - self.bfa
self._vscrolladdr(a)
def _vscrolladdr(self, addr):
self._writecommand(TFT.VSCSAD)
data2 = bytearray([addr >> 8, addr & 0xff])
self._writedata(data2)
# @micropython.native
def _setColor(self, aColor):
self.colorData[0] = aColor >> 8
self.colorData[1] = aColor
self.buf = bytes(self.colorData) * 32
# @micropython.native
def _draw(self, aPixels):
'''Send given color to the device aPixels times.'''
self.dc(1)
self.cs(0)
for i in range(aPixels // 32):
self.spi.write(self.buf)
rest = (int(aPixels) % 32)
if rest > 0:
buf2 = bytes(self.colorData) * rest
self.spi.write(buf2)
self.cs(1)
# @micropython.native
def _setwindowpoint(self, aPos):
'''Set a single point for drawing a color to.'''
x = self._offset[0] + int(aPos[0])
y = self._offset[1] + int(aPos[1])
self._writecommand(TFT.CASET) # Column address set.
self.windowLocData[0] = self._offset[0]
self.windowLocData[1] = x
self.windowLocData[2] = self._offset[0]
self.windowLocData[3] = x
self._writedata(self.windowLocData)
self._writecommand(TFT.RASET) # Row address set.
self.windowLocData[0] = self._offset[1]
self.windowLocData[1] = y
self.windowLocData[2] = self._offset[1]
self.windowLocData[3] = y
self._writedata(self.windowLocData)
self._writecommand(TFT.RAMWR) # Write to RAM.
# @micropython.native
def _setwindowloc(self, aPos0, aPos1):
'''Set a rectangular area for drawing a color to.'''
self._writecommand(TFT.CASET) # Column address set.
self.windowLocData[0] = self._offset[0]
self.windowLocData[1] = self._offset[0] + int(aPos0[0])
self.windowLocData[2] = self._offset[0]
self.windowLocData[3] = self._offset[0] + int(aPos1[0])
self._writedata(self.windowLocData)
self._writecommand(TFT.RASET) # Row address set.
self.windowLocData[0] = self._offset[1]
self.windowLocData[1] = self._offset[1] + int(aPos0[1])
self.windowLocData[2] = self._offset[1]
self.windowLocData[3] = self._offset[1] + int(aPos1[1])
self._writedata(self.windowLocData)
self._writecommand(TFT.RAMWR) # Write to RAM.
# @micropython.native
def _writecommand(self, aCommand):
'''Write given command to the device.'''
self.dc(0)
self.cs(0)
self.spi.write(bytearray([aCommand]))
self.cs(1)
# @micropython.native
def _writedata(self, aData):
'''Write given data to the device. This may be
either a single int or a bytearray of values.'''
self.dc(1)
self.cs(0)
self.spi.write(aData)
self.cs(1)
# @micropython.native
def _pushcolor(self, aColor):
'''Push given color to the device.'''
self.colorData[0] = aColor >> 8
self.colorData[1] = aColor
self._writedata(self.colorData)
# @micropython.native
def _setMADCTL(self):
'''Set screen rotation and RGB/BGR format.'''
self._writecommand(TFT.MADCTL)
rgb = TFTRGB if self._rgb else TFTBGR
self._writedata(bytearray([TFTRotations[self.rotate] | rgb]))
# @micropython.native
def _reset(self):
'''Reset the device.'''
self.dc(0)
self.reset(1)
time.sleep_us(500)
self.reset(0)
time.sleep_us(500)
self.reset(1)
time.sleep_us(500)
def initb(self):
'''Initialize blue tab version.'''
self._size = (ScreenSize[0] + 2, ScreenSize[1] + 1)
self._reset()
self._writecommand(TFT.SWRESET) # Software reset.
time.sleep_us(50)
self._writecommand(TFT.SLPOUT) # out of sleep mode.
time.sleep_us(500)
data1 = bytearray(1)
self._writecommand(TFT.COLMOD) # Set color mode.
data1[0] = 0x05 # 16 bit color.
self._writedata(data1)
time.sleep_us(10)
data3 = bytearray([0x00, 0x06, 0x03]) # fastest refresh, 6 lines front, 3 lines back.
self._writecommand(TFT.FRMCTR1) # Frame rate control.
self._writedata(data3)
time.sleep_us(10)
self._writecommand(TFT.MADCTL)
data1[0] = 0x08 # row address/col address, bottom to top refresh
self._writedata(data1)
data2 = bytearray(2)
self._writecommand(TFT.DISSET5) # Display settings
data2[0] = 0x15 # 1 clock cycle nonoverlap, 2 cycle gate rise, 3 cycle oscil, equalize
data2[1] = 0x02 # fix on VTL
self._writedata(data2)
self._writecommand(TFT.INVCTR) # Display inversion control
data1[0] = 0x00 # Line inversion.
self._writedata(data1)
self._writecommand(TFT.PWCTR1) # Power control
data2[0] = 0x02 # GVDD = 4.7V
data2[1] = 0x70 # 1.0uA
self._writedata(data2)
time.sleep_us(10)
self._writecommand(TFT.PWCTR2) # Power control
data1[0] = 0x05 # VGH = 14.7V, VGL = -7.35V
self._writedata(data1)
self._writecommand(TFT.PWCTR3) # Power control
data2[0] = 0x01 # Opamp current small
data2[1] = 0x02 # Boost frequency
self._writedata(data2)
self._writecommand(TFT.VMCTR1) # Power control
data2[0] = 0x3C # VCOMH = 4V
data2[1] = 0x38 # VCOML = -1.1V
self._writedata(data2)
time.sleep_us(10)
self._writecommand(TFT.PWCTR6) # Power control
data2[0] = 0x11
data2[1] = 0x15
self._writedata(data2)
# These different values don't seem to make a difference.
# dataGMCTRP = bytearray([0x0f, 0x1a, 0x0f, 0x18, 0x2f, 0x28, 0x20, 0x22, 0x1f,
# 0x1b, 0x23, 0x37, 0x00, 0x07, 0x02, 0x10])
dataGMCTRP = bytearray([0x02, 0x1c, 0x07, 0x12, 0x37, 0x32, 0x29, 0x2d, 0x29,
0x25, 0x2b, 0x39, 0x00, 0x01, 0x03, 0x10])
self._writecommand(TFT.GMCTRP1)
self._writedata(dataGMCTRP)
# dataGMCTRN = bytearray([0x0f, 0x1b, 0x0f, 0x17, 0x33, 0x2c, 0x29, 0x2e, 0x30,
# 0x30, 0x39, 0x3f, 0x00, 0x07, 0x03, 0x10])
dataGMCTRN = bytearray([0x03, 0x1d, 0x07, 0x06, 0x2e, 0x2c, 0x29, 0x2d, 0x2e,
0x2e, 0x37, 0x3f, 0x00, 0x00, 0x02, 0x10])
self._writecommand(TFT.GMCTRN1)
self._writedata(dataGMCTRN)
time.sleep_us(10)
self._writecommand(TFT.CASET) # Column address set.
self.windowLocData[0] = 0x00
self.windowLocData[1] = 2 # Start at column 2
self.windowLocData[2] = 0x00
self.windowLocData[3] = self._size[0] - 1
self._writedata(self.windowLocData)
self._writecommand(TFT.RASET) # Row address set.
self.windowLocData[1] = 1 # Start at row 2.
self.windowLocData[3] = self._size[1] - 1
self._writedata(self.windowLocData)
self._writecommand(TFT.NORON) # Normal display on.
time.sleep_us(10)
self._writecommand(TFT.RAMWR)
time.sleep_us(500)
self._writecommand(TFT.DISPON)
self.cs(1)
time.sleep_us(500)
def initr(self):
'''Initialize a red tab version.'''
self._reset()
self._writecommand(TFT.SWRESET) # Software reset.
time.sleep_us(150)
self._writecommand(TFT.SLPOUT) # out of sleep mode.
time.sleep_us(500)
data3 = bytearray([0x01, 0x2C, 0x2D]) # fastest refresh, 6 lines front, 3 lines back.
self._writecommand(TFT.FRMCTR1) # Frame rate control.
self._writedata(data3)
self._writecommand(TFT.FRMCTR2) # Frame rate control.
self._writedata(data3)
data6 = bytearray([0x01, 0x2c, 0x2d, 0x01, 0x2c, 0x2d])
self._writecommand(TFT.FRMCTR3) # Frame rate control.
self._writedata(data6)
time.sleep_us(10)
data1 = bytearray(1)
self._writecommand(TFT.INVCTR) # Display inversion control
data1[0] = 0x07 # Line inversion.
self._writedata(data1)
self._writecommand(TFT.PWCTR1) # Power control
data3[0] = 0xA2
data3[1] = 0x02
data3[2] = 0x84
self._writedata(data3)
self._writecommand(TFT.PWCTR2) # Power control
data1[0] = 0xC5 # VGH = 14.7V, VGL = -7.35V
self._writedata(data1)
data2 = bytearray(2)
self._writecommand(TFT.PWCTR3) # Power control
data2[0] = 0x0A # Opamp current small
data2[1] = 0x00 # Boost frequency
self._writedata(data2)
self._writecommand(TFT.PWCTR4) # Power control
data2[0] = 0x8A # Opamp current small
data2[1] = 0x2A # Boost frequency
self._writedata(data2)
self._writecommand(TFT.PWCTR5) # Power control
data2[0] = 0x8A # Opamp current small
data2[1] = 0xEE # Boost frequency
self._writedata(data2)
self._writecommand(TFT.VMCTR1) # Power control
data1[0] = 0x0E
self._writedata(data1)
self._writecommand(TFT.INVOFF)
self._writecommand(TFT.MADCTL) # Power control
data1[0] = 0xC8
self._writedata(data1)
self._writecommand(TFT.COLMOD)
data1[0] = 0x05
self._writedata(data1)
self._writecommand(TFT.CASET) # Column address set.
self.windowLocData[0] = 0x00
self.windowLocData[1] = 0x00
self.windowLocData[2] = 0x00
self.windowLocData[3] = self._size[0] - 1
self._writedata(self.windowLocData)
self._writecommand(TFT.RASET) # Row address set.
self.windowLocData[3] = self._size[1] - 1
self._writedata(self.windowLocData)
dataGMCTRP = bytearray([0x0f, 0x1a, 0x0f, 0x18, 0x2f, 0x28, 0x20, 0x22, 0x1f,
0x1b, 0x23, 0x37, 0x00, 0x07, 0x02, 0x10])
self._writecommand(TFT.GMCTRP1)
self._writedata(dataGMCTRP)
dataGMCTRN = bytearray([0x0f, 0x1b, 0x0f, 0x17, 0x33, 0x2c, 0x29, 0x2e, 0x30,
0x30, 0x39, 0x3f, 0x00, 0x07, 0x03, 0x10])
self._writecommand(TFT.GMCTRN1)
self._writedata(dataGMCTRN)
time.sleep_us(10)
self._writecommand(TFT.DISPON)
time.sleep_us(100)
self._writecommand(TFT.NORON) # Normal display on.
time.sleep_us(10)
self.cs(1)
def initb2(self):
'''Initialize another blue tab version.'''
self._size = (ScreenSize[0] + 2, ScreenSize[1] + 1)
self._offset[0] = 2
self._offset[1] = 1
self._reset()
self._writecommand(TFT.SWRESET) # Software reset.
time.sleep_us(50)
self._writecommand(TFT.SLPOUT) # out of sleep mode.
time.sleep_us(500)
data3 = bytearray([0x01, 0x2C, 0x2D]) #
self._writecommand(TFT.FRMCTR1) # Frame rate control.
self._writedata(data3)
time.sleep_us(10)
self._writecommand(TFT.FRMCTR2) # Frame rate control.
self._writedata(data3)
time.sleep_us(10)
self._writecommand(TFT.FRMCTR3) # Frame rate control.
self._writedata(data3)
time.sleep_us(10)
self._writecommand(TFT.INVCTR) # Display inversion control
data1 = bytearray(1) #
data1[0] = 0x07
self._writedata(data1)
self._writecommand(TFT.PWCTR1) # Power control
data3[0] = 0xA2 #
data3[1] = 0x02 #
data3[2] = 0x84 #
self._writedata(data3)
time.sleep_us(10)
self._writecommand(TFT.PWCTR2) # Power control
data1[0] = 0xC5 #
self._writedata(data1)
self._writecommand(TFT.PWCTR3) # Power control
data2 = bytearray(2)
data2[0] = 0x0A #
data2[1] = 0x00 #
self._writedata(data2)
self._writecommand(TFT.PWCTR4) # Power control
data2[0] = 0x8A #
data2[1] = 0x2A #
self._writedata(data2)
self._writecommand(TFT.PWCTR5) # Power control
data2[0] = 0x8A #
data2[1] = 0xEE #
self._writedata(data2)
self._writecommand(TFT.VMCTR1) # Power control
data1[0] = 0x0E #
self._writedata(data1)
time.sleep_us(10)
self._writecommand(TFT.MADCTL)
data1[0] = 0xC8 # row address/col address, bottom to top refresh
self._writedata(data1)
# These different values don't seem to make a difference.
# dataGMCTRP = bytearray([0x0f, 0x1a, 0x0f, 0x18, 0x2f, 0x28, 0x20, 0x22, 0x1f,
# 0x1b, 0x23, 0x37, 0x00, 0x07, 0x02, 0x10])
dataGMCTRP = bytearray([0x02, 0x1c, 0x07, 0x12, 0x37, 0x32, 0x29, 0x2d, 0x29,
0x25, 0x2b, 0x39, 0x00, 0x01, 0x03, 0x10])
self._writecommand(TFT.GMCTRP1)
self._writedata(dataGMCTRP)
# dataGMCTRN = bytearray([0x0f, 0x1b, 0x0f, 0x17, 0x33, 0x2c, 0x29, 0x2e, 0x30,
# 0x30, 0x39, 0x3f, 0x00, 0x07, 0x03, 0x10])
dataGMCTRN = bytearray([0x03, 0x1d, 0x07, 0x06, 0x2e, 0x2c, 0x29, 0x2d, 0x2e,
0x2e, 0x37, 0x3f, 0x00, 0x00, 0x02, 0x10])
self._writecommand(TFT.GMCTRN1)
self._writedata(dataGMCTRN)
time.sleep_us(10)
self._writecommand(TFT.CASET) # Column address set.
self.windowLocData[0] = 0x00
self.windowLocData[1] = 0x02 # Start at column 2
self.windowLocData[2] = 0x00
self.windowLocData[3] = self._size[0] - 1
self._writedata(self.windowLocData)
self._writecommand(TFT.RASET) # Row address set.
self.windowLocData[1] = 0x01 # Start at row 2.
self.windowLocData[3] = self._size[1] - 1
self._writedata(self.windowLocData)
data1 = bytearray(1)
self._writecommand(TFT.COLMOD) # Set color mode.
data1[0] = 0x05 # 16 bit color.
self._writedata(data1)
time.sleep_us(10)
self._writecommand(TFT.NORON) # Normal display on.
time.sleep_us(10)
self._writecommand(TFT.RAMWR)
time.sleep_us(500)
self._writecommand(TFT.DISPON)
self.cs(1)
time.sleep_us(500)
# @micropython.native
def initg(self):
'''Initialize a green tab version.'''
self._reset()
self._writecommand(TFT.SWRESET) # Software reset.
time.sleep_us(150)
self._writecommand(TFT.SLPOUT) # out of sleep mode.
time.sleep_us(255)
data3 = bytearray([0x01, 0x2C, 0x2D]) # fastest refresh, 6 lines front, 3 lines back.
self._writecommand(TFT.FRMCTR1) # Frame rate control.
self._writedata(data3)
self._writecommand(TFT.FRMCTR2) # Frame rate control.
self._writedata(data3)
data6 = bytearray([0x01, 0x2c, 0x2d, 0x01, 0x2c, 0x2d])
self._writecommand(TFT.FRMCTR3) # Frame rate control.
self._writedata(data6)
time.sleep_us(10)
self._writecommand(TFT.INVCTR) # Display inversion control
self._writedata(bytearray([0x07]))
self._writecommand(TFT.PWCTR1) # Power control
data3[0] = 0xA2
data3[1] = 0x02
data3[2] = 0x84
self._writedata(data3)
self._writecommand(TFT.PWCTR2) # Power control
self._writedata(bytearray([0xC5]))
data2 = bytearray(2)
self._writecommand(TFT.PWCTR3) # Power control
data2[0] = 0x0A # Opamp current small
data2[1] = 0x00 # Boost frequency
self._writedata(data2)
self._writecommand(TFT.PWCTR4) # Power control
data2[0] = 0x8A # Opamp current small
data2[1] = 0x2A # Boost frequency
self._writedata(data2)
self._writecommand(TFT.PWCTR5) # Power control
data2[0] = 0x8A # Opamp current small
data2[1] = 0xEE # Boost frequency
self._writedata(data2)
self._writecommand(TFT.VMCTR1) # Power control
self._writedata(bytearray([0x0E]))
self._writecommand(TFT.INVOFF)
self._setMADCTL()
self._writecommand(TFT.COLMOD)
self._writedata(bytearray([0x05]))
self._writecommand(TFT.CASET) # Column address set.
self.windowLocData[0] = 0x00
self.windowLocData[1] = 0x01 # Start at row/column 1.
self.windowLocData[2] = 0x00
self.windowLocData[3] = self._size[0] - 1
self._writedata(self.windowLocData)
self._writecommand(TFT.RASET) # Row address set.
self.windowLocData[3] = self._size[1] - 1
self._writedata(self.windowLocData)
dataGMCTRP = bytearray([0x02, 0x1c, 0x07, 0x12, 0x37, 0x32, 0x29, 0x2d, 0x29,
0x25, 0x2b, 0x39, 0x00, 0x01, 0x03, 0x10])
self._writecommand(TFT.GMCTRP1)
self._writedata(dataGMCTRP)
dataGMCTRN = bytearray([0x03, 0x1d, 0x07, 0x06, 0x2e, 0x2c, 0x29, 0x2d, 0x2e,
0x2e, 0x37, 0x3f, 0x00, 0x00, 0x02, 0x10])
self._writecommand(TFT.GMCTRN1)
self._writedata(dataGMCTRN)
self._writecommand(TFT.NORON) # Normal display on.
time.sleep_us(10)
self._writecommand(TFT.DISPON)
time.sleep_us(100)
self.cs(1)
def maker():
t = TFT(1, "X1", "X2")
print("Initializing")
t.initr()
t.fill(0)
return t
def makeb():
t = TFT(1, "X1", "X2")
print("Initializing")
t.initb()
t.fill(0)
return t
def makeg():
t = TFT(1, "X1", "X2")
print("Initializing")
t.initg()
t.fill(0)
return t

263
sysfont.py 100644
View File

@ -0,0 +1,263 @@
#Font used for ST7735 display.
#Each character uses 5 bytes.
#index using ASCII value * 5.
#Each byte contains a column of pixels.
#The character may be 8 pixels high and 5 wide.
sysfont = {"Width": 5, "Height": 8, "Start": 0, "End": 254, "Data": bytearray([
0x00, 0x00, 0x00, 0x00, 0x00,
0x3E, 0x5B, 0x4F, 0x5B, 0x3E,
0x3E, 0x6B, 0x4F, 0x6B, 0x3E,
0x1C, 0x3E, 0x7C, 0x3E, 0x1C,
0x18, 0x3C, 0x7E, 0x3C, 0x18,
0x1C, 0x57, 0x7D, 0x57, 0x1C,
0x1C, 0x5E, 0x7F, 0x5E, 0x1C,
0x00, 0x18, 0x3C, 0x18, 0x00,
0xFF, 0xE7, 0xC3, 0xE7, 0xFF,
0x00, 0x18, 0x24, 0x18, 0x00,
0xFF, 0xE7, 0xDB, 0xE7, 0xFF,
0x30, 0x48, 0x3A, 0x06, 0x0E,
0x26, 0x29, 0x79, 0x29, 0x26,
0x40, 0x7F, 0x05, 0x05, 0x07,
0x40, 0x7F, 0x05, 0x25, 0x3F,
0x5A, 0x3C, 0xE7, 0x3C, 0x5A,
0x7F, 0x3E, 0x1C, 0x1C, 0x08,
0x08, 0x1C, 0x1C, 0x3E, 0x7F,
0x14, 0x22, 0x7F, 0x22, 0x14,
0x5F, 0x5F, 0x00, 0x5F, 0x5F,
0x06, 0x09, 0x7F, 0x01, 0x7F,
0x00, 0x66, 0x89, 0x95, 0x6A,
0x60, 0x60, 0x60, 0x60, 0x60,
0x94, 0xA2, 0xFF, 0xA2, 0x94,
0x08, 0x04, 0x7E, 0x04, 0x08,
0x10, 0x20, 0x7E, 0x20, 0x10,
0x08, 0x08, 0x2A, 0x1C, 0x08,
0x08, 0x1C, 0x2A, 0x08, 0x08,
0x1E, 0x10, 0x10, 0x10, 0x10,
0x0C, 0x1E, 0x0C, 0x1E, 0x0C,
0x30, 0x38, 0x3E, 0x38, 0x30,
0x06, 0x0E, 0x3E, 0x0E, 0x06,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x5F, 0x00, 0x00,
0x00, 0x07, 0x00, 0x07, 0x00,
0x14, 0x7F, 0x14, 0x7F, 0x14,
0x24, 0x2A, 0x7F, 0x2A, 0x12,
0x23, 0x13, 0x08, 0x64, 0x62,
0x36, 0x49, 0x56, 0x20, 0x50,
0x00, 0x08, 0x07, 0x03, 0x00,
0x00, 0x1C, 0x22, 0x41, 0x00,
0x00, 0x41, 0x22, 0x1C, 0x00,
0x2A, 0x1C, 0x7F, 0x1C, 0x2A,
0x08, 0x08, 0x3E, 0x08, 0x08,
0x00, 0x80, 0x70, 0x30, 0x00,
0x08, 0x08, 0x08, 0x08, 0x08,
0x00, 0x00, 0x60, 0x60, 0x00,
0x20, 0x10, 0x08, 0x04, 0x02,
0x3E, 0x51, 0x49, 0x45, 0x3E,
0x00, 0x42, 0x7F, 0x40, 0x00,
0x72, 0x49, 0x49, 0x49, 0x46,
0x21, 0x41, 0x49, 0x4D, 0x33,
0x18, 0x14, 0x12, 0x7F, 0x10,
0x27, 0x45, 0x45, 0x45, 0x39,
0x3C, 0x4A, 0x49, 0x49, 0x31,
0x41, 0x21, 0x11, 0x09, 0x07,
0x36, 0x49, 0x49, 0x49, 0x36,
0x46, 0x49, 0x49, 0x29, 0x1E,
0x00, 0x00, 0x14, 0x00, 0x00,
0x00, 0x40, 0x34, 0x00, 0x00,
0x00, 0x08, 0x14, 0x22, 0x41,
0x14, 0x14, 0x14, 0x14, 0x14,
0x00, 0x41, 0x22, 0x14, 0x08,
0x02, 0x01, 0x59, 0x09, 0x06,
0x3E, 0x41, 0x5D, 0x59, 0x4E,
0x7C, 0x12, 0x11, 0x12, 0x7C,
0x7F, 0x49, 0x49, 0x49, 0x36,
0x3E, 0x41, 0x41, 0x41, 0x22,
0x7F, 0x41, 0x41, 0x41, 0x3E,
0x7F, 0x49, 0x49, 0x49, 0x41,
0x7F, 0x09, 0x09, 0x09, 0x01,
0x3E, 0x41, 0x41, 0x51, 0x73,
0x7F, 0x08, 0x08, 0x08, 0x7F,
0x00, 0x41, 0x7F, 0x41, 0x00,
0x20, 0x40, 0x41, 0x3F, 0x01,
0x7F, 0x08, 0x14, 0x22, 0x41,
0x7F, 0x40, 0x40, 0x40, 0x40,
0x7F, 0x02, 0x1C, 0x02, 0x7F,
0x7F, 0x04, 0x08, 0x10, 0x7F,
0x3E, 0x41, 0x41, 0x41, 0x3E,
0x7F, 0x09, 0x09, 0x09, 0x06,
0x3E, 0x41, 0x51, 0x21, 0x5E,
0x7F, 0x09, 0x19, 0x29, 0x46,
0x26, 0x49, 0x49, 0x49, 0x32,
0x03, 0x01, 0x7F, 0x01, 0x03,
0x3F, 0x40, 0x40, 0x40, 0x3F,
0x1F, 0x20, 0x40, 0x20, 0x1F,
0x3F, 0x40, 0x38, 0x40, 0x3F,
0x63, 0x14, 0x08, 0x14, 0x63,
0x03, 0x04, 0x78, 0x04, 0x03,
0x61, 0x59, 0x49, 0x4D, 0x43,
0x00, 0x7F, 0x41, 0x41, 0x41,
0x02, 0x04, 0x08, 0x10, 0x20,
0x00, 0x41, 0x41, 0x41, 0x7F,
0x04, 0x02, 0x01, 0x02, 0x04,
0x40, 0x40, 0x40, 0x40, 0x40,
0x00, 0x03, 0x07, 0x08, 0x00,
0x20, 0x54, 0x54, 0x78, 0x40,
0x7F, 0x28, 0x44, 0x44, 0x38,
0x38, 0x44, 0x44, 0x44, 0x28,
0x38, 0x44, 0x44, 0x28, 0x7F,
0x38, 0x54, 0x54, 0x54, 0x18,
0x00, 0x08, 0x7E, 0x09, 0x02,
0x18, 0xA4, 0xA4, 0x9C, 0x78,
0x7F, 0x08, 0x04, 0x04, 0x78,
0x00, 0x44, 0x7D, 0x40, 0x00,
0x20, 0x40, 0x40, 0x3D, 0x00,
0x7F, 0x10, 0x28, 0x44, 0x00,
0x00, 0x41, 0x7F, 0x40, 0x00,
0x7C, 0x04, 0x78, 0x04, 0x78,
0x7C, 0x08, 0x04, 0x04, 0x78,
0x38, 0x44, 0x44, 0x44, 0x38,
0xFC, 0x18, 0x24, 0x24, 0x18,
0x18, 0x24, 0x24, 0x18, 0xFC,
0x7C, 0x08, 0x04, 0x04, 0x08,
0x48, 0x54, 0x54, 0x54, 0x24,
0x04, 0x04, 0x3F, 0x44, 0x24,
0x3C, 0x40, 0x40, 0x20, 0x7C,
0x1C, 0x20, 0x40, 0x20, 0x1C,
0x3C, 0x40, 0x30, 0x40, 0x3C,
0x44, 0x28, 0x10, 0x28, 0x44,
0x4C, 0x90, 0x90, 0x90, 0x7C,
0x44, 0x64, 0x54, 0x4C, 0x44,
0x00, 0x08, 0x36, 0x41, 0x00,
0x00, 0x00, 0x77, 0x00, 0x00,
0x00, 0x41, 0x36, 0x08, 0x00,
0x02, 0x01, 0x02, 0x04, 0x02,
0x3C, 0x26, 0x23, 0x26, 0x3C,
0x1E, 0xA1, 0xA1, 0x61, 0x12,
0x3A, 0x40, 0x40, 0x20, 0x7A,
0x38, 0x54, 0x54, 0x55, 0x59,
0x21, 0x55, 0x55, 0x79, 0x41,
0x21, 0x54, 0x54, 0x78, 0x41,
0x21, 0x55, 0x54, 0x78, 0x40,
0x20, 0x54, 0x55, 0x79, 0x40,
0x0C, 0x1E, 0x52, 0x72, 0x12,
0x39, 0x55, 0x55, 0x55, 0x59,
0x39, 0x54, 0x54, 0x54, 0x59,
0x39, 0x55, 0x54, 0x54, 0x58,
0x00, 0x00, 0x45, 0x7C, 0x41,
0x00, 0x02, 0x45, 0x7D, 0x42,
0x00, 0x01, 0x45, 0x7C, 0x40,
0xF0, 0x29, 0x24, 0x29, 0xF0,
0xF0, 0x28, 0x25, 0x28, 0xF0,
0x7C, 0x54, 0x55, 0x45, 0x00,
0x20, 0x54, 0x54, 0x7C, 0x54,
0x7C, 0x0A, 0x09, 0x7F, 0x49,
0x32, 0x49, 0x49, 0x49, 0x32,
0x32, 0x48, 0x48, 0x48, 0x32,
0x32, 0x4A, 0x48, 0x48, 0x30,
0x3A, 0x41, 0x41, 0x21, 0x7A,
0x3A, 0x42, 0x40, 0x20, 0x78,
0x00, 0x9D, 0xA0, 0xA0, 0x7D,
0x39, 0x44, 0x44, 0x44, 0x39,
0x3D, 0x40, 0x40, 0x40, 0x3D,
0x3C, 0x24, 0xFF, 0x24, 0x24,
0x48, 0x7E, 0x49, 0x43, 0x66,
0x2B, 0x2F, 0xFC, 0x2F, 0x2B,
0xFF, 0x09, 0x29, 0xF6, 0x20,
0xC0, 0x88, 0x7E, 0x09, 0x03,
0x20, 0x54, 0x54, 0x79, 0x41,
0x00, 0x00, 0x44, 0x7D, 0x41,
0x30, 0x48, 0x48, 0x4A, 0x32,
0x38, 0x40, 0x40, 0x22, 0x7A,
0x00, 0x7A, 0x0A, 0x0A, 0x72,
0x7D, 0x0D, 0x19, 0x31, 0x7D,
0x26, 0x29, 0x29, 0x2F, 0x28,
0x26, 0x29, 0x29, 0x29, 0x26,
0x30, 0x48, 0x4D, 0x40, 0x20,
0x38, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x38,
0x2F, 0x10, 0xC8, 0xAC, 0xBA,
0x2F, 0x10, 0x28, 0x34, 0xFA,
0x00, 0x00, 0x7B, 0x00, 0x00,
0x08, 0x14, 0x2A, 0x14, 0x22,
0x22, 0x14, 0x2A, 0x14, 0x08,
0xAA, 0x00, 0x55, 0x00, 0xAA,
0xAA, 0x55, 0xAA, 0x55, 0xAA,
0x00, 0x00, 0x00, 0xFF, 0x00,
0x10, 0x10, 0x10, 0xFF, 0x00,
0x14, 0x14, 0x14, 0xFF, 0x00,
0x10, 0x10, 0xFF, 0x00, 0xFF,
0x10, 0x10, 0xF0, 0x10, 0xF0,
0x14, 0x14, 0x14, 0xFC, 0x00,
0x14, 0x14, 0xF7, 0x00, 0xFF,
0x00, 0x00, 0xFF, 0x00, 0xFF,
0x14, 0x14, 0xF4, 0x04, 0xFC,
0x14, 0x14, 0x17, 0x10, 0x1F,
0x10, 0x10, 0x1F, 0x10, 0x1F,
0x14, 0x14, 0x14, 0x1F, 0x00,
0x10, 0x10, 0x10, 0xF0, 0x00,
0x00, 0x00, 0x00, 0x1F, 0x10,
0x10, 0x10, 0x10, 0x1F, 0x10,
0x10, 0x10, 0x10, 0xF0, 0x10,
0x00, 0x00, 0x00, 0xFF, 0x10,
0x10, 0x10, 0x10, 0x10, 0x10,
0x10, 0x10, 0x10, 0xFF, 0x10,
0x00, 0x00, 0x00, 0xFF, 0x14,
0x00, 0x00, 0xFF, 0x00, 0xFF,
0x00, 0x00, 0x1F, 0x10, 0x17,
0x00, 0x00, 0xFC, 0x04, 0xF4,
0x14, 0x14, 0x17, 0x10, 0x17,
0x14, 0x14, 0xF4, 0x04, 0xF4,
0x00, 0x00, 0xFF, 0x00, 0xF7,
0x14, 0x14, 0x14, 0x14, 0x14,
0x14, 0x14, 0xF7, 0x00, 0xF7,
0x14, 0x14, 0x14, 0x17, 0x14,
0x10, 0x10, 0x1F, 0x10, 0x1F,
0x14, 0x14, 0x14, 0xF4, 0x14,
0x10, 0x10, 0xF0, 0x10, 0xF0,
0x00, 0x00, 0x1F, 0x10, 0x1F,
0x00, 0x00, 0x00, 0x1F, 0x14,
0x00, 0x00, 0x00, 0xFC, 0x14,
0x00, 0x00, 0xF0, 0x10, 0xF0,
0x10, 0x10, 0xFF, 0x10, 0xFF,
0x14, 0x14, 0x14, 0xFF, 0x14,
0x10, 0x10, 0x10, 0x1F, 0x00,
0x00, 0x00, 0x00, 0xF0, 0x10,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
0xFF, 0xFF, 0xFF, 0x00, 0x00,
0x00, 0x00, 0x00, 0xFF, 0xFF,
0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
0x38, 0x44, 0x44, 0x38, 0x44,
0x7C, 0x2A, 0x2A, 0x3E, 0x14,
0x7E, 0x02, 0x02, 0x06, 0x06,
0x02, 0x7E, 0x02, 0x7E, 0x02,
0x63, 0x55, 0x49, 0x41, 0x63,
0x38, 0x44, 0x44, 0x3C, 0x04,
0x40, 0x7E, 0x20, 0x1E, 0x20,
0x06, 0x02, 0x7E, 0x02, 0x02,
0x99, 0xA5, 0xE7, 0xA5, 0x99,
0x1C, 0x2A, 0x49, 0x2A, 0x1C,
0x4C, 0x72, 0x01, 0x72, 0x4C,
0x30, 0x4A, 0x4D, 0x4D, 0x30,
0x30, 0x48, 0x78, 0x48, 0x30,
0xBC, 0x62, 0x5A, 0x46, 0x3D,
0x3E, 0x49, 0x49, 0x49, 0x00,
0x7E, 0x01, 0x01, 0x01, 0x7E,
0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
0x44, 0x44, 0x5F, 0x44, 0x44,
0x40, 0x51, 0x4A, 0x44, 0x40,
0x40, 0x44, 0x4A, 0x51, 0x40,
0x00, 0x00, 0xFF, 0x01, 0x03,
0xE0, 0x80, 0xFF, 0x00, 0x00,
0x08, 0x08, 0x6B, 0x6B, 0x08,
0x36, 0x12, 0x36, 0x24, 0x36,
0x06, 0x0F, 0x09, 0x0F, 0x06,
0x00, 0x00, 0x18, 0x18, 0x00,
0x00, 0x00, 0x10, 0x10, 0x00,
0x30, 0x40, 0xFF, 0x01, 0x01,
0x00, 0x1F, 0x01, 0x01, 0x1E,
0x00, 0x19, 0x1D, 0x17, 0x12,
0x00, 0x3C, 0x3C, 0x3C, 0x3C
])}

90
widgets.py 100644
View File

@ -0,0 +1,90 @@
from colors import *
from sysfont import sysfont
class Widget:
def __init__(self, pos, callback=None, bg_color=RED):
self.has_focus = False
self.pos = pos
self.size = (0,0)
self.orig_pos = pos
self.callback = callback
self.back_color = bg_color
def draw(self, display):
if self.has_focus:
display.line(self.orig_pos, (self.orig_pos[0]+10, self.orig_pos[1]+8), RED)
display.line(self.orig_pos, (self.orig_pos[0], self.orig_pos[1]+16), RED)
display.line((self.orig_pos[0], self.orig_pos[1]+16), (self.orig_pos[0]+10, self.orig_pos[1]+8), RED)
display.fillrect(self.pos, (100, 100), NAVY)
if self.back_color is not None:
display.fillrect(self.pos, self.size, self.back_color)
def has_focus(self):
return self.has_focus
def set_focus(self, focus):
self.has_focus = focus
if self.has_focus:
self.pos = (self.orig_pos[0] + 12, self.orig_pos[1])
else:
self.pos = self.orig_pos
class Label(Widget):
def __init__(self, text, pos: tuple[int, int], text_offset:tuple[int, int]=None, f_color=BLACK, back_color=0, f_size=2, nowrap=True):
super().__init__(pos, bg_color=back_color)
self.ch_w = 5
self.ch_h = 8
self.text = text
self.text_offset = (0, 0)
if text_offset is not None:
self.text_offset = text_offset
self.f_color = f_color
self.f_size = f_size
self.nowrap = nowrap
self.size = (len(self.text)*(self.f_size*self.ch_w)+self.text_offset[0]+self.ch_w*self.f_size, self.f_size*self.ch_h+self.text_offset[1])
def draw(self, display):
super().draw(display)
display.text((self.pos[0] + self.text_offset[0], self.pos[1] + self.text_offset[1]), self.text, self.f_color, sysfont, self.f_size, nowrap=self.nowrap)
class Checkbox(Label):
def __init__(self, text, pos: tuple[int, int], checked=False, f_color=BLACK, back_color=0, f_size=2, nowrap=True):
self.ch_w = 5
self.ch_h = 8
self.b_pos = pos
self.box_size = (self.ch_w * f_size, self.ch_h * f_size)
self.checked = checked
super().__init__(text, pos, (self.box_size[0]+self.ch_w, 0), f_color, back_color, f_size, nowrap)
def draw(self, display):
super().draw(display)
display.rect(self.b_pos, self.box_size, self.f_color)
if self.checked:
display.line(self.b_pos, (self.b_pos[0]+self.box_size[0]//2, self.b_pos[1]+self.box_size[1]), self.f_color)
display.line((self.b_pos[0]+self.box_size[0]//2, self.b_pos[1]+self.box_size[1]),\
(self.b_pos[0]+self.box_size[0]+self.ch_w//2, self.b_pos[1]-self.ch_h//2), self.f_color)
class RadioButton(Label):
def __init__(self, text, pos: tuple[int, int], checked=False, f_color=BLACK, back_color=0, f_size=2, nowrap=True):
self.ch_w = 5
self.ch_h = 8
self.b_pos = pos
self.box_size = (self.ch_w * f_size, self.ch_h * f_size)
self.checked = checked
super().__init__(text, pos, (self.box_size[0]+self.ch_w, 0), f_color, back_color, f_size, nowrap)
def draw(self, display):
super().draw(display)
display.circle((self.b_pos[0]+self.ch_w*self.f_size//2, self.b_pos[1]+self.ch_w*self.f_size//2),
self.box_size[0]*0.75, self.f_color)
if self.checked:
display.circle((self.b_pos[0] + self.ch_w * self.f_size // 2, self.b_pos[1] + self.ch_w * self.f_size // 2),
self.box_size[0]*0.75, self.f_color)
display.fillcircle((self.b_pos[0] + self.ch_w * self.f_size // 2, self.b_pos[1] + self.ch_w * self.f_size // 2),
self.box_size[0]//2, self.f_color)