Idea for font anti-aliasing on displays

Post your requests and ideas on the future development of Visual TFT Software.
Post Reply
Author
Message
peini
Posts: 46
Joined: 28 Dec 2011 09:56

Idea for font anti-aliasing on displays

#1 Post by peini » 22 Feb 2015 11:21

I have an idea for font anti-aliasing on displays and want to know whether you think this would be possible or not.
At the moment if i use a windows font in VisualTFT the font will be exported as an array that contains the pixels of each character.
Would it be possible, that VisualTFT generates more than one fonts and each font contains other subpixels of the same font.
I mean that one font-array just contains the main pixels of the characters like at the moment.
And then there are two or three other fonts that just contains the surrounding pixels of the characters.

For a black anti-aliased text on the display i would then do the following:
1) Select a light gray font color and the first font and draw my text.
2) Select a darker gray font color and the second font and draw the same text at the same location.
3) Select the black color and third font and draw the text at the same location.

It's just an idea, but i think this would draw a nicely anti-aliased text.
Do you think this would be possible?

Thx.

User avatar
petar.timotijevic
mikroElektronika team
Posts: 1739
Joined: 19 Feb 2014 13:46
Location: Serbia
Contact:

Re: Idea for font anti-aliasing on displays

#2 Post by petar.timotijevic » 23 Feb 2015 17:45

Hi Peini,

You can make experiments with examples and you can attach results here in forum.


Best regards,
Peter

peini
Posts: 46
Joined: 28 Dec 2011 09:56

Re: Idea for font anti-aliasing on displays

#3 Post by peini » 09 Apr 2015 09:59

In the meantime i found something that works better than my idea.
It's called "BitPack Library" and can be found on libstock.
http://www.libstock.com/projects/view/7 ... nt-library

This library can draw antialiased texts by reading back from the graphics RAM.
I've tested it successfully on my old mikromedia for PIC32 board.

No i'am trying to get it to work with my EasyPIC Fusion v7 and the EasyTFT in 8bit mode.
Problem is that the library at the moment only supports the HX... controller so i have to write my own GetPixel-method for the ILI9341.

I'am using the TFT example that ships with the compiler and changed everything so that it's now using the PMP.
This is already working correctly.
Then i've written a Read_Data() function that looks like this:

Code: Select all

unsigned int Read_Data ( void )
{
   unsigned int _data = 0;
   TFT_RS = 1;
   _data = PMDIN << 8;
   PMPWaitBusy();
   _data |= PMDIN;
   PMPWaitBusy();
   return _data;
}
and the GetPixel function looks like this:

Code: Select all

unsigned int ILI9341_GetPixel( unsigned int x, unsigned int y )
{
  //return 65535; // Just for testing

  volatile unsigned int color = 0;

  TFT_CS = 0;
  //SetRegion( x, y );
  TFT_Set_Address_ILI9340( x, y );

  Set_Index( 0x2E ); // ILI9341_CMD_MEMORY_READ
  color = Read_Data(); // Dummy read (see datasheet: http://www.newhavendisplay.com/app_notes/ILI9341.pdf )
  
  color = Read_Data(); // Should return 65535 on white background
  
  TFT_CS = 1;
  return color;
}
But the color returend by GetPixel is allways 252, but should be 65535, because i have a white background.
I've attached my sample code. Does anyone has an idea what i'am doing wrong here?

To test the code you will need to install the BitPack library from the link above.
Thx.

Daniel
Attachments
TFT.zip
(373.72 KiB) Downloaded 379 times

peini
Posts: 46
Joined: 28 Dec 2011 09:56

Re: Idea for font anti-aliasing on displays

#4 Post by peini » 10 Apr 2015 13:01

After testing a lot i've got the solution.
Instead of reading two dummy bytes (1 16bit Dummy word) i have to read 3 dummy bytes.
And then i have to read 1 byte per color instead of 2 bytes for the 16bit 5:6:5 color.

I think the datasheet isn't correct here (Memory Read (2Eh)). Also the Arrow-symbol (rising edge) in the WRX-column is wrong. Should be an arrow in the RDX-column because we're reading.

This are the corrected functions:

Code: Select all

