Thank you for your reply, I did not use MCU Ram for the TFT. Just some small bytearray for a 5x8 font,
My code (as of my experimental design), working but not yet as class, and yes I'm a "C" Programmer
Code: Select all
import stm
import time
import machine
from math import trunc
import glcdfont
def FSMC_Init():
#constants of register
RCC_AHB3ENR_FSMCEN = 0x1 #bit to enable FSMC clock
RCC_AHB1ENR_GPIODEN = 0x00000008 #bit to enable D port clock
RCC_AHB1ENR_GPIOEEN = 0x00000010 #bit to enable E port clock
FSMC_Bank1_base = 0xA0000000 # 0xA0000000 FSMC registers base address
FSMC_BCR_bank1_offset = 0x0
FSMC_BTR_bank1_offset = 0x4
FSMC_BTR1_ADDSET_0 = 0x00000001
FSMC_BTR1_ADDSET_1 = 0x00000002
FSMC_BTR1_ADDSET_2 = 0x00000004
FSMC_BTR1_ADDSET_3 = 0x00000008
FSMC_BTR1_ADDSET_T = 0x0000000F # ILI9341, this is equivalent to RD high duration, 90ns, we set ADDSET to 15,is 15*6=90ns
FSMC_BTR1_DATAST = 0x0000FF00 #<DATAST [3:0] bits (Data-phase duration) */
FSMC_BTR1_DATAST_0 = 0x00000100
FSMC_BTR1_DATAST_1 = 0x00000200
FSMC_BTR1_DATAST_2 = 0x00000400
FSMC_BTR1_DATAST_3 = 0x00000800
FSMC_BTR1_DATAST_T = 0x00003C00 # DATAST to 60, which is 60 HCLK cycles, and the time is approximately 360ns.
FSMC_BTR1_BUSTURN = 0x000F0000 #<BUSTURN[3:0] bits (Bus turnaround phase duration) */
FSMC_BTR1_BUSTURN_0 = 0x00010000
FSMC_BTR1_BUSTURN_1 = 0x00020000
FSMC_BTR1_BUSTURN_2 = 0x00040000
FSMC_BTR1_BUSTURN_3 = 0x00080000
FSMC_BTR1_ACCMOD = 0x03000000
#FSMC_BTR1_ADDSET_1 = 0x2
#FSMC_BTR1_DATAST_1 = 0x00000200
FSMC_BCR1_MWID_0 = 0x00000010
FSMC_BCR1_WREN = 0x00001000
FSMC_BCR1_MBKEN = 0x1
machine.mem32[stm.RCC + stm.RCC_AHB3ENR] |= RCC_AHB3ENR_FSMCEN
machine.mem32[stm.RCC + stm.RCC_AHB1ENR] |= RCC_AHB1ENR_GPIODEN | RCC_AHB1ENR_GPIOEEN
# MODER allows a programmer to define the functionality of a GPIO pin
# Each pin has2 bitsthat permits the following configurations:
# 00: Input
# 01: Output
# 10: Alternate Function
# 11: Analog
# MODER15(1:0)... MODER0(1:0)
machine.mem32[stm.GPIOD + stm.GPIO_MODER] = 0b10101000001010101000101000101010 #10 10 10 00 00 10 10 10 10 00 10 10 00 10 10 10
machine.mem32[stm.GPIOE + stm.GPIO_MODER] = 0xAAAA8000
# OTYPER allows a programmer to configure the output stage of anoutput GPIO pin
# Each pin has1 bits that permits the following configurations:
# 0: Push-pull
# 1: Open Drain
machine.mem32[stm.GPIOD + stm.GPIO_OSPEEDR] = 0xFFFFFFFF #0x54154525
machine.mem32[stm.GPIOE + stm.GPIO_OSPEEDR] = 0xFFFFFFFF #0x55554000
machine.mem32[stm.GPIOD + stm.GPIO_AFR0] = ( (0b1100<<(4*0)) | (0b1100<<(4*1)) | (0b1100<<(4*2)) | (0b1100<<(4*4)) | (0b1100<<(4*5)) | (0b1100<<(4*7)) )
machine.mem32[stm.GPIOD + stm.GPIO_AFR1] = ( (0b1100<<(4*(8-8))) | (0b1100<<(4*(9-8))) | (0b1100<<(4*(10-8))) | (0b1100<<(4*(13-8))) | (0b1100<<(4*(14-8))) | (0b1100<<(4*(15-8))))
machine.mem32[stm.GPIOE + stm.GPIO_AFR0] = 0b1100<<(4*7)
machine.mem32[stm.GPIOE + stm.GPIO_AFR1] = 0xCCCCCCCC
FSMC_BTR1_ADDHLD_0 = 0x00000010 #<Bit 0 */
FSMC_BTR1_CLKDIV_0 = 0x00100000 # <Bit 0 */
FSMC_BTR1_CLKDIV_1 = 0x00200000 #<Bit 1 */
FSMC_BCR1_FACCEN = 0x00000040 #<Flash access enable
machine.mem32[FSMC_Bank1_base + FSMC_BTR_bank1_offset] = FSMC_BTR1_ADDSET_T | FSMC_BTR1_DATAST_T | FSMC_BTR1_ADDHLD_0 # | FSMC_BTR1_CLKDIV_1 | FSMC_BTR1_ACCMOD
machine.mem32[FSMC_Bank1_base + FSMC_BCR_bank1_offset] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN
def TFT_Init():
#SOFTWARE RESET
machine.mem8[LCD_REG] = 0x01
time.sleep_ms(1000)
machine.mem8[LCD_REG] = 0x01
time.sleep_ms(1000)
#POWER CONTROL A
machine.mem8[LCD_REG] = 0xCB
machine.mem8[LCD_RAM] = 0x39
machine.mem8[LCD_RAM] = 0x2C
machine.mem8[LCD_RAM] = 0x00
machine.mem8[LCD_RAM] = 0x34
machine.mem8[LCD_RAM] = 0x02
#POWER CONTROL B
machine.mem8[LCD_REG] = 0xCF
machine.mem8[LCD_RAM] = 0x00
machine.mem8[LCD_RAM] = 0xC1
machine.mem8[LCD_RAM] = 0x30
#DRIVER TIMING CONTROL A
machine.mem8[LCD_REG] = 0xE8
machine.mem8[LCD_RAM] = 0x85
machine.mem8[LCD_RAM] = 0x00
machine.mem8[LCD_RAM] = 0x78
#DRIVER TIMING CONTROL B
machine.mem8[LCD_REG] = 0xEA
machine.mem8[LCD_RAM] = 0x00
machine.mem8[LCD_RAM] = 0x00
#POWER ON SEQUENCE CONTROL
machine.mem8[LCD_REG] = 0xED
machine.mem8[LCD_RAM] = 0x64
machine.mem8[LCD_RAM] = 0x03
machine.mem8[LCD_RAM] = 0x12
machine.mem8[LCD_RAM] = 0x81
#PUMP RATIO CONTROL
machine.mem8[LCD_REG] = 0xF7
machine.mem8[LCD_RAM] = 0x20
#POWER CONTROL,VRH[5:0]
machine.mem8[LCD_REG] = 0xC0
machine.mem8[LCD_RAM] = 0x23
#POWER CONTROL,SAP[2:0]BT[3:0]
machine.mem8[LCD_REG] = 0xC1
machine.mem8[LCD_RAM] = 0x10
#VCM CONTROL
machine.mem8[LCD_REG] = 0xC5
machine.mem8[LCD_RAM] = 0x3E
machine.mem8[LCD_RAM] = 0x28
#VCM CONTROL 2
machine.mem8[LCD_REG] = 0xC7
machine.mem8[LCD_RAM] = 0x86
#MEMORY ACCESS CONTROL
machine.mem8[LCD_REG] = 0x36
machine.mem8[LCD_RAM] = 0x48
#PIXEL FORMAT 16bit
machine.mem8[LCD_REG] = 0x3A
machine.mem8[LCD_RAM] = 0x55
#FRAME RATIO CONTROL, STANDARD RGB COLOR
machine.mem8[LCD_REG] = 0xB1
machine.mem8[LCD_RAM] = 0x00
machine.mem8[LCD_RAM] = 0x18
#DISPLAY FUNCTION CONTROL
machine.mem8[LCD_REG] = 0xB6
machine.mem8[LCD_RAM] = 0x08
machine.mem8[LCD_RAM] = 0x82
machine.mem8[LCD_RAM] = 0x27
#3GAMMA FUNCTION DISABLE
#machine.mem8[LCD_REG] = 0xF2
#machine.mem8[LCD_RAM] = 0x00
#GAMMA CURVE SELECTED
#machine.mem8[LCD_REG] = 0x26
#machine.mem8[LCD_RAM] = 0x01
#POSITIVE GAMMA CORRECTION
#machine.mem8[LCD_REG] = 0xE0
#machine.mem8[LCD_RAM] = 0x0F
#machine.mem8[LCD_RAM] = 0x31
#machine.mem8[LCD_RAM] = 0x2B
#machine.mem8[LCD_RAM] = 0x0C
#machine.mem8[LCD_RAM] = 0x0E
#machine.mem8[LCD_RAM] = 0x08
#machine.mem8[LCD_RAM] = 0x4E
#machine.mem8[LCD_RAM] = 0xF1
#machine.mem8[LCD_RAM] = 0x37
#machine.mem8[LCD_RAM] = 0x07
#machine.mem8[LCD_RAM] = 0x10
#machine.mem8[LCD_RAM] = 0x03
#machine.mem8[LCD_RAM] = 0x0E
#machine.mem8[LCD_RAM] = 0x09
#machine.mem8[LCD_RAM] = 0x00
#NEGATIVE GAMMA CORRECTION
#machine.mem8[LCD_REG] = 0xE1
#machine.mem8[LCD_RAM] = 0x00
#machine.mem8[LCD_RAM] = 0x0E
#machine.mem8[LCD_RAM] = 0x14
#machine.mem8[LCD_RAM] = 0x03
#machine.mem8[LCD_RAM] = 0x11
#machine.mem8[LCD_RAM] = 0x07
#machine.mem8[LCD_RAM] = 0x31
#machine.mem8[LCD_RAM] = 0xC1
#machine.mem8[LCD_RAM] = 0x48
#machine.mem8[LCD_RAM] = 0x08
#machine.mem8[LCD_RAM] = 0x0F
#machine.mem8[LCD_RAM] = 0x0C
#machine.mem8[LCD_RAM] = 0x31
#machine.mem8[LCD_RAM] = 0x36
#machine.mem8[LCD_RAM] = 0x0F
#EXIT SLEEP
machine.mem8[LCD_REG] = 0x11
time.sleep_ms(1200)
#TURN ON DISPLAY
machine.mem8[LCD_REG] = 0x29
#display inversion
#machine.mem8[LCD_REG] = 0x21
#setup Memory Access Control
machine.mem8[LCD_REG] = 0x36
machine.mem8[LCD_RAM] = 0b00111111
def ILI9341_Set_Address(X1, Y1, X2, Y2):
#set X min and max
machine.mem8[LCD_REG] = 0x2A
machine.mem16[LCD_RAM] = X1>>8
machine.mem16[LCD_RAM] = X1
machine.mem16[LCD_RAM] = X2>>8
machine.mem16[LCD_RAM] = X2
#set y min and max
machine.mem8[LCD_REG] = 0x2B
machine.mem16[LCD_RAM] = Y1>>8
machine.mem16[LCD_RAM] = Y1
machine.mem16[LCD_RAM] = Y2>>8
machine.mem16[LCD_RAM] = Y2
#write data command
machine.mem8[LCD_REG] = 0x2C
def drawPixel(X, Y, color):
ILI9341_Set_Address(X, Y, X, Y)
machine.mem16[LCD_RAM] = color
def fill(x = 0, y = 0, width = 320, height = 240, color = 0):
ILI9341_Set_Address(x, y, x + width, x + height)
for x in range(width):
for y in range(height):
machine.mem16[LCD_RAM] = color
def _set_ortho_line(width, length, color):
pixels = width * (length + 1)
for i in range(pixels):
machine.mem16[LCD_RAM] = color
curWidth = 240 # Current TFT width
curHeight = 320 # Current TFT height
def drawVline(x, y, length, color, width = 1):
if length > curHeight: length = curHeight
if width > 10: width = 10
ILI9341_Set_Address(x, y, x + (width - 1), y + length - 1)
_set_ortho_line(width, length, color)
def drawHline(x, y, length, color, width = 1):
if length > curWidth: length = curWidth
if width > 10: width = 10
ILI9341_Set_Address(x, y, x + length - 1, y + (width - 1))
_set_ortho_line(width, length, color)
def drawLine(x, y, x1, y1, color):
if x == x1:
drawVline( x, y if y <= y1 else y1, abs(y1 - y), color )
elif y==y1:
drawHline( x if x <= x1 else x1, y, abs(x-x1), color )
else:
# keep positive range for x
if x1 < x:
x, x1 = x1, x
y, y1 = y1, y
r = (y1 - y) / (x1 - x)
# select ratio > 1 for fast drawing (and thin line)
if abs(r) >= 1:
for i in range(x1 - x + 1):
drawPixel(x + i, trunc(y + (r * i)), color)
else:
# keep positive range for y
if y1 < y:
x, x1 = x1, x
y, y1 = y1, y
# invert the ratio (should be close of r = 1/r)
r = (x1 - x) / (y1 - y)
for i in range(y1 - y + 1):
drawPixel(trunc(x + (r * i)), y + i, color)
def drawRect(x, y, width, height, color, border = 1, infill = None):
if border is None:
border = 0
border = 10 if border > 10 else border
if width > curWidth:
width = curWidth
if height > curHeight:
height = curHeight
#height = 2 if height < 2 else height
#width = 2 if width < 2 else width
#self._graph_orientation()
if border > 0:
if border > width // 2:
border = width // 2 - 1
X, Y = x, y
for i in range(2):
if i == 1:
Y = y + height - (border - 1)
else:
Y = y
drawHline(X, Y, width, color, border)
print(X, Y, width)
if border > 1:
Y = y + 1
H = height
else:
Y = y
H = height + 1
if i == 1:
X = x + width - (border - 1)
else:
X = x
drawVline(X, Y, H, color, border)
print(X, Y, H)
else:
infill = color
if infill:
fill(x, y, width, height, infill)
def char(x, y, color):
cb, l = glcdfont.get_ch('0')
new = 0
# rotate pixel by 90 degree
buf = bytearray(8)
for j in range(8):
for i in range(l):
c = cb[i] # erste Reihe
c = c >> j
if (c & 0x01) == 0x01:
new |= 1 << i
#print (hex(new))
buf[j] = new
new = 0
# print pixel of char
ILI9341_Set_Address(x, y, x + 5, y + 8)
for i in range(8):
c = buf[i]
for j in range(l):
#print(j, (c & 0x01))
if (c & 0x01) == 0x01:
machine.mem16[LCD_RAM] = color
else:
machine.mem16[LCD_RAM] = 0
c = c >> 1
def show_bits(first, second, len = 8):
out =""
for i in range(len):
f = (first << i) & 0x80
#print(hex(f))
if f:
out = out + "1"
else:
out = out + "0"
for i in range(len):
f = (second << i) & 0x80
if f:
out = out + "1"
else:
out = out + "0"
print (out)
def big_char(x, y, char, fgcolor=0xffff, bgcolor=0):
k = 0
cb, l = glcdfont.get_ch(char)
pix = bytearray(24)
for i in range(6):
# first Byte
a = cb[i]
pix[k] = 0
if (a&0x10): pix[k]|=0x03
if (a&0x20): pix[k]|=0x0c
if (a&0x40): pix[k]|=0x30
if (a&0x80): pix[k]|=0xc0
k += 1
pix[k] = 0
if (a&0x01): pix[k]|=0x03 # die vier doppelten punkte setzen
if (a&0x02): pix[k]|=0x0c
if (a&0x04): pix[k]|=0x30
if (a&0x08): pix[k]|=0xc0
k += 1
pix[k] = 0
if (a&0x10): pix[k]|=0x03
if (a&0x20): pix[k]|=0x0c
if (a&0x40): pix[k]|=0x30
if (a&0x80): pix[k]|=0xc0
k += 1
pix[k] = 0
if (a&0x01): pix[k]|=0x03 # die vier doppelten punkte setzen
if (a&0x02): pix[k]|=0x0c
if (a&0x04): pix[k]|=0x30
if (a&0x08): pix[k]|=0xc0
k += 1
new = 0
# rotate pixel by 90 degree
buf = bytearray(32)
for j in range(8):
for i in range(8):
c = pix[(i * 2) + 1] # (High) Low
c = c >> j
if (c & 0x01) == 0x01:
new |= 0x80 >> i
buf[(j * 2)] = new
new = 0
for i in range(4):
c = pix[(i * 2) + 17] # zweite Reihe
c = c >> j
if (c & 0x01) == 0x01:
new |= 0x80 >> i
buf[(j * 2)+1] = new
#show_bits(buf[j*2], buf[(j*2)+1])
new = 0
for j in range(8):
for i in range(8):
c = pix[i * 2] # erste Reihe
c = c >> j
if (c & 0x01) == 0x01:
new |= 0x80 >> i
buf[(j * 2) + 16] = new
new = 0
for i in range(4):
c = pix[(i * 2) + 16] # zweite Reihe
c = c >> j
if (c & 0x01) == 0x01:
new |= 0x80 >> i
buf[(j * 2) + 17] = new
new = 0
#show_bits(buf[(j*2) + 16], buf[(j*2)+17])
# print pixel of char
ILI9341_Set_Address(x, y, x + 11, y + 15)
for i in range(16):
#show_bits(buf[i*2], buf[(i*2)+1])
c = buf[i * 2]
for j in range(8):
if (c & 0x80) == 0x80:
machine.mem16[LCD_RAM] = fgcolor
else:
machine.mem16[LCD_RAM] = bgcolor
c = c << 1
c = buf[(i * 2) + 1]
for j in range(4):
if (c & 0x80) == 0x80:
machine.mem16[LCD_RAM] = fgcolor
else:
machine.mem16[LCD_RAM] = bgcolor
c = c << 1
def string_big(x, y, string, fgcolor=0xffff, bgcolor=0):
for i in range(len(string)):
big_char(x + (i*11), y, string[i], fgcolor, bgcolor)
LCD_REG = const(0x60000002)
LCD_RAM = const(0x60080002)