Due support for Nokia 6100 display

The gLCD-Library has been updated to add support for the Arduino Due. Version 3.2 and future versions will support both AVR and SAM/DUE processors in a single library.

Quick update:

I have added a high-speed mode for the due which uses direct port writes rather than digitalWrite(). As a result the speed on the due has increased dramatically.

How dramatically? Well, it has gone from 0.5FPS to 12FPS. By my count that means the Due can send approximately 200,000 pixels per second.

Version 3.2b is available at the link in my last post.

Hi Tom,

I checked your code and you did really impressive work.
I just would like to know why you don't inherit from the SPI class to obtain the SPI management done by the SAM3X SPI Peripheral.
Is it because the shield could be used without using the SPI dedicated pins?

In case of you would like to use SPI, it could be useful to add a small buffer in RAM and then use it as DMA input for a given maximum drawing object size.
That way, you should greatly improve the framerate, I hope.
This could also bring an accelerated bitmap blit from Flash/RAM to LCD, couldn't it?

There are two reasons for not using SPI:

  1. Neither the AVR nor the SAM chip (as far as I'm aware) have support for 9bit SPI, which means it is not possible to use the hardware SPI without some additional programming to disable it, send the first bit, reenable it, send the 8 bits. At that point it just becomes easier to use software SPI.

  2. As you noticed different boards have the hardware spi pins located in different places (take the mega for example which is what I originally programmed it for). Without some jumper wires it would mean the library couldn't be used. What should also be noted is that when I wrote the library it was written for a project which required an 8bit SPI device and the screen, so I used the hardware SPI for 8bit and a bitbanged one for 9 bit.

As for a buffer on the Arm chip, it would be possible. However the library is designed to work with both AVR and Arm and so I don't want to add features that only work on one or the other.
As always though the library is just a starting point. If there is a need for a change in it, the person using the library is free to add the features they require.

Bitmap images was one thing I have done previously but didn't incorperate into the library as it takes a fairly large buffer to process an image and print it to the display (as the bitmap format stores the data in the opposite direction to which it is needed). I did succeed in the end for the Mega bit it needed a 1.5kB buffer. I will have to find the time to clean up and post the code I wrote for this.

Good points, I was pretty sure about that but wanted to them to be confirmed.

About point 1), I double checked the SAM3X datasheet and if you look at chapter 33, more precisely at 33.8.9 SPI Chip Select Register, you will see that you are able to configure the SPI to handle frames with a length from 8 to 16 bits:

• BITS: Bits Per Transfer
The BITS field determines the number of data bits transferred. Reserved values should not be used.
Value Name Description
0 8_BIT 8 bits for transfer
1 9_BIT 9 bits for transfer
2 10_BIT 10 bits for transfer
...

As you said, to obtain something compatible between all boards and all device architecture it is better to use software SPI and impacts dedicated performance optimizations.

Thanks for finding that out, it could come in handy in future projects! If you want to try and implement it, you are welcome to fork my repository on github and add hardware support for the due :).

Dear Tom,

Your library is awesome, but I have a little problem. I want to display continuously changing values, basically numbers. For example I put the cursor to 0,0 and print 1234 value, but if the value changes to three digits, 234, the last digit stays on the display. The number on the display 2344 instead of 234.

Another example, I put some text on the display, but when I print something shorter on the same place, the original text stays on.
The graphic.Clear() is so slow, I also tried to "overwrite" the area with a white box, but it flickers. I read 12 fps in earlier posts, 3-4 would be more than enough for me. I'm using mega board. I have LCD with Philips controller and use this code:

gLCD graphic(RST,CS,Clk,Data,HIGH_SPEED); //High speed

What do you suggest to clear the previous information from the screen, and quickly update it?

Thanks

The simplest way to clear the extra letters is to have a set area of the screen that you are going to print the value to, say 4 characters in this case, then pad your string with ' ' (space) until those four letters have been written. For example:

char x = 0;
char y = 0;