unsigned int Read_Data ( void )
{
   unsigned char _data = 0;
   TFT_RS = 1;
   _data = PMDIN;
   PMPWaitBusy();
   return _data;
}

unsigned int ILI9341_GetPixel( unsigned int x, unsigned int y )
{
  volatile unsigned int color = 0;

  //return 65535; // Just for testing

  TFT_CS = 0;
  //SetRegion( x, y );
  TFT_Set_Address_ILI9340( x, y );

  Set_Index( 0x2E ); // ILI9341_CMD_MEMORY_READ
  Read_Data(); // Dummy read (see datasheet: http://www.newhavendisplay.com/app_notes/ILI9341.pdf )
  Read_Data();
  Read_Data();
  
  color = ( Read_Data() & 0xF8 ) << 8;
  color |= ( Read_Data() & 0xFC ) << 3;
  color |= Read_Data() >> 3;
  
  TFT_CS = 1;
  return color;
}

vt23
Posts: 44
Joined: 17 Jun 2014 10:36

Re: Idea for font anti-aliasing on displays

#5 Post by vt23 » 17 Apr 2015 09:42

Hi peini,

you've opened very good and useful topic. Your first idea:
For a black anti-aliased text on the display i would then do the following:
1) Select a light gray font color and the first font and draw my text.
2) Select a darker gray font color and the second font and draw the same text at the same location.
3) Select the black color and third font and draw the text at the same location.
would be nice but I found it very complicated, time consuming (of mine and of processor) and you can't set the size of font spaces (in a String), nad so on.
I also thought about the anti-aliasing - for mixing it with background color we need to read the colour data from display controller.
Then I found your posts. I've tried to implement the reading pixel too. Nevetheless I spent many many hours with rearranging your useful code and the reading is still bad.
I tested that at least 2 dummy reads are needed (first it reads the last command: 0x2E) and second is 0x0000 (in 16 bit mode). There is lack of information in the datasheet ILI9341. I don't know how it reads data especially in 16bit MCU mode compared to 8bit. I hope it sends valid 16 bits in one Read_Data() but I'm not sure if it reads all colours (5:6:5) because it read bad data as I wrote above.

I should mention I use PIC32MX460F512L and 3.2" display (with RTP) with ILI9341 controller. I use PMP 16bit interface in PIC32 (PMMODEbits.MODE16 = 1) and IM[3:0]=1000= 8080 MCU 16-bit bus interface II in ILI9341. I use my own PCB based on Mikromedia for PIC32 originally.
My code:

Code: Select all

unsigned int Read_Data ( void )
{
   volatile unsigned int _data = 0;
   TFT_RS = 1;
   //TFT_RD = 0; // start of Read_Strobe
   // asm nop;
   _data = PMDIN;
   PMPWaitBusy();
   //TFT_RD = 1; // end of Read_Strobe
   return _data;
}

void Write_Command( unsigned short cmd ) {
  TFT_RS = 1;
  PMDIN = cmd;
  PMPWaitBusy();
  //TFT_WR = 0;  asm nop; TFT_WR = 1;  // I didn't find any influence of this TFT_Write_Strobe()
}

unsigned int GetPx_ILI9341_16b( unsigned int x, unsigned int y )
{
  volatile unsigned int color = 0;

  TFT_CS = 0;
  
  // Writing part - only for testing
  /*TFT_Set_Address_ILI9340( x-1, y+2 );
  TFT_RS = 1;
  PMDIN = 0x00FF;
  PMPWaitBusy();
  PMDIN = 0x0;
  PMPWaitBusy();
  PMDIN = 0xF800;
  PMPWaitBusy(); 
  */
  
  //TFT_Set_Address_ILI9340( x, y );  //same commands as for ILI9341
                                                       //it uses TFT_Write_Strobe(), I don't know it is needed
                                                       //but TFT_Set_Index_Ptr(0x2C); =writing command is at the end
  Set_Index(0x2A);
  Write_Command(x>>8);
  Write_Command(x);
  Set_Index(0x2B);
  Write_Command(y>>8);
  Write_Command(y);

  Set_Index( 0x2E ); // ILI9341_CMD_MEMORY_READ

  Read_Data(); // Dummy read
  Read_Data();
  Read_Data(); // maybe

  color = Read_Data(); // should contain one pixel 16bit (5:6:5) colour I think
  
  /* peini's 8bit reading
  color = ( Read_Data() & 0xF8 ) << 8;
  color |= ( Read_Data() & 0xFC ) << 3;
  color |= Read_Data() >> 3;
  */
  
  TFT_CS = 1;
  return color;
}
Important note: It reads different data (but also not right) if I set PMMODEbits.WAITM = 2 instead of 1. WAITB and WAITE don't have any influence probably (default is 0 in both).
"Writing part - only for testing" - It can write 3 pixels on the display (on x-1, y+2 position) perfectly

