Go Down

Topic: Highspeed LCD (LCD4Bit + Assembler) (Read 6525 times) previous topic - next topic

designer2k2

Hello,

for my multidisplay, i need a fast LCD, and like others have seen the basic Arduino Libarys are quite slow...

so, with some changes the LCD4Bit Libary can reach impressive speeds!  8-)

[media]http://www.youtube.com/watch?v=XjI0MHSNJO4[/media]


you can modify the LCD4Bit with some assembler, and never use the "cursorTo" Function.

heres the change:

Code: [Select]
void LCD4Bit::pulseEnablePin(){
 digitalWrite(Enable,LOW);
 asm("nop\n");
 // send a pulse to enable
 digitalWrite(Enable,HIGH);
 asm("nop\n");
 digitalWrite(Enable,LOW);
 asm("nop\n");
}


delete the LCD4Bit.o after modifying LCD4Bit.cpp.

and for positioning the cursor use:

Code: [Select]
 
     lcd.commandWrite(0x80);                   //Line=1, Cursor 0
     lcd.commandWrite(0xC0+val);            //Line=2, Cursor val
     lcd.commandWrite(0x94+7);               //Line=3, Cursor 7
     lcd.commandWrite(0xD4);                   //Line=4, Cursor 0



give it a try, the difference is impressive for so little changes  8-)


the code in the samplevid from above:

Code: [Select]


#include <LCD4Bit.h>

LCD4Bit lcd = LCD4Bit(4);  

/*==============================================================================
* GLOBAL VARIABLES
*============================================================================*/


//Variables:
int val = 0;            // variable to store the value coming from the sensor
int val2 = 0;
int valT1 = 0;          // variable to store the Temp Case


/*==============================================================================
* FUNCTIONS                                                                
*============================================================================*/


/*==============================================================================
* SETUP()
*============================================================================*/

void setup() {
 
 
 lcd.init();                             //Inits the LCD

 
}

/*==============================================================================
* LOOP()
*============================================================================*/

void loop() {  
 
 //Lets start the loop for the Value Displaying:
 //get the Analog Value:
   
  val = analogRead(0)/50;
 
 lcd.commandWrite(0x80);
 
 for (int i=0; i <= 20; i++){

     lcd.commandWrite(0x80+i);
     //lcd.cursorTo(1,i);
     lcd.print(255);                          
     
     lcd.commandWrite(0xC0+i);
     //lcd.cursorTo(2,i);      
     lcd.print(255);                          
     
     lcd.commandWrite(0x94+i);
     lcd.print(255);                          

     lcd.commandWrite(0xD4+i);
     lcd.print(255);                            

 delay(val);

 }
 
  lcd.commandWrite(0x80);
 
 for (int i=0; i <= 20; i++){

     lcd.commandWrite(0x80+i);
     //lcd.cursorTo(1,i);
     lcd.print(23);                          
     
     lcd.commandWrite(0xC0+i);
     //lcd.cursorTo(2,i);
     lcd.print(23);                          
     
     lcd.commandWrite(0x94+i);
     lcd.print(23);                          

     lcd.commandWrite(0xD4+i);
     lcd.print(23);  

 delay(val);

 }
 
 


 
}




designer2k2
http://www.designer2k2.at

jener8tionx

I like it!!!  Now all I have to do is figure out what is going on there!  So can this change work on any LCD?

designer2k2

basically ive increased the refresh rate, so you can write data faster to the display  :)

it should work on quite a lot of LCD´s, but the timing is a little bit faster as the datasheet tells...
http://www.designer2k2.at

Mike Mc

Is it possible to address individual pixels on those displays? If so you could show video :)

designer2k2

pixels? not directly...

you can create custom characters what only lit the pixel you want, but only like 5 or 7 characters are possible to make.

what you want to do with that?

making a random pixel flying all over the display is not a problem, but showing some graphics may be  :-?
http://www.designer2k2.at

Nachtwind

that looks quite awesome...
Especially since it is 4Lines compatible ^^ one thing i missed at the original 4Bit library (it never worked with my 4Line display..)

Very very interestering...
Believe me, Mike, I calculated the odds of this succeeding against the odds I was doing something incredibly stupid[ch8230] and I went ahead

designer2k2

to get it running for 4 lines just init a 2line and then use the commands i postet to access all the lines  ;)
http://www.designer2k2.at

floresta

designer2k2
Quote
it should work on quite a lot of LCD´s, but the timing is a little bit faster as the datasheet tells...
If you move one nop and stick in a few more you will be a lot closer to meeting the datasheet requirements (at least with a 16 MHz clock).  My evaluation is based on an efficient compiler which I believe is the case for the Arduino.

Your program as I would do it in assembly language:
cbi lcd_E_port, lcd_E_pin   ; [2] digitalWrite(Enable,LOW);
nop                         ; [1] asm("nop\n");
sbi lcd_E_port, lcd_E_pin   ; [2] digitalWrite(Enable,HIGH);
nop                         ; [1] asm("nop\n");
cbi lcd_E_port, lcd_E_pin   ; [2] digitalWrite(Enable,LOW);
nop                         ; [1] asm("nop\n");

