Author Topic: Graphics Libraries for MCUs (target: dsPIC/PIC32), what are the options?  (Read 5568 times)

0 Members and 1 Guest are viewing this topic.

Online JPorticiTopic starter

  • Super Contributor
  • ***
  • Posts: 3527
  • Country: it
Some time ago i got a couple of those cheap ILI9341 based TFTs. I was never able to get them to work but in the last couple of days (National Holiday :D) i decided to sit down until i figured it out.

And i did! (it wasn't really clear to me that the thing interfaced at 3.3V even if it said 5V compatible)
Anyway, i can initialize the display, draw lines and rectangles... Actually i just ported the adafruit library

Now i see that things are going to become really complicated very soon so the smart thing should be to start looking into a ready made library. What are my options?

For now my requirements are
- Don't care for colors, i am okay with black/white.. so i can just operate on a monochrome framebuffer, write an intermediate function that converts a chunk of the buffer into 16bit colors and send it, repeat with next portion
- I want custom fonts.
- I don't think i want to have support for touchscreen
- I don't have enough memory to keep the entire framebuffer in ram, unless it's monochrome

I know that microchip has two libraries, one in the MLA and the other in Harmony, i have started reading some literature (AN1182) but it seems really complicated, tutorials are scarce and i wonder if i should go on or look for alternatives..
 

Offline @rt

  • Super Contributor
  • ***
  • Posts: 1071
Here’s an option. Planning to upload to SourceForge later tonight once documentation is done.
Monochrome 1k framebuffer. Without any other image buffers, certain functions won’t work, such as patterns for flood fill.

The drawscreen() function would need replacing of course. My hardware uses a shift register for the 8 bit data bus,
and you might want to pass x,y coords as arguments, but for me that wasn’t conducive to easily port to other languages.


Code: [Select]
// clear the frame buffer and both image buffers
void clrgraphics();
// clear the graphics frame buffer
void clrframebuffer();
// clear second image buffer
void clrimagebufferb();
// set pixel at screen coordinates to black
void setpixel();
// clear pixel at screen coordinates
void clearpixel();
// set pixel at image coordinates to black
void setpixelimage();
// clear pixel at image coordinates
void clearpixelimage();
// toggle pixel value at screen coordinates
void flippixel();
// get pixel value at screen coordinates
int getpixel();
// get pixel value at image coordinates
int getpixelimage();
// sets pixel every second time the function is called
void togpixel();
// sets image pixel every second time the function is called
void togpixelimage();
// rotate screen coordinates at an angle
void pixelrotation();
// rotate multiple screen coordinates at the same angle
// after calling pixelrotation function once
void multiplerotation();
// draw a line between a pair of coordinates
void drawline (int bx1,int by1,int bx2,int by2);
// draw solid or dotted line between a pair of image coordinates
void drawlineimage (int bx1,int by1,int bx2,int by2,int dot);
// draw circle of radius, centered at input coordinates
void drawcircle();
// draw filled circle of radius, centered at input coordinates
void drawfilledcircle(int quality);
// draw small text in text buffer at screen coordinates
void drawtext();
// draw small text in text buffer to image buffer
void drawtextimage();
// draw small clear text in text buffer to image buffer
void drawtextimageclear();
// draw small text rotated at angle to image buffer
void drawtextimagerotated();
// draw large text in text buffer at screen coordinates
void drawtextlarge();
// draw large animated sin wave text to frame buffer
void drawtextlargesin();
// draw large sin text masked with existing graphics
void drawtextlargesinmasked();
// draw small horizontally centered string in text buffer
void drawtextcentered();
// draw variable width horizontally centered text string
void drawtextvarwidthcentered();
// draw variable width text string centered at input position
void drawtextvarwidthcenteredpos(int center);
// measure variable length text string in text buffer
int measuretextvarwidth();
// draw variable length text in buffer to framebuffer
void drawtextvarwidth();
// draw variable length text in buffer to image buffer
void drawtextvarwidthimage();
// draw tall variable length text in buffer to frame buffer
void drawtextvarwidthtall();
// draw grey text in text buffer at screen coordinates
void drawtextgrey();
// draw large numeric digit in text buffer at screen coordinates
void drawtextbolddigit();
// private function for the sine text functions
void drawsinprivate();
// read characters from an image buffer into text string
int readtextimage(int dmode);
// draw amiga style mouse pointer at screen coordinates
void drawpointerautoflip();
// draw rectangle with rounded corners of length and width at coordinates
// the rectangle should be at least 11 pixels long and 11 pixels wide
void drawroundedrectangle(int posx, int posy, int lenx, int leny);
// draw hollow rectangle using four lines
void drawrectangle (int posx, int posy, int lenx, int leny);
// draw rectangle outline filled clear
void drawrectanglefilledclear (int posx, int posy, int lenx, int leny);
// fill enclosed area of clear pixels in image
void floodfill(int ffx, int ffy, int pattern);
// refresh the display by drawing frame buffer to display
void drawscreen();
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 15413
  • Country: fr
 

Offline asgard20032

  • Regular Contributor
  • *
  • Posts: 184
Its been a problem that was resolved many decade ago on old console ; driving a certain resolution where there is not enough ram to contain the whole framebuffer. Three solution ; vectorial graphic (generate graphic as needed), lower the resolution by a certain factor (eache pixel then are grouped by 4 to form one big pixel if you divide by 2 the vertical and horizontal resolution) and my favorite solution, a tile engine ; you separate the screen in a gride and you create aome reusable tile / sprite ; one for each character (thus creating a font) and you can even have image that you just split in multiple square. Each of these technic may save enough ram to even have full color.
 

Online JPorticiTopic starter

  • Super Contributor
  • ***
  • Posts: 3527
  • Country: it
in the meantime i went on porting the adafruit library to dsPIC... it's still a good learning experience :) i have yet to do fonts though..

This guy developed something that looks great: LittlevGL

see: https://www.eevblog.com/forum/microcontrollers/embedded-graphics-lcd/msg1388961/#msg1388961


I saw it and it looks promising, however the biggest PIC in DIP package i have at home is a dsPIC30F4013 (2kB ram) and LVGL wants at least 2k, i couldn't make it compile.

For this project i'm going to use a PIC32MX270F512L (64kB) which will also use the parallel port instead of SPI for the display.
After i draw, get and assemble the board i will write the LCD initialization and control routines.
Then i will try LVGL and also the Harmony Graphics Library... If i find out if it's possible to use it with a monochrome display (I want to use a TFT because it's many times cheaper than a white-on-black TFT or OLED of that size but i don't care for colours)
 

Offline @rt

  • Super Contributor
  • ***
  • Posts: 1071
I posted a link in open source forum you’re welcome to check out,
but what do you mean by customisable fonts?
How could fonts in a micro source not be?
 

Offline MarkF

  • Super Contributor
  • ***
  • Posts: 2671
  • Country: us
I wrote a library (actually 2 headers and a C file) for Adafruit's SSD1351 OLED breakout boards.  I started with the Adafruit library and an OpenGL library I wrote for Windows and Linux computers.  But, they were far too large to fit a PIC18F2550 MCU that I was using.  Also, the Adafruit library was VERY messy and convoluted.

The SSD1351 does NOT use MCU memory.  It has it's own video memory on-board.

If you're interested and it can help you develop you library, you're welcome to it.
Here are the functions in the library:

Code: [Select]
// SSD1351 Prototypes

void oledCmd(uint8_t cmd);
void oledDat(uint8_t dat);
void oledSetup(void);

bp_t ORGB(uint8_t r, uint8_t g, uint8_t b);

void oledClear(void);
void oledPixel(int x, int y, bp_t color);
void oledHorzLine(int x, int y, int w, bp_t color);
void oledVertLine(int x, int y, int h, bp_t color);
void oledRectFill(int x, int y, int w, int h, bp_t color);
void drawLine(int x0, int y0, int x1, int y1, bp_t color);
void drawRectangle(int x0, int y0, int w, int h, bp_t color);
void drawCircle(int xm, int ym, int r, bp_t color);
void drawEllipse(int xm, int ym, int a, int b, bp_t color);
void fillCircle(int xm, int ym, int r, bp_t color);
void fillEllipse(int xm, int ym, int a, int b, bp_t color);
void drawTxt(int x0, int y0, uint8_t size, bp_t color, char *str);
 

Online JPorticiTopic starter

  • Super Contributor
  • ***
  • Posts: 3527
  • Country: it
i am not responding to all but i am not ignoring anything :)