graphic.setCoordinate(x,y);
graphic.setFont(Normal_SolidBG);
char numSent = graphic.print("123"); //prints the number 123. The print function returns how many letters have been written, so numSent=3
char oldX = x;
x += (numSent*6); //for normal size font, each character is 6 pixels wide
while(numSent < 4){
  graphic.print(' '); //pad up to 4 characters.
  numSent++;
  x += 6;
}
x = oldX; //restore original print location.

Hi,

Thanks for the quick reply. I started to work today on the code and just realized that graphic.print() doesn't handle float numbers. I'm reading the value from DS18B20. Finally I multiplied the temperature reading and put into an array digit by digit, and put the decimal point while printing out the digits separately. Than I had to solve the positioning issues, to keep the value at the same place regardless how many digits were printed, I dealt with the minus sign also. It was hard work, the code a bit complicated, there must be a more elegant was to do this, but I'm happy with it. Sorry if it isn't formatted and commented well, I'm new to programming.

I would like to add a button to navigate through different pages, with an interrupt to increment the "item" variable of switch case. To erase the previous page I draw a white box before printing the new data. This makes a little slow to navigate through the pages, I will try to erase the rows with "spaces" only.

Is there any way to send custom bitmaps to the display? I mean a snowflake for example when the temperature is below freezing.

switch(item)

