Skip to content
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

Different OLED font sizes #6650

Closed
1 of 3 tasks
burlapsax opened this issue Aug 31, 2019 · 20 comments
Closed
1 of 3 tasks

Different OLED font sizes #6650

burlapsax opened this issue Aug 31, 2019 · 20 comments

Comments

@burlapsax
Copy link

burlapsax commented Aug 31, 2019

Is it possible to use larger than 6x8 fonts on the 128x32 SSD1306 display using the standalone OLED library packaged with qmk_firmware?

I have the display working fine with an old ADB keyboard. Currently it just shows a simple monitor of the highest-selected layer.
20190831_144949
This is based on the default glcdfont.c, with slightly modified characters but mostly the same and still on the 6x8 grid.
(Sorry about the picture – I tried rotating it 180 degrees and re-uploading but it's still upside down...)

This is awesome, but the text is so small it's hard for me to read. I'd like to use a larger font size. Here is what I tried:

  1. copy the hex from glcdfont.c and convert to image
  2. open in an image editor and resize 200% (nearest neighbor / hard edges)
  3. save image and convert back to hex
  4. paste the result back into glcdfont.c, replacing the existing hex copied in step 1
  5. set OLED_FONT_WIDTH 12 and OLED_FONT_HEIGHT 16 in keyboards/converter/adb_usb/config.h
  6. make and flash

Here's what that looks like:
20190831_151540
It seems like it's displaying the full width of the 12x16 characters – but only horizontal cross-sections of them at the same height as the 6x8 font. Some are obviously the top halves of the character; others are less discernible.

I'm not sure whether this means OLED_FONT_HEIGHT is not behaving as expected, the steps I took were wrong, or that the library does not support different font sizes at all.

What can I do to display a different (specifically, larger) font size than 6x8 with this OLED library?

System Information

  • Keyboard: 1987 Apple Desktop Bus keyboard -> Arduino Pro Micro (custom build of keyboards/converter/adb-usb with OLED_DRIVER_ENABLE) + SSD1306 128x32 OLED display
  • Operating system: macOS 10.14.6
  • AVR GCC version: avr-gcc (GCC) 9.1.0
  • ARM GCC version: arm-none-eabi-gcc (GNU Tools for Arm Embedded Processors 7-2018-q2-update) 7.3.1 20180622 (release) [ARM/embedded-7-branch revision 261907]
  • QMK Firmware version: forked from 0.6.459 // 43b0309 Add 2015 revision of Pegasus Hoof to QMK (Add 2015 revision of pegasus hoof to QMK #6595)
  • Any keyboard related software installed?
    • AutoHotKey
    • Karabiner
    • Other:
@drashna
Copy link
Member

drashna commented Sep 26, 2019

Tagging @XScorpion2 as they're the author of the OLED Driver feature, for help here.

And very neat/nice mod!

@XScorpion2
Copy link
Contributor

XScorpion2 commented Sep 26, 2019

Adding tall font support is on my list of todos. I just haven't gotten around to it yet.

save image and convert back to hex

Depending on how you convert to hex, this result may or may not be correct.

@su8044
Copy link
Contributor

su8044 commented Jan 19, 2020

Did you ever find a solution? I'm having the same issue with a 128x64 display and the font is just too small and there is too much screen wasted

@brickbots
Copy link
Contributor

Hi @XScorpion2! I'm happy to take this on as I'm interested in using larger font sizes myself. I've taken a look at the current code and I believe it shouldn't be too hard or memory intensive to support fonts that are multiples of 8 pixels tall with fixed (but arbitrary) width. I'm thinking 2x, 3x, 4x height to start.

One thing I've run into playing with this is the font format currently used. The comment in the font file:
// Helidox 8x6 font with QMK Firmware Logo
// Online editor: http://teripom.x0.com/

Refers to an online editor which seems defunct. I've found this one, which seems fairly well put together:
http://oleddisplay.squix.ch/#/home

But generates variable width font files with a more complicated encoding/more overhead than we probably want here. In the future we can implement a fully raster system for the oled which is compatible with some of the existing GFX libs, but I think it will be difficult to get something this complex to fit memory along with all the core features.

Are we okay using our own font file format with no user-friendly tool to create them?
If so, we can slightly alter the current format to support taller fonts and include a few different font files that people can use. This will allow us to keep the implementation fairly lightweight, but provide a few font options in various sizes, with the ability to mix them on screen at once.

Here is what I propose:

  • Add two bytes to the start of the font array, one for width, and one for height. This will allow predictable indexing into the font array to render characters without needing a lookup table.
  • Create a number of font files supporting various sizes/styles
  • Create specific font files for the glyphs currently used for logos and such
  • Come up with some sort of clever way to allow multiple arbitrary font file includes (?)
  • Add a setup/helper function to allow font changes. I imagine this will work by setting a pointer to the active font array and setting the current height/width which are currently defines, but will be changes to dynamic vars.
  • Modify the oled_write_char and related functions to support these new font files, making them use the active font array pointer and dynamic height/width.

I think this can all be done without breaking anything which relies on the existing behavior. And should allow mutiple font sizes on the display at once, memory allowing. Anyone with a custom font file may have to make some changes (i.e add the width/height bytes to the start), but I've not see to much of this browsing through the user space directories.

@brickbots
Copy link
Contributor

I've done a bit more digging, and I think that this font file may be a good base:

https://lexus2k.github.io/ssd1306/ssd1306__fonts_8c_source.html

It looks like these are from the GLCD Font Creator program, and have a format very similar to what I was thinking, if you exclude the few non-fixed fonts. Here is an example of the preamble:

0x00, // 0x00 means fixed font type - the only type supported by the library
0x08, // 0x08 = 8 - font width in pixels
0x10, // 0x10 = 16 - font height in pixels
0x20, // Standard filler/delimiter before font data starts

Then the font data is a series of bytes from left to right / top to bottom. Unless anyone objects I'll grab this file as a base and see if I can make the required driver changes to support it.

@zigotica
Copy link
Contributor

hi @brickbots @XScorpion2 any update on using custom 8x16 font? thank you

@brickbots
Copy link
Contributor

Thanks for asking @zigotica. After my last update I got several fonts setup in the correct format and roughed in some code, but it's not working reliably yet. I'm sorry to say I've not spent much time on this since then, but your inquiry is good motivation for me to finish this up and get a merge request in.

Did you have any thoughts about the implementation of this, or just interest in the status and when it might be available?

@zigotica
Copy link
Contributor

zigotica commented Sep 4, 2020

hi @brickbots and thank you. sorry i was out for hols. I didn't get my hands dirty with this just yet. was curious and found out no one had yet tackled this.
pro micro size (ATmega32U4 free space) is an issue for sure, so options might be limited

@zigotica
Copy link
Contributor

zigotica commented Sep 8, 2020

OK, retried using the 8x16 font suggested by @brickbots above,

#define OLED_FONT_H "keyboards/kyria/keymaps/zigotica/glcdfont.c"
#define OLED_FONT_WIDTH 8
#define OLED_FONT_HEIGHT 16

When running qmk compile (latest version, I am at cd73949) still complains about it:

Compiling: drivers/oled/oled_driver.c                                                              drivers/oled/oled_driver.c: In function 'oled_write_char':
drivers/oled/oled_driver.c:388:27: error: 'font' undeclared (first use in this function); did you mean 'float'?
     _Static_assert(sizeof(font) >= ((OLED_FONT_END + 1 - OLED_FONT_START) * OLED_FONT_WIDTH), "OLED_FONT_END references outside array");
                           ^~~~
                           float
drivers/oled/oled_driver.c:388:27: note: each undeclared identifier is reported only once for each function it appears in
drivers/oled/oled_driver.c:388:20: error: expression in static assertion is not an integer
     _Static_assert(sizeof(font) >= ((OLED_FONT_END + 1 - OLED_FONT_START) * OLED_FONT_WIDTH), "OLED_FONT_END references outside array");
                    ^~~~~~
 [ERRORS]
 |
 |
 |
make[1]: *** [.build/obj_kyria_rev1_zigotica/oled_driver.o] Error 1
make: *** [kyria:zigotica] Error 1
Make finished with errors

Apparently the sizeof is out of range. I think I saw a fix somewhere subtracting one to the size, but I'm not really sure it is 100% related, nor remember the link.

@zigotica
Copy link
Contributor

zigotica commented Sep 8, 2020

OK I think my problem above is related to #8145 but that was merged in February

@brickbots
Copy link
Contributor

Hi @zigotica ! Just to clarify a bit... I've thought about how this might work, and played around a bit on a branch, but I've not committed anything yet. So, for now I believe only the 8x8 fonts will work out of the box.

Sorry for any false hope here, I have started working on this (thanks again for pinging about it), but it will probably be a while before it's ready to issue a merge request as I want to try to enable a wider array of fonts without breaking all the other OLED stuff already in play :-)

@XScorpion2
Copy link
Contributor

XScorpion2 commented Sep 9, 2020

A big part of the issue with going to larger font sizes is the structure of the buffer. Currently it's an array where each byte represents 8 pixels vertically, starting top left corner, going right, wrapping to the next row of pixels when we reach the end. 8 bit tall fonts take advantage of this layout by using a memcopy approach copying the 8 bits tall x N bytes wide pixel data directly to the buffer for performance. For increased size fonts (IE: 16 bit high by N bits wide), you would need to do 2 passes shifting the bits, and copying 1 byte at a time to the buffer in 2 passes to get the upper and lower bits. Now this could be improved by storing the font data itself differently, separating the upper bytes in one chunk and lower bytes in another chunk. The problem is I haven't done much digging into font creation apps that split the data up like that. The few I have tried instead go horizontal with their bits, so you could do an 8 bits wide, N bytes tall font.

@brickbots
Copy link
Contributor

Indeed, anything other than 8x8 will definitely be less performant. I was hoping to get the most flexible, slowest case up and running (arbitrary placement of arbitrary sizes) and see how bad it would be. Then we could start to maybe set some conditions to speed it up... font sizes must be multiples of 8 high, or only limited to only specific placement in the buffer.

Might ultimately be a fools errand, but it would be nice to have a bit more flexibility on offer if we can make it user-friendly enough.

@zigotica
Copy link
Contributor

zigotica commented Sep 9, 2020

Hey guys, thank you for the insights. I understand it's a hard problem to solve, given the small amount of free space in ATmega32U4 which is the most used micro, I guess.

Hi @zigotica ! Just to clarify a bit... I've thought about how this might work, and played around a bit on a branch, but I've not committed anything yet. So, for now I believe only the 8x8 fonts will work out of the box.

No pressure at all @brickbots I understood.

I was also thinking of creating an array and build each char (reduced to alphas and numbers) in 2 or 4 pieces and using a custom method to write each line in 2 runs. Kind of painting a logo but for words (lines actually). That should probably be doable, but again, space is limited. We'll see.

Thank you again

@brickbots
Copy link
Contributor

@zigotica That's a great approach, and would definitely work and not require any core changes. You'd have to come up with a nice font file and a helper function in your keymap, but it's doable and would get you where you want to go.

Ultimately, it may actually be a good way of handling the bit more general case of double height chars. It's very much along the lines of what @XScorpion2 was talking about above with a specially encoded font file that works with the 8 bit memory structure.

@XScorpion2
Copy link
Contributor

@brickbots @zigotica Yup, that is pretty much what I was suggesting.

@zigotica
Copy link
Contributor

zigotica commented Sep 9, 2020

Great then! I will let you know. Thank you both.

@memco
Copy link

memco commented Mar 1, 2021

Hi all, I have low vision and would love to be able to use a larger font so I can read the text. Any chance updates are coming soon?

@BifbofII
Copy link

I don't know if anybody is still working on this, but I have started some work on this issue and will create a PR draft soon. What I'm trying to implement is basically what was talked about by @brickbots and @XScorpion2 before, more details in the PR. Feedback is very welcome.

@zvecr
Copy link
Member

zvecr commented Aug 28, 2022

This issue has been automatically closed because it has not had any recent activity.
If this issue is still valid, re-open the issue and let us know.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants