[SOLVED] Lcd Rgb Instruction register bits


#1

Hi,
I’m using the Grove LCD Rgb Backlight module in 8bit - 2Lines mode with GrovePi.
As long as I’m setting the rgb or text it’s working fine and clear. Regarding the “basic” functionalities I was able to figure out what to send over I2C. Data register is fine, my focus is only on the instruction register. I also understood that the instruction register has enable, register select, and read/write bits. The problem started when I wanted to read from the device. (always returned 0xFF).
So what do I know?
instruction - function
0x80 1000 0000 - this is how you write to the data register
0x40 0100 0000 - this is the instruction to write the character codes

And in 8bit mode you send 2 bytes: one for the Instruction register the other one for the Data register. That is ok.
What is the byte and command sequence to read for example the busy flag?

Could you please describe all the bits of the instruction register to solve this puzzle!
Thanks


#2

Hi @andras75,


A really good source of information is Seeed's repository. You can look at their code (which is much more elaborate) and search. Here’s a link.

Unfortunately, I can’t find the datasheet of the LCD driver. It was on Seeed's website, but not anymore. It helped me a lot when I needed.

Last but not least, the simplified procedure for reading a register via the I2C is this:
send device address (with write bit) -> send register address -> send device address (with read bit) -> read register value.

Also, what are you trying to achieve?


Please let know how it goes for you and after that I’ll get back to you.

Thank you!


#3

Alright, here is the thing.
I needed a little bit more than setting the text and the rgb color of the lcd device, - so as per usual - I checked everybody’s source codes. (hehh, almost literally).

There are two main ways to deal with wiring/i2c:
Lowlevel - The low level way where each ping is paired to a boolean (or a boolean returning function). So they do the protocol kinda bit by bit. Here is a good and related example:

//monitor the busy flag of LCD on its DB7
void waitLCD(void)
{

   unsigned char busy=1;
   //unsigned char cnt=0;
   do
   {
      DDRC=0xff;
      PORTC=0xff;   //Set all data pins to 1 initially
       DDRC=0x00;   //configure all bits as inputs
      EN=0;      //Start LCD command
      RS=0;      //It's a command
      RW=1;      //It's a read command
      EN=1;
      busy=BF;   //read the busy flag
      //cnt++;
      
   } while(busy==1);// && cnt<255);
   EN=0;   //Finish the command
   RW=0;   //Turn off RW for future commands

Highlevel - Using a library like the fivdi’s i2c-bus. In these cases the usual atomic unit is a byte, and the physical wiring is paired with bits of the particular byte.
Example:

...
let chc = line[i].charCodeAt(0);
i2cBus.writeByteSync(TEXT_I2C_ADDR, 0x40, chc);
...

Both approaches have their role, it’s not about that. :slight_smile:
I use the highlevel approach since I’m developing in nodejs for node-RED and other than these conditions the lib I’m referring to is a very nice one, covers all the I2C householding for me. (setting the write bit, receiving nacks, acks, etc.) Also it’s fully async and sync, so I have that flexibility as well. Well, having mentioned the advantages of the lib: it has writeQuick and readQuick which are commands to send a single bit. (never had to use that)

I read the HD44780 datasheet and every second page they warn us to check the busy bit. Being a good geek I thought I’ll implement that thing, and it also gives back address values other than the busy bit.
Also understood, that we are - other than the initialization - talking about microseconds, and with software level delays they are going to work fine keeping the code device agnostic. In fact you don’t even have to deal with the busy flag at all. I went for this solution obviously.

What do I want to achieve? Well, it’s more like I’m kinda frustrated not being able to work out the solution from the datasheet. It’s more like learning how to translate a datasheet to code. Having a 0x80 and 0x40 in the code works, but you know… wouldn’t it be nicer with constants?

mehh, it was long.


#4

Hi @andras75,

This sounds like a really awesome project, we would love to hear more about the GrovePi and NodeJs.

It sounds amazing! Unfortunately you seem to have gone beyond our expertise level.
I’m not sure we can help with this one. You might want to reach out to Hitachi, the OEM (the Seeed for instance), for clarification on this.


If we can help in any way, please let us know. It sounds like you’ve gone deeper into the firmware and registers than anyone on our team has.
Again, we’d love to see what you make with it and help out in any way we can.


Thank you!


#5

Robert, many thanks for the honest answer, much appreciated. The HD44780 datasheet is indeed the bible in this case. You can close the thread, consider it solved. Thanks for your time!

my conclusions:
Very little blocking waits can solve the problem. 2ms is enough. This is most important when you init the device. I know it’s a “compromise” if one is a firm believer of the async nodejs god…

ps: I’ll be glad to present you our project, it’s coming together nicely. The GrovePi and all around it (support, example codes, etc) helps a lot.


#6