{
  case 1:
  graphic.setCoordinate(5,5);
  graphic.print("case 1");
sensors.requestTemperatures(); // Send the command to get temperatures
temp= (int)(sensors.getTempCByIndex(0)*10);

sprintf(array, "%i", temp);
  

if (temp>=0 && temp<10) {  
    graphic.setCoordinate(temp_pos,temp_posY);
  graphic.print("  ");
  temp_pos +=12*size_factor; 

      
      graphic.setCoordinate(temp_pos,temp_posY);
      graphic.print("0.");
      temp_pos += 12*size_factor; 
      graphic.setCoordinate(temp_pos,temp_posY);
      graphic.print(array[0]);
      temp_pos=temp_posX;
  }
  
if (temp>=10 && temp<100) {
  
  graphic.setCoordinate(temp_pos,temp_posY);
  graphic.print("  ");
  temp_pos += 12*size_factor; 
  graphic.setCoordinate(temp_pos,temp_posY);
  graphic.print(array[0]);
  temp_pos += 6*size_factor;
  graphic.setCoordinate(temp_pos,temp_posY);
  graphic.print(".");
  temp_pos += 6*size_factor; 
  graphic.setCoordinate(temp_pos,temp_posY);
  graphic.print(array[1]);
  temp_pos=temp_posX;
}

if (temp>=100)
    {
     graphic.setCoordinate(temp_pos,temp_posY);
  graphic.print("  ");
      temp_pos += 6*size_factor; 
      for (int a=0; a<=1;a++){
       graphic.setCoordinate(temp_pos,temp_posY);
       graphic.print(array[a]);
       temp_pos += 6*size_factor; 
       }
       graphic.setCoordinate(temp_pos,temp_posY);
      graphic.print(".");
      temp_pos += 6*size_factor; 
      graphic.setCoordinate(temp_pos,temp_posY);
      graphic.print(array[2]);
      temp_pos=temp_posX;
    }
   

if (temp<0 && temp>-10)

  {  
graphic.setCoordinate(temp_pos,temp_posY);
graphic.print(" ");
  temp_pos += 6*size_factor; 
      graphic.setCoordinate(temp_pos,temp_posY);
      graphic.print(array[0]);
      temp_pos += 6*size_factor; 
      graphic.setCoordinate(temp_pos,temp_posY);
      graphic.print("0.");
      temp_pos += 12*size_factor; 
      graphic.setCoordinate(temp_pos,temp_posY);
      graphic.print(array[1]);
      temp_pos=temp_posX;
  }
    if (temp<-10 && temp>-100)
  {  
graphic.setCoordinate(temp_pos,temp_posY);
graphic.print(" ");
temp_pos+=6;
graphic.setCoordinate(temp_pos,temp_posY);
      graphic.print(array[0]);
      temp_pos += 6*size_factor; 
     graphic.setCoordinate(temp_pos,temp_posY);
      graphic.print(array[1]);
      temp_pos += 6*size_factor; 
      graphic.setCoordinate(temp_pos,temp_posY);
      graphic.print(".");
      temp_pos += 6*size_factor; 
      graphic.setCoordinate(temp_pos,temp_posY);
      graphic.print(array[2]);
      
      temp_pos=temp_posX;
  }
 
 if (temp<=-100)
      {
      for (int a=0; a<=2;a++){
      graphic.setCoordinate(temp_pos,temp_posY);
      graphic.print(array[a]);
      temp_pos += 6*size_factor; 
      }
      
      graphic.setCoordinate(temp_pos,temp_posY);
      graphic.print(".");
      temp_pos += 6*size_factor; 
      graphic.setCoordinate(temp_pos,temp_posY);
      graphic.print(array[3]);
      temp_pos=temp_posX;
    }

It is possible, but you would have to write the code to decode bitmaps youself.

I have done it in a previous project (displaying album art for an MP3 Player), but I never got around to cleaning up the code and posting it. Unfortunately I am rather busy with university work and won't have the time to be much help.

Bitmaps are fairly straight forward to decode. The issue is they store the pixel data in reverse (BGR with the first pixel data in the file being the last on the screen). I basically ended up having to use a large (2kB) ram array to extract and reverse the data chunk by chunk and print it to the display.

If you save the image as raw data in a PROGMEM array, then you can display it directly by calling:

graphic.Window(x1,y1,x2,y2);

to create a window on the screen, then fill it with pixels by calling:

twoPixels(red1,green1,blue1,red2,green2,blue2);

where the 6 values are 4 bits (0-F) and represent the red, green and blue data for two consecutive pixels.

fantastic! although i wonder if you could tell me if this library could be used for the following [urlhttps://www.adafruit.com/products/438]graphic LCD[/url]?

The two types of display are completely different.

One is Colour, one is B/W. One uses 9bit SPI, the other uses 8bit SPI. All of the command registers have different addresses. I you were to write your own driver code, then you could possibly reuse alot of the code from my library.

thanks for the info tom, i now see that they aren't that similar. do you know of an already existing library which has been ported to the Due and which could run this type of display?

Tom, excellent work on making both the library and adding Due compatibility. I myself have pulled my hair out since Sunday looking at the code for 9 bit SPI addressing for Adafruit 1.8" and 2.2" SPI displays (which use different low level but similar code bases). Found UTFT not helpful for SPI displays then found your code. You are the only person I have found to map the low-level SPI addressing on the Due to be compatible with anywhere near similar calls on the '328 Arduinos.

I'll be looking to see if I can update the Adafruit code for their HX8340B unless you object. Arduino Code | 2.2" TFT Display | Adafruit Learning System, GitHub - adafruit/Adafruit-HX8340B: Adafruit 2.2" TFT with SPI interface and microSD card holder

Update: I've suspended the work for now. It would be helpful to see a diagram of how you wired your displays along with the test program to check the pins used. Mike

Thanks for creating the library and making it Due compatible!

About the Due: it has so much RAM, you can easily store a full 128x128 bitmap in an array, stored in RAM. Here's the code:

and here's an example of a photo being displayed:

To create the code for the 3-bytes-for-2-pixels array I wrote this little script:

Ideally, the image would be loaded from some kind of non-volatile memory, like the ROM but since the ROM is completely erased on a Due for each upload this is not really a solution for me.

Nice.

I have done bitmaps before, but on a Mega. Its actually possible to get a mega (and I'm sure a Due would have no issue) to read a 24bit BMP file off an SD card, scale it to 128 pixels square and display it. It would be a lot easier to do on the due as you could buffer the entire image after scaling and that would make it easy to display - for the mega there isn't enough RAM, so I had to get creative.