In ...events_code.c file I have this

Code: Select all

void SetColorBtnStr(unsigned int x, unsigned int y)
{
     char *colorStr[7];
     unsigned int color16b;
     color16b = GetPx_ILI9341_16b(x, y);

     color16b = GetPx_ILI9341_16b(x, y);
     WordToHex(color16b, colorStr);
     strcpy(BtnCol1Scr4_Caption, colorStr);
     strcpy(colorStr, "      ");
     DrawButton(&BtnCol1Scr4);
//...
}
//Event handler
void BtnColScr4OnCl() {
     SetColorBtnStr(3,3);   // here (3,3) is background colour only
}
I have set background color (of 4th screen) to SettCalib_4.Color = 0x3172;
Unfortunately it reads hexadecimal number:
1. 0000 with 1 preceding dummy Read_Data() after Set_Index( 0x2E )
2. 302C with 2 preceding dummy Read_Data()
3. 9430 with 3 preceding dummy Read_Data()
4. 2C94 with 4 preceding dummy Read_Data()
5. 302C with 5 preceding dummy Read_Data()
...
and put it to the button BtnCol1Scr4.Caption (can be seen from code above). You can see the read values are bad.
Digits 3 in background colour code and read data relate to each other somehow maybe. It is strange for me.

Regards

Vitek

vt23
Posts: 44
Joined: 17 Jun 2014 10:36

Re: Idea for font anti-aliasing on displays

#6 Post by vt23 » 17 Apr 2015 14:06

Hi all,
I finally got it! :idea: :)
I will post it later with explanation.

Regards
Vitek

peini
Posts: 46
Joined: 28 Dec 2011 09:56

Re: Idea for font anti-aliasing on displays

#7 Post by peini » 17 Apr 2015 16:47

Great news :)
I know this, its allways the same. You try and try and then you'll find the answer by yourself :)

But one other thing:
I have attached a patched file for the BitPack library which i've got from the author directly
because the TFT_BP_Write_Text function wasn't correct. It doesn't work with anti-aliased fonts but with this patch it works.
I've already told him that it works now but i think he hasn't updated the version on libstock at the moment.
So just overwrite your local emcl file after you have installed the BitPack library.
Attachments
__Lib_BitPack_TFT.zip
(5.33 KiB) Downloaded 278 times

vt23
Posts: 44
Joined: 17 Jun 2014 10:36

Re: Idea for font anti-aliasing on displays

#8 Post by vt23 » 20 Apr 2015 09:50

Hello,

I finally found out how the reading of a pixel coulour from ILI9341 is processed. In 16bit mode it is slightly different from peini's 8bit mode, but so little, I don't know why I didn't figure it out sooner.
First: Main cause of the bad read values was default setting of the middle wait state of the PMP. Default is PMMODEbits.WAITM = 1 (in Init_MCU() function).
We need to set PMMODEbits.WAITM = 2 to be able to start decode a loaded value (colour). (WAITM = 2 means 3 peripheral bus clock cycles of the processor. It should represent "Data Read/Write Strobe Wait States"). Maybe this PMP wait states can replace the strobe - TFT_WR = 0; asm nop; TFT_WR = 1 - which is used in __Lib_TFT_Defs.c. Also you can see a strobe TFT_RD = 0; asm nop; TFT_RD = 1 process at the page 32 of the datasheet. Can somebody explain it right? Why my "read" and "write" works without the strobe?
After I discovered the influence of the WAITM I found this topic (for different controller) and it quite helped me: https://www.mikroe.com/forum/viewtopic. ... 65&t=29223
Then I checked the value loaded (read) to PMDIN is presented in the format word1:(RRRRRRxxGGGGGGxx), word2:(BBBBBBxxRRRRRRxx), ... which I didn't find in the datasheet :!: . It means 262144 colours (in 3 bytes) and the format can't be changed, I think. But for writing we usually use format 5:6:5 (in 2 bytes) which means 65536 colours and the format can be changed optionally.
Here is my code for 16 bit reading (in ..._driver.c file):

