บทความนี้เขียนไว้เพื่อกันลืมในอนาคต หลังจากได้ลองหาวิธีการทำให้ OLED แสดง font ภาษาไทยได้ แต่ก็ติดปํยหาเรื่องสระ ที่แสดงผลแยกออกจากกัน หรือ สระลอย

โดยโปรแกรมนี้เขียนด้วย Micro Python ใช้ Lib ssd1306.py ที่ได้เพิ่ม option ขยายขนาด bitmap ไว้แล้ว

# 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)


class SSD1306:
	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)
		fb = framebuf.FrameBuffer(self.buffer, self.width, self.height, framebuf.MONO_VLSB)
		self.framebuf = fb
		# Provide methods for accessing FrameBuffer graphics primitives. This is a
		# workround because inheritance from a native class is currently unsupported.
		# http://docs.micropython.org/en/latest/pyboard/library/framebuf.html
		self.fill = fb.fill
		self.pixel = fb.pixel
		self.hline = fb.hline
		self.vline = fb.vline
		self.line = fb.line
		self.rect = fb.rect
		self.fill_rect = fb.fill_rect
		self.text = fb.text
		self.scroll = fb.scroll
		self.blit = fb.blit
		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.height == 32 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)

	def write_text(self, text, x, y, size):
		''' Method to write Text on OLED/LCD Displays with a variable font size

			Args:
				text: the string of chars to be displayed
				x: x co-ordinate of starting position
				y: y co-ordinate of starting position
				size: font size of text
				color: color of text to be displayed
		'''
		background = 0
		# clear screen
		self.fill(background)
		info = []
		# Creating reference characters to read their values
		self.text(text, x, y)
		for i in range(x, x + (8 * len(text))):
			for j in range(y, y + 8):
				# Fetching and saving details of pixels, such as
				# x co-ordinate, y co-ordinate, and color of the pixel
				px_color = self.pixel(i, j)
				info.append((i, j, px_color))
		# Clearing the reference characters from the screen
		self.text(text, x, y, background)
		# Writing the custom-sized font characters on screen
		for px_info in info:
			self.fill_rect(size * px_info[0] - (size - 1) * x,
			               size * px_info[1] - (size - 1) * y,
			               size, size, px_info[2])


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)
		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.temp[0] = self.addr << 1
		self.temp[1] = 0x40  # Co=0, D/C#=1
		self.i2c.start()
		self.i2c.write(self.temp)
		self.i2c.write(buf)
		self.i2c.stop()


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)

และไฟล์ writer.py ที่ใช้ควบคุมการสร้าง ตัวอักษรใหม่

import framebuf

class Writer():
    text_row = 0        # attributes common to all Writer instances
    text_col = 0
    row_clip = False    # Clip or scroll when screen full
    col_clip = False    # Clip or new line when row is full

    @classmethod
    def set_textpos(cls, col, row):
        cls.text_row = row
        cls.text_col = col

    @classmethod
    def set_clip(cls, col_clip, row_clip):
        cls.row_clip = row_clip
        cls.col_clip = col_clip

    def __init__(self, device, font, verbose=True):
        self.device = device
        self.font = font
        # Allow to work with any font mapping
        if font.hmap():
            self.map = framebuf.MONO_HMSB if font.reverse() \
                else framebuf.MONO_HLSB
        else:
            raise ValueError('Font must be horizontally mapped.')
        if verbose:
            print('Orientation: {} Reversal: {}'.format('horiz' \
                if font.hmap() else 'vert', font.reverse()))
        self.screenwidth = device.width  # In pixels
        self.screenheight = device.height

    def _newline(self):
        height = self.font.height()
        Writer.text_row += height
        Writer.text_col = 0
        margin = self.screenheight - (Writer.text_row + height)
        if margin < 0:
            if not Writer.row_clip:
                self.device.scroll(0, margin)
                Writer.text_row += margin

    def printstring(self, string):
        for char in string:
            self._printchar(char)

    # Method using blitting. Efficient rendering for monochrome displays.
    # Tested on SSD1306. Invert is for black-on-white rendering.
    def _printchar(self, char, invert=False):
        if char == '\n':
            self._newline()
            return
        glyph, char_height, char_width = self.font.get_ch(char)
        if Writer.text_row + char_height > self.screenheight:
            if Writer.row_clip:
                return
            self._newline()
        if Writer.text_col + char_width > self.screenwidth:
            if Writer.col_clip:
                return
            else:
                self._newline()
        buf = bytearray(glyph)
        if invert:
            for i, v in enumerate(buf):
                buf[i] = 0xFF & ~ v
        fbc = framebuf.FrameBuffer(buf, char_width, char_height, self.map)
        self.device.blit(fbc, Writer.text_col, Writer.text_row)
        Writer.text_col += char_width

    def stringlen(self, string):
        l = 0
        for char in string:
            l += self._charlen(char)
        return l

    def _charlen(self, char):
        if char == '\n':
            char_width = 0
        else:
            _, _, char_width = self.font.get_ch(char)
        return char_width

