Page 1 of 1

Help with KS0073 Initialization

Posted: Thu Aug 01, 2013 4:50 pm
by PINTO
Hi all,

I need help.

I have a BTHQ42003AV-STF-06 Display module that doesn't initialize with FlowCode LCD Makro.
I bielieve the reason is that FlowCode Makro was designed based on the HD44780 Hitachi Driver.
My LCD Module is based on the KS0073 display driver and apparently are certain dicrepancies in the initialization procedures.
I've searched the net for a couple days now to see if I could find something that I could do, But apparently the solution is beyond
my understanding of C Progaming (Tha's why I choose Flowcode).
I know there a lot of champion programers on this forum and maybe one of you could lend me a helping hand.

I only need to initialize the LCD properly and the adressing of the 4 lines the rest I bilieve is straight forward with flow code
wich I'm getting confortable by now.

My display:
20 characters(5x8 dots) x 4 lines STN Positive Transflective Yellow Dot Matrix LCD module.
Data sheet:
http://za.rs-online.com/web/p/lcd-monoc ... s/7436153/

Thank you

Pinto Ramos

Re: Help with KS0073 Initialization

Posted: Fri Aug 02, 2013 4:47 am
by Spanish_dude
Looks like the controller used is a RW1067. I don't know if it's the same as a KS0073, but I've found this datasheet : http://www.newhavendisplay.com/app_notes/RW1067.pdf

Take a look at it, it explains what you need to do to drive that LCD. There's even an initialization flowchart.
Try to program it yourself using flowcode and flowcode macros. If you have any trouble, let me know.

Others or myself will try to help you.

- Nicolas

Re: Help with KS0073 Initialization

Posted: Tue Aug 06, 2013 11:15 am
by beambase
Or you could use this display or a different colour of it.
http://www.crystalfontz.com/product/CFAH2004BTMIET
Almost the same dimensions, cheaper and it works directly with Flowcode. I have tested it.

Re: Help with KS0073 Initialization

Posted: Tue Aug 06, 2013 1:27 pm
by PINTO
Thanks guys for your help.
I found the data sheet for the KS0073 Sumsung LCD Driver.
http://www.lcd-module.de/eng/pdf/zubehoer/ks0073.pdf
Changing LCD's at this time is not possible.

I wrote a initialazation makro in Flow5 and works 0n 2 lines only.
According to the data sheet the instruction to set it up in 4 lines is on the extended instruction set have to set NW=1
In order to get to the extended instruction set i have to set RE=1 set NW=1 and RE=0

I have tried all possible combinations for the last 2 days and the display just goes blank.

I now sort of hit a dead end.

If someone could help I would appreciated.

This is my Flowcode.

Pinto

Re: Help with KS0073 Initialization

Posted: Tue Aug 06, 2013 2:16 pm
by kersing
Have you tried the sequence listed on page 63 of the data sheet?

Looking at your flow chart I do not see any similarities between the commands in the documentation and the bytes you are sending to port D in the LCD_INIT routine. Also, according to your comments you set the display to 8 bit mode with the same command used to set it to 4 bit mode?

What I would do is:
- Add a delay of at least 10 ns at the end of Enable_E as the data is required to stay stable after the falling edge of E (page 77 of the data sheet, th2)
- For initialization (assuming you use 8 bit mode) after power on wait 1 second and send:
R/W = 0, RS=0: 0x3C, 0x09, 0x38, 0x0C (or in decimal: 60, 9, 56, 12)
Then set RS and start sending some string.

Re: Help with KS0073 Initialization

Posted: Wed Aug 07, 2013 7:18 am
by Spanish_dude
I've recently made a WS0010 driver (only 8 bit mode done).
Here's how I've done it.

First thing I did, is I made a "sendByte" function that is able to send instructions, as well as data to be written on the LCD.
So my function looked something like this:

Code: Select all

/*
u8 = unsigned 8 bit value (unsigned char)
CONTROL_PORT is the port where you connected the RS, RW and EN pins
DATA_PORT is the port where you connected the DB0~7 pins
RS_BIT is the pin number where you attached your RS pin on the microcontroller
RW_BIT ...
EN_BIT ...
*/ 
int sendByte(u8 RS, u8 RW, u8 data)
{
    if (RW != 0)
        return -1; // RW need to be 0 to write something to the controller
    else
        clear_bit(CONTROL_PORT, RW_BIT);

    // If it's data, set to 1, if not, set to 0
    if (RS != 0)
        set_bit(CONTROL_PORT, RS_BIT);
    else
        clear_bit(CONTROL_PORT, RS_BIT);

    DATA_PORT = data

    // Set your data BEFORE your enable bit
    set_bit(CONTROL_PORT, EN_BIT);
    delay_ms(1);
    // Once you set your enable bit, give the controller a little bit of time and then clear every bit you set
    clear_bit(CONTROL_PORT, EN_BIT);
    clear_bit(CONTROL_PORT, RS_BIT);

    return 0;
}
Second thing to do is make a "readBusyFlag" function. Every controller, when an instruction is sent to it, sets its DB7 bit high (RS & RW need to be set to "01") whenever it's busy processing an instruction.
You could leave this only if you give the controller enough time to process the instructions and you are sure it has done processing data.

Code: Select all

/*
retval is the value of DB7 (either 0 or 1)
DATA_TRIS is the TRIS register of the data port to set a pin as input or output
CONTROL_TRIS is the TRIS register of the control port
*/
u8 readBusyFlag(void)
{
    u8 retval = 0;

    set_bit(DATA_TRIS, 7); // set data port pin 7 to an input
    clear_bit(CONTROL_PORT, RS_BIT); // clear RS bit
    set_bit(CONTROL_PORT, RWB_BIT); // set RW bit (read-mode)
    delay_ms(1);
    set_bit(CONTROL_PORT, EN_BIT); // set enable bit
    delay_ms(1); // wait for a ms
    retval = GETBIT(DATA_PORT, 7); // read pin 7 (DB7)
    clear_bit(CONTROL_PORT, EN_BIT); // disable the controller
    clear_bit(DATA_TRIS, 7); // set pin 7 back to output
    clear_bit(CONTROL_PORT, RWB_BIT); // clear the RW bit (write mode)

    return retval; // return the value of DB7
}
Now you can use both those function to either send instruction or data and wait for the controller to process that information.

Your next step will be to make an initialization function. This consist in using the sendByte function, readBusyFlag function and delay_ms function.
Based on page 63 of your KS0073 datasheet, this is what your initialization code could look like:
(1) Note that in the function set, setting the LCD to 1 or 2 lines doesn't really matter because you're going to use the extended function set to set it to 4 lines.
But you have to use the function set first, because this is what determines if you're using 8 bit mode or 4 bit mode.
(2) Don't forget that not all the instruction can be executed when the extended register is set. Take a look at Display ON/OFF Control instruction. RE needs to be 0 for it to be recognized and processed the way it should!

Code: Select all

void initLCD(void)
{
    delay_ms(25); // wait more than 20 ms after power up

    // Set Extended Register to 1
    // Function Set (check datasheet p.27)
    sendByte(0, 0, 0b00111100); // send instruction (RS=0, RW=0) Function Set: 8 bit mode (1), 2 lines (1), extended register enable (1)
    while (readBusyFlag()); // while busy flag is set, do nothing
    delay_ms(1); // wait for a ms

    //Extended Function Set (check datasheet p.26)
    sendByte(0, 0,  0b00001001); // send instruction Ext. Function Set: 5-dot font (0), cursor blink invert disabled (0), 4 line display mode (1)
    while (readBusyFlag()); // while busy flag is set, do nothing
    delay_ms(1); // wait for a ms

    // Clear Extended Register
    // Function Set (check datasheet p.27)
    sendByte(0, 0, 0b00111000); // send instruction (RS=0, RW=0) Function Set: 8 bit mode (1), 2 lines (1), extended register enable (0)
    while (readBusyFlag()); // while busy flag is set, do nothing
    delay_ms(1); // wait for a ms

    // Display ON/OFF control (datasheet p.26)
    sendByte(0, 0, 0b00001100); // set display on (1), cursor off (0), blink off (0)
    while (readBusyFlag()); // while busy flag is set, do nothing
    delay_ms(1); // wait for a ms

    // Clear Display
    sendByte(0, 0, 0b00000); // send instruction clear display
    while (readBusyFlag()); // while busy flag is set, do nothing
    delay_ms(2); // wait for more than 1.53 ms

    // Entry mode set
    sendByte(0, 0, 0b00000110); // set cursor increment (1), disable shift (0)
    while (readBusyFlag()); // while busy flag is set, do nothing
    delay_ms(1); // wait for a ms
}
Check out p.28 to set the DDRAM address and to write data to that address (RS=1, RW=0).
I think I've said enough for you to continue.

PS: I don't think using the LCD macro's from flowcode will work with your LCD.

Re: Help with KS0073 Initialization

Posted: Wed Aug 07, 2013 9:51 am
by kersing
Hi Spanish_dude,

A few comments:
  • * Slight optimization would be to check for the busy flag before sending a command, not wait after sending.
    * Your write sequence does not match the timing diagram on page 77 (fig 21) where there is a minimum delay between setting WR/RS and enable. Also according to the timing enable is set to one before new data is presented.
    * The init sequence on the page 63 is for 4 lines. The one you refer to is for 2 lines. You code (almost, see next item) implements the right one.
    * In the init routine you are sending the extended function set twice, once after resetting the extended register enable.
    * The TRIS bits for the outputs are not explicitly set. You are assuming the setting is right, good practice is to make sure ;)
    * I fear the code might be beyond the capabilities of the original poster. A flow chart implementing this might be better for the OP.
Regards,

Jac

Re: Help with KS0073 Initialization

Posted: Wed Aug 07, 2013 3:59 pm
by Spanish_dude
Hi Jac,

1) I do both: "while(readBusyFlag());" and then a delay.
Just to be sure and because the controller needs 1/2Fosc before sending a new instruction. (I think I read that somewhere)
2) It does not match the timings, but I think it should work.
I have made my WS0010 driver like that. I didn't find any timings so I've just set/clear everything before enabling the controller and it works just fine.
3) Yes, I started with the one on p.58, but I saw that that's for the 2 line mode and changed it like the one on p.63.
4) Oh, yes my bad, copy pasted the thing and forgot to remove it. I'll remove it.
5) I thought that was pretty obvious so I didn't add it in the init function, but yes, the data and control port should be set to output at the start of the init function.
6) Well don't really think there's anything very complicated. If the OP knows how to set or clear an IO, he just has to take my code and make it into flowcode.
Hopefully it works and I'm not wasting OPs time :lol: .

- Nicolas

Re: Help with KS0073 Initialization

Posted: Wed Aug 07, 2013 6:08 pm
by kersing
Hi Nicolas,

1) My point was that there is no need to wait first and delay after. The delay (on in an other flow chart you other operations) will probably give the display all the time it needs to process the command, so just a check if it is still busy when you want to send a command will work. It saves a few cycles waiting for the display while the PIC can do something useful.

2) Regarding the timing, it might work, it might not work or it might work most of the time and fail unexpectedly (a nasty condition to debug). No need to guess, I would just add a very small delay (1 ms) before setting enable to 1 and change the data bits after setting enable to 1.

5) What experienced users consider obvious can be magic for a beginner...

6) Would you have thought it was complicated before you started programming in C? ;-)

On the whole I like your code, just wanted to give some pointers for improvements/clear up some possible issues.

Best regards,

Jac

Re: Help with KS0073 Initialization

Posted: Wed Aug 07, 2013 9:27 pm
by Spanish_dude
Hi again,

1) We are talking about the initialization of an LCD. This is done at the power up of the microcontroller and LCD. I've never seen anyone do an LCD initialization in the middle of his code.
I don't think you need to optimize this as much as you'd want.
Whenever you are initializing something, you do just that or else any other code executed could make the initialization fail (by setting I/Os used by the LCD for ex.).
This is a function that initializes the LCD, and it will do just that. If someone wants to start an interrupt while the init is being processed, I don't see a problem as long as it doesn't interfere with the I/O used by the LCD.
What I wouldn't like to see is have some external code to the initialization of the LCD, inside this function. That wouldn't make any sense :mrgreen: .

2) Yes, you're correct. It has been working for me, might not work with OP's LCD.

5) Very true...

6) That's right, but I don't think my code is that difficult. There's two "main functions" the OP can read and "translate" to flowcode, just by following step by step what I did.
I've not done anything particularly difficult and I think I added plenty of comments to the code. It's like reading plain text :mrgreen: .

I appreciate the feedback.

- Nicolas

Re: Help with KS0073 Initialization

Posted: Thu Aug 08, 2013 9:18 am
by PINTO
Thanks Nicolas, Thanks Jac.
Your help has been an eye opener for me.
I manadged to get the KS0073 working from Flowcode.
I will post the FCF when I'm donne.
My next hurdle is to split the ADC value into High and Low bites like the old thermometer in flow3. (whatever happen to the thermometer component?)
I need to display the following "Motor-1 20.16 Ma".
With the thermometer component this future was available but the thermometer is no longer available. Is it??
Some pic's of my project.

Thanks

Pinto