Basic questions about PASM, round two
Carl Hayes
Posts: 841
Consider the following, abstracted from a much longer program:
CON
·_clkmode········ = xtal1 + pll16x
·_xinfreq········ = 5_000_000
PUB Main
·cognew (@Display,0)
DAT
Relbearing···· LONG········· 8
Heading······· LONG········· 7
Absbearing··· LONG········· 6
················· ORG·········· 0
Display
················· some code
···············
················· RDLONG······· DISrel,Relbearing
··············· · RDLONG······· DIShdg,Heading
················· RDLONG······· DISabs,Absbearing
················ ·more code
DISrel········· LONG········· 0··················· ' Relative bearing 0-359
DIShdg······· LONG········· 0··················· ' Vehicle heading
DISabs······· LONG········· 0··················· ' Absolute bearing
················ more stuff
The intent is that Relbearing, Heading, and Absbearing will eventually be set by another cog.
I expected that after the RDLONGs, the destination DISrel would have the contents of Relbearing, and so forth.· However, these destinations were not as expected.· Have I missed some (undocumented) requirement?
Also, I originally had WORDs and not LONGs for the source fields and used RDWORD instead of RDLONG.· I got an error message for the second one (Heading), but not for the other two, complaining that Heading was not a LONG.· I knew that; that's why I had used RDWORD instead of RDLONG.· What's going on here?
··
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
· -- Carl, nn5i@arrl.net
Post Edited (Carl Hayes) : 2/11/2009 3:36:18 AM GMT
CON
·_clkmode········ = xtal1 + pll16x
·_xinfreq········ = 5_000_000
PUB Main
·cognew (@Display,0)
DAT
Relbearing···· LONG········· 8
Heading······· LONG········· 7
Absbearing··· LONG········· 6
················· ORG·········· 0
Display
················· some code
···············
················· RDLONG······· DISrel,Relbearing
··············· · RDLONG······· DIShdg,Heading
················· RDLONG······· DISabs,Absbearing
················ ·more code
DISrel········· LONG········· 0··················· ' Relative bearing 0-359
DIShdg······· LONG········· 0··················· ' Vehicle heading
DISabs······· LONG········· 0··················· ' Absolute bearing
················ more stuff
The intent is that Relbearing, Heading, and Absbearing will eventually be set by another cog.
I expected that after the RDLONGs, the destination DISrel would have the contents of Relbearing, and so forth.· However, these destinations were not as expected.· Have I missed some (undocumented) requirement?
Also, I originally had WORDs and not LONGs for the source fields and used RDWORD instead of RDLONG.· I got an error message for the second one (Heading), but not for the other two, complaining that Heading was not a LONG.· I knew that; that's why I had used RDWORD instead of RDLONG.· What's going on here?
··
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
· -- Carl, nn5i@arrl.net
Post Edited (Carl Hayes) : 2/11/2009 3:36:18 AM GMT
Comments
This is normally done via the PAR register. When you start a COG, you get to pass it one 'long aligned' value, and that value appears in COG space via the PAR register.
Typical simple use case is to declare all your HUB variables, to be used as a parameter block, sequentially in the calling SPIN program. I like to use an array, just because.
In your case, the order is fine, just use it as is. The key here is that your HUB values exist in HUB address space, and that address isn't yet known, or communicated to the COG.
You do that, via the PAR register, in your COGNEW thus:
cognew(@display, @Relbearing)
The first arg for the cognew is the location of the start of the COG assembly code. The second is an address for a block of memory to be used for passing values. There are other uses for the PAR register, but that's the most common.
In your assembly language program, you then fetch those HUB values into the COG.
Here's one way to do it:
When working in HUB address space, be sure and remember to add the right index; namely, 1, 2 or 4, depending on whether it's a byte, word or long. This gets me quite often, as I'll be thinking in COG space, and only add 1 for a long, when it should have been 4.
TEMP is your index register for the duration of the fetching to be done, then can be used for other things as you see fit!
In the SPIN portion, you can also just declare the variables and work that way too. I use arrays because the sequence and type are always consistent, as arrays are atomic.
That could be then:
Hub_Values
HUB_Values := something
etc...
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Propeller Wiki: Share the coolness!
Chat in real time with other Propellerheads on IRC #propeller @ freenode.net
Safety Tip: Life is as good as YOU think it is!
Post Edited (potatohead) : 2/11/2009 4:02:56 AM GMT
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
· -- Carl, nn5i@arrl.net
In any other assembler, if I want the displacment (difference in address) between two locations A and B, I code (B-A) where here I coded #0 or #4 or #8.· Is there a way to do that with·this assembler?· It would be a drag to go back and recompute ever-so-many manually computed displacements every time I insert or remove a variable.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
· -- Carl, nn5i@arrl.net
Post Edited (Carl Hayes) : 2/11/2009 4:40:53 AM GMT
I suppose you could have the assembler add the base address, thus yielding absolute values. Still would have to pack them into a long though, so I'm not sure what, if anything you save.
The 9 bits of immediate addressing space is a problem there. Otherwise, I'm sure it would handle something like (@HUB_Value1 + 4). This result will be more than 9 bits, unless you take care to actually locate things in the first two pages of HUB memory address space.
There is also (@var - @another_var). I've done this to determine length of things, and have used that as an immediate address.
Others are gonna be better at this than I currently am, so maybe they will chime in and we both learn something!
[noparse]:)[/noparse]
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Propeller Wiki: Share the coolness!
Chat in real time with other Propellerheads on IRC #propeller @ freenode.net
Safety Tip: Life is as good as YOU think it is!
Post Edited (potatohead) : 2/11/2009 4:45:45 AM GMT
I'll experiment a bit.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
· -- Carl, nn5i@arrl.net
They are all the same size. If you build a loop, all you really need to manage then is the number of values to be passed. Bet a clever subtract would tidy that up.
On the SPIN side of things, the array is dead simple. Need another value? Just add an element, and off you go!
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Propeller Wiki: Share the coolness!
Chat in real time with other Propellerheads on IRC #propeller @ freenode.net
Safety Tip: Life is as good as YOU think it is!
There's a convenient shortcut you can use if your objective is only to transfer initial values into the cog's address space:
or, even more simply
Also, unless you need to make sure that TEMP is initialized to zero, you can use RES for it, instead of LONG, to save hub space in your program.
-Phil
Arrays are not the solution. I've found the solution. In the PASM program, I have now defined three longs:
DISreloffset LONG (@Relbearing-@Sharedstuff) ' @Sharedstuff is what I passed in the parameter
DIShdgoffset LONG (@Heading-@Sharedstuff)
DISabsoffset LONG (@Absbearing-@Sharesstuff)
Then, instead of #0, #4, and #8 for my offsets, I add the contents of these longs, which contain the offsets. Voila.
It's clumsier than other assemblers, but at least the program will be maintainable.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
· -- Carl, nn5i@arrl.net
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
· -- Carl, nn5i@arrl.net
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
· -- Carl, nn5i@arrl.net
this works as long as the offsets are not higher then 511.
Andy
Your way is easier to maintain, too, which is the whole idea. Super!
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
· -- Carl, nn5i@arrl.net
http://forums.parallax.com/showthread.php?p=783988
Doing it this way you don't have to worry about offset calculations and you don't waste any valuable LONGs in your COG fetching params from par.
I start to wonder why we have "par" at all....
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
For me, the past is not over yet.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
· -- Carl, nn5i@arrl.net
There's yet another way to do this. The "address plus" operator (@@) can be used with a zero argument to provide the object's base address (known only at runtime). This can be added to the offsets (known at compile time) to get the absolute argument addresses, viz:
What results is code that may be preferred for readability, since the longs contain data with the @ notation. Also note that, typically, one must put all res pseudo-ops after any longs, but that's not necessary in this case since Relbearing, et al., do not need to exist in cog space. In fact, the way this is written, DISrel, et al., will be preinitialized with their complements in hub space, since they overlap one-for-one. Finally, it's become a convention for the Propeller that values that get filled in later be initialized with 0-0 to indicate that fact.
-Phil
As for using 0-0 as a convention, it fits well with prior art -- the convention since Adam first taught Eve to program has been similar to that, usually *-* in machines in whose assembler languages "*" represents "address of this instruction". I'm going to adopt 0-0.
And next I've got to start learning Spin, which I think will be much more difficult than PASM.· The code that fills in the heading and bearings (for DISplay to read and display on an LCD)·will run in another cog.· My display code now works as intended.· Pizza time!
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
· -- Carl, nn5i@arrl.net
Post Edited (Carl Hayes) : 2/11/2009 9:48:23 PM GMT
-Phil
It'll probably take you a bit before you're using it to its full potential (I'm certainly not there yet) but it's a pretty easy language to learn.
Jason
Having the COG read its params from par on start up prevents this race condition. As would stopping the COG prior to param changes then starting it again.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
For me, the past is not over yet.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
· -- Carl, nn5i@arrl.net
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
· -- Carl, nn5i@arrl.net
-Phil