และ แม่แบบ font ตั้งชื่อไฟล์ตามชื่อฟอนต์ หรืออื่นๆได้เลย

# Code generated by font_to_py.py.
# Font: THSarabunNew.ttf Char set: กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤลฦวศษสหฬอฮฯะัาำิีึืฺุู฿เแโใไๅๆ็่้๊๋์ํ๎๏๐๑๒๓๔๕๖๗๘๙๚๛
# Cmd: .\font_to_py.py .\source\THSarabunNew.ttf 20 -x -c กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤลฦวศษสหฬอฮฯะัาำิีึืฺุู฻฼฽฾฿เแโใไๅๆ็่้๊๋์ํ๎๏๐๑๒๓๔๕๖๗๘๙๚๛ font_20.py
version = '0.42'

def height():
    return 20

def baseline():
    return 15

def max_width():
    return 12

def hmap():
    return True

def reverse():
    return False

def monospaced():
    return False

def min_ch():
    return 63

def max_ch():
    return 3675

_font =\
b'\x05\x00\x00\x00\x00\x00\x00\x00\x00\x60\x90\x10\x20\x20\x20\x00'\
b'\x20\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x60\x90\x10\x20\x20\x20\x00\x20\x00\x00\x00\x00\x00\x00\x00'\
b'\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x38\x44\x24\x44\x44\x44'\
b'\x44\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x64\xd4\xd4\x24\x24\x24\x18\x00\x00\x00\x00\x00\x00\x00'\
b'\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x74\xd4\xb4\xd4\x14\x14'\
b'\x1c\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x78\x84\xb4\xb4\x44\x44\x44\x00\x00\x00\x00\x00\x00\x00'\
b'\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x78\xa4\xbc\xbc\x44\x44'\
b'\x44\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x54\x74\x54\x24\x24\x7c\x64\x00\x00\x00\x00\x00\x00\x00'\
b'\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x30\x30\x10\x90\x50\x50'\
b'\x30\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x70\x88\x08\x68\x68\x28\x18\x00\x00\x00\x00\x00\x00\x00'\
b'\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x70\x88\x08\xc8\xc8\x7c'\
b'\x4c\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x64\xd8\xd4\x24\x24\x24\x3c\x00\x00\x00\x00\x00\x00\x00'\
b'\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x54\xb8\xd4\xe4\x24\x24'\
b'\x3c\x00\x00\x00\x00\x00\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x39\x00\x45\x00\x25\x00'\
b'\x45\x00\x45\x00\x6f\x00\x6d\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x00\x00\x00\x00\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x31\x00\x49\x00\x29\x00'\
b'\x49\x00\x49\x00\x69\x00\x6f\x00\x00\x00\x0d\x00\x0e\x00\x00\x00'\
b'\x00\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x38\x44\x24\x44\x44\xc4\xc4\x04\x24\x74\x6c\x00\x00\x00'\
b'\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x38\x44\x24\x44\x44\xc4'\
b'\xc4\x04\x64\x6c\x74\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x68\x90\x70\x08\x68\x28\x38\x00\x58\xe8\xd8\x00\x00\x00'\
b'\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x56\xb6\xda\xda\x32\x32'\
b'\x22\x00\x00\x00\x00\x00\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x49\x00\xb5\x00\x85\x00'\
b'\xb5\x00\xb5\x00\x6f\x00\x4d\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x00\x00\x00\x00\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x31\x00\x49\x00\x29\x00'\
b'\x49\x00\x4a\x00\x6f\x00\x6b\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x78\x84\xb4\xb4\x54\x64\x44\x00\x00\x00\x00\x00\x00\x00'\
b'\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x48\xb4\x84\xb4\x54\x64'\
b'\x44\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x38\x44\x24\x44\x44\x64\x64\x00\x00\x00\x00\x00\x00\x00'\
b'\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x66\x6a\x2a\x32\x32\x22'\
b'\x22\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x78\x80\x70\x08\x48\x48\x30\x00\x00\x00\x00\x00\x00\x00'\
b'\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x62\x62\x22\x22\x22\x2e'\
b'\x36\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x62\x62\x22\x22\x22\x22\x1c\x00\x00\x00\x00\x00\x00\x00'\
b'\x07\x00\x00\x00\x00\x00\x00\x02\x02\x02\x62\x62\x22\x22\x22\x22'\
b'\x1c\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x62\x62\x42\x42\x5a\x66\x42\x00\x00\x00\x00\x00\x00\x00'\
b'\x07\x00\x00\x00\x00\x00\x00\x02\x02\x02\x62\x62\x42\x42\x5a\x66'\
b'\x42\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x6a\x6a\x2a\x36\x36\x22\x22\x00\x00\x00\x00\x00\x00\x00'\
b'\x08\x00\x00\x00\x00\x00\x00\x02\x02\x02\x6a\x6a\x2a\x36\x32\x22'\
b'\x22\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x38\x44\x34\x24\x24\x64\x64\x00\x00\x00\x00\x00\x00\x00'\
b'\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x64\x64\x24\x24\x24\x74'\
b'\x6c\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x34\x74\x44\x34\x44\x44\x38\x00\x00\x00\x00\x00\x00\x00'\
b'\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x68\x90\x60\x10\x10\x30'\
b'\x30\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x38\x44\x24\x44\x44\x64\x64\x04\x04\x04\x00\x00\x00\x00'\
b'\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x38\x44\x3c\x44\x44\x64'\
b'\x64\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x38\x44\x24\x24\x24\x64\x64\x04\x04\x04\x00\x00\x00\x00'\
b'\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x70\x88\x08\x08\x08\x18'\
b'\x18\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x04\x7c\x8c\xf4\xb4\x44\x44\x44\x00\x00\x00\x00\x00\x00\x00'\
b'\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x62\x62\x3b\x3e\x22\x22'\
b'\x1c\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x04\x38\x4c\x14\x3c\x44\x64\x64\x00\x00\x00\x00\x00\x00\x00'\
b'\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x66\x66\x24\x2a\x32\x32'\
b'\x22\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x02\x66\x66\x22\x2a\x3a\x36\x22\x00\x00\x00\x00\x00\x00\x00'\
b'\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x38\x44\x04\x64\x64\x44'\
b'\x38\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x04\x78\x7c\x04\x64\x64\x44\x38\x00\x00\x00\x00\x00\x00\x00'\
b'\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x6c\x74\x04\x04\x04\x04'\
b'\x04\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x00\xc8\xc8\x70\xc8\xc8\x70\x00\x00\x00\x00\x00\x00\x00'\
b'\x05\x00\x00\x00\x00\x00\xc8\xc8\x70\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x70\x88\x08\x08\x08\x08\x08\x00\x00\x00\x00\x00\x00\x00'\
b'\x08\x00\x00\x00\x00\x00\x40\xa0\x40\x00\x0e\x11\x01\x01\x01\x01'\
b'\x01\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x70\x88'\
b'\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
b'\x06\x00\x00\x00\x00\x00\x68\x98\xf8\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x7c\x8c'\
b'\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
b'\x06\x00\x00\x00\x00\x14\x74\x8c\xfc\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc0\xc0\x40\x00\x00\x00\x00'\
b'\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\xd0\xd0\x50\x70\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00'\
b'\x07\x00\x00\x00\x00\x00\x00\x00\x10\x78\x44\x44\x44\x7a\x42\x42'\
b'\x7c\x10\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x40\x40\x40\x40\x40\x60\x60\x00\x00\x00\x00\x00\x00\x00'\
b'\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x48\x48\x48\x48\x48\x6c'\
b'\x6c\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\xe8\x90'\
b'\x60\x20\x20\x20\x20\x20\x20\x30\x30\x00\x00\x00\x00\x00\x00\x00'\
b'\x05\x00\x00\x00\x00\x00\x60\xd0\xd0\x20\x20\x20\x20\x20\x20\x30'\
b'\x30\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\xa0\xa0'\
b'\xe0\x20\x20\x20\x20\x20\x20\x38\x38\x00\x00\x00\x00\x00\x00\x00'\
b'\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x70\x90\x10\x10\x10\x10'\
b'\x10\x10\x10\x10\x00\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x28\x74\x54\x24\x04\x04\x04\x04\x04\x04\x00\x00\x00\x00'\
b'\x05\x00\x00\x00\x00\x10\x60\x90\xf0\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x80\x80\x00\x00\x00'\
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
b'\x04\x00\xd0\x50\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\xf4\x94\x98\x00\x00'\
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
b'\x03\x00\x00\x40\xe0\x40\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x10\x60\xc0\xc0\x00\x00'\
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
b'\x03\x00\x00\x00\x00\x00\x40\xa0\x40\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\xe0\x80\xc0'\
b'\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
b'\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x3c\x7e\x66\x66\x5a'\
b'\x3c\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x00\x00\x3c\x42\x42\x42\x3c\x00\x00\x00\x00\x00\x00\x00'\
b'\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x3c\x42\x5a\x5a'\
b'\x32\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x40\x40\x40\x54\x6a\x72\x42\x3c\x00\x00\x00\x00\x00\x00\x00'\
b'\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x36\x49\x49\x69'\
b'\x69\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x01\x01\x3e\x40\x4c\x48\x3f\x00\x00\x00\x00\x00\x00\x00'\
b'\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x0c\x80\x0d\x00\x3e\x00\x40\x00\x4c\x00\x48\x00\x3f\x00'\
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
b'\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x40\x5e\x21\x01\x31'\
b'\x3e\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x01\x01\x35\x4b\x4b\x63\x62\x00\x00\x00\x00\x00\x00\x00'\
b'\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x01\x3e\x40\x43\x5b'\
b'\x26\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x01\x01\x35\x4e\x44\x5a\x39\x00\x00\x00\x00\x00\x00\x00'\
b'\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x7f\x00\x77\x00\x05\x00\x05\x00\x05\x00\x05\x00\x05\x00'\
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
b'\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\
b'\x00\x00\x00\x00\x30\x00\x48\x00\x5f\x00\x56\xe0\x4e\x00\x38\x00'\
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

