4 bit bus mode for a LCD

hello.

Im putting this out while investigating the lcd -library:

Im currently trying to understand howto communicate with a 2x16 LCD in general in 4 bit bus mode. No code made yet.

Ive read some docs on internet and the specific LCD datasheet itself. (GDM1602k) http://www.sparkfun.com/datasheets/LCD/GDM1602K-Extended.pdf

I notice from using a LCD library following Arduinoapplication, its possible to manipulate the display both for instructionmode and information mode (text to display) by using only 4 databits (4 digital input pins on arduino) and some for the E-RS and RW command.

What I dont quite understand is howto "mark" the 4 bits sent as either a command (i.e...cursorpos,cleardisplay...) or text to be seen on display (written to dpy ram), as the high nibble or the low nibble(4 bits)?

Thank You in advance for any links or hints to my question.

regards
Jan

What I dont quite understand is howto "mark" the 4 bits sent as either a command (i.e...cursorpos,cleardisplay...) or text to be seen on display (written to dpy ram), as the high nibble or the low nibble(4 bits)?

That is determined by the RS (Register Select) pin. You drive it low for a command and high for data.

Don

Thanks for answer. Sorry Im a bit unclear.
Im aware of the RS status.
What Im not aware of is howto send 8bit value to the display when You only have 4 bits data available at the hardware(Arduino)?

I think I read somewhere You might send the 4bit information twice. Howto do that is, to me, not understandable atm.
Do I send the two 4 bits nibbles right after each other and then change the enable status?

regards
Jan

(ive studied the lcd library, but sadly I just know some of the C programming style so I didnt get answer to the above question).

floresta:

What I dont quite understand is howto "mark" the 4 bits sent as either a command (i.e...cursorpos,cleardisplay...) or text to be seen on display (written to dpy ram), as the high nibble or the low nibble(4 bits)?

That is determined by the RS (Register Select) pin. You drive it low for a command and high for data.

Don

look at the LiquidCrystal.cpp file in the liquidcrystal library which is in {installdir}/libraries/LiquidCrystal.

Focus on routines at the bottom of the code
near the comment:

/************ low level data pushing commands **********/

Its not much code so I'll duplicate it here:

// write either command or data, with automatic 4/8-bit selection
void LiquidCrystal::send(uint8_t value, uint8_t mode) {
  digitalWrite(_rs_pin, mode);

  // if there is a RW pin indicated, set it low to Write
  if (_rw_pin != 255) { 
    digitalWrite(_rw_pin, LOW);
  }
  
  if (_displayfunction & LCD_8BITMODE) {
    write8bits(value); 
  } else {
    write4bits(value>>4);
    write4bits(value);
  }
}

void LiquidCrystal::pulseEnable(void) {
  digitalWrite(_enable_pin, LOW);
  delayMicroseconds(1);    
  digitalWrite(_enable_pin, HIGH);
  delayMicroseconds(1);    // enable pulse must be >450ns
  digitalWrite(_enable_pin, LOW);
  delayMicroseconds(100);   // commands need > 37us to settle
}

void LiquidCrystal::write4bits(uint8_t value) {
  for (int i = 0; i < 4; i++) {
    pinMode(_data_pins[i], OUTPUT);
    digitalWrite(_data_pins[i], (value >> i) & 0x01);
  }

  pulseEnable();
}

Notice the check in send() for 8 bit mode.
It either calls write8bits() or write4bits() twice.
(I admit the code there is a a bit obtuse)

In either case the bits are set and the EN is strobed.
In 8 bit mode you send all 8 bits.
In 4 bit mode you send the upper 4 bits, strobe EN, then the lower 4 bits, then strobe EN.

you will see in send() the two calls to write4bits()
The value passed to the first write4bits() is value >> 4 which is the upper 4 bits since the value is shifted to the right 4 bits.
The value passed to the second call to write4bits() is the full original 8 bit value.
write4bits() sends the lower 4 bits of the value it received by placing those bits on d4-d7 of the lcd module pins.
The first call will write the upper 4 bits
and while the 2nd call to write4bits() received the full 8 bit value since only the lower 4 bits are used,
the lower 4 bits is sent to the lcd.

