lexus2k / lcdgfx

Driver for LCD displays running on Arduino/Avr/ESP32/Linux (including Rasperry) platforms
MIT License
371 stars 51 forks source link

How to set font size on canvas? #1

Closed joaomcarlos closed 4 years ago

joaomcarlos commented 4 years ago

Hi.

I am trying to write some screens on a SSD1306 (128_32) and to avoid screen flickering I am trying to use double buffering by writing all my display code to draw on a canvas, as per your monochrome double buffering example.

However I cant seem to find a way to set the font size when drawing to a canvas.

Is this not supported?

lexus2k commented 4 years ago

Hi Carlos,

Using font scaling is not possible in canvas API. Creating such support in for printFixed() API will dramatically increase code size in flash. It is possible to create slow function, universal for all graphics modes: monochrome, 8-bit and 16-bit color, if it is suitable for you.

Best regards

joaomcarlos commented 4 years ago

Perhaps the Canvas API is not what I am supposed to use?

I just need to draw to the SSD1306 (128_32, over i2c) and to avoid screen flickering.

Would you suggest doing it differently than using the Canvas API?

And yes, I would like to keep the size down, I switched specifically to this library because the one I was using was too big. I am using a Pro Micro

lexus2k commented 4 years ago

It depends on what you're trying to implement. ssd1306 controller RAM utilizes 1 byte per 8 pixels. There is no way to read memory from ssd1306 controller, the library can only write. Thus if to put 2 pixels near each other, without double buffering, the application will send first pixel, the second pixel as bytes (0b00010000 and 0b00001000), and finally because second byte sent to the same RAM cell overwrites previous value, you will get 0b00001000, but not 0b00011000. If you update the same pixels area many times, you will see flickering. But if you don't need to draw 2 different primitives in the same area, you can use direct graphics operations without causing to see any flickering.

joaomcarlos commented 4 years ago

I am making a controller for an airsoft gun, that displays ammo count, full/semi/safe status, shows weapon tilt using a gyro/accel combo and has menus to change settings.

One of the screens would be a big number with shot count decreasing from a set amount (sort of like the gun from Halo games) and a sort of progress bar. The other would be a sort of bubble level with markers of saved angles. And the menu has sub-menus on it, with stuff like changing settings and re-calibrating the gyro, etc.

It does not need to be as speedy refreshing as a normal game.

The way I have been doing is to call a display.clear() before each "draw call". The "draw call" is called by a tasker (task scheduler) every 40 miliseconds and has a bool parameter, such that it only draws if anything changed. All other functions within the code are controlled via the tasker at different intervals. The tasker allows tasks to be scheduled with priority so its not guaranteed that a task will be called at specific intervals, if a more important task comes along.

Currently the only important task I have is triggered by the trigger button to fire the gun, as I want it to fire as soon as I press the button and its release to happen 40 milis afterwards.

Other than that, all the code is non-blocking as much as possible (other than its normal execution).

With canvas what I do instead is use it as a screen, and all my functions "draw" to it, then when time comes, the main function draws the canvas to the display.

lexus2k commented 4 years ago

Ok, I've got you.

Here is what I mean:

You will not see any flickering in this example:

void setup()
{
    display.begin();
    display.fill(0x00);
    display.setFixedFont(ssd1306xled_font6x8);
}

void loop()
{
    static int speed = 5;
    char speed_str[8] = "00 MPH";
    speed++;
    speed_str[0] = speed/10 + '0';
    speed_str[1] = speed%10 + '0';
    display.printFixedN (0, 0, speed_str, STYLE_BOLD, FONT_SIZE_2X);
    delay( 1000 );
}

But you will see any flickering in this example:

void setup()
{
    display.begin();
    display.fill(0x00);
    display.setFixedFont(ssd1306xled_font6x8);
}

void loop()
{
    static int speed = 5;
    char speed_str[8] = "00 MPH";
    speed++;
    speed_str[0] = speed/10 + '0';
    speed_str[1] = speed%10 + '0';
    display.drawRect(0,0,127,15);
    display.printFixedN (0, 0, speed_str, STYLE_BOLD, FONT_SIZE_2X);
    delay( 1000 );
}
joaomcarlos commented 4 years ago

Sorry for the delay answering back.

I have been very busy and haven't had time to work on this.

I appreciate your feedback. I will try to tackle this soon. The main problem with this technique is that it doesnt reset pixels that were lit previously, correct? So they are left behind.

lexus2k commented 4 years ago

Hi Carlos,

Not really. When you draw text directly, it clear all pixels under the new text. The only you need to do is to clear pixels via fillRect at the end of new text, if needed. Also, you may find useful getTextSize() method of NanoFont class to calculate region, required for old and new text.

Alexey