Is there a library of sub-routines somewhere?
Chris_D
Posts: 305
Hi everyone,
Perhaps I use the propeller differently than others, but the one thing I think that is missing is a library of sub routines similar to the object exchange. The object exchange is a great resource, nearly all of the items in there are designed to occupy one or more cogs to perform some sort of function. The prop's multi-core technology is well suited to this object based solution. A programmer needs a solution to a problem, selects the object, dedicates a COG or COGS to run the object and life is good.
But at some point you run out of COGs and the solutions you seek are very simple in nature. For example you need a 32 bit integer divide sub routine. However, you have no COGs available to use one of the existing objects so you can't just grab an object to help out. So you search through the forums to try and find a subroutine that you can place within a COG. The problem with this is that some of the posts present a routine, but you have no idea if it is fully functional or a work in progress.
Now I will be the first to admit, I suck at PASM math and frankly I just don't have the "mind power" to figure out how to do 32 bit signed math in PASM. But I know there are others that do and have sub routines to do it. They simply are not orgranized into simple resource data bank like the object exchange.
Perhaps this already exists somewhere and I sure would appreciate a link to where it is. If it doesn't exist, would others see the same value in such a library? Perhaps Parallax could expand the object exchange with a grouping of subroutines that can be called from within a COG program.
Just a thought that I think could benefit others.
Chris
Perhaps I use the propeller differently than others, but the one thing I think that is missing is a library of sub routines similar to the object exchange. The object exchange is a great resource, nearly all of the items in there are designed to occupy one or more cogs to perform some sort of function. The prop's multi-core technology is well suited to this object based solution. A programmer needs a solution to a problem, selects the object, dedicates a COG or COGS to run the object and life is good.
But at some point you run out of COGs and the solutions you seek are very simple in nature. For example you need a 32 bit integer divide sub routine. However, you have no COGs available to use one of the existing objects so you can't just grab an object to help out. So you search through the forums to try and find a subroutine that you can place within a COG. The problem with this is that some of the posts present a routine, but you have no idea if it is fully functional or a work in progress.
Now I will be the first to admit, I suck at PASM math and frankly I just don't have the "mind power" to figure out how to do 32 bit signed math in PASM. But I know there are others that do and have sub routines to do it. They simply are not orgranized into simple resource data bank like the object exchange.
Perhaps this already exists somewhere and I sure would appreciate a link to where it is. If it doesn't exist, would others see the same value in such a library? Perhaps Parallax could expand the object exchange with a grouping of subroutines that can be called from within a COG program.
Just a thought that I think could benefit others.
Chris
Comments
Sorry if this already is obvious to you.
That is true for Spin methods of course. But what about a library of PASM functions?
Would have to be a repository of functionality is PASM source code that can be cut and pasted into ones PASM programs. Or included from external files if one is using the latest HomeSpun compiler. 32 bit divide is a good example.
I believe the problem here lies in that the Parallax Propeller tool do not support any mechanisms handling PASM library functions. No includes, no macros, no nothing. The only way is textual cut and paste, and then you can of course cut and paste code from OBEX as well as from any other source. Using third part products solves this, but since we all are using different third part products, we miss the benefit of one library, like the OBEX.
People who must use Propeller Tool for some reason can use the GNU C preprocessor (cpp) to generate "clean" SPIN code. Anyone who knows about #include and macros could surely use cpp without tears.
I use bst and PropTool, depending on requirements. There is no doubt that bst and homespun are both superior to PropTool. Since both are free, there has not been the focus by Parallax to do anything better, although they were going to improve PropTool. Homespun has recently added #include which is not (yet) supported by bst. Both support #define and #ifdef although the implementation is slightly different. Homespun is only a compiler whereas bst is a complete editor tool as well and runs on *nix and mac too.
As for your specific 32bit divide, I suggest you look at the Spin Interpreter code. It's a little convoluted in places to minimise the footprint. My Interpreter is cleaner in the maths area.
You are missing the point. If I do that, I no longer can upload my code to OBEX.
I don't think kuisma was considering licensing issues when he said "If I do that, I no longer can upload my code to OBEX.". And by the way use of some form of cpp is not necessarily anything to do with the GPL. After all C and cpp existed before the GPL.
No, I believe it is a concern over the practical reality that if your source code depends on this or that tool, or only compiles with this or that non-Parallax compiler then it makes it hard or impossible for users to just "plug'n'play" objects from the OBEX as it was originally intended.
Which is true. However:
a) OBEX is already "polluted" with non-Spin objects.
b) As Cluso says, if you use a pre-processor to massage a non-standard Spin or PASM primary source there is no reason why the output sources cannot be added to OBEX for use by users of the "standard" Parallax Prop Tool.
This sounds a great idea. I'm working on something similar but from a slightly different angle. To clarify, there are a few ways to do this:
1) Spin only routines. These don't need a cog, so it is possible to use these as you describe. I'm not sure about math routines, but as an example, Kye wrote some spin-only string routines that are very easy to use.
2) Loading and unloading cogs on the fly from within software. I'm not sure this has been solved - others might be able to clarify this better. This would only apply to 'cog only' code, and not many objects are cog only
3) Most obex code is a fusion of cog and spin code, and I am not sure this sort of code can be loaded and unloaded. This is the fundamental problem you are describing.
4) Loading entire binary files off an sd card and chaining one to the other. This is a very slow solution as it takes a few seconds for each load/unload, but code for this does exist.
5) Taking an existing piece of cog code and adding a way of passing commands to say which bit of code you want to run, then adding your new bit of code. I did something similar to this with Cluso's ram driver code when I added code to drive an LCD display. The problem with this is there isn't usually much room left in cog code in most obex objects.
As you can see, there are limitations. So the simple task of loading in a little bit of pasm code to do a 32 bit divide becomes quite a complicated problem. It is even more complex if you have run out of cogs.
The simplest answer might be to do this purely in spin. A library of spin routines (a bit like Kye's string routines) would be very useful, particularly if it were possible to sort the Obex in such a way as to exclude any code that had pasm.
Due to these limitations, I've ended up exploring other answers.
6) Use a Z80 emulation. There are libraries of Z80 code, including 32 bit maths. 32 bit math on a propeller running a Z80 simulation and written in assembly will be faster than spin.
7) Use Catalina and code in C and load and unload cog code as required. Catalina has some cutting edge code that allows cogs to be loaded and unloaded on the fly from within code. However, pasm library code has yet to be written for many things as this is all very new.
8) Use Catalina and write your code in C. C code on the propeller is fairly 'close to the metal' and in terms of speed, comes in somewhere between spin and pasm, and probably closer to pasm than spin. There are vast libraries of existing C code to do math including all the standard routines in the library math.h
9) Use Catalina running in external memory. Now this is really cutting edge, because it appears that you can use pasm code 'inline' in amongst the C code. This is because C code running from external memory is already running as a kind of pasm emulation - almost as fast as pure pasm. So it is possible to mix and match C and pasm together. I don't believe we have even begun to explore the possibilities this raises.
So in summary, I think it is a great idea to think about libraries of code. Let's keep brainstorming this.
There is no reason you cannot upload to obex code or a set of routines that require the use of bst or homespun or catalina or ImageC or anything else, so long as you make it clear what is required.
As for routines, I think it would be a good idea to have a specific section for "code snippets" (i.e. routines) for pasm, spin, c, forth, etc.
So you knew SPIN before delving into Z80 emulation? Fact check?
Where are these Z80 emulation -vs- SPIN performance comparisons?
-Phil
This seems to be very unlikely. Any examples?
Thinking about that more, if there is a simple piece of spin code to do 32 bit signed math, then our original poster need look no further. Quote For example you need a 32 bit integer divide sub routine
Do we have such examples?
(addit: I'm a bit unclear if the math routine had to be pasm only, because if it is, then it would be in the context of other pasm code presumably, and that code in itself will place limitations on things like the code space available).
(I've actually clocked up some simple counting example quite a while back, comparing with a old computer, and it was a lot closer than I thought it would be, which means to me, SPIN is fast, not slow, just FYI.)
Re: OBEX.
I think the Parallax tool should be the default. That's largely why I use it on most everything. SPIN + PASM is great for a ton of stuff. The problem comes into play with you advanced computing pioneers.
The only resolution I can think of, is to post both! Where possible, output something that works with Prop Tool, adding to it for the other tools, maybe even adding features. Seems to me more work, but then again more usability. Clearly, that's a choice up to the author, and not one I would always make.
That said, if there is code out there, I consider that a better start than no code. If it's Prop code, that's better still. If it's Propeller Tool code, that's golden.
So, just post it up, if nothing else. Whether or not the OBEX wins the mindshare contest really is a organic thing. I personally believe enough people use it by default to not worry about this just yet. Again, most uses are well served by the tool, leading me to believe it's the primary dev environment out there. It's not here though, or if it is, it's closer than the broader community of Propeller users, based on my gut. Yours may vary.
I really, really like the idea of little routines in both PASM and SPIN. For me personally, these are extremely handy, and I will often go looking for them to apply as needed. Non experienced programmers, such as myself, where it's just not a full time, or regular enough thing to really solidify the basics to that "thought is action" level we all desire, having starter code is a huge leg up.
IMHO, the readability of SPIN + PASM is a huge benefit on that alone. I find it much easier to process some snippet in SPIN, than I do one that's got more layers of complexity in it, or that is C, or....
Again, not a bad thing, and clearly we all vary. I'm basically just tossing those impressions out there.
Perhaps we could coax Parallax into hosting something for just code, not completed code, but proven out snippets of code?
Or, a tiny bit of work on our Wiki could easily do that. Ale posted up some math a while back, it was in PASM, and it was not a bad example of what could be out there, if people were inclined.
Thinking about a input with debounce, interval timer, case statement with example comparison, jump table in PASM, more MATH in PASM, waitvid video loop, closed loop with multiple interval and branch, logic mapped to a use case / flow chart, string compare, output, combine, etc...
That kind of stuff doesn't need to be a full program, but may prove useful.
One other thought I had was add-ons to existing projects. Say some graphics buffering scheme comes up. (I'm actually gonna try this one) Why not code it in such a way that it can add to, or be a simple derivative of graphics_demo.spin? That way, somebody can go and take a look see, copy paste the method they like, and continue on? That's what happened with the commented graphics_demo.spin
Is that a bad idea? Right now we've no way to really do that, other than to document the object, and include the original, but what if we could? On one hand, we enter dependency hell, on the other, it's another option for people to build from, and we've already kind of got dependencies now anyway.
Again, all that said, I really like contained bits of code, with inputs and outputs. Handy. All in favor of that kind of thing.
I would imagine that as soon as you want to do a 32 bit addition the Z80 emulation will be left in the dust. Perhaps if you are only working on bytes it might stand a chance against Spin.
The idea of a benchmark would be interesting, to see just where those things align, that's all I was really saying.
This is a good point. It might result in somewhat strange code in the OBEX, since it is partly obfuscated by the pre-processor, but still usable, and if it would impose a problem (e.g. heavy use of macros to reflect the hardware), there is always the option to use the same pre-processor. The best of two worlds.
Is there any suitable pre-processor able to handle the Parallax syntax out there? Both easy to integrate in the tool chain, and handles the column position dependencies the Parallax code uses. I get the impression cpp may have problems with this?
I like a design challenge.
There are some great points above. There are many solutions but I'm going to set myself some restrictions to this:
1) must run on the demo board
2) no external ram
3) no sd card
4) must compile with the Prop tool.
Ok, well that rules out catalina in external memory, as well as the emulations.
Is this still solvable?
Well, our OP gives another little restriction - he says "you run out of cogs", so that implies that a solution can't just cram code into cogs, as cogs are in short supply. So - lets relax that a little and assume we have one cog free that we carefully saved for this purpose.
Is it possible to move little subroutines in and out of that cog on the fly from within code?
I've been thinking about what such code might look like. It would be a list of DAT code, either contiguous or spread out through the entire program. You need a pointer at the beginning of that code.
Maybe my understanding of this is not quite right, but by my thinking, you can do a cogstart and point it to the beginning of each bit of code. That loads up 2k of data each time but most of that is not used.
You could then use that spare cog to load a multiply routine, then a divide routine, then the multiply routine etc etc.
But there will be a time penalty as loading a cog takes time. Would spin end up faster than this sort of pasm? Is that why such pasm blobs of code don't exist?
I've been thinking in the same circles. The problem is that hub memory is as sparse as cogs and cog memory, so move code in and out of what? A three level pager: cog memory <-> hub memory <-> sd card, paging routines as needed could solve this, but requires relaxation of your constraint about external memory. sd card is still much cheaper (in io pins, with spi) compared to a sdram, and paging blocks instead of single instructions (as in LMM) would gain speed.
It will be slower due to sd card => buffer => cog.
But you could group subroutines together - eg put all the math routines in 2k of cog space. Then you would be reading in code less often.
The routines could still be available individually eg multiply, divide, add - the end user can work out how they want to group them together.
Unfortunately, you cannot predict what the user will have available. They may have free hub, so overlaying could work fine. They may have a cog(s) free, so in it goes. Problem is, we just don't know. That is why self-contained snippets is a good idea. The user can decide how they use the snippets to best advantage. But they need to be posted first!
I guess the one thing that needs clarification is where the subroutine would be placed and where it runs...
I was thinking very simple and in fact very conventional. Comparing to a language like BASIC on single core devices, a program consists of many subroutines. Each sub routine is called, executed, and flow is returned to the call statement. So, to respond to the one of the early questions, yes, the sub routine would reside and execute from the same COG. Remember, the larger part of the problems is that there are no available COGs to use. The performance would be slower, but when you need to do whatever the routine can do, you have no choice.
Someone suggested looking in the SPIN code and I have tried that. But that effort led me to this request. There are plenty of code fragments (sub routines) people have created to accomplish tasks in both SPIN and PASM. Having a logical resource of those would make programming much more efficient and certainly more accessible to those of us that are "Math challenged" (or challenged in whatever the routine does).
While it would be cool if it were part of the Prop tool, I would be just as happy as copying a subroutine from a web page and pasting it into my PASM program. As long as there was some description on how to use it (set these two variables as inputs, and provide this variable for the results).
In reality, it could be very similar to the object exchange. Subroutines could be listed in categories by function type, a description of what it can do, perhaps how fast it is, who wrote it, how to use it, and the source code to be copied and pasted.
Perhaps after a large library of sub routines is created, the SPIN Tool could be modified to be able to grab and use these upon request. But frankly just having the routines availble for copy and paste would be a BIG help for many of us.
Chris
In My opinion all type of code/code snippets in OBX have value if them are correctly described what them suppose to do and as someone pointed have description what TOOL was used to compile it.
As them can show what can be done if anyone use tools that fit its needs.
Seems to me the idea behind the OBEX is/was simply this:
1) A user has Props and a Prop Tool.
2) Prop has no normal peripherals only COGs. Out of the box it's a clean slate and almost useless without a lot of effort.
3) Solution to 2) is to develop and make available a growing collection of objects that turns COGs in peripherals, I2C, SPI, UART, video etc etc etc
4) This should all be as easy as possible, choose your object, tweak perhaps the clock and pin settings, drop it into your application, it works.
Thus with OBEX the Prop becomes an infinite variety of different micro-controllers, brilliant.
Now the Prop has matures, or should I say it's user base has. There are a multitude of different languages available, there are operating systems, there are all sorts of exotic hardware platforms. The users have realised they need/want all sorts of sophisticated programming techniques and tools.
Problem is, if the OBEX were to be flooded with all kinds of code snippets, subroutines, language dependent, operating system dependent and tool dependent code. it would make it harder and harder to find just that simple object you want. Just browsing the thing to see what nice objects are available to try out would become a major chore.
Conclusion, I think the OBEX itself should be kept pure according to the original plan. That vast wealth of other useful code snippets, examples, subroutines for whatever language should have a home in a totally different repository.
Just a thought.
Wiki then?
The latest GNU cpp works fine with SPIN files. Files using Parallax font chars will need conversion to utf8 first.
I agree with the comments that the code snippets should be kept separate from the OBEX or it will get too cluttered. So, unless Parallax want to jump in now, I guess the wiki will do. I am not a fan of the wiki because it is more open to abuse than a privately held site like the OBEX.