The pulseEnable() routine is doing more than just handling the EN line for the LCD as it is also waiting
for the faster low level commands to complete. That is what the 100us delay is for.

Don, correct me if I'm wrong but in 4 bit mode this extra delay between nibbles is not really needed.
It is only there because of the way the code was written as 4 bit mode shares the same routine
as the 8 bit routine.

--- bill

Thank You very much for clearing up :slight_smile:

I guess I wasnt clever enough to read the solution from the timing sequence diagram in the LCD documentation.
Ill write my code here after trying out some basics.

Acctually its a test for two groups of my pupils, programming a LCD not using a library :-). I nearly manage to keep a horsehead ahead of them.
Thanks for the helpout.

regards

Jan

bperrybap:
look at the LiquidCrystal.cpp file in the liquidcrystal library which is in {installdir}/libraries/LiquidCrystal.

Focus on routines at the bottom of the code
near the comment:

/************ low level data pushing commands **********/

Its not much code so I'll duplicate it here:

// write either command or data, with automatic 4/8-bit selection

void LiquidCrystal::send(uint8_t value, uint8_t mode) {
  digitalWrite(_rs_pin, mode);

// if there is a RW pin indicated, set it low to Write
  if (_rw_pin != 255) {
    digitalWrite(_rw_pin, LOW);
  }
 
  if (_displayfunction & LCD_8BITMODE) {
    write8bits(value);
  } else {
    write4bits(value>>4);
    write4bits(value);
  }
}

void LiquidCrystal::pulseEnable(void) {
  digitalWrite(_enable_pin, LOW);
  delayMicroseconds(1);   
  digitalWrite(_enable_pin, HIGH);
  delayMicroseconds(1);    // enable pulse must be >450ns
  digitalWrite(_enable_pin, LOW);
  delayMicroseconds(100);   // commands need > 37us to settle
}

void LiquidCrystal::write4bits(uint8_t value) {
  for (int i = 0; i < 4; i++) {
    pinMode(_data_pins[i], OUTPUT);
    digitalWrite(_data_pins[i], (value >> i) & 0x01);
  }

pulseEnable();
}




Notice the check in send() for 8 bit mode.
It either calls write8bits() or write4bits() twice.
(I admit the code there is a a bit obtuse)

In either case the bits are set and the EN is strobed.
In 8 bit mode you send all 8 bits.
In 4 bit mode you send the upper 4 bits, strobe EN, then the lower 4 bits, then strobe EN.

you will see in send() the two calls to write4bits()
The value passed to the first write4bits() is value >> 4 which is the upper 4 bits since the value is shifted to the right 4 bits.
The value passed to the second call to write4bits() is the full original 8 bit value.
write4bits() sends the lower 4 bits of the value it received by placing those bits on d4-d7 of the lcd module pins.
The first call will write the upper 4 bits 
and while the 2nd call to write4bits() received the full 8 bit value since only the lower 4 bits are used,
the lower 4 bits is sent to the lcd.

The pulseEnable() routine is doing more than just handling the EN line for the LCD as it is also waiting
for the faster low level commands to complete. That is what the 100us delay is for.

Don, correct me if I'm wrong but in 4 bit mode this extra delay between nibbles is not really needed.
It is only there because of the way the code was written as 4 bit mode shares the same routine
as the 8 bit routine. 

--- bill

ive studied the lcd library, but sadly I just know some of the C programming style so I didnt get answer to the above question

Would assembly language examples help?

Don

Don, correct me if I'm wrong but in 4 bit mode this extra delay between nibbles is not really needed.
It is only there because of the way the code was written as 4 bit mode shares the same routine
as the 8 bit routine.

That is correct. The delay is not needed until after the LCD controller reassembles the two nibbles and it is actually executing the command.

Don

jan,
If you are looking for another C++ example library,
there is another LiquidCrystal library by forum member "fm".
It is a direct fully backward compatible replacement that is quite a bit faster.
It supports:
4bit, 8 bit parallel
i2c
2 pin or 3 pin shift register.
Here is a link to the code site:
https://bitbucket.org/fmalpartida/new-liquidcrystal/wiki/Home

--- bill

hello.

Using that on an Amiga years ago, long time forgotten, I dont think so.
Thanks for the offer though.

regards