_sparse =\
b'\x3f\x00\x03\x00\x01\x0e\x06\x00\x02\x0e\x09\x00\x03\x0e\x0c\x00'\
b'\x04\x0e\x0f\x00\x05\x0e\x12\x00\x06\x0e\x15\x00\x07\x0e\x18\x00'\
b'\x08\x0e\x1b\x00\x09\x0e\x1e\x00\x0a\x0e\x21\x00\x0b\x0e\x24\x00'\
b'\x0c\x0e\x27\x00\x0d\x0e\x2d\x00\x0e\x0e\x33\x00\x0f\x0e\x36\x00'\
b'\x10\x0e\x39\x00\x11\x0e\x3c\x00\x12\x0e\x3f\x00\x13\x0e\x45\x00'\
b'\x14\x0e\x4b\x00\x15\x0e\x4e\x00\x16\x0e\x51\x00\x17\x0e\x54\x00'\
b'\x18\x0e\x57\x00\x19\x0e\x5a\x00\x1a\x0e\x5d\x00\x1b\x0e\x60\x00'\
b'\x1c\x0e\x63\x00\x1d\x0e\x66\x00\x1e\x0e\x69\x00\x1f\x0e\x6c\x00'\
b'\x20\x0e\x6f\x00\x21\x0e\x72\x00\x22\x0e\x75\x00\x23\x0e\x78\x00'\
b'\x24\x0e\x7b\x00\x25\x0e\x7e\x00\x26\x0e\x81\x00\x27\x0e\x84\x00'\
b'\x28\x0e\x87\x00\x29\x0e\x8a\x00\x2a\x0e\x8d\x00\x2b\x0e\x90\x00'\
b'\x2c\x0e\x93\x00\x2d\x0e\x96\x00\x2e\x0e\x99\x00\x2f\x0e\x9c\x00'\
b'\x30\x0e\x9f\x00\x31\x0e\xa2\x00\x32\x0e\xa5\x00\x33\x0e\xa8\x00'\
b'\x34\x0e\xab\x00\x35\x0e\xae\x00\x36\x0e\xb1\x00\x37\x0e\xb4\x00'\
b'\x38\x0e\xb7\x00\x39\x0e\xba\x00\x3a\x0e\xbd\x00\x3f\x0e\xc0\x00'\
b'\x40\x0e\xc3\x00\x41\x0e\xc6\x00\x42\x0e\xc9\x00\x43\x0e\xcc\x00'\
b'\x44\x0e\xcf\x00\x45\x0e\xd2\x00\x46\x0e\xd5\x00\x47\x0e\xd8\x00'\
b'\x48\x0e\xdb\x00\x49\x0e\xde\x00\x4a\x0e\xe1\x00\x4b\x0e\xe4\x00'\
b'\x4c\x0e\xe7\x00\x4d\x0e\xea\x00\x4e\x0e\xed\x00\x4f\x0e\xf0\x00'\
b'\x50\x0e\xf3\x00\x51\x0e\xf6\x00\x52\x0e\xf9\x00\x53\x0e\xfc\x00'\
b'\x54\x0e\xff\x00\x55\x0e\x02\x01\x56\x0e\x08\x01\x57\x0e\x0b\x01'\
b'\x58\x0e\x0e\x01\x59\x0e\x11\x01\x5a\x0e\x14\x01\x5b\x0e\x1a\x01'\

