How to learn Pasm equivalent of Spin?
lardom
Posts: 1,659
in Propeller 1
I hit a wall with my current project. I wrote Spin code that does one of three things individually:
Wirelessly control two DC motors differentially, four servos for an arm or two servos for a pan/tilt camera.
I can't do all three in the same object because of the overhead.
This means I'll have to learn to write equivalent code in assembly.
Can anyone recommend a good place to start?
Wirelessly control two DC motors differentially, four servos for an arm or two servos for a pan/tilt camera.
I can't do all three in the same object because of the overhead.
This means I'll have to learn to write equivalent code in assembly.
Can anyone recommend a good place to start?
Comments
But moving to PASM is not a bad idea at all. It is way faster, and PASM is a quite nice language.
Look in the sticky's for deSilvia or so.
Enjoy!
Mike
In this case I need PASM. I developed the code on a single Propeller which worked fine. The wireless device is a bottleneck. One limitation is 8-bits. The other problem is I have to insert delays or the device tends to hang.
spincvt is a GUI that will let you convert Spin code to PASM. The underlying program (spin2cpp) was originally designed to convert Spin to C++, but it's since grown and can now convert to PASM as well. In fact you can use it to compile your program to a binary that will run much faster than one produced by openspin (but is also much larger, because it contains PASM instructions instead of bytecode).
You said you need to insert delays - if that's true, PASM can't wait any faster than Spin. Would it be possible to change the code so it's doing something else during that wait time?
Easy solution: Rewrite in PropBASIC.
I have a servo method that gets refreshed every 25ms. In my code it takes 6.7ms for the tx radio to transmit the data packet to the rx radio and I could reduce that to 5.4ms if necessary. I have the time.
I was causing the irq flag to get set before the repeat loop had time to finish. Life is good again. Thanks.
...I still need to understand Pasm so I will follow up on the recommendations.
Inserting delays = wasting time. You might re-code your cog as a state-machine and use a timer variable (referenced to cnt) to run when it's time to run.
Of course, if you posted your code, you'd get more and very specific help. Just sayin'.
@JasonDorie, I tested sending data packets at a rate that matches the refresh rate of the rx servo method. The servos rotate smoothly and I've gained close to 18ms per wireless tx. Thanks for your input.
@JonnyMac, I have special folders on my pc for your work. What's a "state machine" and how can I make use of it?
Good question. I have what I understand to be a state machine in most of my coding but I don't call it that just in case I'm wrong
First, enumerate all those chunks and call them state_X.
Now being in a state, don't just wait, but wait for something to happen. Create a list of all possible events end enumerate the events.
Being in a state and experiencing an event, you leave that state and switch over to another state.
So write down: being in State X, experiencing event Y, switch over to State Z.
Thats boring, just wait and switch, this calls for action. So when leaving a state as an event happens, do something. Start to enumerate all actions that make sense when leaving state X following an Event Y before entering State Z. Let this action be A, C, D, ..
So you just have to program a loop, have a switch state statement and if nothing happens, do nothing. If something happens, execute action, switch to the dedicated state and continue looping.
This is a quite stupid, mechanical process, just the right stuff for a machine, so this is called state machine.
https://en.wikipedia.org/wiki/Finite-state_machine
And here's a simple example:
https://en.wikipedia.org/wiki/Event-driven_finite-state_machine
And finally, look up the CASE statement in the Propeller Manual, which would substitute for the C equivalent, switch(state), in the second link.
In your case with servos it works out nicely to divide the 20ms servo refresh rate into four, 5ms chunks; a constant called MS5 is created which is the number of system ticks in 5ms. A timer variable is referenced to the cnt register which uses the MS5 constant. I find it simplest to call the process and let it decide if it's time to run. When that's the case it does what it has to do. In the example the current servo is updated, the servo state (index) is advanced, and the next process is called. No waitcnt to slow anything down.
Here's an example from my PAB template that runs a 1ms background loop. The ADC on that board requires a lot of clocks -- too many to do a full reading in 1ms. Since I'm not looking for high-speed analog input do a pulse every time through the loop. Not appropriate for everything, but this works for my simple apps.
Give this a try, by using differential timing versus delays, you may be able to pack everything into the time you have.