floresta:

ive studied the lcd library, but sadly I just know some of the C programming style so I didnt get answer to the above question

Would assembly language examples help?

Don

I guess Im doing something really bad here as nothing works as expected. (init 4bit data comm and setting cursorblink,home...)

/*
testing av lcd display
 */
byte pin4=4; // pinnumber of datapin LSB
byte pin5=5;
byte pin6=6;
byte pin7=7;
byte registerselect= 9;
byte enable = 8;
byte readwrite = 10;
byte highnib = B00000000; //contains the highnibble to be sent first, to LCD in 4 bit datamode
byte lownib= B00000000;  // contains the lownibble to be sent as 2dn to LCD in 4 bit datamode
void cleardpy();
void enablepulse();
void writetodpy();

void setup() 
{
  Serial.begin(9600);
  pinMode(pin4, OUTPUT);
  pinMode(pin5, OUTPUT);
  pinMode(pin6, OUTPUT);
  pinMode(pin7, OUTPUT);
  
  pinMode(enable, OUTPUT);
  pinMode(readwrite, OUTPUT);
  pinMode(registerselect, OUTPUT);

 
 
// To send data to the LCD, your program should make sure 
// enable is low (0) and then set the other two control lines 
// and/or put data on the data bus. When the other lines are completely ready, bring EN high (1) and wait for the minimum amount of time required by the LCD datasheet (this varies from LCD to LCD), and end by bringing it low (0) again.
 digitalWrite(enable,LOW);
 digitalWrite(readwrite,LOW);
 digitalWrite(registerselect,HIGH);
 
 delayMicroseconds(50000); //await start process to finish
 
 
  cleardpy();
  writetodpy(); //write 4bits twice to display using shift
  init4dpy();
}

void loop() 
{
  
}

void cleardpy()
{


}

void writetodpy()
{

}

void enablepulse() //send a pulse to the enable output
{
  digitalWrite(enable,HIGH);
  delayMicroseconds(1);
  digitalWrite(enable,HIGH);
 }
 
void init4dpy()
{
  
//  highnib=B00110000; //according to instruction table and masked 4 low order bits.
//  lownib=B00000000;  //according to instruction table and masked 4 high order bits
digitalWrite(pin4,HIGH);
digitalWrite(pin5,HIGH);
digitalWrite(pin6,LOW);
digitalWrite(pin7,LOW);
enablepulse();

digitalWrite(pin4,LOW);
digitalWrite(pin5,LOW);
digitalWrite(pin6,LOW);
digitalWrite(pin7,LOW);
enablepulse();
delayMicroseconds(4500); 

//set 4 bit data mode
digitalWrite(pin4,LOW);
digitalWrite(pin5,HIGH);
digitalWrite(pin6,LOW);
digitalWrite(pin7,LOW);
enablepulse();

digitalWrite(pin4,LOW);
digitalWrite(pin5,LOW);
digitalWrite(pin6,LOW);
digitalWrite(pin7,LOW);
enablepulse();
delayMicroseconds(4500); 


// display on-cursor on, cursor blink i.e.: highnib=B00000000 lownib=B00001111

digitalWrite(pin4,LOW);
digitalWrite(pin5,LOW);
digitalWrite(pin6,LOW);
digitalWrite(pin7,LOW);
enablepulse();
digitalWrite(pin4,HIGH);
digitalWrite(pin5,HIGH);
digitalWrite(pin6,HIGH);
digitalWrite(pin7,HIGH);
enablepulse();
delayMicroseconds(4500);

// home cursor
digitalWrite(pin4,LOW);
digitalWrite(pin5,LOW);
digitalWrite(pin6,LOW);
digitalWrite(pin7,LOW);
enablepulse();

digitalWrite(pin4,LOW);
digitalWrite(pin5,HIGH);
digitalWrite(pin6,LOW);
digitalWrite(pin7,LOW);
enablepulse();

/*
  delay(lcd_delay);
                lcd_init_write(0x30);   //Special Sequence:Write Function Set.
                delay(lcd_delay);
                lcd_init_write(0x30);              //Special Sequence:Write Function Set.
                delay(lcd_delay);
                lcd_init_write(0x30);              //Special Sequence:Write Function Set.
                delay(lcd_delay);
                lcd_init_write(0x20);   // 0x20 for 4-bit
                delay(lcd_delay);
                lcd_com(0x28);         //Display Off, Cursor Off, Blink Off
                delay(lcd_delay);
                lcd_com(4);                                                // Clear Screen & Returns the Cursor Home
                delay(lcd_delay);
                lcd_com(0x85);       
                delay(lcd_delay);       
                lcd_com(6);           //Inc cursor to the right when writing and don’t shift screen
                delay(lcd_delay);
                lcd_com(1);
                delay(lcd_delay);
*/

}

