Object organization
parsko
Posts: 501
Hello all,
I can honestly say that I have read every post in the past 2 months on this forum. Sounds a little nuts, but I am trying to keep up with the rest of you. I have spent a little time playing with my Prop, but have not written any of my own code yet. I have one simple question:
How does the object orgainizaiton work?
I have read the posts about this topic, but I still am confused. I look at the tool, and see examples that show multiple levels of objects. These include subobjects. I understand that if two objects each use a third, that only the 3 will be compiled, as opposed to copying the 3rd and having 4 compiled. I have Wiki'd "object orieted programming", but it does not give detail how it works.
If you go to the help menu, and select the "object view", you will see a picture of the structure I am stupid about. I feel like this will be one major "aha" for me. I'm trying to figure out why I can't figure it out...
Any advice?
-Parsko
I can honestly say that I have read every post in the past 2 months on this forum. Sounds a little nuts, but I am trying to keep up with the rest of you. I have spent a little time playing with my Prop, but have not written any of my own code yet. I have one simple question:
How does the object orgainizaiton work?
I have read the posts about this topic, but I still am confused. I look at the tool, and see examples that show multiple levels of objects. These include subobjects. I understand that if two objects each use a third, that only the 3 will be compiled, as opposed to copying the 3rd and having 4 compiled. I have Wiki'd "object orieted programming", but it does not give detail how it works.
If you go to the help menu, and select the "object view", you will see a picture of the structure I am stupid about. I feel like this will be one major "aha" for me. I'm trying to figure out why I can't figure it out...
Any advice?
-Parsko
Comments
Sid
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Chip Gracey
Parallax, Inc.
If you're just getting started with objects, think of an object as a file with a collection of subroutines (although with spin, they should be called methods instead of subroutines).··The thing that makes object files special is that multiple copies of them can be declared, and each can have its own variables, which means that you can assign different attributes to the various objects your program uses.
The top file below includes three object files: Delay, LED, and Pushbutton.· The filenames are in quotes to the right of the colons in the OBJ section.· Each object has been given a name (to the left of the colon) for use in the program.· The Delay and LED object files were named delay and led.· The Pushbutton file was named pb, which is nice and short.· This is a nice feature; the object's name can be whatever you choose, including the filename.·
Here is the·object info for this top file.· Notice·the top file uses the delay, led and·pushbutton object files.· Notice also that the·led object·uses another copy of the delay object.· That's because the LED object declares Delay in its OBJ section, and one of its subroutines calls its copy of the Delay object.· Although the Propeller will execute the same delay object code, there will be two separate·instances of the delay object's global variables, one for the top file program's instance of the delay object, and the other for the LED Delay object's instance.·
In the top file program's PUB main method, the first command is led.SetDir(16, 1).· Well, inside the LED file, there is a method (again, think subroutine every time you see method if you are coming from PBASIC) named SetDir, which expects two arguments, pin and state (see below).· So, all the top file's led.SetDir statement is really doing is calling a·method in a separate "object" file.· The second·statement in the top file's main method·is led.on(16).· Just another method call in the LED object file.
On one hand, the Delay.config(1000) in the top file is just another call to a method inside an object, the Delay obhect this time.· On the other hand, that method sets a property for the instance of the delay object the top file is using.· Reason being, the config method sets·one of the delay object's·global variables, which is named divider.· Below is the delay object.· Notice how there is a variable in the VAR section called divider.··After the config method sets the value of divider, any of the other methods in the delay object can use it.· The pause method relies on the divider variable, and since divider was set to 1000, whenever pause is called, the count parameter will specify the pause duration in milliseconds.· So when the top file executes delay.pause(2000), there will be a 2 second pause.
Up to now, the top file called·the led object's "on" method with led.on(16).· Then it called delay.config, and delay.pause, then it called led.off(16).· So P16 was on for 2 seconds, then off again.·
After all that, the top file called led.start, and passed 16 to its pin parameter and 5 to its secdiv parameter.· Notice that inside the LED object, there's another OBJ declaration of delay.· This is a separate instance from the one the top file is using.· The start method inside the LED file calls this second instance of delay.· It received a value of secdiv from the top file, which was 5 - led.start(17, 5).· The LED object takes this value and multiplies it by 2, then calls its instance of the delay object with delay.config(secdiv*2).· So, whenever the led object calls the its delay object's pause method, it gets delays in terms of·tenths of a second instead of thousandths of a second.· Next, the led object's start method creates a new cog and starts the Blinker method in it, and the LED starts blinking.· Since the LED object is using its own copy of delay, and since the delay object has been configured to work in tenths of a second, when the LED object calls delay.pause, it only needs to pass it 1, to specify a delay of one tenth of a second.
After the top file calls led.start, there are two separate cogs running.··The top file is still running in cog zero, and the·LED object's blinker subroutine is running in cog 1.· After the top·file called·the led object's start method, led.start(17, 5), it uses the command repeat·while pb.check(4) ==·0 to wait for·an active high pushbutton to be pressed before continuing.· Below is the pushbutton file (which was named pb in the top program).· In PUB check(pin) : state, the : state means that the check method will return the value of its state variable when it's done.· So, repeat while pb.check(4) == 0 keeps on calling the pb (pushbutton file) object's check method.· Eventually, when somebody presses the pushbutton connected to P4, the check method will return a 1, and the program will move on from the top file's one line repeat loop.· While the top file's repeat while...·loop was doing its thing, in cog 0, the P17 LED was blinking 5 times per second in cog 1.· After the pushbutton·is pressed, the top file program moves on from repeat while loop, and calls the LED object's stop method, which shuts down cog 1.· No more blinking P17.··Cog 0 also runs out of commands, so the Propeller goes into low power mode.
Post Edited (Andy Lindsay (Parallax)) : 5/20/2006 7:27:32 PM GMT
PUB start(pin, state, rcvalueaddress) : okay···
What is rcvalueaddress?· I went on the forum with the question and Jon told me that rcaddress = @a variable.· Nowhere did I see that information in the files I downloaded.· That is typical of the problem I am have - filling in the paramaters that are expressed in the examples as vague terms.· Sorry to be so dumb - I would love to be able to master SPIN.
Sid
1.· Did you save ALL of the files as TOP File?
2.· How do I view "Object Info".·· I can't get that little screen to come up.
I have just started studying this.· It looks like the best explanation I have seen so far.
Sid
PUB setDir(pin, state)
· '' For state, 1 is output and 0 is input
From my point of view, if you use parameter names instead of actual values, it would be helpful if you explained each parameter, i.e.:
PUB setDir(pin, state)
··· ''pin = Prop pin that outputs the delay
· · '' For state, 1 is output and 0 is input
This one was really easy to understand·but some are not clear.· The
"rctimeaddress" in the RCTime object snowed me until Jon explained it meant
rctimeaddress·= @ a variable
Sid
I just spent an afternoon reading Wikipedia's listing for OOP. I think it will help many people.
Slowly I am catching on. One problem with OOP that Wikipedia clears up is that there are a lot of rumors and beliefs that confuse people. It is a reasonably short introduction and not slanted toward any particular language. Since SPIN is new, you don't need someone that loves C++, Python, or whatever trying to push their own beliefs.
Many of you are focused in the PUBlic and PRIvate declarations. It is possible to write a program that is all PUBlic or all PRIvate as a stand alone program. Those two declarations are used to prepare your present program for future use as an OBJect and do not have any objects being used in them unless they are declared in the OBJ section of the program.
To begin with, you may want to look at each object as a separate program. Some like the blinking LEDs really are. Others are quite obiviously dependent on TV_terminal; keyboard; mouse; and so on. Try to figure out which depend on only ONE object and see how the object is used (maybe just the TV_terminal OBJECT as a display device which uses only one lower object called TV). The structure will be obvious when compared with the blinking LED program.
If you look in the OBJ section of the program, you have a chance to see what objects are being used and the alias that is given to them (if only one is being used, there will only be one). Take a look at that Objects PUBlic sections for the actual names of the parts being called up and to see what requires data and/or variables.
Hopefully, this makes sense. I am trying to keep it quite short.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
"When all think alike, no one is thinking very much.' - Walter Lippmann (1889-1974)
······································································ Warm regards,····· G. Herzog [noparse][[/noparse]·黃鶴 ]·in Taiwan
Post Edited (Kramer) : 5/20/2006 1:58:18 PM GMT
I've had pretty good success starting with the partial manuals and examples, and applying the examples slowly to a PropStick. Most recently, I've been struggling with the assembly in FullSerialDuplex, and it's pretty tough. Especially without a manual.
Before I found Parallax, I would never have thought I'd understand microcontrollers, circuitry and code like I do. They do a fantastic job with PBasic and SX/B with their associated demo boards and educational materials. I'm hoping they will eventually get it like that with the Propeller and Spin. And maybe even spin assembly.
After all that, the top file called led.start, and passed 16 to its pin parameter and 5 to its secdiv parameter.
In the Top file it says:
led.start(17, 5)·
Did you mean 16 instead of 17?
Sid
· '' File - LED
VAR
· long cog, stack[noparse][[/noparse]16]
OBJ
· delay : "Delay"
PUB setDir(16, 1)
· '' For state, 1 is output and 0 is input
· dira[noparse][[/noparse]16] := state
PUB on(16)
· outa[noparse][[/noparse]0] := 1
PUB off(16)
· outa[noparse][[/noparse]16] := 0
When I clocked on Run/Compile/View Info a got an error message "Expected unique parameter name" and it highlighted the 16 in
PUB setDir(16, 1)
What am I doing wrong?· I do not have a Propeller attached - just studying your post.
Sid
The LED file has local variables, which cannot be replaced with numbers. It is an object (a collection of methods with some global variables) that is designed to be used by another program and not run on its own.
So, instead of setDir(16, 1), you have to use setDir(pin, state). pin and state are local variables, meaning they only exist while that method is being executed. The method call (subroutine call if you will), is executed in the top file.
The line in the top file that reads led.setdir(16, 1) means that the program should go from the top file to the led object and pass the values 16 and 1 to its setDir method. As soon as those values are passed to·the setDir method,·16 goes to the pin (local) variable and the 1 goes to the state variable. Then the setDir method does its job. After dira[noparse][[/noparse]pin] := state, it returns control. to the top file.
You'll need to type in the LED file as-is for it to play nice with the top file.
Also, keep in mind that the four spin files should all be saved in the same folder. Otherwise, they won't be able to find each other.
Andy
Post Edited (Andy Lindsay (Parallax)) : 5/20/2006 3:45:05 PM GMT
1. Did you save ALL of the files as TOP File?
The top file should be saved as Top File.spin. The LED file should be saved separately as LED.spin. The Delay file should be saved as Delay.spin, and Pushbutton should be saved as Pushbutton.spin. They should all be saved in the same folder so that the Propeller Tool softere can find them.
2. How do I view "Object Info". I can't get that little screen to come up.
Press F8 to view object info. Or, click Run -> Compile Current -> View Info.
Andy
Did you mean 16 instead of 17?
I meant to say: "After all that, the top file called led.start, and passed 17 to its pin parameter and 5 to its secdiv parameter."
The P16 LED will·stay on·for 2 seconds, then the P17 LED will flash at 5 Hz until the active high pushbutton connected to P4 is pressed.
Andy
Post Edited (Andy Lindsay (Parallax)) : 5/20/2006 3:42:36 PM GMT
'' File - LED
VAR
· long cog, stack[noparse][[/noparse]16]
OBJ
· delay : "Delay"
I get the same error and it highlights delay in
·delay : "Delay"
Sid
·
The delay object has to be typed in and saved as Delay.spin in the same folder as LED.spin. The compiler is looking for the file. The compiler takes all the separate files and puts them together into one big program before it downloads it to the Propeller.
On the delay error, if I save top file by itself, then save led by itself, the error will go away?
Sorry to be so much trouble.
Sid
No trouble at all.
Yes, save all four files in the "My programs" folder (provided there aren't already programs with those names there).
For the delay error, you have to enter and save the file named Delay in "My programs". While you are in the delay file, press F8 to make sure it compiles, then save it. After that, move back over to your LED file and press F8 again. The delay error should then go away.
Andy
led.start(17, 5)····
I understand this will run two LEDs, one on P16 and one on P17.· I assume they will run·consectutively and use·one cog.
If I wrote:
·led.start(17, 5)
·led.start(18, 10)
· repeat while pb.check(4) == 0
· led.stop
· repeat
Would I have 3 LEDs running consecutively, all at different blink rates?
Sid
Thanks.
Although the LEDs "should" blink at different rates, I don't think they will due to a bug I introduced while trying to keep the example simple.
I'll check right now.
Andy
The top file will compile, but the LED object has to be different to support multiple cogs.
I've been called to run a few errands right now, but I'll post a revised version later today.
Andy
In Top File
pb······· : "Pushbutton"·
if I wrote pb···· : "PB", could I then save it as PB.spin and have everything mesh?
A lot of the samples I have seen have
CON
· _CLKMODE = XTAL1 + PLL16X
· _XINFREQ = 5_000_000
Do I need anything like this for Top File?
Now then, to press on, the 2 (or 3) LEDs would blink in succession - 16,
17 and 18.· What if I wanted them all to blink at the same time, using 3 cogs.· How would I do that?
My best to Stephanie - I've seen her name recently on documentation.
Sid
Yes, if you renamed or copied the file as "PB.spin" everything would still mesh with the OBJ directive pb : "PB"
Without _CLKMODE and _CLKFREQ directives, the program defaults to using the Propeller's internal clock, which is about 12 MHz.
There's a pretty good write-up on _CLKMODE and _CLKFREQ in Chapter 4 of the Propeller Manual, which is available for download from http://www.parallax.com/propeller/downloads.asp.
Andy
I wasn't thinking about it correctly.··The LED file was alright.· The top file can be modified to either make LEDs blink consecutively, or at the same time in different cogs.··Here is a consecutive blinking example that will blink P16 for a while, then P17 until the P4 pushbutton is pressed:
Here is the top file modified to blink six LEDs in different cogs at different rates until the pushbutton is pressed.· Notice that I changed the led object declaration from led : "LED" to led[noparse][[/noparse]6] : "LED".· This change places six LED objects at my disposal.· Each led object's start method launches the blinker method into a new cog.· Likewise, each LED object's stop method shuts down the cog it launched its Blinker method into.
Post Edited (Andy Lindsay (Parallax)) : 5/20/2006 7:56:59 PM GMT
and two subobjects it calls. I want to have debugging statements in the
top object and both subobjects. The debugging statements use, for
instance, tv_terminal, to generate output.
How can I do this? I only want one copy of "tv_terminal", but I want it to
be accessible by my top level object and the lower level objects. Can I
pass an object reference down to the lower levels?
Any help appreciated!
Hmm, multiple instances of the TV_terminal wouldn't work all that well would they...· I think the intended approach was to have your various objects pass the addresses of the variables you want to examine to the object that's running TV_Terminal.
BTW rokicki, your Tandy Color Computer from 1980 Emulator with built-in BASIC Interpreter is the by far the coolest Propeller application I've seen to date!
Post Edited (Andy Lindsay (Parallax)) : 5/20/2006 8:26:46 PM GMT
Now is I wanted to keep both the consecutive and concurrent programs I would save the modified Top File as "Top File", 9 replacing the Top File I presently have, and I would save the concurret Top File as "Top File 2", or something similar.· The LED, Delay and PB files would remain the same, although called by either of the Top Files.
If I wanted to add a second PB for the concurrent program I would change
repeat while pb.check(4) == 0
to
repeat while pb.check(5) == 0······ ''or whatever·in Top File 2.
One thing that's not quite clear -· when you start the 6 LEDs and there is no LED stop, does that automatically start a new cog for each LED?
More omn cogs later - that's a very fuzzy area.
Have I got it so far?
Sid
Okay, not being able to share an object among different other objects is a real difficulty. This means that the
object organization we can use is severely limited.
Right now, an object is just a static chunk of methods and variables, and if you "declare" that object multiple
times you get multiple instances. This works great when this is what you want, but frequently it is *not*
what you want---you want to be able to share access to an object among different things, and different
levels. What we really need is the ability to take the address of an object (the @ operator), and then in
other modules, reference that object/invoke its methods. That is,
obj
tv: "TV_Terminal" ;
otherObj: "My_obj"
pub start
tv.start(12) ;
otherObj.start(@tv) ;
and then in otherObj we want something like
obj
&tv: "TV_Terminal" ; // holds an *address*, does not create a *new* one
pub start(debuggingTerm)
tv = debuggingTerm ;
tv.str(string("otherObj is alive"))
Of course this syntax is far from optimal, but you get the idea.
We also need interfaces and inheritance and constructor constants and all sorts of other things.
Luckily all this can be done in the IDE with no change to the chip itself.
I agree with your suggestion though. If they get a future rev of the Propeller Tool set up with a system like what you're proposing, it would make debugging and a number of other programming tasks much easier. It would also make the Spin more object oriented in the way we have become accustomed to with other OOPs.
Yes, either version of the top file can access the objects.· You could even make another program that treats both of your top files as objects.· Here is an example that incorporates both the top files as objects for its own use.· It first calls Top File's main method.· When Top File's main·method finishes, the program returns to this super top file.· Then, it calls Top File 2's main routine, and waits for that to finish.· When it finishes, the program goes into low power mode.
newzed said:If I wanted to add a second PB for the concurrent program I would change
repeat while pb.check(4) == 0
to
repeat while pb.check(5) == 0······ ''or whatever·in Top File 2.
Yes.· You could also do something like this:
Method calls can also be used·in expressions and·expressions like IF...ELSEIF and CASE.· Their·results can also be used in math expressioins like result = 10 * pb.check(4) + 100 * pb.check(5).·
newzed said: One thing that's not quite clear -· when you start the 6 LEDs and there is no LED stop, does that automatically start a new cog for each LED?· More omn cogs later - that's a very fuzzy area.·
Each·LED object's·Blinker method is started in a new cog.··led[noparse][[/noparse]0].start(16, 1) calls the 0th led objct's start method, which starts starts it's Blinker method in cog 1 (cog 0 is running the top file, and cog 1 is the next available cog.).··led[noparse][[/noparse]1].start(17, 2) calls the 1st led objct's start method, which launches its Blinker method into cog 2 (the next available cog).··led[noparse][[/noparse]2].start(18.3) calls the 2nd led object's method, which launches its Blinker method into cog 3, and so on...· All 6 LEDs are blinking at differnt rates after all 6 object's start methods are called.· It's kind of a fun example, with 6 separate processors, each blinking an LED at a different rate.· P16·blinks at 1 Hz, P17 at 2 Hz, P18 at 3 Hz, etc.·
After the P4 pushbutton is pressed, there is a repeat·from...to loop, that stops all the cogs (below).· The first time through the repeat loop, counter is 0, and the led[noparse][[/noparse]0] object's stop method is called.· It shuts down the instance of the LED Blinker method that was blinking in cog 1.· The second time through the loop, counter is 1, and the led[noparse][[/noparse]1] object's stop method is called.· So it shuts down cog 2 (and the instance of the blinker method that was running it).· In this way, the·loop·shuts down all 6 cogs that were blinking LEDs at different rates.· Note, a similar loop could be written to call the six LED start methods as well.
Post Edited (Andy Lindsay (Parallax)) : 5/21/2006 3:42:33 AM GMT