Ucglib: Color OLED and TFT Library...

Hi

Since some years i am working on monochrome graphics libraries for the Arduino world (dogm128 lib, U8glib). I got a lot of requests to add support for true color displays to U8glib, however U8glib has been optimized for monochrome graphics and does not really allow true color displays. So i finally ended up in creating a new library (mostly based on the algorithms and concepts of U8glib): Ucglib. I added support for some of my color displays and optimized everything for color displays.

A first beta release is attached here. It supports 18 bit true color for SSD1351, ILI9324 and ILI9341 controllers. Reference manual is here: GitHub - olikraus/ucglib: Arduino True Color Library for TFTs and OLEDs
.

The video below shows the library running on a classical Arduino Uno:

Please let me know what you think and into which direction the library should be developed.

Thanks,
Oliver

Edit: Link update to new project location: GitHub - olikraus/ucglib: Arduino True Color Library for TFTs and OLEDs

ucglib_arduino_v0.01.zip (695 KB)

So, I think I am the first one who is trying to use your library. The code seems ok, but despide the provided examples, there is one thing that is missing (or for me is confusing):

I am trying to use ILI3925C with the SPI interface. I discovered in the examples this constructor:

Ucglib8BitPortD ucg(ucg_dev_ili9325_18x240x320_itdb02, ucg_ext_ili9325_18, /* wr= / 18 , / cd= / 19 , / cs= / 17, / reset= */ 16 );

The SPI ports are CLK, MISO, MOSI. The WR and CD are port names used in the paralel interface (which is not the case).

Maybe this is the first thing that it should be clear.

Btw, Congrats! I don;t know if is it working, but before finding your library, it was a pain in the ass :slight_smile:

Regarding the UTFT support: there is support for that chip but on paralell interface.

Thanks a lot for your reply.

So, I think I am the first one who is trying to use your library. The code seems ok, but despide the provided examples, there is one thing that is missing (or for me is confusing):

There are already some good libs. So maybe my lib is not required...

Ucglib8BitPortD ucg(ucg_dev_ili9325_18x240x320_itdb02, ucg_ext_ili9325_18, /* wr= / 18 , / cd= / 19 , / cs= / 17, / reset= */ 16 );

I have only a ILI9325 display with parallel interface, so i did not test the SPI interface, but it should look like this:

Ucglib4WireSWSPI ucg(ucg_dev_ili9325_18x240x320_itdb02, ucg_ext_ili9325_18, /*scl=*/ 76, /*sda=*/ 75, /*cd=*/ 9 , /*cs=*/ 10, /*reset=*/ 8);

Of course you need to update the pin numbers. You might also consider to use Ucglib4WireHWSPI(). Basically you could combine the ucg_dev_XXX with any of the Ucglib constructors. But i did not test all combination (due to missing hardware).

Oliver

SO, I start digging int your library ....
I am trying to use the Ucglib4WireHWSPI(ucg_dev_fnptr dev, ucg_dev_fnptr ext, uint8_t cd, uint8_t cs = UCG_PIN_VAL_NONE, uint8_t reset = UCG_PIN_VAL_NONE)

I don;t get what's CD, and I think it's a copy paste from the paralel port. I saw that you are using here that value:

