Menu

Tiny Fonts for a Tiny GLCD Screen

2025-04-13
2025-04-17
  • Roger Jönsson

    Roger Jönsson - 2025-04-13

    Hi, Working on a small game, I ran out of memory trying to add some text to the little 0.49" OLED SSD1306_64x32 screen. I noted that by just adding the first digit or letter I lost about 1kword of Program memory. At that point I only wanted to print some digits for score and I wanted them to look old school. It set me on a path making a tiny font needing tiny space both on screen and in the chip. With tiny size charachters and only upper case letters I saved a little more than 600 words. Keeping only the digits (which was my original goal) >700words. On the other hand it uses > 30 bytes extra RAM.
    The fonts are 3col x5 height each saved in a word. The bit pattern is; bottom and up (left column, middle column, right column).
    The result is a "cheap" font that is hardly readable :)
    Yeah, I know it is kind of silly, but here it is.

     
  • Roger Jönsson

    Roger Jönsson - 2025-04-13

    Here is the program.
    Learned a lot making it. Still learning.

     
  • Anobium

    Anobium - 2025-04-14

    Genius stuff!!

    Can I post to the demos?

    Evan


    This is the readme.md

    🌟 Tiny Fonts, Big Challenges: A Developer's Tale 🌟

    👾 Roger Jönsson was working on a small game, and he stumbled upon a rather unique challenge with my tiny 0.49" OLED SSD1306_64x32 screen. While trying to add some text for a score display, I realized how much memory was being consumed—just adding the first character would eat up about 1 kword of Program memory!

    Determined to find a solution, he set out to create a custom tiny font that would save precious space—both on-screen and in the chip. By focusing on the essentials and designing 3x5 pixel characters, he has managed to save over 600 words of Program memory by keeping only uppercase letters, and more than 700 words by sticking to digits alone. 🎉

    Here’s how it works:

    • Each character is 3 pixels wide and 5 pixels tall.
    • The bit pattern is stored column-by-column: bottom to top (left, middle, and right columns).

    While the font does use a little extra RAM (>30 bytes), the memory savings more than make up for it!

    The result? A super “cheap” font that is... well, let’s just say it’s barely readable, but it gets the job done! 😅


    Can you review the program attached? I have documented and renamed the variables. The single letter variables will not work on many other microcontrollers. Please check I have not broken the demonstration program.

     
  • Roger Jönsson

    Roger Jönsson - 2025-04-14

    :) Sure! I would be glad if anyone would find it useful. Yes, the updated version seems to work fine.

    I spent several hours when working on the digits, on the logic separating the extra digit going from 9 to 10---99, trying to simplify it using only little resources. I did ok, but I did not find a simple magic trick. The day after I looked into the ASCII-stuff and wondered if using it could do it for me. It did and it didn't take up more resources. Also since I could easily pass a string into the routine. -Wow! Now I must try some letters...
    (I skipped testing for blank spaces which are separated from the letters in the ASCII table, since it returns what prints as a blank anyway.)
    I used the attached tiny spreadsheet attached to draw the fonts. It's easy to add more.

    Starting using a GLCD I find it extremely useful when debugging. The GCB routines are so simple to use! Really Great stuff! I should have tried it a long time ago, but I was kind of intidated by it. Now I really can't understand why.

    I didn't know about single letter variables not working on many other microcontrollers. Now I know.

     
  • Anobium

    Anobium - 2025-04-14

    Thank you for your permission.

    The ASC() function is probably used somewhere in the program, therefore you calling it does not increase the size of the program.

    Debugging to any output device like a GLCD or Serial is so much easier than LEDs or an LCD. You throw some much information!

    I am glad you are enjoying yourself!!

     
  • Roger Jönsson

    Roger Jönsson - 2025-04-14

    I remembered wrong. Using my program were I handled separating the second digit (tens). The was no ASC() function and sure it uses less RAM than the other versions. I was mainly focusing on program memory and must have missed comparing RAM. Still the benefit of the ASCII-way is huge in simplifying things so I will stick with it. Unless...-Who knows. :)
    What I am saying is that my demo with ASC() function uses more RAM than using GCfonts and doing it without any of them uses less RAM.

     

    Last edit: Roger Jönsson 2025-04-14
  • Anobium

    Anobium - 2025-04-14

    Looks good to me!

     
  • Anobium

    Anobium - 2025-04-16

    @Roger.

    I have an idea. I have an LGT328P ( a much faster AVR clone, fully supported by GBASIC).

    Can I send you chip/board? I an wondering how fast can your game be?

    Evan

     
  • Roger Jönsson

    Roger Jönsson - 2025-04-17

    I'm still working on the Pong alike thingy, now and then, on the little spare time I have.
    I will probably call it Pingis (Swedish slang for table tennis). It is mainly logic, with logic patterns for each possible event; if sent from here and bouncing there, then this pattern forward until hitting next boundry (not much math) for the angles and therefor fast as is. Most of the speed limitation would be the writing on the screen (i2C). I slow the program down with a wait sub and have tuned the delays to suit the different times it takes to draw the ball and move the players to make speed consistent. My plan is to use this central wait sub to easilly increase the speed gradually as time passes into the game. If I set this wait sub to zero then it was too fast, the last time I tried. Running the PIC att half clockrate. The screen redraws being the main factor slowing it down. Even though only a few pixels are updated while the ball is moving.
    So for this game it would not be beneficial to make it faster (unless I bloat it up severely on the way) and I am not sure much would happen with a faster processor.

    I probably would have finished it by now if I hadn't side stepped adding blipp, brrr sounds, then making the tiny font. Pinings is kind of a mess, with it starting to live its own life being hard to overview. I hope I can sort it out. A week on pause and dustin it off, the hair scratching starts again trying to remember, not quite understanding my own instructions and the nested layout. Pingis has grown so it will not fit the chip I aimed for, unless I rewrite the whole thing and plans things properly. Tiny fonts did not save as much as I wasted elsewhere. :) I keep thinking, its ok, I'm not really a programmer. Then I think of todays operatingsystems and it feels fine again. :)

    Since you wrote this, I tried to get a grasp of how LGT328P performs but it is not so easy to find with much conflicting info and opinions. It is said to have some math stuff in it, which could be handy for future projects.

     
  • Anobium

    Anobium - 2025-04-17

    The LGT is fast. When reading online reviews that are using ARDUINO... means the code is not optimal.

    GCBASIC is optimised for the LGT and it twice as fast as an AVR. 1.5 faster than PIC.

    Want to send one?

     
  • Roger Jönsson

    Roger Jönsson - 2025-04-17

    Yes. please. It could be interesting to explore.

    Is there a trustworthy overview of its capabillites that you could link to?

     
  • Anobium

    Anobium - 2025-04-17

    Send me your address, privately!

    Look in your demos\LGT8F_core_based_solutions folder. There is a Readme.md that I put together when I implemented the LGTs.

     
  • Roger Jönsson

    Roger Jönsson - 2025-04-17

    This link is broken (you pointed to it for Analog comparator and Computation Accelerator):
    Datasheet (English) LGT8FX8P_databook_V1.04 thanks to #metallurge

    No big deal. The link to V1.05 version works

    Q: Is the behaviour of the timers similar to a PIC or is this to be found out?

    When I tested this for 8-bit timer in a PIC, I could make it run repeated interrupts from the main thread without the code in the called sub affecting the timing/period of the interrupt repeating (as long as the sub finished before next interrupt). This would be good for multifrequency signal generation while still being able to simltaneously running some stuff in the main thread, without changing the frequency of waveform generated in the sub repeatedly called. I still don't know why this is possible in 8-bit but not in 16-bit (where the reset couldn't be done before the code in the called sub has finished, if I understood it correctly, moving the next interrupt in time). For this type of job, it would be nice if the interrupts could just repeat steadidly, while it is up to the routine in the sub called to be short enough to be able to complete before next interrupt. Not many % of the total computing time for the main loop would be needed.

     
    • Anobium

      Anobium - 2025-04-17

      All the URLs are external. It a collection and I have no control. :-(


      AVR&LGT timers are different but they work the same.

      Re the ISRhandling. The completion of interrupt is an architectural constraint. I am not sure how to redirect the vector the same ISR handler. If you can find some research that implements then... if can be done in GCBASIC as your able to low level magic. :-)

       

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.