Code: Select all

unsigned int Read_Data ( void )
{
   volatile unsigned int _data = 0;
   TFT_RS = 1;
   _data = PMDIN;
   PMPWaitBusy();
   return _data;
}


void Write_Command( unsigned short cmd ) {
  TFT_RS = 1;
  PMDIN = cmd;
  PMPWaitBusy();
}

unsigned int GetPx_ILI9341_16b( unsigned int x, unsigned int y )
{
  volatile unsigned int color = 0;

  TFT_CS = 0;
  //SetRegion( x, y );
  //TFT_Set_Address_ILI9340( x, y ); //as same commands as for ILI9341
                      //TFT_Set_Index_Ptr(0x2C); = writing command is at the end
  Set_Index(0x2A);
  Write_Command(x>>8);
  Write_Command(x);
  Set_Index(0x2B);
  Write_Command(y>>8);
  Write_Command(y);

  Set_Index( 0x2E );     // ILI9341_CMD_MEMORY_READ
  Read_Data();           // Dummy read (PMDIN = 0x002E)
  Read_Data();           // Dummy read (PMDIN = 0x0000)
  color = Read_Data();   // 1st 16 bits (red and green)
  color = (color & 0xF800) | (color & 0x00FC) << 3;
  color |= Read_Data() >> 11; // 2nd 16 bits (blue and red)

  TFT_CS = 1;
  return color;
}
You can see that 2 dummy reads are sufficient in 16bit mode.
edit: Maybe better specification for reading data from GRAM will be useful for somebody:
Every execution of read command and loading data to PMDIN register cause incrementing of the pointer to the address in the GRAM. So in practice: Every call of Read_Data() will load succeeding word (16bit) from GRAM to PMDIN. So for reading a pixel colour at position (x+2,y), we just need to append Read_Data() two times.
word1:(R1R1R1R1R1R1xxG1G1G1G1G1G1xx), word2:(B1B1B1B1B1B1xxR2R2R2R2R2R2xx), word3:(G2G2G2G2G2G2xxB2B2B2B2B2B2xx), word4:(R3R3R3R3R3R3xxG3G3G3G3G3G3xx),...
For sequential reading (pixel by pixel), my function "GetPx_ILI9341_16b(x,y)" would have to be modyfied.

Thanks, peini. It is very positive message you have found out that the TFT_BP_Write_Text function wasn't correct and have passed the repaired library here. I don't know why author didn't find it out during a testing. It would make me mad if I would find the library was bad. :shock: (Anyway, BitPack library isn't useful unless the user has reading routines for his display controller.)

Regards

Vitek

peini
Posts: 46
Joined: 28 Dec 2011 09:56

Re: Idea for font anti-aliasing on displays

#9 Post by peini » 30 May 2015 13:06

Hi again,

i'am currently playing around with a great new display. It's a 4.3" display with a resolution of 480x800px. and the HX8369A controller. :)
After a lot of testing i've got it to work with my custom initialization routine in 16bit mode.
If i'am directly writing to the GRAM by sending the commands directly everything works great.

But if i try to use the TFT_Fill_Screen() function nothing happens. Also the TFT_Write_Text method won't work.
The command for writing to the GRAM (0x2C) is the same as for the ILI9341, so it should work.

Does anyone has an idea, what i'am doing wrong?
I've attached my sample code, maybe someone has the display. (http://www.digikey.at/product-search/de ... -CTXP%23-T)
Attachments
TFT_HX8369A.zip
(250.97 KiB) Downloaded 348 times

vt23
Posts: 44
Joined: 17 Jun 2014 10:36

Re: Idea for font anti-aliasing on displays

#10 Post by vt23 » 19 Nov 2015 07:34

Hello peini,