case UCG_COM_MSG_SEND_CD_DATA_SEQUENCE:
while(arg > 0)
{
if ( *data != 0 )
{
if ( *data == 1 )
{
digitalWrite(ucg->pin_list[UCG_PIN_CD], 0);
}
else
{
digitalWrite(ucg->pin_list[UCG_PIN_CD], 1);
}

Also the CS i think it's the Chip Select, which can be already know (eliminate from the signature).

If the CD pin is still available, could you please show me where that pin must be connected ?

This is the only library that I could find for SPi displays. Do you know other one ?

The CD (=command / data selection) pin is required. However it has a lot of different names. In your case this is called RS (register select pin). Well, of course this should be part of the upcoming documentation for this lib.

If it is still failing to work, you could also send a picture of your setup, Arduino+TFT board including the constructor call.

This is the only library that I could find for SPi displays. Do you know other one ?

Unfortunately not.

BTW: I ordered exactly the same display module some days back, but exected shipping time will be several weeks :frowning:

Oliver

@tilutza:

The site you linked to, also offers the datasheet of the chip used.
Things like this are explained in there, so i suggest you read that one.
You will understand your display better after reading this.

I've already looked into that document. After I was reading that, I concluded that the Arduino is too slow to work with that device on the SPI port.
In the provided example of the device (on the website manufacturer) they used 24Mhz much more than Arduino can have.
However, I connected the display using this configuration:

CS -> pin10
SCK -> pin13
SDI -> pin11
SDO -> pin12
RS -> pin5
RESET -> pin6

Defined the class:

const uint8_t LCD_CD_RS = DD5;
const uint8_t LCD_RESET = DD6;
const uint8_t LCD_CS = 10;
Ucglib4WireHWSPI tft(ucg_dev_ili9325_18x240x320_itdb02, ucg_ext_ili9325_18,
LCD_CD_RS /CD=/,
LCD_CS /CS/,
LCD_RESET /RESET/);

in the setup() i called tft.setup, and in the loop i just write some simple code:

tft.setFont(ucg_font_ncenR14r);
tft.setColor(0x22, 0x33, 0x66);
tft.println("Hello");
tft.println("World");

I had a surprise, to see that the device is not working. However, I will still investigate the SPI Mode, which from their example seems to be 3 and not 2.

I will post here my progress

Hi

I have some bad news here. I checked the datasheet of the ILI9325. It does not have a 4 wire interface (clock, data, register select, chip select) but instead it has a 3 wire interface (clock, data, chip select). The register select is part of the low level protocol. The 3 wire interface is not yet implemented for Ucglib, but i have ordered the same display, and i try to add this interface as soon as the display has reached my house.

I am sorry for assuming that this display has a 4-wire interface. I should have read the datasheet more carefully. After reading the datasheet i also understand why there is no other library available. The low level protocol is very special.

Oliver

With the RST and RESET pin changed, I can confirm that the schetch from http://src-one.com/dev/ili9320_test.ino is working so ...

I will see how this could be adapted to your library :wink:

I am using an ATmega 1284P and “Mighty 1284P 8MHz” option to compile, Arduino 1.05

I used the “hello World!” example (attached) with this set:

#include <SPI.h>
#include “Ucglib.h”

Ucglib4WireHWSPI ucg(ucg_dev_ssd1351_18x128x128_ilsoft, ucg_ext_ssd1351_18, /cd=/ 21 , /cs=/ 22, /reset=/ 23); /* Display connected to HW SPI, use SPI Library */

But I get an “Compile error”

In file included from C:\Users\James\arduino-1.0.5\libraries\Ucglib/Ucglib.h:61,
from HelloWorld.ino:39:
C:\Users\James\arduino-1.0.5\libraries\Ucglib/utility/ucg.h:89: error: section attribute not allowed for ‘ucg_pgm_uint8_t’

Please advice on what I can do to fix it?

/*

  HelloWorld.ino
  
  A very simple example for Ucglib
 
*/

#include <SPI.h>
#include "Ucglib.h"

Ucglib4WireHWSPI ucg(ucg_dev_ssd1351_18x128x128_ilsoft, ucg_ext_ssd1351_18, /*cd=*/ 21 , /*cs=*/ 22, /*reset=*/ 23);			/* Display connected to HW SPI, use SPI Library */

void setup(void)
{
  delay(1000);
  ucg.begin();
  ucg.clearScreen();
}

void loop(void)
{
  ucg.setFont(ucg_font_ncenR14r);
  ucg.setPrintPos(0,25);
  ucg.setColor(255, 255, 255);
  ucg.print("Hello World!");
  delay(500);  
}

Hi

Please check, if this problem also appears with version 0.02 (attached).

ucglib_arduino_v0.02.zip (827 KB)

Yes, same problem compile error

But I did use the FreeTronics 20MHz 1284P “Goldilocks”
This did work…But at 20MHz

So if some one can advice on how to change the clock speed (firmware) I think “board.txt” in hardware, but not sure
Then that might solve my problem

Thanks

I do not think that this is related to the clock speed. It is probably a PROGMEM issue. Is it possible to reproduce this with the standard installation of the Arduino IDE?

Oliver

Hi
Have not seen a standard Arduino of the ATmega1284P except "Goldilocks"...
Would it be due to "pin outs" of the Mighty 1284P being different?

I have tried all the version of CPU's in "boards" but all compile.

As the Goldilocks version is working, I will see if I can change the clock speed in the "board.txt" and see what happens.
If you get any other insight into the issue, please let me know

Thanks
James

Great work, Oliver!

I'm using your Arduino library on an SPI Adafruit TFT Touch Shield (ILI9341) and it's fast and works well.

I'm wondering if there is any hope of support for Ucglib devices in m2tklib, or if you might be able to give me some advice on hacking in such support. (I've just started looking through m2tklib and so far don't understand how graphics primitives are sent to the screen libraries... I'm new to this!)

Alternately, if I could get my SPI ILI9341 device running under U8glib, that would be just as good for my project, but I do like the extra color support and speed of the Ucglib libraries.

Thanks

Yes, i plan to add support for Ucglib in M2tklib, however i did not find time to do so.

In prinziple, you need to write a graphics procedure, like for example this: http://code.google.com/p/m2tklib/source/browse/dev/glcd/m2ghglcdffs.cpp

From a long term perspective, I will probably remove color support in U8glib. U8glib is optimized for monochrome devices and the software architecture of U8glib does not support color devices very well.

Oliver

OK, good to know. There seems to be a void right now in this area. I've been beating my head against the desk all night trying to get any of the Arduino GUI toolkits to work with this display. :roll_eyes: Quite frustrating. I should qualify all this by saying that I am a database "programmer" :wink: with minimal C++ experience.

I'm currently back to uCglib, and starting to write my own button functions etc.; I'll have to handle touch screen functions myself as well, I guess. It looks like every time somebody else runs into unsupported hardware in the existing libraries, we wind up with another GUI toolkit. Cool, but inefficient, and leads to most of them being incomplete and/or abandoned; it's vaguely reminiscent of 1988.

Your libraries seem like the strongest candidates for canonicity, although I am surprised to see different invocations even for string and shape drawing primitives between u8glib and uCglib, which surprised me considering these primitives don't even embed a color descriptor. I would think code portability between libraries would be a virtue to aspire to, as projects would not then have to be entirely rewritten when switching displays. (Maybe the community could get behind a generic abstract 'display' class supported by a standard basic dictionary of functions in multiple graphics libraries?)

Pontificating aside -- Is there a way for the user to easily access the GetStrSize, GetStrMinBox, or GetStrWidth functions in ucg_font.c? If we could supply a font and string and get a minimal bounding box returned, we could more easily generate a rect frame to serve as a button. Right now I have a padding value subtracted to and added to a manually entered font size for bounding box height, and the same padding combined with a scaling percentage to roughly generate bounding box length, but it's ugly.. so ugly...

Let me start to answer your question on the last section: The calculation of a frame around a string is discussed here for U8glib: http://code.google.com/p/u8glib/wiki/tstring. It should be the same for Ucglib, although function names might differ a little bit.

I agree to your other statements. But i would call it an impossible task to create a generic open source graphics library. As an open source project, there is no budget to buy all the different hardware. I had some fun to buy new displays and spent time to make it work with U8glib, but my resources are limited. Same applies to Ucglib also. I rewrote Ucglib based on the sources of U8glib, but i also tried to improve the architecture and the commands. So some differences are there.
U8lib is optimized for monochrome displays.
Ucglib is optimized for true color displays.

M2tklib is even more complicated. I tried to make it as portable as possible, but i also see some limitations meanwhile.

Oliver

olikraus:
Let me start to answer your question on the last section: The calculation of a frame around a string is discussed here for U8glib: Google Code Archive - Long-term storage for Google Code Project Hosting.. It should be the same for Ucglib, although function names might differ a little bit.

So how would this be invoked in a uCglib sketch? Can I somehow send a string to a ucg object, after passing it setFont(), and get its size back? Again, I'm not well-versed with object-oriented functions, variable scope, etc., and everything I've tried just gives various errors. I don't see any functions in uCglib exposing font or string metrics except getFontAscent() and getFontDescent().

olikraus:
I agree to your other statements. But i would call it an impossible task to create a generic open source graphics library. As an open source project, there is no budget to buy all the different hardware.

What about an abstraction class, providing a standard graphics primitive and geometry query vocabulary which can then be parsed into calls to hardware-optimized libraries, thereby reusing the hardware driver work you've already done? So, rather than invoking u8glib or uCglib directly, we'd pass the hardware library of choice to a generic Display class, something like this:

Display display(uCglib, ili9341, hwspi, 240, 320, 18, 9, 10, 8);
// Display anyDisplay(hardwareLibrary, hardwareChipset, hardwareInterface, displayHeight, displayWidth, displayBitDepth, cdPin, csPin, rsPin);

void setup(void) {
    display.begin();
    int lcdWidth = display.getWidth():
    int lcdHeight = display.getHeight();
    int padding = 8;
    display.clearScreen();
    drawWindow();
}

void loop (void) {
}

void drawWindow(void) {
    display.setColor(0,255,255,255);
    display.drawRect(padding, padding, lcdWidth-padding, lcdHeight-padding);  
}

For that matter, why not then let the Display class pick which hardware library to use, based on the chipset definition? Can the Arduino IDE handle conditional includes properly yet?

Basic bitmap primitives should be the same across every display other than character LCDs, shouldn't they? I would also think that character devices have less in common at an abstract level than pixel devices, so it makes more sense from a user perspective to group all pixel devices into a single abstract class, excepting character devices. And the Display class could allow unsupported calls to fail gracefully by, for instance, thresholding RGB values for 1-bit displays, etc...

Any reason this wouldn't make sense?

Thank you again, by the way, for the mind-blowing amount of work you've put into all these libraries. I'm so impressed. I just wish I could figure out how to get u8glib to work on my TFT for the moment, until M2Tklib supported full-color devices...!

  1. Frame around string:
    You are a right, the "getStrWidth()" function is missing, correct?
    As a workaround use:
    ucg_GetStrWidth(ucg.getUcg(), const char *s);

  2. Abstract class
    This is already implemented for Ucglib and U8glib, although it is not done in C++. I started to document this interface here: Google Code Archive - Long-term storage for Google Code Project Hosting.

Oliver

Edit: I have created issue 20 for the missing getStrWidth function. Thanks for this.