#Driver for Sainsmart 1.8" tft display ST7735 #Translated by Guy Carver from the ST7735 sample code. #Display uses SPI interface. #todo: Use const() import pyb from math import sqrt @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) class tft(object) : '''Sainsmart tft-7735 display driver.''' #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 = const(0x08) #When set color is bgr else rgb. _TFTRGB = const(0x00) _NOP = const(0x0) _SWRESET = const(0x01) _RDDID = const(0x04) _RDDST = const(0x09) _SLPIN = const(0x10) _SLPOUT = const(0x11) _PTLON = const(0x12) _NORON = const(0x13) _INVOFF = const(0x20) _INVON = const(0x21) _DISPOFF = const(0x28) _DISPON = const(0x29) _CASET = const(0x2A) _RASET = const(0x2B) _RAMWR = const(0x2C) _RAMRD = const(0x2E) _COLMOD = const(0x3A) _MADCTL = const(0x36) _FRMCTR1 = const(0xB1) _FRMCTR2 = const(0xB2) _FRMCTR3 = const(0xB3) _INVCTR = const(0xB4) _DISSET5 = const(0xB6) _PWCTR1 = const(0xC0) _PWCTR2 = const(0xC1) _PWCTR3 = const(0xC2) _PWCTR4 = const(0xC3) _PWCTR5 = const(0xC4) _VMCTR1 = const(0xC5) _RDID1 = const(0xDA) _RDID2 = const(0xDB) _RDID3 = const(0xDC) _RDID4 = const(0xDD) _PWCTR6 = const(0xFC) _GMCTRP1 = const(0xE0) _GMCTRN1 = const(0xE1) _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) _SCREENSIZE = (128, 160) @staticmethod def color( aR, aG, aB ) : '''Create a 565 rgb TFTColor value''' return TFTColor(aR, aG, aB) def __init__( self, aLoc, aDC, aReset ) : '''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 = tft._SCREENSIZE self.rotate = 0 #Vertical with top toward pins. self._rgb = True #color order of rgb. self.dc = pyb.Pin(aDC, pyb.Pin.OUT_PP, pyb.Pin.PULL_DOWN) self.reset = pyb.Pin(aReset, pyb.Pin.OUT_PP, pyb.Pin.PULL_DOWN) rate = 200000 #100000000 #Set way high but will be clamped to a maximum in SPI constructor. cs = "X5" if aLoc == 1 else "Y5" self.cs = pyb.Pin(cs, pyb.Pin.OUT_PP, pyb.Pin.PULL_DOWN) self.cs.high() self.spi = pyb.SPI(aLoc, pyb.SPI.MASTER, baudrate = rate, polarity = 1, phase = 0, crc=None) self.colorData = bytearray(2) self.windowLocData = bytearray(4) def size( self ) : return self._size def on( self, aTF = True ) : '''Turn display on or off.''' self._writecommand(_DISPON if aTF else _DISPOFF) def invertcolor( self, aBool ) : '''Invert the color data IE: Black = White.''' self._writecommand(_INVON if aBool else _INVOFF) def rgb( self, aTF = True ) : '''True = rgb else bgr''' self._rgb = aTF self._setMADCTL() 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) def text( self, aPos, aString, aColor, aFont, aSize = 1 ) : '''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]: py += aFont["Height"] * wh[1] + 1 px = aPos[0] 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 : for c in charA : py = aPos[1] for r in range(fonth) : if c & 0x01 : self.pixel((px, py), aColor) py += 1 c >>= 1 px += 1 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] 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 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._draw(aLen, aColor) 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._draw(aLen, aColor) 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) 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._draw(numPixels, aColor) 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) 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 _draw( self, aPixels, aColor ) : '''Send given color to the device aPixels times.''' self.colorData[0] = aColor >> 8 self.colorData[1] = aColor self.dc.high() self.cs.low() for i in range(aPixels): self.spi.send(self.colorData) self.cs.high() def _setwindowpoint( self, aPos ) : '''Set a single point for drawing a color to.''' x = int(aPos[0]) y = int(aPos[1]) self._writecommand(_CASET) #Column address set. self.windowLocData[0] = 0x00 self.windowLocData[1] = x self.windowLocData[2] = 0x00 self.windowLocData[3] = x self._writedata(self.windowLocData) self._writecommand(_RASET) #Row address set. self.windowLocData[1] = y self.windowLocData[3] = y self._writedata(self.windowLocData) self._writecommand(_RAMWR) #Write to RAM. def _setwindowloc( self, aPos0, aPos1 ) : '''Set a rectangular area for drawing a color to.''' self._writecommand(_CASET) #Column address set. self.windowLocData[0] = 0x00 self.windowLocData[1] = int(aPos0[0]) self.windowLocData[2] = 0x00 self.windowLocData[3] = int(aPos1[0]) self._writedata(self.windowLocData) self._writecommand(_RASET) #Row address set. self.windowLocData[1] = int(aPos0[1]) self.windowLocData[3] = int(aPos1[1]) self._writedata(self.windowLocData) self._writecommand(_RAMWR) #Write to RAM. @micropython.native def _writecommand( self, aCommand ) : '''Write given command to the device.''' self.dc.low() self.cs.low() self.spi.send(aCommand) self.cs.high() @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.high() self.cs.low() self.spi.send(aData) self.cs.high() @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(_MADCTL) rgb = _TFTRGB if self._rgb else _TFTBGR self._writedata(tft._TFTRotations[self.rotate] | rgb) @micropython.native def _reset( self ) : '''Reset the device.''' self.dc.low() self.reset.high() pyb.delay(500) self.reset.low() pyb.delay(500) self.reset.high() pyb.delay(500) # def initb( self ) : # '''Initialize blue tab version.''' # self._size = (ScreenSize[0] + 2, ScreenSize[1] + 1) # self._reset() # self._writecommand(_SWRESET) #Software reset. # pyb.delay(50) # self._writecommand(_SLPOUT) #out of sleep mode. # pyb.delay(500) # # data1 = bytearray(1) # self._writecommand(_COLMOD) #Set color mode. # data1[0] = 0x05 #16 bit color. # self._writedata(data1) # pyb.delay(10) # # data3 = bytearray([0x00, 0x06, 0x03]) #fastest refresh, 6 lines front, 3 lines back. # self._writecommand(_FRMCTR1) #Frame rate control. # self._writedata(data3) # pyb.delay(10) # # self._writecommand(_MADCTL) # data1[0] = 0x08 #row address/col address, bottom to top refresh # self._writedata(data1) # # data2 = bytearray(2) # self._writecommand(_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(_INVCTR) #Display inversion control # data1[0] = 0x00 #Line inversion. # self._writedata(data1) # # self._writecommand(_PWCTR1) #Power control # data2[0] = 0x02 #GVDD = 4.7V # data2[1] = 0x70 #1.0uA # self._writedata(data2) # pyb.delay(10) # # self._writecommand(_PWCTR2) #Power control # data1[0] = 0x05 #VGH = 14.7V, VGL = -7.35V # self._writedata(data1) # # self._writecommand(_PWCTR3) #Power control # data2[0] = 0x01 #Opamp current small # data2[1] = 0x02 #Boost frequency # self._writedata(data2) # # self._writecommand(_VMCTR1) #Power control # data2[0] = 0x3C #VCOMH = 4V # data2[1] = 0x38 #VCOML = -1.1V # self._writedata(data2) # pyb.delay(10) # # self._writecommand(_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(_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(_GMCTRN1) # self._writedata(dataGMCTRN) # pyb.delay(10) # # self._writecommand(_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(_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(_NORON) #Normal display on. # pyb.delay(10) # # self._writecommand(_RAMWR) # pyb.delay(500) # # self._writecommand(_DISPON) # self.cs.high() # pyb.delay(500) # # def initr( self ) : # '''Initialize a red tab version.''' # self._reset() # # self._writecommand(_SWRESET) #Software reset. # pyb.delay(150) # self._writecommand(_SLPOUT) #out of sleep mode. # pyb.delay(500) # # data3 = bytearray([0x01, 0x2C, 0x2D]) #fastest refresh, 6 lines front, 3 lines back. # self._writecommand(_FRMCTR1) #Frame rate control. # self._writedata(data3) # # self._writecommand(_FRMCTR2) #Frame rate control. # self._writedata(data3) # # data6 = bytearray([0x01, 0x2c, 0x2d, 0x01, 0x2c, 0x2d]) # self._writecommand(_FRMCTR3) #Frame rate control. # self._writedata(data6) # pyb.delay(10) # # data1 = bytearray(1) # self._writecommand(_INVCTR) #Display inversion control # data1[0] = 0x07 #Line inversion. # self._writedata(data1) # # self._writecommand(_PWCTR1) #Power control # data3[0] = 0xA2 # data3[1] = 0x02 # data3[2] = 0x84 # self._writedata(data3) # # self._writecommand(_PWCTR2) #Power control # data1[0] = 0xC5 #VGH = 14.7V, VGL = -7.35V # self._writedata(data1) # # data2 = bytearray(2) # self._writecommand(_PWCTR3) #Power control # data2[0] = 0x0A #Opamp current small # data2[1] = 0x00 #Boost frequency # self._writedata(data2) # # self._writecommand(_PWCTR4) #Power control # data2[0] = 0x8A #Opamp current small # data2[1] = 0x2A #Boost frequency # self._writedata(data2) # # self._writecommand(_PWCTR5) #Power control # data2[0] = 0x8A #Opamp current small # data2[1] = 0xEE #Boost frequency # self._writedata(data2) # # self._writecommand(_VMCTR1) #Power control # data1[0] = 0x0E # self._writedata(data1) # # self._writecommand(_INVOFF) # # self._writecommand(_MADCTL) #Power control # data1[0] = 0xC8 # self._writedata(data1) # # self._writecommand(_COLMOD) # data1[0] = 0x05 # self._writedata(data1) # # self._writecommand(_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(_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(_GMCTRP1) # self._writedata(dataGMCTRP) # # dataGMCTRN = bytearray([0x0f, 0x1b, 0x0f, 0x17, 0x33, 0x2c, 0x29, 0x2e, 0x30, # 0x30, 0x39, 0x3f, 0x00, 0x07, 0x03, 0x10]) # self._writecommand(_GMCTRN1) # self._writedata(dataGMCTRN) # pyb.delay(10) # # self._writecommand(_DISPON) # pyb.delay(100) # # self._writecommand(_NORON) #Normal display on. # pyb.delay(10) # # self.cs.high() @micropython.native def initg( self ) : '''Initialize a green tab version.''' self._reset() self._writecommand(_SWRESET) #Software reset. pyb.delay(150) self._writecommand(_SLPOUT) #out of sleep mode. pyb.delay(255) data3 = bytearray([0x01, 0x2C, 0x2D]) #fastest refresh, 6 lines front, 3 lines back. self._writecommand(_FRMCTR1) #Frame rate control. self._writedata(data3) self._writecommand(_FRMCTR2) #Frame rate control. self._writedata(data3) data6 = bytearray([0x01, 0x2c, 0x2d, 0x01, 0x2c, 0x2d]) self._writecommand(_FRMCTR3) #Frame rate control. self._writedata(data6) pyb.delay(10) self._writecommand(_INVCTR) #Display inversion control self._writedata(0x07) self._writecommand(_PWCTR1) #Power control data3[0] = 0xA2 data3[1] = 0x02 data3[2] = 0x84 self._writedata(data3) self._writecommand(_PWCTR2) #Power control self._writedata(0xC5) data2 = bytearray(2) self._writecommand(_PWCTR3) #Power control data2[0] = 0x0A #Opamp current small data2[1] = 0x00 #Boost frequency self._writedata(data2) self._writecommand(_PWCTR4) #Power control data2[0] = 0x8A #Opamp current small data2[1] = 0x2A #Boost frequency self._writedata(data2) self._writecommand(_PWCTR5) #Power control data2[0] = 0x8A #Opamp current small data2[1] = 0xEE #Boost frequency self._writedata(data2) self._writecommand(_VMCTR1) #Power control self._writedata(0x0E) self._writecommand(_INVOFF) self._setMADCTL() self._writecommand(_COLMOD) self._writedata(0x05) self._writecommand(_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(_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(_GMCTRP1) self._writedata(dataGMCTRP) dataGMCTRN = bytearray([0x03, 0x1d, 0x07, 0x06, 0x2e, 0x2c, 0x29, 0x2d, 0x2e, 0x2e, 0x37, 0x3f, 0x00, 0x00, 0x02, 0x10]) self._writecommand(_GMCTRN1) self._writedata(dataGMCTRN) self._writecommand(_NORON) #Normal display on. pyb.delay(10) self._writecommand(_DISPON) pyb.delay(100) self.cs.high() #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