tuupola/hagl_pico_mipi

having a hard time scaling up words

Closed this issue · 15 comments

I'm making a digital log with encryption I hope (starting a YouTube channel)!
The 6x9 font is way too small for the 1.8 screen I'm using so I scaled it up using

hagl_bitmap_t bitmap;
bitmap.buffer = (uint8_t *) malloc(6 *  9 * sizeof(hagl_color_t));
    while (1) {
        adc_select_input(2);
        uint adc_x_mod = (adc_read()-70) /160;
        adc_select_input(1);
        uint adc_y_mod = (adc_read()+60) /160;
        if(adc_y_mod >12){
         int16_t x0 =80;
         int16_t y0 =64;
         cde++;
         hagl_color_t color = rand() % 0xffff;
         hagl_put_char(display,chaw(8,9), x0, y0, color, font6x9);
         //hagl_get_glyph(display, a, color, &bitmap, font6x9);
         printf("%d\n",cde);

        hagl_blit_xywh(display, x0, y0, 18, 27, &bitmap);
        hagl_flush(display);
        sleep_ms(50);
        }
        else{
         int16_t x0 =80;
         int16_t y0 =64;
         hagl_color_t color = rand() % 0xffff;
         uint16_t a = chaw(8,9) + cde;
         hagl_get_glyph(display, a, color, &bitmap, font6x9);

        hagl_blit_xywh(display, x0, y0, 18, 27, &bitmap);
        hagl_flush(display);
        sleep_ms(50);
        }
        }

the structure worked out fine for generating random things, but my goal is to create an editor.
So I create an array