I just have been playing around with HX8369A too (for a few days, first time). There is also 480x800 pixels and display is similar to yours.
First I have to thank you for your code because I can't make it work untill I found (by a look in your code) that I have to set LUT (it could be better preset :evil: ).
After many attempts I make it work (basics are working).
Maybe you have made it work but I can write for others - I have some notes to your code:
See ILI9341 init routine:

Code: Select all

void TFT_Init_ILI9341_8bit(unsigned int display_width, unsigned int display_height) {
  if (Is_TFT_Set() != 1) {
    TFT_Set_Index_Ptr = TFT_Set_Index;
    TFT_Write_Command_Ptr = TFT_Write_Command;
    TFT_Write_Data_Ptr = TFT_Write_Data;
  }

  TFT_DISP_WIDTH = display_width;
  TFT_DISP_HEIGHT = display_height;
  if (display_width >= display_height)
    TFT_Disp_Rotation = 0;
  else
    TFT_Disp_Rotation = 90;

  TFT_Set_Pen(CL_BLACK, 1);
  TFT_Set_Brush(0, 0, 0, 0, 0, 0);

  TFT_Move_Cursor(0, 0);
  ExternalFontSet = 0;
  TFT_DataPort_Direction = 0;
  // Reset device
  TFT_Reset_ILI9341();
  TFT_Set_Address_Ptr = TFT_Set_Address_ILI9342;
}
You have this old init routine written in InitializeTouchPanel() in Start_TP() but later you will have to modify it to HX8369A. (Of course, you don't have to use all - like Disp_Rotation settings.) You know you can use some routines from inside of Start_TP separately.
I think that it is important to assign e.g.

Code: Select all

TFT_Set_Address_Ptr = TFT_Set_Address_HX8369A;
and replace TFT_Reset_ILI9341();
I think that also function pointers TFT_Set_Index_Ptr, TFT_Write_Command_Ptr, TFT_Write_Data_Ptr are also important (you have to use them in your init) because they are maybe used in TFT library functions (like TFT_Fill_Screen).

Code: Select all

void TFT_Set_Address_HX8369A(unsigned int x, unsigned int y) {
  TFT_Set_Index_Ptr(0x2A);
  TFT_Write_Command_Ptr(x>>8);
  TFT_Write_Command_Ptr(x);
  TFT_Write_Command_Ptr(479>>8); //(TFT_DISP_WIDTH-1)>>8
  TFT_Write_Command_Ptr(479); //TFT_DISP_WIDTH
  TFT_Set_Index_Ptr(0x2B);
  TFT_Write_Command_Ptr(y>>8);
  TFT_Write_Command_Ptr(y);
  TFT_Write_Command_Ptr(799>>8); //(TFT_DISP_HEIGHT-1)>>8
  TFT_Write_Command_Ptr(799); //TFT_DISP_HEIGHT
  TFT_Set_Index_Ptr(0x2C);
}
Little correction - I think you can use better WindowSet(0,0,479,799) like inside TFT_Set_Address_HX8369A instead of WindowSet(0,0,480,800) - maybe it doesn't matter. But I found you can't use only 2 successive commands like in

Code: Select all

void TFT_Set_Address_ILI9342(unsigned int x, unsigned int y) {
  TFT_Set_Index_Ptr(0x2A);
  TFT_Write_Command_Ptr(x>>8);
  TFT_Write_Command_Ptr(x);
  TFT_Set_Index_Ptr(0x2B);
  TFT_Write_Command_Ptr(y>>8);
  TFT_Write_Command_Ptr(y);
  TFT_Set_Index_Ptr(0x2C);
}
- it didn't work to me.
Another note: You don't have to use so long delays in your Init_HX8369A - I tried only 50 ms and then only 5 ms and it is sufficient (maybe less is possible). Also I don't init all LATs and TRISs to LOW (it consumes little more power) - only what I need.

Code: Select all

static void TFT_Reset_HX8369A() {
  TFT_RS_Direction = 0;
  TFT_RS = 1;

  TFT_RST_Direction = 0;
  TFT_RST = 0;
  Delay_ms( 5 );
  TFT_RST = 1;

  TFT_CS = 0;
  TFT_CS_Direction = 0;
  Delay_ms( 5 );
  
  Set_Index(0x28); // DISPOFF
  ...
Regards Vitek

Post Reply

Return to “Visual TFT Wish List”