I wrote a library (actually 2 headers and a C file) for Adafruit's SSD1351 OLED breakout boards.  I started with the Adafruit library and an OpenGL library I wrote for Windows and Linux computers.  But, they were far too large to fit a PIC18F2550 MCU that I was using.  Also, the Adafruit library was VERY messy and convoluted.

The SSD1351 does NOT use MCU memory.  It has it's own video memory on-board.

If you're interested and it can help you develop you library, you're welcome to it.
Here are the functions in the library:

Code: [Select]
// SSD1351 Prototypes

void oledCmd(uint8_t cmd);
void oledDat(uint8_t dat);
void oledSetup(void);

bp_t ORGB(uint8_t r, uint8_t g, uint8_t b);

void oledClear(void);
void oledPixel(int x, int y, bp_t color);
void oledHorzLine(int x, int y, int w, bp_t color);
void oledVertLine(int x, int y, int h, bp_t color);
void oledRectFill(int x, int y, int w, int h, bp_t color);
void drawLine(int x0, int y0, int x1, int y1, bp_t color);
void drawRectangle(int x0, int y0, int w, int h, bp_t color);
void drawCircle(int xm, int ym, int r, bp_t color);
void drawEllipse(int xm, int ym, int a, int b, bp_t color);
void fillCircle(int xm, int ym, int r, bp_t color);
void fillEllipse(int xm, int ym, int a, int b, bp_t color);
void drawTxt(int x0, int y0, uint8_t size, bp_t color, char *str);