char commonChars[8][10] = {
        {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'},
        {'!', '@', '#', '$', '%', '^', '&', '*', '(', ')'},
        {'-', '_', '=', '+', '[', ']', '{', '}', '|', '\\'},
        {';', ':', '\'', '"', ',', '.', '<', '>', '/','?'},
        {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'},
        {'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't'},
        {'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D'},
        {'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N'}
    };

it didn't work when casting variables
#define chaw(i,j) (uint16_t)(commonChars[i][j])
so I noticed the number aren't created the same way and discover
#define chaw(i,j) (uint16_t)(commonChars[i][j]) -178
but it only work for capital letters
Can you tell me how to modify hagl_put_char for creating 18X27 char or I'm going to do it the hard way like finding it with a joystick (different formulas for each categories)
"my first code may be messed up hope you get my point"

It might be easier to use one of the larger from from here:
https://github.com/tuupola/embedded-fonts/tree/master/X11

To scale a 6x9 glyph to 18x27 you could use something like:

hagl_bitmap_t glyph;

hagl_bitmap_init(&glyph, 6, 9, display->depth, NULL);
glyph.buffer = (uint8_t *) malloc(glyph.size);
    
if (0 == hagl_get_glyph(display, ascii, colour, &glyph, font6x9)) {
    hagl_blit_xywh(display, x0, y0, 18, 27, &glyph);
}

Which is basically the same you have been doing. I am not sure what is the actual problem you have difficulties with. Is the scaling the glyph or is it finding a correct code for each character?

#define chaw(i,j) (uint16_t)(commonChars[i][j])
the number generated from chaw(8,9)fed into glyph isn't "M" ,is something out of the array

I need to use this to get "M"
#define chaw(i,j) (uint16_t)(commonChars[i][j]) -178
the char to int conversion is different ?!?!,so I need to minus 178
finding a correct code for each character it is

I have trouble installing fontx_tools
Screenshot 2023-02-28 at 3 37 44 PM
can't link
Can you paste me the header file generated from font18x18ja.fnt

Damn! Should have went into it
But I get this
IMG_2393

using example and commented out put_char ( no warnings generated)

#include <stdio.h>
#include "font6x9.h"
#include "font18x18ja.h"
#include "font18x18ko.h"
#include <hagl_hal.h>
#include <hagl.h>
#include "pico/stdlib.h"
#include "hardware/adc.h"
#define chaw(i,j) (uint16_t)(commonChars[i][j])
static hagl_backend_t backend;
static hagl_backend_t *display;
volatile uint16_t cde = 0;
int main() {
  char commonChars[8][10] = {
    {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'},
    {'!', '@', '#', '$', '%', '^', '&', '*', '(', ')'},
    {'-', '_', '=', '+', '[', ']', '{', '}', '|', '\\'},
    {';', ':', '\'', '"', ',', '.', '<', '>', '/','?'},
    {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'},
    {'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't'},
    {'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D'},
    {'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N'}
  };
  stdio_init_all();
  adc_init();
  // Make sure GPIO is high-impedance, no pullups etc
  adc_gpio_init(26);
  sleep_ms(50);
  display = hagl_init();
  hagl_clear(display);
  while (1) {
  /*
    adc_select_input(2);
    uint adc_x_mod = (adc_read()-70) /160;
    adc_select_input(1);
    uint adc_y_mod = (adc_read()+60) /160;
    */
    for (uint16_t i = 1; i < 10000; i++) {
      int16_t x0 = rand() % display->width;
      int16_t y0 = rand() % display->height;
      hagl_color_t color = rand() % 0xffff;
      char code = rand() % 255;

      hagl_put_char(display, code, x0, y0, color, font18x18ko);
      //    hagl_put_char(display,chaw(8,9), x0, y0, color,font18x18ko);
      //   hagl_put_char(display,commonChars[7][9], x0, y0, color,font18x18ko);
      //hagl_put_char(display,chaw(8,9), x0, y0, color,font18x18ja);
hagl_flush(display);
    }
    //hagl_flush(display);
    sleep_ms(50);
  }
  hagl_close(display);
}

Looking at the font dump that is how first 250 or so characters look.

https://github.com/tuupola/embedded-fonts/blob/master/X11/png/font18x18ko.png

Korean character codes do not fall into ASCII range so you need to change your random generator to something like:

wchar_t code = rand() % 65535;

That said, looking at the large Asian font dumps they seem to be missing part of the bitmap data. Probably because they are too big to fit into two byte boundary. Anything up to 16 x something should be ok.

Photo on 2023-3-1 at 8 35 PM
Since ja and ko stands for jpn and kor ,I'm looking for at least 18x18 with

char commonChars[8][10] = {
    {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'},
    {'!', '@', '#', '$', '%', '^', '&', '*', '(', ')'},
    {'-', '_', '=', '+', '[', ']', '{', '}', '|', '\\'},
    {';', ':', '\'', '"', ',', '.', '<', '>', '/','?'},
    {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'},
    {'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't'},
    {'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D'},
    {'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N'}
     {O to Z}
  };

Is there any chance you have one lying around

Screenshot 2023-03-01 at 8 50 01 PM

They may be these, not a too big to fit into two byte boundary issue?

Is there any chance you have one lying around

No. I have only converted the fonts in the repository. If your concern is that the pixels are too small to show in a YouTube video you could also try using the HAGL_HAL_PIXEL_SIZE = 2 setting.

Thank you for taking a long time to tell me this method. It really does have a lot of drawbacks, but it does work in the short term. Mind if I ask which datasheet are you using for the ST7735 series , I can't get my head around which chip does my display use the S, the R or the B.

This library follows the MIPI Display Command Set standard. Most Sitronix (ST), Ilitek (ILI) and GalaxyCore (GC) support this standard. Solomon (SSD) chips have their own proprietary standard.

What information are you looking for from the datasheet? There are only small differences between the versions of the ST7735. IIRC something like the original version did not have support for hardware scrolling. Other than that the datasheets are pretty much identical.

Is there any function in this library utilizes hardware scrolling?
It's nice to know that they follow some standard, it would be way easier to open source one day to create bigger uses less memory fonts.It took me more than 10s to transfer it to my pico, thus I'm afraid that my 4MB pico mayl run out of memory with bigger fonts.
The display displayed more than one character out of the array is it some safety you added, if not I'm posting it to forums.
IMG_2400
The switching works fine(it changes colors nonstop when I'm not touching it). I only wanted these characters in my typing function

char commonChars[12][8] = {
  {' ', '!', '\"', '#', '$', '%', '&', '\''},
  {'(', ')', '*', '+', ',', '-', '.', '/'},
  {'0', '1', '2', '3', '4', '5', '6', '7'},
  {'8', '9', ':', ';', '<', '=', '>', '?'},
  {'@', 'A', 'B', 'C', 'D', 'E', 'F', 'G'},
  {'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O'},
  {'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W'},
  {'X', 'Y', 'Z', '[', '\\', ']', '^', '_'},
  {'`', 'a', 'b', 'c', 'd', 'e', 'f', 'g'},
  {'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o'},
  {'p', 'q', 'r', 's', 't', 'u', 'v', 'w'},
  {'x', 'y', 'z', '{', '|', '}', '~', '\0'},
};

Code:

#include <stdio.h>
#include "font6x9.h"
#include "font9x18B.h"
#include <hagl_hal.h>
#include <hagl.h>
#include "pico/stdlib.h"
#include "hardware/adc.h"
char commonChars[12][8] = {
  {' ', '!', '\"', '#', '$', '%', '&', '\''},
  {'(', ')', '*', '+', ',', '-', '.', '/'},
  {'0', '1', '2', '3', '4', '5', '6', '7'},
  {'8', '9', ':', ';', '<', '=', '>', '?'},
  {'@', 'A', 'B', 'C', 'D', 'E', 'F', 'G'},
  {'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O'},
  {'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W'},
  {'X', 'Y', 'Z', '[', '\\', ']', '^', '_'},
  {'`', 'a', 'b', 'c', 'd', 'e', 'f', 'g'},
  {'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o'},
  {'p', 'q', 'r', 's', 't', 'u', 'v', 'w'},
  {'x', 'y', 'z', '{', '|', '}', '~', '\0'},
};
static int h = 0, k =0;
char chaw (int *m,int *n){
  return commonChars[*m][*n];
}
static hagl_backend_t backend;
static hagl_backend_t *display;
void fuse(int *o,int *p){
  if (*o > 12){
    *o = 0;}
  if (*p > 8){
    *p = 0;}
}
int main() {
  stdio_init_all();
  adc_init();
  adc_gpio_init(28);
  adc_gpio_init(27);
  sleep_ms(50);
  display = hagl_init();
  hagl_clear(display);
  while (1) {
    uint adc_x_mod,adc_y_mod;
    adc_select_input(2);
    adc_x_mod = (adc_read()-70) /160;//keep it stable
    adc_select_input(1);
    adc_y_mod = (adc_read()-30) /160;//keep it stable
    if (adc_x_mod > 12){
      h++;}
    else if (adc_x_mod < 12){
      h--;}
    else{
      h = h;
    }
    if (adc_y_mod > 12){
      k++;}
    else if (adc_y_mod < 12){
      k--;}
    else{
      k = k;
    }
    fuse(&h,&k);
    int16_t x0 = 40;
    int16_t y0 = 32;
    hagl_color_t color = rand() % 0xffff;
    hagl_put_char(display,chaw(&h,&k), x0, y0, color,font9x18B);
    hagl_flush(display);
    sleep_ms(30);
  }
  hagl_close(display);
}

Is there any function in this library utilizes hardware scrolling?

I have not had time to test it but you can write any MIPI DCS command / register with mipi_display_ioctl(). The two registers which control the scrolling are:

#define MIPI_DCS_SET_SCROLL_AREA            0x33
#define MIPI_DCS_SET_SCROLL_START           0x37

I think the default for scroll area is full screen. The driver chips usually have sane defaults. Scroll start parameter does the actual scrolling. Page 129 in ILI9341 datasheet has a nice drawing how it works.

This driver is kept reasonably low level on purpose. It is a building block for higher level libraries.

Nice to know
The display still displayed more than one character out of the array

IMG_2461
IMG_2460

after adding more conditions and delay

if (adc_x_mod > 12 && adc_y_mod ==12){
      h++;
      sleep_ms(30);
      }
    else if (adc_x_mod > 12 && adc_y_mod > 12){
      k++;
      h++;
      sleep_ms(30);
      }
    else if (adc_x_mod > 12 && adc_y_mod < 12){
      k--;
      h++;
      sleep_ms(30);
      }
    else if (adc_x_mod < 12 && adc_y_mod ==12){
      h--;
      sleep_ms(30);
      }
    else if (adc_x_mod == 12 && adc_y_mod < 12){
      k--;
      sleep_ms(30);
      }
    else if (adc_x_mod == 12 && adc_y_mod > 12){
     k++;
      sleep_ms(30);
     }
    else if (adc_x_mod < 12 && adc_y_mod > 12){
      k++;
      h--;
      sleep_ms(30);
      }
    else if (adc_x_mod < 12 && adc_y_mod < 12){
      k--;
      h--;
      sleep_ms(30);
      }
    else if (adc_x_mod == 12 && adc_y_mod == 12){
      h = h;
      k = k;
      sleep_ms(30);
    }

is it some safety you added, if not I'm posting it to forums.

My fuse didn't work correctly it underflowed. The right one:

void fuse(int *o,int *p){
  if (*o > 11){
    *o = 0;}
  if (*o < 0){
    *o = 0;}
  if (*p < 0){
    *p = 0;}
  if (*p > 7){
    *p = 0;}
}