_mvfont = memoryview(_font)
_mvsp = memoryview(_sparse)
ifb = lambda l : l[0] | (l[1] << 8)

def bs(lst, val):
    while True:
        m = (len(lst) & ~ 7) >> 1
        v = ifb(lst[m:])
        if v == val:
            return ifb(lst[m + 2:])
        if not m:
            return 0
        lst = lst[m:] if v < val else lst[:m]

def get_ch(ch):
    doff = bs(_mvsp, ord(ch)) << 3
    width = ifb(_mvfont[doff : ])

    next_offs = doff + 2 + ((width - 1)//8 + 1) * 20
    return _mvfont[doff + 2:next_offs], 20, width

โค้ดหลักในการทดสอบ main.py

from machine import Pin
from machine import SoftI2C
from ssd1306 import SSD1306_I2C

import time
import framebuf
import font_7x8
import writer

WIDTH  = 128
HEIGHT = 64

i2c = SoftI2C(sda=Pin(23), scl=Pin(18))
oled = SSD1306_I2C(WIDTH, HEIGHT, i2c)

while True:
	oled.fill(0)
	oled.write_text("ไทย", 5, 5, 4) # ใช้ขยายขนาดได้
	font_writer = writer.Writer(oled, font_7x8, False)
	font_writer.set_textpos(5, 30)
	font_writer.printstring("ไทยดี สวัสดี")
	oled.show()
	time.sleep(0.5)

วิธีการสร้าง Font อื่นๆ

ในการสร้าง font อื่นๆ จะใช้ Tool ที่มีชื่อว่า micropython-font-to-py ในการสร้าง

ใช้คำสั่งในการสร้าง Font คือ

python .\font_to_py.py .\source\THSarabunNew.ttf 20 -x font_size20.py

หรือ

python .\font_to_py.py .\source\THSarabunNew.ttf 20 -x -c กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤลฦวศษสหฬอฮฯะัาำิีึืฺุู฻฼฽฾฿เแโใไๅๆ็่้๊๋์ํ๎๏๐๑๒๓๔๕๖๗๘๙๚๛ font_20.py

จากนั้นโปรแกรมจะสร้างไฟล์ขึ้นมาให้เราสามารถนำไป import เข้ากับ Project ได้