-
Notifications
You must be signed in to change notification settings - Fork 48
external SPI font #304
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
t's not using SPI flash but a font chip. |
OoOoo Hmmm... You would need to write a driver to access the data on the font chip That is not the hard part. what the hard part is is figuring out how the font is stored on the chip. What is the format of it? I would need to know the make and model of the chip to pull up the datasheet and see what is says.... |
Not that detailed, I just don’t know how to call my own get_glyph_bitmap. I just want to understand the general structure. With this operation, I can only use get_glyph_dsc.
|
You are not really explaining what you are trying to do. Unless I know what you are wanting to do I am really not going to be able to offer any advise on how to go about it. For a custom font loader my understanding of how it works is this. class FontChip:
def __init__(self, ...):
# code needed to access font chip
....
def get_glyph(self, dsc, letter):
# code needed to collect the data from the font chip.
dsc.adv_w = ... # number of pixels between glyphs
dsc.box_w = ... # height of glyph including extra pixels to normalize the height across the entire font
dsc.box_h = ... # width of glyph
dsc.ofs_x = 0
dsc.ofs_y = 0
dsc.format = lv.FONT_GLYPH_FORMAT.IMAGE
dsc.gid.src = ... # glyph data for image font
dsc.entry = ... # have no clue how to use this
return True # return True if the glyph was found False otherwise
def get_glyph_dsc_cb(font, font_glyph_dsc, letter, letter_next):
font_cls = font.user_data.__cast__()
if font_cls.get_glyph(font_glyph_dsc, letter):
font_glyph_dsc.resolved_font = font
return True
# didn't find the glyph so try the fallback font
return font.get_glyph_dsc(font.fallback, font_glyph_dsc, letter, letter_next)
font_chip = FontChip()
font = lv.font_t()
font.get_glyph_dsc = get_glyph_dsc_cb
font.get_glyph_bitmap = None # callback function to get the bitmap of the glyph
font.release_glyph = None # callback function to release memory used by a glyph
font.line_height = ... # tallest glyph height
font.base_line = ... # not sure what this does
font.subpx = lv.FONT_SUBPX.NONE
font.kerning = lv.FONT_KERNING.NONE
font.underline_position = 0
font.underline_thickness = 1
font.fallback = lv.font_montserrat_10
font.user_data = font_chip |
Thank you for your response. I tried the method you provided, but it didn't work.
My intention is that the type of myfont.font() should be 'lv_font_t', so that I can use it in the same way as lv.font_montserrat_16. However, I have tried several methods but haven't achieved this yet.
|
it's not going to work. It is an example of what you need to do. I don't know exactly what you have to do because I don't know what the font chip is or how it stores the data. |
if you get me a link to the data sheet for the font chip I will be able to help more with this. |
test.zip
|
Fantastic. |
OK so here you go. Make sure to read the comments near the top. import lvgl as lv
from micropython import const # NOQA
import machine
# replace the "..." in the line below with the size of the `_pbits` array
_PBITS_SIZE = const(...)
# set up your SPI bus. If the bus is shared with something else then you only
# need to create the device passing the shared bus to all of the things that
# use the bus.
spi_bus = machine.SPI.Bus(
host=1,
mosi=...,
miso=...,
sck=...,
)
spi_device = machine.SPI.Device(
spi_bus=spi_bus,
cs=...,
freq=20000000
)
_ASCII_5X7 = const(1)
_ASCII_7X8 = const(2)
_ASCII_6X12 = const(3)
_ASCII_12_A = const(4) # 12 * 16
_ASCII_8X16 = const(5)
_ASCII_12X24_A = const(6)
_ASCII_12X24_P = const(7)
_ASCII_16X32 = const(8)
_ASCII_16_A = const(9)
_ASCII_24_B = const(10)
_ASCII_32_B = const(11)
def gt_read_data(sendbuf, _, receivebuf, receivelen):
spi_device.write(sendbuf)
buf = bytearray(0x00)
for i in range(receivelen):
buf[0] = 0x00
spi_device.write_readinto(buf, buf)
receivebuf[i] = buf[0]
return 1
def r_dat_bat(address, DataLen, pBuff):
buf = bytearray([0x03])
spi_device.write(buf) # <发送读取命令
buf[0] = (address >> 16) & 0xFF
spi_device.write(buf) # <发送24bit地址
buf[0] = (address >> 8) & 0xFF
spi_device.write(buf)
buf[0] = address & 0xFF
spi_device.write(buf)
for i in range(DataLen):
buf[0] = 0XFF
spi_device.write_readinto(buf, buf) # <循环读数
pBuff[i] = buf[0]
return pBuff[0]
_GT_UID_MD5_FLAG = const(1)
_GBCODE_5139 = const(0)
def Uncompress(result, a2):
for i in range(5 + 1):
result[4 * i] = a2[3 * i]
result[4 * i + 1] = a2[3 * i + 1] & 0xF0
result[4 * i + 2] = a2[3 * i + 2]
result[4 * i + 3] = 16 * a2[3 * i + 1]
return 1
def check_dot_null(DZ_Data, num):
for i in range(num):
if DZ_Data[i]:
return 1
return 0
def ASCII_GetData(asc, ascii_kind, DZ_Data):
if _GT_UID_MD5_FLAG == 0:
return 0
if asc <= 0x1F or asc > 0x7E:
return 0
if ascii_kind == 1:
r_dat_bat(8 * (asc + 259932), 8, DZ_Data)
elif ascii_kind == 2:
r_dat_bat(8 * (asc + 260028), 8, DZ_Data)
elif ascii_kind == 3:
r_dat_bat(12 * asc + 2080864, 0xC, DZ_Data)
elif ascii_kind == 4:
r_dat_bat(26 * asc + 2090144 + 2, 0x18, DZ_Data)
elif ascii_kind == 5:
r_dat_bat(16 * (asc + 130174), 0x10, DZ_Data)
elif ascii_kind == 6:
r_dat_bat(48 * asc + 1543800, 0x30, DZ_Data)
elif ascii_kind == 7:
r_dat_bat(48 * asc + 1549944, 0x30, DZ_Data)
elif ascii_kind == 8:
r_dat_bat(((asc + 67108832) << 6) + 2084832, 0x40, DZ_Data)
elif ascii_kind == 9:
r_dat_bat(34 * asc + 2092384 + 2, 0x20, DZ_Data)
elif ascii_kind == 0xA:
r_dat_bat(74 * asc + 1559864 + 2, 0x48, DZ_Data)
elif ascii_kind == 0xB:
r_dat_bat(130 * asc + 2092576, 0x82, DZ_Data)
else:
return 1
return 1
def ASCII_GetInterval(asc, ascii_kind):
data = bytearray(2)
if _GT_UID_MD5_FLAG == 0:
return 0
if asc <= 0x1F or asc > 0x7E:
return 0
if ascii_kind == 1:
r_dat_bat(8 * (asc + 259932), 2, data)
elif ascii_kind == 2:
r_dat_bat(8 * (asc + 260028), 2, data)
elif ascii_kind == 3:
r_dat_bat(12 * asc + 2080864, 2, data)
elif ascii_kind == 4:
r_dat_bat(26 * asc + 2090144, 2, data)
elif ascii_kind == 5:
r_dat_bat(16 * (asc + 130174), 2, data)
elif ascii_kind == 6:
r_dat_bat(48 * asc + 1543800, 2, data)
elif ascii_kind == 7:
r_dat_bat(48 * asc + 1549944, 2, data)
elif ascii_kind == 8:
r_dat_bat(((asc + 67108832) << 6) + 2084832, 2, data)
elif ascii_kind == 9:
r_dat_bat(34 * asc + 2092384, 2, data)
elif ascii_kind == 0xA:
r_dat_bat(74 * asc + 1559864, 2, data)
elif ascii_kind == 0xB:
r_dat_bat(130 * asc + 2092576, 2, data)
return data[1]
def gt_12_GetData(MSB, LSB, DZ_Data):
pBuff = bytearray(20)
offset = 2109216
address = 0
if _GT_UID_MD5_FLAG == 1:
if MSB != 169 or LSB <= 0xA3:
if MSB <= 0xA0 or MSB > 0xA3 or LSB <= 0xA0:
if 0xAF < MSB <= 0xF7 and LSB > 0xA0:
address = 18 * (94 * MSB + LSB) + offset - 294246
else:
address = 18 * (94 * MSB + LSB) + offset - 275310
else:
address = 18 * LSB + offset + 2124
r_dat_bat(address, 0x12, pBuff)
Uncompress(DZ_Data, pBuff)
def GBK_24_GetData(c1, c2, DZ_Data):
temp = c2
address = 0
if _GT_UID_MD5_FLAG == 0:
return 0
if c2 == 127:
address = 0
if c1 <= 0xA0 or c1 > 0xA3 or c2 <= 0xA0:
if c1 != 166 or c2 <= 0xA0:
if c1 == 169 and c2 > 0xA0:
address = 94 * c1 + c2 - 15671
else:
address = 94 * c1 + c2 - 15483
else:
address = 94 * c1 + c2 - 15295
if c1 <= 0xAF or c1 > 0xF7 or c2 <= 0xA0:
if c1 > 0xA0 or c1 <= 0x80 or c2 <= 0x3F:
if c1 > 0xA9 and c2 <= 0xA0:
if (c2 & 0x80) != 0:
temp = c2 - 1
address = 96 * c1 + temp - 3081
else:
if (c2 & 0x80) != 0:
temp = c2 - 1
address = 190 * c1 + temp - 17351
else:
address = 94 * c1 + c2 - 16250
r_dat_bat(72 * address, 0x48, DZ_Data)
return 72 * address
def U2G(unicode):
pBuff = bytearray(2)
address = 0
offset = 2517590
if _GT_UID_MD5_FLAG == 0:
return 0
if unicode > 0x451 or unicode <= 0x9F:
if unicode > 0x2642 or unicode <= 0x200F:
if unicode > 0x33D5 or unicode < 0x3000:
if unicode > 0x9FA5 or unicode < 0x4E00:
if unicode > 0xFE6B or unicode <= 0xFE2F:
if unicode > 0xFF5E or unicode <= 0xFF00:
if unicode > 0xFFE5 or unicode <= 0xFFDF:
if unicode > 0xFA29 or unicode <= 0xF92B:
if unicode > 0xE864 or unicode <= 0xE815:
if unicode > 0x2ECA or unicode <= 0x2E80:
if unicode > 0x49B7 or unicode <= 0x4946:
if unicode > 0x4DAE or unicode <= 0x4C76:
if unicode > 0x3CE0 or unicode <= 0x3446:
if 0x478D >= unicode > 0x4054:
address = 2 * (unicode + 2147467178) + 55380
else:
address = 2 * (unicode + 2147470265) + 50976
else:
address = 2 * (unicode + 2147464073) + 50352
else:
address = 2 * (unicode + 2147464889) + 50126
else:
address = 2 * (unicode + 2147471743) + 49978
else:
address = 2 * (unicode + 2147424234) + 49820
else:
address = 2 * (unicode + 2147419860) + 49312
else:
address = 2 * (unicode + 2147418144) + 49142
else:
address = 2 * (unicode + 2147418367) + 48954
else:
address = 2 * (unicode + 2147418576) + 48834
else:
address = 2 * (unicode + 2147463680) + 7030
else:
address = 2 * (unicode + 2147471360) + 5066
else:
address = 2 * (unicode + 2147475440) + 1892
else:
address = 2 * (unicode + 2147483488)
address += offset
r_dat_bat(address, 2, pBuff)
return (pBuff[0] << 8) + pBuff[1]
# Callback function to get the glyph descriptor
def myGetGlyphDscCb_16(_, dsc_out, unicode_letter, __):
# Set the glyph descriptor, including information such as glyph width, height, offset, etc.
# print("ff")
dsc_out.box_h = 12 # Height of the glyph bitmap (in pixels)
dsc_out.box_w = 16 # Width of the glyph bitmap (in pixels)
if unicode_letter < 128:
dsc_out.adv_w = ASCII_GetInterval(unicode_letter, _ASCII_12_A) # Letter spacing
else:
dsc_out.adv_w = 12
dsc_out.ofs_x = 0 # X offset of the glyph bitmap (in pixels)
dsc_out.ofs_y = 0 # Y offset of the glyph bitmap (in pixels), relative to the baseline
dsc_out.bpp = 1 # Bits per pixel: 1/2/4/8
dsc_out.is_placeholder = False
return True # true: glyph found false: glyph not found
_pBits = bytearray(_PBITS_SIZE)
# Callback function to get the glyph bitmap
def myGetGlyphBitmapCb_16(_, unicode_letter):
# Return pointer to glyph bitmap data
# Replace the example return value below with actual bitmap data for character "你"
if unicode_letter < 128:
ASCII_GetData(unicode_letter, _ASCII_12_A, _pBits)
else:
u2g = U2G(unicode_letter)
gt_12_GetData((u2g >> 8) & 0xff, u2g & 0xff, _pBits)
return _pBits # Return pointer to array containing bitmap data for character "你"
# Callback function to get the glyph descriptor
def myGetGlyphDscCb_24(_, dsc_out, unicode_letter, __):
# Set glyph descriptor, including glyph width, height, offset, etc.
dsc_out.box_h = 24 # Height of the glyph bitmap (in pixels)
dsc_out.box_w = 24 # Width of the glyph bitmap (in pixels)
if unicode_letter < 128:
dsc_out.adv_w = ASCII_GetInterval(unicode_letter, _ASCII_24_B) # Letter spacing
else:
dsc_out.adv_w = 24 # Letter spacing
dsc_out.ofs_x = 0 # X offset of the glyph bitmap (in pixels)
dsc_out.ofs_y = 0 # Y offset of the glyph bitmap (in pixels), relative to the baseline
dsc_out.bpp = 1 # Bits per pixel: 1/2/4/8
dsc_out.is_placeholder = False
return True # true: glyph found false: glyph not found
# Callback function to get the glyph bitmap
def myGetGlyphBitmapCb_24(_, unicode_letter):
# Return pointer to glyph bitmap data
# Replace the example return value below with actual bitmap data for character "你"
if unicode_letter < 128:
ASCII_GetData(unicode_letter, _ASCII_24_B, _pBits)
else:
u2g = U2G(unicode_letter)
GBK_24_GetData((u2g >> 8) & 0xff, u2g & 0xff, _pBits)
return _pBits # Return pointer to array containing bitmap data for character "你"
my_custom_font_16 = lv.font_t(dict(
get_glyph_dsc=myGetGlyphDscCb_16,
get_glyph_bitmap=myGetGlyphBitmapCb_16,
line_height=15, # Line height
base_line=3, # Baseline
subpx=lv.FONT_SUBPX.NONE # NOQA
)) # Font parsing structure for the font chip
my_custom_font_24 = lv.font_t(dict(
get_glyph_dsc=myGetGlyphDscCb_24,
get_glyph_bitmap=myGetGlyphBitmapCb_24,
line_height=27,
base_line=3,
subpx=lv.FONT_SUBPX.NONE, # NOQA
)) # Font parsing structure for the font chip
|
That is only the first version of the code and I am expecting it to be pretty slow. We can always tweak and optimize the code once we know it is working properly. |
Thank you very much for your reply, it looks like exactly what I was looking for. I will verify it on my end. Thanks again. |
no worries m8. It may or may not work properly out of the box but at least we have something to work off of. |
Hello, now I also encountered the same problem, using the above method to run the error, the error content:
|
what? Why are you trying to hijack someone else's issue? |
It was provided by a friend of mine who can't handle it right now. |
I want to extend an external SPI font library. Is there a way to implement this at the Python layer? I found that I can't reassign get_glyph_bitmap at the Python level.
The text was updated successfully, but these errors were encountered: