Pico Display and Fonts

I just bought the Pico display and have it working with text on the screen but there doesn’t seem to be any information on different fonts and whatever I send it always appears in uppercase! any help on why this is and what can be done?

I think at the moment there’s no built-in way to change the font or case, it’s hard-coded because I don’t think there is any good way to support font packages on a microcontroller. There was talk of bringing in Markdown support which might allow headings, lists etc. but for fonts and casing I think you may need to figure out the character designs yoursef for the time being.

OK, thanks for the info, the font just looks too blocky when scaled up, I’ve not had this issue with other displays with arduinos!

The font included in the UF2 file uses the same character definitions for both upper and lower case. Perhaps a different font could be substituted in the next version upgrade.
A 5x8 font with proper lower case letters would be nice. This is perfectly readable on small pixel displays.

A fixed width font would be very useful.

I agree, right justification with this one is a real pain.

The font used on the Adafruit CLUE is much clearer on the same size screen - looks normal and has lower case! I’m not very happy with the current font as no space is saved by using the same shape definitions for upper and lower case.

Please change it on the next MicroPython UF2

Something like this?
I just rolled my own 5*7 Found the patterns on the web, and wrote a program in PHP to convert to C++ syntax. (NB owing to an end-of-line bug in my demo prog, ‘I’ and ‘s’ are not displayed)
Happy to upload when tidied up.

1 Like

That would be brilliant. Looking forward to seeing it.
Can you get it to work with MicroPython, which has a much larger user base?

Well, I’ll happily upload the data table, but as complete Python novice, I wouldn’t presume… :-)

OK, here’s the stripped down font demo program. I took out the background image stuff because it’s big!
Enjoy, and feel free to port to python.

#include <string.h>

#include <math.h>



#include <stdio.h>

#include “pico_display.hpp”

#include “pico/stdlib.h”

using namespace pimoroni;