right now i am at this point, minus the draw text.. things have been a mess last few days and i have not had a single moment of peace where i can just sit down and write code for fun..
 

Online JPorticiTopic starter

  • Super Contributor
  • ***
  • Posts: 3527
  • Country: it
Shit gets fun sometimes :D

 

Online JPorticiTopic starter

  • Super Contributor
  • ***
  • Posts: 3527
  • Country: it
And now custom fonts.

« Last Edit: May 05, 2018, 04:31:41 pm by JPortici »
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 15413
  • Country: fr
Looks like it's moving forward! :-+
 

Online JPorticiTopic starter

  • Super Contributor
  • ***
  • Posts: 3527
  • Country: it
yes :) a very satisfying feeling
 
The following users thanked this post: Howardlong

Offline Howardlong

  • Super Contributor
  • ***
  • Posts: 5410
  • Country: gb
yes :) a very satisfying feeling

Which way did you go in the end? It’s been about three years since I last delved into embedded graphics libraries on PICs, it was the wild west back then.

Edit: on second thoughts that’s not quite true, I’ve twice ported the Adafruit linraries to small PIC24 devices in the past couple of years, but the interfaces were mainly for diagnostics, not for the end user.
« Last Edit: May 05, 2018, 08:52:40 pm by Howardlong »
 

Online JPorticiTopic starter

  • Super Contributor
  • ***
  • Posts: 3527
  • Country: it
neither, i just wanted to finish porting the text routine so that i can have a library ready to put aside.

Then i dicked around with interface mockups for like 5 minutes, spent hours looking for button caps and knobs and lightpipes and the saturday evening called
 

Offline dmills

  • Super Contributor
  • ***
  • Posts: 2093
  • Country: gb
I managed a full colour graphics setup with 8 colour overlays on a PIC32 using some 57k or so of the ram, and lots of bit fiddling, it does not store a frame buffer, instead storing a set of 3 bit values corresponding to the overlays (There are two layers of these), packed as densely as possible into the memory .

It is in products for work so I cannot publish the code (Which in any case tends to be rather application specific and somewhat tuned for particular applications), but here are a couple of cut sheets for products using it:

https://tslproducts.com/media/1861/data-sheet-template_mpa1-solo-sdi.pdf
http://www.soundfield.com/products/dsfbmk2

The graphics and text rendering core took maybe a week to write.

I commend Breshenans line and circle drawing algorithms together with a reading of Glassners excellent "Graphics gems" series of books for all sorts of fun ideas in CPU based graphics (More modern books tend to assume you can just throw commands at GL or Direct X). Some of the really old X11 books are also surprisingly useful for details of how to do filled lines with various end styles.

Regards, Dan.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf