Another LCD driver (HD44780)
MagIO2
Posts: 2,243
I had a look into two LCD drivers I found in the object exchange. Of course they work ...
(more or less - initialization of one driver is weird as you can not restart the code without restarting the display)
But both are objects that run in the SPIN interpreter, steeling runtime from that COG ;o) I like a TV-driver approach, where the LCD communication is done in a dedicated COG. That's because code running in the COG is no longer needed in HUB-RAM.
The current version is simply a LCD driver without any extras. As you can read in the drivers comment-section I already have plans to improve that driver.
What do you think? Is there a need for an additional LCD driver in the ObEx? What features do you have in mind?
PS: The drivers first usage will be a intelligent DCC booster. That explains the text and user defined characters in the test-code.
One or two years ago I started the iBooster project on an AVR - in between I build our house. But now I want to redo the project with a prop.
Added new archive .. please find some words about the changes in the todays post further down (01-24-2010)
Replaced archive with the next iteration ... find some words about the change in my post (01-26-2010)
And here is the list of current features and what you can do with it:
- CMD_INSTR: of course you can send any LCD instruction like "Clear display", "Home", "Set cursor"·.....
- CMD_PRINT: print a string
- CMD_WRITE: write one byte (character or data-value)
- CMD_SETCHAR: write 8 bytes, which can be used to transfer the definition of a user defined·character
-·CMD_SETBLINK: set's one of eight blinking characters - or better alternating characters, because·you can define both. Using " " and "*" would give·you a blinking star, "a" and "A" would give a letter periodically·switching from upper to lower-case
- CMD_SETRATE: allows to alter the speed of blinking·AND scrolling
- CMD_SHIFT:·With this you can move the address with which the upper left corner of the display starts. So you can do horizontal scrolling with this without·moving the whole content. In 2 line displays you can use that for·a second screen.
- CMD_SETLINE:·here you address a screen position and a string which is bigger than the screen. The driver then takes care of scrolling the·string from right to left. It also allows to use a subsection of a row instead.
- CMD_SETLEN: This was the old instruction to choose a subsection for SETLINE. Now you can choose the incrementor for the scrolling. For example an incrementor of 0 will stop scrolling. This is cool, as now you can use the string-buffer as a screen buffer. Whatever you write in that buffer will appear on the display according to the refresh-rate.
You can set it to 2 to scroll in steps of 2 characters.
You can set it to the width of your display and you have an alternating row.
### update on 02-07-2010 ###
- CMD_SATOMIC: Don't interrupt the subsequent LCD.execute instructions by blinking character and/or scrolling lines
- CMD_EATOMIC: End atomic-state
- CMD_OTSCROLL: If you switched off automatic scrolling for a scrolling line, you can scroll it manually with this instruction. This has been introduced for menu-support.
LCD_test_2 contains a demo for a 2 lines display.
LCD_test_4 contains a demo for a 4 lines display.
Please note: I put the driver to the object exchange, so please find the latest version there
SSteve reported a problem in post #26 (-THANKS FOR THAT-):
The output of the driver contained garbage. The problem most propably is the wiring in combination with the high frequency of the signals. It can be fixed easily by opening the BenkyLCDdriver.spin, searching for
w500ns long 25
and replace the 25 with 200. This will change the clock-timing.
Post Edited (MagIO2) : 3/4/2010 4:43:46 AM GMT
(more or less - initialization of one driver is weird as you can not restart the code without restarting the display)
But both are objects that run in the SPIN interpreter, steeling runtime from that COG ;o) I like a TV-driver approach, where the LCD communication is done in a dedicated COG. That's because code running in the COG is no longer needed in HUB-RAM.
The current version is simply a LCD driver without any extras. As you can read in the drivers comment-section I already have plans to improve that driver.
What do you think? Is there a need for an additional LCD driver in the ObEx? What features do you have in mind?
PS: The drivers first usage will be a intelligent DCC booster. That explains the text and user defined characters in the test-code.
One or two years ago I started the iBooster project on an AVR - in between I build our house. But now I want to redo the project with a prop.
Added new archive .. please find some words about the changes in the todays post further down (01-24-2010)
Replaced archive with the next iteration ... find some words about the change in my post (01-26-2010)
And here is the list of current features and what you can do with it:
- CMD_INSTR: of course you can send any LCD instruction like "Clear display", "Home", "Set cursor"·.....
- CMD_PRINT: print a string
- CMD_WRITE: write one byte (character or data-value)
- CMD_SETCHAR: write 8 bytes, which can be used to transfer the definition of a user defined·character
-·CMD_SETBLINK: set's one of eight blinking characters - or better alternating characters, because·you can define both. Using " " and "*" would give·you a blinking star, "a" and "A" would give a letter periodically·switching from upper to lower-case
- CMD_SETRATE: allows to alter the speed of blinking·AND scrolling
- CMD_SHIFT:·With this you can move the address with which the upper left corner of the display starts. So you can do horizontal scrolling with this without·moving the whole content. In 2 line displays you can use that for·a second screen.
- CMD_SETLINE:·here you address a screen position and a string which is bigger than the screen. The driver then takes care of scrolling the·string from right to left. It also allows to use a subsection of a row instead.
- CMD_SETLEN: This was the old instruction to choose a subsection for SETLINE. Now you can choose the incrementor for the scrolling. For example an incrementor of 0 will stop scrolling. This is cool, as now you can use the string-buffer as a screen buffer. Whatever you write in that buffer will appear on the display according to the refresh-rate.
You can set it to 2 to scroll in steps of 2 characters.
You can set it to the width of your display and you have an alternating row.
### update on 02-07-2010 ###
- CMD_SATOMIC: Don't interrupt the subsequent LCD.execute instructions by blinking character and/or scrolling lines
- CMD_EATOMIC: End atomic-state
- CMD_OTSCROLL: If you switched off automatic scrolling for a scrolling line, you can scroll it manually with this instruction. This has been introduced for menu-support.
LCD_test_2 contains a demo for a 2 lines display.
LCD_test_4 contains a demo for a 4 lines display.
Please note: I put the driver to the object exchange, so please find the latest version there
SSteve reported a problem in post #26 (-THANKS FOR THAT-):
The output of the driver contained garbage. The problem most propably is the wiring in combination with the high frequency of the signals. It can be fixed easily by opening the BenkyLCDdriver.spin, searching for
w500ns long 25
and replace the 25 with 200. This will change the clock-timing.
Post Edited (MagIO2) : 3/4/2010 4:43:46 AM GMT
Comments
I may just port my own Spin driver for the HD44780 to PASM -- will be a good exercise and provide a different take for those like me who enjoy differing viewpoints.
By writing the first object yourself you ensure your understanding of the basic concepts is sound, which makes it that much easier when you are scratching your head wondering "why the heck did he write it like that?!?".
Often it's a tradeoff of size vs speed or the ease of adding new features. In any case, you can never have too many examples to learn from, particularly in diverse languages.
I recently got back into the PIC's with a dsPIC, and went in search of a flashy led hello world example in asm. Do you think I could find one? 50 examples in C (and one in Pascal) but none in asm. Plenty of forum posts asking for one and lots of replies saying "nobody uses asm on those chips". You are never short of an example in Spin or PASM [noparse]:)[/noparse]
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
lt's not particularly silly, is it?
Current status is that blinking characters work ... currently I support 8 blinking characters
I added a shift instruction ... with this you can shift the start adress to be displayed to the left or to the right by as many steps as you want ... so you can switch between 2 screens for example
With the next "milestone" (the scrolling text) I will provide the sources again.
Post Edited (MagIO2) : 10/29/2009 10:03:17 AM GMT
Things changed:
CMD_SETRATE => the general rate used for blinking and scrolling can be changed
CMD_SHIFT => if you have a 1 or 2 lines display you have unused display RAM. With shift you can have independent screens or shift the content of the display n characters to the left/right
CMD_SETLINE => here you can point to a string which can be much longer than the screen. The driver will then take care of scrolling this string in one line. It can even be a subsection of this line.
Other usage is, to define a screen-buffer for a line. So you don't have to use 'set cursor', print or write to update the screen. Just write what you want to display into the screen buffer and the driver takes care of sending it to the display.
CMD_SETLEN => this is for setting the number of characters to print by the SETLINE. This will most likely be changed in next step, so you can have one line which scrolls across the whole screen while another one only scrolls 10 chars.
Nice feature in the LCD test is the progress bar.
Cleanup still needed. So it's just another iteration to a version that I could put into the Ob-Ex. Is someone using the driver? Feedback welcome!
Added the current archive to the top post.
Post Edited (MagIO2) : 1/25/2010 8:57:06 AM GMT
Another usage came into my mind. If you have a string of n*16 characters and you set string incrementor to 16 it will show the first string ... then the second .... up to n and start from beginning again. I don't have a demo for that yet ... maybe later.
Another improvement:
I found a small ... well ... it's not really a bug. But the code that generates the signals was waiting far to long. Instead setting E to high, wait ~250ns and set E to low for at least ~250ns, I did not change the setting from init-phase. It was 500ns, 500us ... Changed that to ~300ns for both. Now compare the progress bar with the old version ;o)))
Still no feedback? Then I'll propably put the next version into ObEx.
Have fun!
PS: added the following code as demo for the alternating text:
And I also have some code for a 4 row display:
Post Edited (MagIO2) : 1/26/2010 9:25:19 PM GMT
Please have a look at the feature list I've added to the first post. I still have ~200 longs free in the LCD COG.
Current planning is to include menu support.
But I could also think of a PWM for fading the backlights of the LCD.
any other ideas?
I'm not sure if adjustable contrast is that useful. My current feeling is that a adjustable resistor gives a constant contrast, as I never changed it after initial setup. But on the other hand, having both is a good use for the 2 counters and not to much code is needed for that.
PS: I checked that There is no PASM code which uses a fixed line-length - just set your display size in the constant
STG_LINE_WIDTH
Post Edited (MagIO2) : 1/28/2010 9:25:53 PM GMT
What shall I say: IT WORKS!
Well ... it depends on the display. First I used a 2x16 blue/white display and it did not work. Then I used a 4x16 green/black display and here it works.
So, if you want to display a little splash-screen when starting the application ...
... or you want to show a temperature curve ....
... or you want to show a frequency spectrum ...
... or you simply want to double the available user defined characters ...
no need to spend extra $ for a graphical display if the graphics can be simple.
Enjoy
The bug I found·was related to the graphics output·introduced with the·previous post. I played a bit with it for a temperature logger. It measures the temperature periodically and displays the actual value in degree Celsius and plots the value in a curve showing the last 40 measurements. So it was using the screen-buffer-mode for the line containing the temperature together with the graphics output. This combination does not work correctly and leads to trash-output.
Problem is, that both outputs (the line containing the temperature and the graphics) need to send LCD instructions. (Set CRAM or set cursor). But the screenbuffer-output is done periodically and can·be processed in the middle of the·SPIN code·sending the new graphics data.
Solution: I introduced 2 new instructions for setting a bunch of LCD commands·to being atomic. So, neither blinking characters nor a scrolling line will be executed unless the atomic operation is finished.
CMD_SATOMIC
CMD_EATOMIC
The next instruction is for supporting menus - but can be usefull for other things as well. This is possibly the first step in menu support ... maybe the only one ... don't know yet ... depends on how much need is out there for menu support ? ;o)
CMD_OTSCROLL
(for one time scroll)
will scroll the text in a line by the given number of characters. You can see how·to create scrolling menus with that in the demo. (The demo has been written for a 4x16 LCD, should also work with other 4 line displays, but needs changes for 2 line displays)
Post Edited (MagIO2) : 2/7/2010 9:45:17 PM GMT
just for us newbbbb's
What you found is not a problem in the driver itself. But changing the constant in the driver is only half of the truth. The demos themself are written for 16x displays. To make them work you have to check the function calls which contain cursor positioning. And as the CMD_SETLINE also set's the cursor the 16x4 demo won't work properly for your 20x4 display (.... maybe I should add constants to the demo-code as well ...)
[noparse][[/noparse]code]
· LCD.exec( LCD#CMD_SETLINE, LCD#PAR_LINE1 +·········· @scrbuf1 )
· LCD.exec( LCD#CMD_SETLINE, LCD#PAR_LINE2 + $40<<16 + @scrbuf2 )
· LCD.exec( LCD#CMD_SETLINE, LCD#PAR_LINE3 + $10<<16 + @scrbuf3 )
· LCD.exec( LCD#CMD_SETLINE, LCD#PAR_LINE4 + $50<<16 + @scrbuf4 )
[noparse][[/noparse]/code]
The part which sets the cursor is the xx<<16. Rather than working with x any y coordinates, this instruction works with display RAM addresses.
The first line starts at address $00, the second at $40 (that's true for 16x and 20x displays) But the 3rd and 4th start at $10 and $50 for 16x and at $14 and $54 for 20x displays.
By the way ... the function that sets the cursor looks like that:
[noparse][[/noparse]code]
··· LCD.exec( LCD#CMD_INSTR, ( %10000000 + $45 ) )
[noparse][[/noparse]/code]
This one would set the cursor to 2nd line 6th character.
I see that it would be easier for newbies to have comfort-functions. But I'm not sure if this is a good service in the end. We talk about programming a microcontroller. In my opinion comfort is only good where it does not cost RAM or runtime.
As a newbie you not only learn how to program, you also learn habits. If you get used to comfort functions at this time, you will also use them when you're more experienced - and possibly forget about the fact that you could do it wasting less RAM when you'd need it.
Of course there are drivers which really do hardcore stuff and need to be translated to easier functions. But I think an LCD-driver is not that difficult to understand.
... and hey ... if you really want those functions, then write a wrapper for the driver like in TV and TV_Text.
like how to solve problems with programs. My school days are long behind me.
anyway as soon as i hit send on the keyboard. i saw what was going on with the code.
I figured it out. I am going to port the driver to my timer project.
Another good source of wisdom is code .... search for well documented source-code in the object exchange and not only have a look at how to use it correctly, but also look how the things are solved. If you can not figure out why things are done in that particular way, simply ask here in the forum.
Experience it worth a thousand books.
··I have a satisfactory collection of reworked unipolar stepper methods·but there is nothing in the obex the last time I looked. I know there is better code...somewhere. Because I·think unipolar stepper code should be·in that basic building block list of objects I may submit my own code.
· I, for one, have to study seasoned programmers to get up to speed. MagIO2 is one of the classes I attend.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
PropellerHead
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Jon McPhalen
Hollywood, CA
after a first glance into jm_lcd4_demo.zip, I'd say that your scrolling is doing nearly the same thing as my LCD#CMD_SETLINE instruction in default mode. I think the difference is that you scroll through the text and return, while SETLINE will start from the beginning again.
@lardom:
I see some flowers in your post -thanks for that-, but I'm not sure whether there is a question or a request for changes in the driver?
When putting the driver into the object-exchange, I also switched to maintenance mode - as I have other things to code ;o)
So, even if I have some more ideas for that driver - especially when reading such feedback - I will only update the driver on request by others (new functions, bugfix), or when I come back to a project that uses a text display and find out that there is something missing.
What I expect to happen is that "First Message" shows up on line 2. After that, it should cycle through ASCII characters first on line 2 then on line 1. But what I see is "First Message" on line 1, then cycling through ASCII characters on the first half on line 1 then the second half of line 1. I've attached a movie to illustrate.
Am I doing something wrong?
If someone can give the attached program a try and let me know if they see the same thing that would be a big help. I have a switch attached to pin 14 to choose which driver to use, but you can also get rid of the if statement and comment out the call the the driver you don't want to use.
I normally use bst under OS X but I also tried this with Propeller Tool to rule out any bst-related issue.
You could also make sure that there is no solder flux between the pads of the LCD. At higher frequencies solder flux can cause problems.