uint8_t FontData[5]={

{0b0000000,0b0000000,0b0000000,0b0000000,0b0000000}, // space

{0b0000000,0b0000000,0b1111101,0b0000000,0b0000000}, // !

{0b0000000,0b1110000,0b0000000,0b1110000,0b0000000}, // "

{0b0010100,0b1111111,0b0010100,0b1111111,0b0010100}, // #

{0b0010010,0b0101010,0b1111111,0b0101010,0b0100100}, // $

{0b1100010,0b1100100,0b0001000,0b0010011,0b0100011}, // %

{0b0110110,0b1001001,0b1010101,0b0100010,0b0000101}, // &

{0b0000000,0b0000000,0b1100000,0b0000000,0b0000000}, // ’

{0b0000000,0b0011100,0b0100010,0b1000001,0b0000000}, // (

{0b0000000,0b1000001,0b0100010,0b0011100,0b0000000}, // )

{0b0010100,0b0001000,0b0111110,0b0001000,0b0010100}, // *

{0b0001000,0b0001000,0b0111110,0b0001000,0b0001000}, // +

{0b0000000,0b0000101,0b0000110,0b0000000,0b0000000}, // ,

{0b0001000,0b0001000,0b0001000,0b0001000,0b0001000}, // -

{0b0000000,0b0000011,0b0000011,0b0000000,0b0000000}, // .

{0b0000010,0b0000100,0b0001000,0b0010000,0b0100000}, // /

{0b0111110,0b1000101,0b1001001,0b1010001,0b0111110}, // 0

{0b0000000,0b0100001,0b1111111,0b0000001,0b0000000}, // 1

{0b0100011,0b1000101,0b1001001,0b1001001,0b0110001}, // 2

{0b0100010,0b1000001,0b1001001,0b1001001,0b0110110}, // 3

{0b0001100,0b0010100,0b0100100,0b1111111,0b0000100}, // 4

{0b1110010,0b1010001,0b1010001,0b1010001,0b1001110}, // 5

{0b0011110,0b0101001,0b1001001,0b1001001,0b0000110}, // 6

{0b1000000,0b1000111,0b1001000,0b1010000,0b1100000}, // 7

{0b0110110,0b1001001,0b1001001,0b1001001,0b0110110}, // 8

{0b0110000,0b1001001,0b1001001,0b1001010,0b0111100}, // 9

{0b0000000,0b0110110,0b0110110,0b0000000,0b0000000}, // :

{0b0000000,0b0110101,0b0110110,0b0000000,0b0000000}, // ;

{0b0001000,0b0010100,0b0100010,0b1000001,0b0000000}, // <

{0b0010100,0b0010100,0b0010100,0b0010100,0b0010100}, // =

{0b0000000,0b1000001,0b0100010,0b0010100,0b0001000}, // >

{0b0100000,0b1000000,0b1000101,0b1001000,0b0110000}, // ?

{0b0100110,0b1001001,0b1001111,0b1000001,0b0111110}, // @

{0b0011111,0b0100100,0b1000100,0b0100100,0b0011111}, // A

{0b1000001,0b1111111,0b1001001,0b1001001,0b0110110}, // B

{0b0111110,0b1000001,0b1000001,0b1000001,0b0100010}, // C

{0b1000001,0b1111111,0b1000001,0b1000001,0b0111110}, // D

{0b1111111,0b1001001,0b1001001,0b1001001,0b1000001}, // E

{0b1111111,0b1001000,0b1001000,0b1001000,0b1000000}, // F

{0b0111110,0b1000001,0b1000001,0b1001001,0b0101111}, // G

{0b1111111,0b0001000,0b0001000,0b0001000,0b1111111}, // H

{0b0000000,0b1000001,0b1111111,0b1000001,0b0000000}, // I

{0b0000010,0b0000001,0b1000001,0b1111110,0b1000000}, // J

{0b1111111,0b0001000,0b0010100,0b0100010,0b1000001}, // K

{0b1111111,0b0000001,0b0000001,0b0000001,0b0000001}, // L

{0b1111111,0b0100000,0b0011000,0b0100000,0b1111111}, // M

{0b1111111,0b0010000,0b0001000,0b0000100,0b1111111}, // N

{0b0111110,0b1000001,0b1000001,0b1000001,0b0111110}, // O

{0b1111111,0b1001000,0b1001000,0b1001000,0b0110000}, // P

{0b0111110,0b1000001,0b1000101,0b1000010,0b0111101}, // Q

{0b1111111,0b1001000,0b1001100,0b1001010,0b0110001}, // R

{0b0110010,0b1001001,0b1001001,0b1001001,0b0100110}, // S

{0b1000000,0b1000000,0b1111111,0b1000000,0b1000000}, // T

{0b1111110,0b0000001,0b0000001,0b0000001,0b1111110}, // U

{0b1111100,0b0000010,0b0000001,0b0000010,0b1111100}, // V

{0b1111110,0b0000001,0b0001110,0b0000001,0b1111110}, // W

{0b1100011,0b0010100,0b0001000,0b0010100,0b1100011}, // X

{0b1110000,0b0001000,0b0000111,0b0001000,0b1110000}, // Y

{0b1000011,0b1000101,0b1001001,0b1010001,0b1100001}, // Z

{0b0000000,0b1111111,0b1000001,0b1000001,0b0000000}, // [

{0b0100000,0b0010000,0b0001000,0b0000100,0b0000010}, // backslash

{0b0000000,0b1000001,0b1000001,0b1111111,0b0000000}, // ]

{0b0010000,0b0100000,0b1000000,0b0100000,0b0010000}, // ^

{0b0000001,0b0000001,0b0000001,0b0000001,0b0000001}, // _

{0b0000000,0b1000000,0b0100000,0b0010000,0b0000000}, // `

{0b0000010,0b0010101,0b0010101,0b0010101,0b0001111}, // a

{0b1111111,0b0001001,0b0010001,0b0010001,0b0001110}, // b

{0b0001110,0b0010001,0b0010001,0b0010001,0b0000010}, // c

{0b0001110,0b0010001,0b0010001,0b0001001,0b1111111}, // d

{0b0001110,0b0010101,0b0010101,0b0010101,0b0001100}, // e

{0b0001000,0b0111111,0b1001000,0b1000000,0b0100000}, // f

{0b0001000,0b0010101,0b0010101,0b0010101,0b0011110}, // g

{0b1111111,0b0001000,0b0010000,0b0010000,0b0001111}, // h

{0b0000000,0b0001001,0b1011111,0b0000001,0b0000000}, // i

{0b0000010,0b0000001,0b0010001,0b1011110,0b0000000}, // j

{0b1111111,0b0000100,0b0001010,0b0010001,0b0000000}, // k

{0b0000000,0b1000001,0b1111111,0b0000001,0b0000000}, // l

{0b0011111,0b0010000,0b0001111,0b0010000,0b0001111}, // m

{0b0011111,0b0001000,0b0010000,0b0010000,0b0001111}, // n

{0b0001110,0b0010001,0b0010001,0b0010001,0b0001110}, // o

{0b0011111,0b0010100,0b0010100,0b0010100,0b0001000}, // p

{0b0001000,0b0010100,0b0010100,0b0001100,0b0011111}, // q

{0b0011111,0b0001000,0b0010000,0b0010000,0b0001000}, // r

{0b0001001,0b0010101,0b0010101,0b0010101,0b0000010}, // s

{0b0010000,0b1111110,0b0010001,0b0000001,0b0000010}, // t

{0b0011110,0b0000001,0b0000001,0b0000010,0b0011111}, // u

{0b0011100,0b0000010,0b0000001,0b0000010,0b0011100}, // v

{0b0011110,0b0000001,0b0000110,0b0000001,0b0011110}, // w

{0b0010001,0b0001010,0b0000100,0b0001010,0b0010001}, // x

{0b0011000,0b0000101,0b0000101,0b0000101,0b0011110}, // y

{0b0010001,0b0010011,0b0010101,0b0011001,0b0010001}, // z

{0b0000000,0b0001000,0b0110110,0b1000001,0b0000000}, // {

{0b0000000,0b0000000,0b1111111,0b0000000,0b0000000}, // |

{0b0000000,0b1000001,0b0110110,0b0001000,0b0000000}, // }

{0b0000100,0b0001000,0b0001000,0b0000100,0b0001000}, // ~

{0b0000110,0b0001001,0b1010001,0b0000001,0b0000010} // Que?


uint16_t buffer[PicoDisplay::WIDTH * PicoDisplay::HEIGHT];

PicoDisplay pico_display(buffer);

void charAt(uint8_t c,int x, int y){

if(c < 0x20 || c > 0x9e) c = 0x9f;

c = c - 0x20; // Font starts at

for(int cx=0; cx<5; cx++){

uint8_t col;

col  = FontData[c][cx];

for(int cy=0; cy<7; cy++){

  if(col & 0x40){




  col <<= 1;




void stringAt(const std::string &p,int x, int y){

for(int i = 0; char c=p[i]; i++){


x += 6;

if(x>= 240){


  y+= 8;

  if(y>=135) return;




int main() {




const uint LED_PIN = 25;


gpio_set_dir(LED_PIN, GPIO_OUT);

int textX = 0, textX2=0;

int textY = 0, textY2=0;

int textdx = 1;

int textdy = 1;

uint32_t i = 0;

while(true) {



std::string s("abcdefghijklmnopqrstuvwxyz");

std::string s2("[The quick brown fox jumps over the lazy dog!]");



std::string s3("Hello there!!");

int textW = s3.length()*6;

int textH = 8;


  textX2 += textdx;

  textY2 += textdy;

  if(textX2 < 0) textdx *= -1;

  if(textX2+textW >= pico_display.bounds.w) textdx *= -1;

  if(textY2 < 0) textdy *= -1;

  if(textY2+textH >= pico_display.bounds.h) textdy *= -1;

// update screen




return 0;


Here is a 16x16 non-proportional font on the Pico Explorer base. I got the font config from the web and modified the pico_graphics code. The top is the on-board font scaled to 3 and below it is the new 16x16 font scaled to 1. Unfortunately I now have work so I’ll look to release the preliminary code and credit the original font author then.



That looks wonderful!

Thanks. I think it does look quite a bit clearer than the original with the slight disadvantage or not being able to go as small.

I went to upload my project to github this morning and found that some of the punctuation characters are exhibiting artefacts where the descender would be. Not sure if it is a bug in my code or the font so will investigate tonight after work.



A bit of a delay on this. After many hours trying to figure out why all 95 characters of the font looked ok on the SSD1306 but had certain characters corrupted on the Pico Explorer Base’s display I have finally found out why. I was using the wrong font on the SSD1306! :-( This font is actually a 16x32 font and not a 16x16 font as I first thought. After using the correct font on the SSD1306 I get the same errors there. So I have emailed the author of the SSD1306 code (which included the font) in the hope that he has a correct definition.

The 16x16 font is a scaled up font so this 16x32 font still provides the best resolution although you will only get one line of 7 characters on an SSD1306 (128x32 variant) with it. You can get 14 characters on each line on a Pico Explorer / Pico Display.

Many thanks to Larry Bank for his SSD1306 library and telling me about the Adafruit fonts. As a result, I can now include as many fonts as I need (memory willing). The code works in the same way as Pimoroni’s except that it can only do character wrapping at the moment. Now I just need to refactor the code a little and learn how to fork etc. on Github and can then release it sometime next week. Here is a photo showing some of the fonts:

1 Like

The project can now be found on GitHub at: GitHub - borgsoftwaresystems/pimoroni-pico-with-adafruit-fonts: Libraries and examples to support Pimoroni Pico add-ons in C++ and MicroPython..

Uf2’s can be found at: Release Version 0.08 Alpha BSS-1 · borgsoftwaresystems/pimoroni-pico-with-adafruit-fonts · GitHub. Either font_demo_explorer.uf2 for Explorer Base or font_demo_display.uf2 for Display Pack.

Sorry, I haven’t done anything with Micro Python yet so they are unlikely to work on anything but C++ for the moment. I will start to investigate how to make the font changes work under Micro Python.

Please read the README for instructions. This is my first fork of a GitHub branch so hopefully I have done everything correctly to allow me to sync with the main Pimoroni library. I can’t guarantee how long I will maintain the sync as it will depend on how the Pimoroni library changes and I expect that Pimoroni will add better font support in the future rendering my library no longer necessary.

I have included 48 fonts which are variations of FreeSans, FreeSerif and FreeMono from the GNU FreeFont library,

I hope this is of use to someone.

P.S. I have tested on the Pico Explorer Base and included a version for the Pico Display Pack. I don’t have a Pico Display Pack at the moment so maybe someone could please test it works on theirs. Thank you.

Best regards,


I’m not sure why I can’t edit the post above. Anyway, I just got a Pico Display Pack and noticed that my code was incorrect - I was doing set_backlight prior to init resulting in a black screen - oops.

I have now corrected this and the new uf2 can be found at:


Sorry, picture a little blurry.

If you want a pure MicroPython solution, with the opportunity to easily design your own fonts, I have a small MicroPython script that does this:


Upper, lower and special chars are implemented.

All fonts are encoded as binary vals in a character map or look up table, but it is easy to create them, with a spreadsheet I put together, simply click the ‘pixels’ and it spits out the binary data you can use in your code.

I have a video rundown of code usage and how to use the spreadsheet here: https://www.youtube.com/watch?v=BMlGyAYNdF8

All code and a short manual can be found here: https://github.com/leswright1977/picofont

Hope this helps!


Magic! Thank you for putting this up. Easy to understand, use and modify. A great tool.

1 Like

Hi Les,

Looks good. I’ve just tried it here and it works well. Can I make a small suggestion though…

If you refactor it slightly so that the various functions take an optional parameter to tell it whether to do a display.update() you can get it so it draws much more quickly. That way those that like the teleprompter type output can leave it to update after each character and those that don’t could update after each string.