Go Down

Topic: LCD4Bit code to support 4 lines (Read 1 time) previous topic - next topic

arduinobob

I am using the LCD4Bit library to connect to a DisplayTech 204A (HD44780-compatible) 4x20 LCD display.
Everything worked fine, except it didn't appear that lines 3 and 4 of the display were supported.
I made some additions/changes to the cursorTo() function in LCD4Bit.cpp and now lines 3 and 4 work fine. [Remember that if you edit a library's .h or .cpp file, you need to delete the .o file, and then Verify/Compile within the Arduino IDE for the changes to take effect.]
I am still in my first week with the Arduino, so if I've missed something, or posted in the wrong place, please have mercy. ;)
/Bob

void LCD4Bit::cursorTo(int line_num, int x){
 //first, put cursor home
 commandWrite(CMD_HOME);

 //if we are on a 1-line display, set line_num to 1st line, regardless of given
 if (g_num_lines==1){
   line_num = 1;
 }
 if (line_num == 2){
   commandWrite(0xC0);      //DDRAM address 0x40
     //was:
     //x += 40;
 }
 if (line_num == 3){
     commandWrite(0x94); //DDRAM address 0x14
 }
 if (line_num == 4){
     commandWrite(0xD4); //DDRAM address 0x54
 }
 //advance the cursor to the right according to position. (second line starts at position 40).
 for (int i=0; i<x; i++) {
   commandWrite(0x14); //shift cursor one position right
 }
}

arduinobob

As a further refinement, I just rewrote the function from scratch so that it's a little smaller and much faster:

void LCD4Bit::cursorTo(int line_num, int x){
       commandWrite(CMD_HOME);            
     int row_address[] = {0x00,0x40,0x14,0x54};      //DDRAM addresses for lines 1 to 4
     commandWrite(row_address[line_num-1] + x + 128);  //128 to set high bit for command
}



MikMo

cool

Maybee you can get a "post permission" in the playgruond and upload your revised code?

Making the size of a lib. smaller is a good thing.

arduinobob

Mikmo,

Happy to do so, but in other open source projects there is a "module owner" of some sort coordinating all the changes in order to avoid random people (like me!) changing the library. Does the Arduino community have a similar notion?

thanks,
/Bob

mem

Quote
As a further refinement, I just rewrote the function from scratch so that it's a little smaller and much faster:

void LCD4Bit::cursorTo(int line_num, int x){
       commandWrite(CMD_HOME);            
     int row_address[] = {0x00,0x40,0x14,0x54};      //DDRAM addresses for lines 1 to 4
     commandWrite(row_address[line_num-1] + x + 128);  //128 to set high bit for command
}


As someone struggling to get the 4bit library to work with my LCDs, I am happy to hear that the code is being actively worked.

I am curious why you invoke  commandWrite(CMD_HOME);   doesn't issuing the cursor positioning command that follows make this redundant?
 
Also, you could save a few more bytes by making the row_address array an unsigned char instead of an int.


arduinobob

Mem,
Good call on both counts! Thanks.
1) The first time I looked at the HD44780 datasheet, I thought it said that the cursor home command did more than reposition the cursor-- something about resetting the display shift... But your comment prompted me to read it again, and to try doing without the cursor home command, which seems to work just fine.
2) As you suggest, we can save 4 bytes by changing the array from int to byte.
All of which leaves just:

//move the cursor to the given absolute position.  line numbers start at 1.
void LCD4Bit::cursorTo(int line_num, int x){
     byte row_address[] = {0x00,0x40,0x14,0x54};      //DDRAM addresses for lines 1 to 4
     commandWrite(row_address[line_num-1] + x + 128);  //128 to set high bit for command
}

paulb

#6
Dec 18, 2007, 05:24 am Last Edit: Dec 18, 2007, 05:29 am by paulb Reason: 1
Arduinobob,

When you finally get some attention, and permission, to change the library maybe take a look at this  issues too.  If the pin assignments for the datapins are not in order the code breaks. This came up with a module that was hardwired, and where I didn't have four consecutive pins. But it could just as easily arise in a prototyping situation, and generate irritating errors just because pin assignments are used as index constants.



Posts: 114
     
4bit LCD library code fixes
18.11.2007 at 05:10:46  
The 4bit LCD library has some too-clever coding that should probably be changed.


Code: [Select]


int DB[] = {7, 8, 9, 10};  //wire these to DB4~7 on LCD.


 for (int i=DB[0]; i <= DB[3]; i++) {

   digitalWrite(i,val_nibble & 01);
   val_nibble >>= 1;

 }





the for loop will break if the pin values for DB[0] - DB[3] are not in order.
This came up on a board with the pins hardwired to an LCD, so it's not just theoretical.

I think this is the fix, although I haven't tested it. I'm not sure whether I can declare variable
j there, but you get the idea.


Code: [Select]

 for (int i=0; i <= 3; i++) {

  int j = DB[i];
   digitalWrite(j,val_nibble & 01);
   val_nibble >>= 1;

 }



paulb



mem

#7
Dec 18, 2007, 09:26 am Last Edit: Dec 18, 2007, 09:27 am by mem Reason: 1
That's a nice simple solution.

You can declare j like that but it's not necessary to do so, the following is equivalent.
Code: [Select]
for (int i=0; i <= 3; i++) {
     digitalWrite(DB[i],val_nibble & 01);


The documentation should note that the pin assignments must be such that they map onto the LCD pins in ascending order:
 DB0->LCD DB4,  DB[1]->LCD DB5 etc.

arduinobob

paulb and mem,
Your proposed change looks great to me.
One question: why must the DB[] pins be in ascending order? Just from reading the code fragment you proposed (I haven't tried it), it appears to me that pins could be assigned in any order, eg int DB[] = {5, 7, 10, 9};
This would greatly increase the likelihood of an error in wiring, but the code would work, wouldn't it?
/Bob

mem

#9
Dec 18, 2007, 08:15 pm Last Edit: Dec 18, 2007, 08:18 pm by mem Reason: 1
Hi Bob,
The pins need to be wired in ascending order with the first assigned pin in the array wired to LCD DB4. It's the assignment order of the array that matters,  not the pin numbers,  because of the way the bits are shifted in the for loop.

Your example will work if  pins 5,7,10,9 are wired to DB4,DB5,DB6,DB7 respectively

arduinobob

mem,
I think we're saying the same thing. The first Arduino pin number in the array must be wired to DB4, the second to DB5, the third to DB6, etc, but the Arduino pin numbers themselves need not be in any particular order, as the 5,7,10,9 example sought to illustrate. Sorry for not being more clear!

mem

bob, I think we are saying the same thing, just not quite clear enough ;). Do you want  to have a go rewording the following to make it less confusing to future users of the new code

'pin assignments must be such that they map onto the LCD data pins in ascending order with whatever pin is assigned to DB[0] wired to LCD DB4, DB[1] wired to LCD DB5 etc.'

arduinobob

I think that wording is amply clear. Besides, any remaining ambiguity can be resolved by consulting the source code. :)

mrmeval

Your explanation is less confusing mem.
If it was designed by man it can be repaired by man.

Go Up