LCD Code Simplification
IRobot2
Posts: 164
I am using the Matrix Orbital LCD (LK204-25) from Parallax (30058) connected to my prop. To communicate with it I am using the FullDuplexSerial Object from the Obex. I am currently using statements like this:
LCD.tx(254)
LCD.tx(71) ‘’Set Cursor Position
LCD.tx(9) ‘’Column Position
LCD.tx(3) ‘’Row Position
LCD.str(string(“Hello World”[noparse];)[/noparse])
As you can see this takes up a lot of space (and time). Is there any way to simplify this into one line? I have page after page of this just to display basic things. All the commands I took right out of the manual. Any help or thoughts would be greatly appreciated.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Alex Burke
"Beware of computer programmers that carry screwdrivers." -Leonard Brandwein
LCD.tx(254)
LCD.tx(71) ‘’Set Cursor Position
LCD.tx(9) ‘’Column Position
LCD.tx(3) ‘’Row Position
LCD.str(string(“Hello World”[noparse];)[/noparse])
As you can see this takes up a lot of space (and time). Is there any way to simplify this into one line? I have page after page of this just to display basic things. All the commands I took right out of the manual. Any help or thoughts would be greatly appreciated.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Alex Burke
"Beware of computer programmers that carry screwdrivers." -Leonard Brandwein
Comments
So as a first hint: Do understand what a "PUB-method" does in general ?
read a little bit in the manual about "PUB"
I think this will get you ahead. If you don't understand it - come back with a new and more concrete questions
best regards
Stefan
The exception is that you can not send a 0 value, as strings are zero-terminated in Spin.
Jonathan
(sorry Stefan, I was going to point to the manual, but it's wasn't overly helpful)
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
lonesock
Piranha are people too.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Alex Burke
"Beware of computer programmers that carry screwdrivers." -Leonard Brandwein
MultiLineMethod(0,0,"hello world", etc, etc, etc, etc ...., terminate)
PUB MultiLineMethod(row, line, string1, sring2, string3, string4 etc etc etc etc etc )
' do the work for row
' do the work for line
' do the work for string1
' do the work for string2
' do the work
' do the work
' do the work
' do the work
You could have a long list of possible 'work' lines, and use some termination scheme to RETURN if a parameter is designated as a terminating value.
This obviously needs to be thought out but this should set you on an easier path.
Another use for PUB while we are on it...
Say you don't like typing out waitcnt(80_000_000 + cnt) a thousands of times in your life of using the Propeller, do this instead:
PUB w(time)
waitcnt(time + cnt)
Then when you need to make a wait you just call w(80_000_000), much shorter and faster to type.
Use PUBs to reduce manual redundant input when a pre-coded method will just receive parameters and do all the work.
Post Edited (Todd Chapman) : 11/6/2009 5:51:16 PM GMT
I made a quick review of the chapter about "PUB" in the manual.
Does say not very much for real newbies.
The fundamental sense of a STRUCTURED programming language is to build complex commands out of basic commands.
You can imagine this similar to a mechanical machine. The mechanical machine is build by many parts.
Screws, ball-bearings, axles, etc. Each part has a basic function. A screw has the function of "keeping two parts together".
A ballbearing has the function of "making the axle turning with ease". All parts mounted together in a certain way result in a
car or a handdrillmachine or whatever - which do very complex things compared to what a single part can "do"
And on that general level of explanation it is the same with "PUB"s.
SPIN has a basic set of commands. And you can use this basic set of commands to create more powerful and or complex commands
In the mechanical analogon a car has functional sub-parts like "motor", "gearbox", "current-generator" etc. etc.
So f.e. the gearbox has a housing that keeps all parts inside the gearbox together.
On the level of the car as a whole thing. it is not interesting what happens inside the gearbox
If the gearbox is broken one solution is to replace the whole gearbox. If you do so
the details inside the gearbox doesn't matter. It's only interesting what size has the gearbox and what is the diameter
of the shaft and what is the profile of the shaft. If this does fit to the motor everything is OK.
And you can understand a "PUB" similar to the gearbox-housing.
If you write a piece of spincode
The PUB "WriteToLCD" holds the more basic commands like lcd.tx(254) etc. together.
Now you can use the PUB-Method named "WriteToLCD" in this way
and this one line of code replaces
This principle can be nested almost endlessly. (until you run out of memory)
This means now you could create another PUB-method
and call this method
and the result on the LCD will be
If you take a look into almost any object-file like
in the FullDuplexSerial-object you will find "PUB-methods" all over
and PUBs using other PUBs
This is like some screws (containing a head and the "winding") and axles, ballbearings, toothwheels) build the gearbox and the gearbox is just a sub-unit of the car
And those cars maybe belong to a company delivering pizza.
best regards
Stefan
Post Edited (StefanL38) : 11/6/2009 7:12:55 PM GMT
i am not sure if this will help you out or not i have used this code and it works for me you might have to do some editing.
http://obex.parallax.com/objects/40/
·
Thanks every one for all your help. I just shrunk the amount of code I had by about 3/4. Funny how learning something so small can save you days of headache!
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Alex Burke
"Beware of computer programmers that carry screwdrivers." -Leonard Brandwein
hm - it's not clear to me what you mean by STACKspace in this case.
Maybee I have "tomatos on my eyes" ) and I have to learn something important to close a gap of knowledge
about programming in SPIN.
Defining complex methods and coding callings of these methods in most cases saves HUB-RAM-memory.
So please can you explain what you mean by
"this means for the stack space to make it perfect. Otherwise your lesson will very soon end in frustration ;o)"
I really don't understand and I appreciate if you explain it to me.
best regards
Stefan
For each function you call you need some memory on the stack (even if it does not have parameters/local variables). The main SPIN interpreter has the whole not used HUB-RAM as stack-space. For each other SPIN function that you start in a new COG, you have to give a stack adress that it can use. (See description of cognew).
If you create a function that calls a function that calls a function that calls ..... you need more and more stack-space for each level. If you don't know that it will very soon become a problem. Because when stackspace is to small a function-call can overwrite memory that's been used otherwise. For example one stack overwrites another stack. Thus the return values and return adress might be overwritten. This can lead to very curious results.
Post Edited (MagIO2) : 11/6/2009 9:28:02 PM GMT
I understand what you mean. And in the backround of my head I was aware of that. So what confused me was that you wrote
"...lesson will very SOON end in frustration" I imagined write a small demoprogram with nested method-calls 4 or 5 levels deep
and you have already a problem.
I remember some threads discussing on that issue and that for an exact caclulation the worst case of nesting has to be found.
I did a research on the forum but I did not find a formula to calculate the stackspace required per one call.
X bytes for every parameter, y bytes for the method itself etc.
If somebody has this formula HANDY I would appreciate if he could post it here. I have no idea how much it will be
1 long per parameter ? 2 or 10 longs for the method ?? I really don't know
best regards
Stefan
As stacks are not cleaned up you can test that with an easy program. Simply initialize the stack with $a5a5a5a5, run the functions and see how many bytes of the stack no longer have that value. I think there is an object in ObExchange for that.
I think the SPIN interpreter is flexible. If the value you have to pass fits into a byt it will only use a byte on stack. So, I'd expect that a function without parameters needs 6 bytes (2 for return adress and 4 for return-value). For each local variable you need a long (the variables you define with a | after the function name/parameter list).
No. Each function call takes 2 longs (4 words) for the internal management, plus one long for the return value (whether you assign it or not), One long for each parameter and one long for each local variable. Return Value, Parameters and Local variables are all longs and are treated the same. The only difference is the interpreter zeros the return value and writes the parameters prior to invoking the method call.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
If you always do what you always did, you always get what you always got.
If I count right for my example above
10 longs / 8188 longs = 0.12 % of the HUB-RAM-space
that's what I thought. As long as the whole program does not use 90% of the HUB-RAM the danger of running out of memory is small
Your abo(expletive)e right MagIO when starting another cog with the command cognew you have to take care that the stackspace for the new cog
is big enough
best regards
Stefan
Thanks for refreshing my DRAM ;o)
@Stefan:
You only miss to count the calls to LCD.tx .. and whatever these functions might call. So, when calling the function in a new COG having only 10 longs stack it could already cause trouble.
All I want to say:
If you nest function calls you need to know what it means for the stack. And if you add a level you should double-check the stack sizes for your SPIN COGs that use this·branch of the code.
Post Edited (MagIO2) : 11/7/2009 2:49:30 PM GMT