It does not look like you are initializing your LCD controller properly. If I am following your code correctly I see that you are sending the initial 'B00110000' only once and you are sending it as two separate 4-bit nibbles. This information has to be sent three times and it is sent as an 8-bit byte (even though the lower four bits are unused) since the device is still in the 8-bit mode. Then, after you change modes you are turning the display ON where the datasheet clearly says to turn it OFF. I know that most of the code that you look at, including the LiquidCrystal library, turns the LCD ON at this point but that doesn't mean that they are doing things correctly. Next you are 'homing' the cursor which is unnecessary if you use the correct instruction which is to clear the display. I don't see where you are setting the entry mode.

At this point I have two suggestions. (1) Follow the LCD Addressing link at http://web.alfredstate.edu/weimandn to find out what you have to do and what sequence you have to do it in, and (2) start out with the 8-bit mode which is a lot easier to get working.

Also - when you post code you should highlight the code and use the code button (#) so that it looks like this excerpt:

//  highnib=B00110000; //according to instruction table and masked 4 low order bits.
//  lownib=B00000000;  //according to instruction table and masked 4 high order bits
digitalWrite(pin4,HIGH);
digitalWrite(pin5,HIGH);
digitalWrite(pin6,LOW);
digitalWrite(pin7,LOW);
enablepulse();

Don

Hello. thanks for the link showing the proper way of init.
I know Im doing lots of error. I did write 3 times but forgot to edit it here.

Ill do the 8bit tranferre trippel initially as I read the 4 lower bits wasnt read my lcd anyway.

Else Ill change accordingly to the init link routines You listed.

I tried to copy the code in the arduinoapp, but it didnt show all code when glued in.

Ow well, I hope Ill manage to learn the trick from 8 to 4 then. The 8bit mode isnt a challenge.

thank You

floresta:
It does not look like you are initializing your LCD controller properly. If I am following your code correctly I see that you are sending the initial 'B00110000' only once and you are sending it as two separate 4-bit nibbles. This information has to be sent three times and it is sent as an 8-bit byte (even though the lower four bits are unused) since the device is still in the 8-bit mode. Then, after you change modes you are turning the display ON where the datasheet clearly says to turn it OFF. I know that most of the code that you look at, including the LiquidCrystal library, turns the LCD ON at this point but that doesn't mean that they are doing things correctly. Next you are 'homing' the cursor which is unnecessary if you use the correct instruction which is to clear the display. I don't see where you are setting the entry mode.

At this point I have two suggestions. (1) Follow the LCD Addressing link at http://web.alfredstate.edu/weimandn to find out what you have to do and what sequence you have to do it in, and (2) start out with the 8-bit mode which is a lot easier to get working.

Also - when you post code you should highlight the code and use the code button (#) so that it looks like this excerpt:

//  highnib=B00110000; //according to instruction table and masked 4 low order bits.

//  lownib=B00000000;  //according to instruction table and masked 4 high order bits
digitalWrite(pin4,HIGH);
digitalWrite(pin5,HIGH);
digitalWrite(pin6,LOW);
digitalWrite(pin7,LOW);
enablepulse();




Don

I have rewritten the code after reading init protocol.
But the display turns on with cursor at random position on the first line.

/*
testing av lcd display
 */
int pin4=4; // pinnumber of datapin LSB
int pin5=5;
int pin6=6;
int pin7=7;
int registerselect= 9;
int enable = 8;
int readwrite = 10;

int enablepulse();
int init4dpy();

void setup() 
{
  
  Serial.begin(9600);
  
  delay(3000);
  
  pinMode(pin4, OUTPUT);
  pinMode(pin5, OUTPUT);
  pinMode(pin6, OUTPUT);
  pinMode(pin7, OUTPUT);
  pinMode(enable, OUTPUT);
  pinMode(readwrite, OUTPUT);
  pinMode(registerselect, OUTPUT); 
 
 
  init4dpy();
}

void loop() 
{
  
}

int enablepulse() //send a pulse to the enable output
{
  digitalWrite(enable,LOW);
  digitalWrite(enable,HIGH);
  delayMicroseconds(1);
  digitalWrite(enable,LOW);
 }
 
int init4dpy()
{
  
// delayMicroseconds(50000); //await start process to finish

 digitalWrite(readwrite,LOW);
 digitalWrite(registerselect,LOW);

// write 3times to lcd with content ox03
digitalWrite(pin4,HIGH);
digitalWrite(pin5,HIGH);
digitalWrite(pin6,LOW);
digitalWrite(pin7,LOW);
enablepulse();
delayMicroseconds(4500); 

digitalWrite(pin4,HIGH);
digitalWrite(pin5,HIGH);
digitalWrite(pin6,LOW);
digitalWrite(pin7,LOW);
enablepulse();
delayMicroseconds(150); 

digitalWrite(pin4,HIGH);
digitalWrite(pin5,HIGH);
digitalWrite(pin6,LOW);
digitalWrite(pin7,LOW);
enablepulse();
delayMicroseconds(150); 


//set 4 bit data mode writing highbit
digitalWrite(pin4,LOW);
digitalWrite(pin5,HIGH);
digitalWrite(pin6,LOW);
digitalWrite(pin7,LOW);
enablepulse();
delayMicroseconds(150); 

// 4 bit mode start from here and downwards 

// function set: 4 bit bus mode, 2 line dpy, 5x8dots format

digitalWrite(pin4,LOW);
digitalWrite(pin5,HIGH);
digitalWrite(pin6,LOW);
digitalWrite(pin7,LOW);
enablepulse();
digitalWrite(pin4,LOW);
digitalWrite(pin5,LOW);
digitalWrite(pin6,LOW);
digitalWrite(pin7,HIGH);
enablepulse();
delayMicroseconds(60);

// turn off dpy, cursor and blink (ddram still exists)

digitalWrite(pin4,LOW);
digitalWrite(pin5,LOW);
digitalWrite(pin6,LOW);
digitalWrite(pin7,LOW);
enablepulse();
digitalWrite(pin4,LOW);
digitalWrite(pin5,LOW);
digitalWrite(pin6,LOW);
digitalWrite(pin7,HIGH);
enablepulse();
delayMicroseconds(60);

// clear dpy
digitalWrite(pin4,LOW);
digitalWrite(pin5,LOW);
digitalWrite(pin6,LOW);
digitalWrite(pin7,LOW);
enablepulse();
digitalWrite(pin4,HIGH);
digitalWrite(pin5,LOW);
digitalWrite(pin6,LOW);
digitalWrite(pin7,LOW);
enablepulse();
delayMicroseconds(35000);

// entry mode: cursor/blink moves to right and ddram adress is increased by 1 and shift right. I dont fully understand SH parameter yet.

digitalWrite(pin4,LOW);
digitalWrite(pin5,LOW);
digitalWrite(pin6,LOW);
digitalWrite(pin7,LOW);
enablepulse();
digitalWrite(pin4,LOW);
digitalWrite(pin5,HIGH);
digitalWrite(pin6,HIGH);
digitalWrite(pin7,LOW);
enablepulse();
delayMicroseconds(60);

// end of initializing

// turn dpy, cursor on and blinking off

digitalWrite(pin4,LOW);
digitalWrite(pin5,LOW);
digitalWrite(pin6,LOW);
digitalWrite(pin7,LOW);
enablepulse();
digitalWrite(pin4,HIGH);
digitalWrite(pin5,HIGH);
digitalWrite(pin6,HIGH);
digitalWrite(pin7,HIGH);
enablepulse();
delayMicroseconds(60);

delay(1000);
}

Oh my, now the display doesnt react on anything. Tested it with lcd.lib following arduino, no response at all.

Ill burry myself 6 feet below $)

Oh my, now the display doesnt react on anything. Tested it with lcd.lib following arduino, no response at all.

You probably just forgot to tell the LiquidCrystal library that you are using the RW pin. Your best bet is to just connect it (LCD pin 5) to GND.

Your own initialization sequence is almost correct. You messed up one bit in the 'Entry Mode Set' command.

Don

floresta:

Oh my, now the display doesnt react on anything. Tested it with lcd.lib following arduino, no response at all.

You probably just forgot to tell the LiquidCrystal library that you are using the RW pin. Your best bet is to just connect it (LCD pin 5) to GND.

Your own initialization sequence is almost correct. You messed up one bit in the 'Entry Mode Set' command.

Don

hi.

I tried what u suggested regarding rw withoout any response.

Im aware of the doc for my display (link in op) regarding entry mode. That bit differ from what my dpy documentatin tells and the general description of lcd display. I tried both version regarding the state of the one bit.

Well, the display seemes not beeing able to receive commands. I think I might have written some to it that might have put it in a non listening mode or destroyed its internal function as there were
much altering of signals input to display until the code became somewhat usable.

Ill head into another dpy to check the above thoughts.

Edit: I have checked that the voltage supply and io from uC are correct according to digitalWrite instructions to display. Its either something buggy with my program or a soldering issue. (soldered all connections twice, no shortcircuits either). Could be static too. A new dpy will probably tell.

regards

Im aware of the doc for my display (link in op) regarding entry mode. That bit differ from what my dpy documentatin tells and the general description of lcd display. I tried both version regarding the state of the one bit.

Your data sheet is wrong on page 6. The correct version of the instruction code, with DB2 high is shown on page 5.

The controller determines which instruction you are intending to send it by looking for the most significant '1' bit. You can clearly see the pattern, if you are looking for it, in the 'Instruction Table' on page 5. Without having DB2 high for an 'Entry Mode Set' instruction the controller cannot distinguish between an 'Entry Mode Set' instruction with DB1 high and DB0 low and a 'Return Home' instruction.

Don

floresta:

Im aware of the doc for my display (link in op) regarding entry mode. That bit differ from what my dpy documentatin tells and the general description of lcd display. I tried both version regarding the state of the one bit.

Your data sheet is wrong on page 6. The correct version of the instruction code, with DB2 high is shown on page 5.

The controller determines which instruction you are intending to send it by looking for the most significant '1' bit. You can clearly see the pattern, if you are looking for it, in the 'Instruction Table' on page 5. Without having DB2 high for an 'Entry Mode Set' instruction the controller cannot distinguish between an 'Entry Mode Set' instruction with DB1 high and DB0 low and a 'Return Home' instruction.

Don

Thank You very much for clearing up. Ill change the code.

regards jan

hi.
Ive posted my last version of code in this posting. Anyone dare run it on their own arduino and a 2x16 text LCD?

I have no idea if its my dpy or uC that doesnt work. Absolutely nothing visual happens on my display
running the code.

regards

/*
testing av lcd display
 */
byte t60=60;
int pin4=4; // pinnumber of datapin LSB
int pin5=5;
int pin6=6;
int pin7=7;
int enable = 8;
int registerselect= 9;
int readwrite = 10;  // or ground

int enablepulse();
int init4dpy();

void setup() 
{
  Serial.begin(9600); 
  pinMode(pin4, OUTPUT);
  pinMode(pin5, OUTPUT);
  pinMode(pin6, OUTPUT);
  pinMode(pin7, OUTPUT);
  pinMode(enable, OUTPUT);
  pinMode(registerselect, OUTPUT); 
  pinMode(readwrite, OUTPUT);

 
 digitalWrite(enable,LOW);
 digitalWrite(registerselect,LOW); 
 digitalWrite(readwrite,LOW);
  init4dpy();
 digitalWrite(enable,HIGH);
}

void loop() 
{

  
}

int enablepulse() //send a pulse to the enable output
{
  digitalWrite(enable,LOW);
  digitalWrite(enable,HIGH);
  delayMicroseconds(1);
  digitalWrite(enable,LOW);
 }
 
int init4dpy()
{

 
// delayMicroseconds(150000); //await start process to finish

// write 3times to lcd with content ox03
digitalWrite(pin4,HIGH);
digitalWrite(pin5,HIGH);
digitalWrite(pin6,LOW);
digitalWrite(pin7,LOW);
enablepulse();
delayMicroseconds(5000); 

digitalWrite(pin4,HIGH);
digitalWrite(pin5,HIGH);
digitalWrite(pin6,LOW);
digitalWrite(pin7,LOW);
enablepulse();
delayMicroseconds(150); 

digitalWrite(pin4,HIGH);
digitalWrite(pin5,HIGH);
digitalWrite(pin6,LOW);
digitalWrite(pin7,LOW);
enablepulse();
delayMicroseconds(150); 


//set 4 bit data mode
digitalWrite(pin4,LOW);
digitalWrite(pin5,HIGH);
digitalWrite(pin6,LOW);
digitalWrite(pin7,LOW);
enablepulse();
delayMicroseconds(150); 

// 4 bit mode start from here and downwards 

// function set: 4 bit bus mode, 2 line dpy, 5x8dots format

digitalWrite(pin4,LOW);
digitalWrite(pin5,HIGH);
digitalWrite(pin6,LOW);
digitalWrite(pin7,LOW);
enablepulse();
digitalWrite(pin4,LOW);
digitalWrite(pin5,LOW);
digitalWrite(pin6,LOW);
digitalWrite(pin7,HIGH);
enablepulse();
delayMicroseconds(t60);

// turn off dpy, cursor and blink (ddram still exists)

digitalWrite(pin4,LOW);
digitalWrite(pin5,LOW);
digitalWrite(pin6,LOW);
digitalWrite(pin7,LOW);
enablepulse();
digitalWrite(pin4,LOW);
digitalWrite(pin5,LOW);
digitalWrite(pin6,LOW);
digitalWrite(pin7,HIGH);
enablepulse();
delayMicroseconds(t60);

// clear dpy
digitalWrite(pin4,LOW);
digitalWrite(pin5,LOW);
digitalWrite(pin6,LOW);
digitalWrite(pin7,LOW);
enablepulse();
digitalWrite(pin4,HIGH);
digitalWrite(pin5,LOW);
digitalWrite(pin6,LOW);
digitalWrite(pin7,LOW);
enablepulse();
delayMicroseconds(4000);

// entry mode: cursor/blink moves to right and ddram adress is increased by 1 and shift right. I dont fully understand SH parameter yet.

digitalWrite(pin4,LOW);
digitalWrite(pin5,LOW);
digitalWrite(pin6,LOW);
digitalWrite(pin7,LOW);
enablepulse();
digitalWrite(pin4,LOW);
digitalWrite(pin5,HIGH);
digitalWrite(pin6,HIGH);
digitalWrite(pin7,LOW);
enablepulse();
delayMicroseconds(t60);

// end of initializing

// turn dpy, cursor on and blinking off

digitalWrite(pin4,LOW);
digitalWrite(pin5,LOW);
digitalWrite(pin6,LOW);
digitalWrite(pin7,LOW);
enablepulse();
digitalWrite(pin4,LOW);
digitalWrite(pin5,LOW);
digitalWrite(pin6,HIGH);
digitalWrite(pin7,HIGH);
enablepulse();
delayMicroseconds(t60);

delay(1000);

  
  // write 'A'  to dpy
digitalWrite(registerselect,HIGH); 
delayMicroseconds(60);
digitalWrite(pin4,LOW);
digitalWrite(pin5,LOW);
digitalWrite(pin6,HIGH);
digitalWrite(pin7,LOW);
enablepulse();
digitalWrite(pin4,HIGH);
digitalWrite(pin5,LOW);
digitalWrite(pin6,LOW);
digitalWrite(pin7,LOW);
enablepulse();
delayMicroseconds(t60);
digitalWrite(registerselect,LOW);
}

Anyone dare run it on their own arduino and a 2x16 text LCD?

I did. It gives me a blank display.

Without changing any wires I can run Hello World with LiquidCrystal lcd(10,9,8,4,5,6,7); and it functions properly. I am running a Boarduino with Arduino v0022.

I will take a look at your code more closely now....

Don

Edit: It's LiquidCrystal lcd(9,10,8,4,5,6,7); -- sorry about that.