This gives the following:
"address hold time" of 3 x 62.5 = 187.5 ns, first nop and sbi, datasheet requires at least 10 nS
"enable pulse width" of 3 x 62.5 = 187.5 ns,  second nop and cbi,  datasheet requires at least 230 nS
"enable cycle time" of 4 x 62.5 = 250 ns, second nop, cbi, and third nop, datasheet requires at least 500 nS

Revised program as I would do it in assembly language:
cbi lcd_E_port, lcd_E_pin  ; [2] digitalWrite(Enable,LOW);
sbi lcd_E_port, lcd_E_pin  ; [2] digitalWrite(Enable,HIGH);
nop                        ; [1] asm("nop\n");
nop                        ; [1] asm("nop\n");
nop                        ; [1] asm("nop\n");
nop                        ; [1] asm("nop\n");
cbi lcd_E_port, lcd_E_pin  ; [2] digitalWrite(Enable,LOW);
nop                        ; [1] asm("nop\n");
nop                        ; [1] asm("nop\n");

This gives the following:
"address hold time" of 2 x 62.5 = 125 ns, sbi, datasheet requires at least 10 nS
"enable pulse width" of 6 x 62.5 = 375 ns, first 4 nop's and cbi, datasheet requires at least 230 nS
"enable cycle time" of 8 x 62.5 = 500 ns, all nop's and cbi,  datasheet requires at least 500 nS

For the non programmers: the instruction asm("nop\n"); implements a "no-operation" instruction which tells the processor to do nothing, but it takes up one clock cycle or 62.5 ns to accomplish this.

floresta


floresta

Nachtwind:

Quote
Especially since it is 4Lines compatible
In order to deal with "lines" you have to understand that there are two different components involved, and they define the term "lines" differently.  You have obtained a device consisting of a printed circuit board on which is mounted a controller made by one manufacturer and a display, probably made by another manufacturer.  The display typically has one, two or four lines of characters.  As far as the controller is concerned, however, there are only two choices, one line or two.  To make a long story short you should almost always program the controller for two lines.  As far as I can tell this choice will also work for true "one line" displays with less than ideal, but still usable, brightness and/or contrast.  

That's why designer2k2 said
Quote
to get it running for 4 lines just init a 2line...


floresta

designer2k2

played some more:

void LCD4Bit::pulseEnablePin(){
 asm("cbi 0x0B, 2\n");
 asm("sbi 0x0B, 2\n");
 delayMicroseconds(10);
 asm("cbi 0x0B, 2\n");
 asm("nop\n");        
}

0x0B,2 is IO Pin 2  ;)

the Microseconds delay is a short as possible, with 8 its already showing strange things on the LCD...

there is no big improvement in speed, but it does speed it up a little  :)
http://www.designer2k2.at

FrankRadio

I fix this issue a little bit easy...
If u do not see is because do not exist. :o

I get a easy way to fix that speed problem, i'm only buffering the data on the LCD RAM, and then i send 0x0C if i'm not wrong and ligth on the cursor, like magic al the text apears complete without blinks and other things. :P

There are a lot of Cmd and plus function to do in the LCD controler.

Best Regards
Frank 8-)

designer2k2

#11
Jun 25, 2009, 10:24 pm Last Edit: Jun 25, 2009, 10:31 pm by designer2k2 Reason: 1
my goal was to get the LCD Speed back to what i was used with direct assembler, not to have workarounds  ;)

the function with the RAM is new to me, but would only fix that i can see how the page is build up.

see the video from 1:01 on.
[media]http://www.youtube.com/watch?v=PuyfSF7vrHQ[/media]

with a little assembler in the LCD4Bit you can write the whole screen without seeing where the cursor is  ;)


PS:

Here is my modified LCD4Bit.cpp : http://multidisplay.googlecode.com/svn/trunk/libs/LCD4Bit/LCD4Bit.cpp

to use it, the Port & Bit for RS & Enable must be fittet  :)
http://www.designer2k2.at

mem

I wonder how much faster that code is than using digitalWrite. Although your assembler i/o will be much faster, the display itself needs delays. For example, your pushNibble function has a 10 microsecond delay so I wonder if the speed improvements from the assembler code get diluted because the display needs these big delays.

If you want the fastest speed you should use use the RW pin to read the display status so you can write the next byte immediately the LCD signals it is ready.

See Peter Fleury's LCD library for an example: http://homepage.hispeed.ch/peterfleury/lcdlibrary.zip

bill2009


designer2k2

i reduced the delays until i got wrong characters displayed, then added 1 nop or 1us for safety  :)

would guess that reading back the result from the LCD could take longer as this  :-?

some speed tests:

LCD4Bit original: 685.8ms
LCD4Bit assembler delays: 5.2ms
LCD4Bit assembler delays & set io:  4.5ms

its the time from a run to the next run. averaged over 100 runs.

done with my "scope display", where quite some calculation and array shifting happens during the run.

so the assembler IO´s dont make much difference...
http://www.designer2k2.at

Go Up