Which settings does an SSD1306 OLED need?
Pages of columns · LSB first Pages of columns, LSB first, lit pixel = 1 — when you write the bytes straight into display memory.
Turn Chinese or English text and images into C arrays for SSD1306, SH1106, ST7920 and Adafruit GFX. Crisp 12×12 and 16×16 pixel fonts, all four PCtoLCD2002 scan modes, plus a decoder for unknown arrays.
System fonts are anti-aliased outlines, so below about 20 px strokes break or merge. For 12 and 16 px use the pixel fonts above.
Drop an image here or click to browse
PNG, JPG, GIF, BMP, WebP or SVG — a logo, icon or screenshot
Dark pixels of the image become lit pixels on the display. Transparent areas count as background.
Got a font array from an old project or a tutorial and do not know how it was generated? Paste it here: every scan direction and bit order is drawn side by side, and the readable one tells you the settings.
Matches SSD1306 / SSD1309 / SH1106 / ST7565 page memory and MicroPython framebuf.MONO_VLSB — write the bytes straight to the display.
Lit pixel = 1, GNU Unifont glyph. Compare these bytes with your own array to tell which settings it was made with.
| Scan direction | Bit order | Bytes (hex) |
|---|---|---|
| Row by row (horizontal bytes) | MSB first — first pixel in bit 7 | 01 00 01 00 01 00 01 00 3F F8 21 08 21 08 21 08 21 08 21 08 3F F8 21 08 01 00 01 00 01 00 01 00 |
| Row by row (horizontal bytes) | LSB first — first pixel in bit 0 | 80 00 80 00 80 00 80 00 FC 1F 84 10 84 10 84 10 84 10 84 10 FC 1F 84 10 80 00 80 00 80 00 80 00 |
| Column by column (vertical bytes) | MSB first — first pixel in bit 7 | 00 00 00 00 0F F0 08 20 08 20 08 20 08 20 FF FF 08 20 08 20 08 20 08 20 0F F0 00 00 00 00 00 00 |
| Column by column (vertical bytes) | LSB first — first pixel in bit 0 | 00 00 00 00 F0 0F 10 04 10 04 10 04 10 04 FF FF 10 04 10 04 10 04 10 04 F0 0F 00 00 00 00 00 00 |
| Pages of columns (vertical bytes, SSD1306 page order) | MSB first — first pixel in bit 7 | 00 00 0F 08 08 08 08 FF 08 08 08 08 0F 00 00 00 00 00 F0 20 20 20 20 FF 20 20 20 20 F0 00 00 00 |
| Pages of columns (vertical bytes, SSD1306 page order) | LSB first — first pixel in bit 0 | 00 00 F0 10 10 10 10 FF 10 10 10 10 F0 00 00 00 00 00 0F 04 04 04 04 FF 04 04 04 04 0F 00 00 00 |
| Columns of rows (horizontal bytes, 8-pixel strips) | MSB first — first pixel in bit 7 | 01 01 01 01 3F 21 21 21 21 21 3F 21 01 01 01 01 00 00 00 00 F8 08 08 08 08 08 F8 08 00 00 00 00 |
| Columns of rows (horizontal bytes, 8-pixel strips) | LSB first — first pixel in bit 0 | 80 80 80 80 FC 84 84 84 84 84 FC 84 80 80 80 80 00 00 00 00 1F 10 10 10 10 10 1F 10 00 00 00 00 |
Pixel fonts: GNU Unifont (16 px) and Fusion Pixel Font (12 px), both under the SIL Open Font License 1.1. License texts
Built and verified by the Go Tools engineering team.
Pages of columns · LSB first Pages of columns, LSB first, lit pixel = 1 — when you write the bytes straight into display memory.
Row by row · MSB first Row by row, MSB first, lit pixel = 1, each row padded to whole bytes.
32 bytes 32 bytes in every scan direction. 12 × 12 is 24 bytes, an 8 × 16 ASCII character is 16.
逆向 = LSB first 顺向 = MSB first (first pixel in bit 7); 逆向 = LSB first (first pixel in bit 0).
Most graphic OLED and LCD controllers — the SSD1306, SH1106 and ST7565 among them — have no built-in font. To show a character, firmware copies a small grid of on/off pixels into display memory, one bit per pixel, eight pixels per byte. Turning a glyph into those bytes is called taking the font modulus — 取模 in Chinese embedded tutorials, the job the Windows program PCtoLCD2002 has done for years.
The bytes alone are not enough. The same 16 × 16 character can be packed four ways (row by row, column by column, pages of columns, strips of rows) and each way can put the first pixel in bit 7 or bit 0. Eight byte streams describe the same glyph, and a display draws only one of them correctly. That is why a font copied from a tutorial so often shows up mirrored, split in half or rotated.
// 中 (16x16), pages of columns, LSB first, lit = 1 — SSD1306 page order
const unsigned char zhong[32] = {
0x00,0x00,0xF0,0x10,0x10,0x10,0x10,0xFF,0x10,0x10,0x10,0x10,0xF0,0x00,0x00,0x00,
0x00,0x00,0x0F,0x04,0x04,0x04,0x04,0xFF,0x04,0x04,0x04,0x04,0x0F,0x00,0x00,0x00
};
// First 16 bytes = page 0 (rows 0-7), one byte per column, bit 0 = top row Browser fonts are anti-aliased outlines; thresholded at 12 px in a Song typeface, the horizontal strokes of 中 simply vanish. This tool ships real bitmap fonts instead: the 16 × 16 font covers all 6,763 GB2312 characters, while the 12 × 12 font lacks 143 rare ones, which fall back to a system font and are flagged.
Row by row, column by column, pages of columns and columns of rows, each MSB-first or LSB-first, lit pixel = 1 or 0. The option names follow PCtoLCD2002 and their meaning is checked against the SSD1306 datasheet and common OLED example projects, so you can pick the same settings an existing project uses.
Pick SSD1306, Adafruit GFX or XBM and the options are set for you. Change any option by hand and the tool tells you which displays and libraries read that byte order — or that none do.
Paste a font array of unknown origin and all eight scan/bit-order readings are drawn side by side. The readable one tells you the settings; one click applies them.
Logos, icons and photos are scaled to your display size and converted with a threshold, Floyd–Steinberg or Atkinson dithering. Transparent areas count as background, and the threshold works in every mode.
C51-style 2-D arrays with /*"中",0*/ comments, Arduino PROGMEM with offsets, MicroPython bytearray dictionaries, A51 DB lines or plain hex. Generated C compiles cleanly with -Wall -Wextra -pedantic.
中
00 00 F0 10 10 10 10 FF 10 10 10 10 F0 00 00 00 00 00 0F 04 04 04 04 FF 04 04 04 04 0F 00 00 00
32 bytes: 16 columns of page 0 (rows 0–7), then 16 columns of page 1 (rows 8–15). In 0xFF at column 7 every bit is set: the vertical stroke runs through all eight rows of both pages.
中
01 00 01 00 01 00 01 00 3F F8 21 08 21 08 21 08 21 08 21 08 3F F8 21 08 01 00 01 00 01 00 01 00
Two bytes per row, 16 rows. 0x01 0x00 is the centre stroke alone: the leftmost pixel is bit 7 of the first byte, so the pixel in column 7 lands in bit 0. Feed these bytes to an SSD1306 page write and you get garbage — same glyph, different packing.
A
00 00 00 00 18 24 24 42 42 7E 42 42 42 42 00 00
ASCII characters are half width: 8 × 16 is 16 bytes, one byte per row when scanning row by row. Tick "Give half-width characters the full cell width" if your driver expects every glyph to be 16 × 16.
中 (12 × 12, row by row, MSB first)
00 00 04 00 04 00 FF E0 84 20 84 20 84 20 FF E0 04 00 04 00 04 00 04 00
Each 12-pixel row needs two bytes; the last four bits of the second byte are padding. 12 rows × 2 bytes = 24. Every display library addresses rows as (width + 7) / 8 bytes, so packing the bits tighter would break all of them.
Text uses a real pixel font: 12 × 12 (Fusion Pixel) or 16 × 16 (GNU Unifont), with ASCII at half width. For logos and icons switch to the Image tab and set the target size, such as 128 × 64.
SSD1306 / SH1106 / ST7565 need vertical bytes in page order with the top pixel in bit 0. Adafruit GFX, TFT_eSPI, U8g2 drawBitmap and LVGL need horizontal bytes with the left pixel in bit 7. XBM / U8g2 drawXBM is the same but with the left pixel in bit 0.
The preview shows exactly the bitmap that is encoded. Click any pixel to toggle it, or nudge the glyph with the shift fields.
Pick C (PCtoLCD2002 C51 style), Arduino PROGMEM, MicroPython bytearray, A51 assembly or plain hex. The first line of the output records the scan direction, bit order and glyph size, so the array documents itself.
Horizontal bytes with the wrong bit order. Adafruit GFX drawBitmap() needs MSB first; XBM and U8g2 drawXBM() need LSB first.
U8g2 drawXBM() fed MSB-first bytes
drawXBM() → XBM preset (row by row, LSB first)
Vertical bytes with the wrong bit order. SSD1306-type controllers put D0 in the top row, so they need LSB first.
Pages of columns, MSB first → SSD1306
Pages of columns, LSB first → SSD1306
Column by column and pages of columns mixed up. They give the same bytes only for glyphs up to 8 pixels tall; at 16 pixels the byte order differs.
Column by column → SSD1306 page writes
Pages of columns → SSD1306 page writes
A diagonal flip means horizontal bytes were read as vertical ones (or the reverse). Dark text on a lit background means lit = 0 was chosen where the display expects lit = 1.
Row by row bytes sent to an SSD1306 page
Paste the array into the decoder tab and pick the readable preview
Conversion Tools
Convert between binary, hex, decimal, octal and any base (2-36) instantly. Free, private — all processing in your browser.
Conversion Tools
Type a signed integer and get sign-magnitude, ones' complement, two's complement and offset binary at once, at 4 to 64 bits. Or paste a bit pattern or hex byte and see all five readings side by side. Local, free, no sign-up.
Conversion Tools
Convert Linux file permissions between octal (755, 644) and rwx symbols. Get chmod commands, spot risky settings like 777 — free, right in your browser.
Conversion Tools
Convert HEX to RGB, HSL, OKLCH, OKLAB and CMYK in your browser — copy any format with one click. Free, no signup, your colors never leave the page.
Conversion Tools
Free lat long converter: paste decimal, DMS or DDM in either order and get WGS84, UTM, Web Mercator plus China's GCJ-02 (AMap) and BD-09 (Baidu) at once. Iterative GCJ-02 inverse under 1 mm, batch CSV, runs in your browser.
Conversion Tools
Convert HEX colors to CMYK in your browser. Naive sRGB-based approximation for print previews. Free, no signup, your colors stay local.