PASM and cogs
I am clearly a newbie here, and I realize that this code sucks in a variety of ways (e.g. redundancy between the x and y servo routines). Please look past that as I try to ask my first question, then help me with that as you address my second question
.
#1. Whichever repeat 10 loop I list first in the code is the only one that works, the second one does nothing. They both work fine independently. Order of the cognew functions has no impact. What am I missing?
#2. Obviously, I ideally want to pass in two parameters to a single 'servo' PASM block. The first being a servo pin, the second being a position. How do I go about that? (I believe I am to pass a memory address and then do some fancy PASM to look it up and pull out the necessary values). I am a total ASM and PASM noob, sadly. So I have no clue on how to go about that. Any tutorials/links/example code?
Thanks for helping out. Much appreciated.
#1. Whichever repeat 10 loop I list first in the code is the only one that works, the second one does nothing. They both work fine independently. Order of the cognew functions has no impact. What am I missing?
#2. Obviously, I ideally want to pass in two parameters to a single 'servo' PASM block. The first being a servo pin, the second being a position. How do I go about that? (I believe I am to pass a memory address and then do some fancy PASM to look it up and pull out the necessary values). I am a total ASM and PASM noob, sadly. So I have no clue on how to go about that. Any tutorials/links/example code?
Thanks for helping out. Much appreciated.
CON
_xinfreq=5_000_000
_clkmode=xtal1+pll16x
LASER = 26
VAR
long x_position
long y_position
PUB Main
cognew(@y_servo,@y_position)
cognew(@x_servo,@x_position)
laser_toggle(1)
'The new cog that is started above continuously reads the "position" variable as it's changed by the example Spin code below
repeat 10
y_position:=70_000
waitcnt(clkfreq+cnt)
y_position:=105_000
waitcnt(clkfreq+cnt)
repeat 10
x_position:=96_000 'Start sending 1ms servo signal high pulses (80_000 * 1/(80MHz clock freq) = 1ms)
waitcnt(clkfreq+cnt) 'Wait for 1 second (1ms high pulses continue to be generated by the other cog)
x_position:=168_000 'Start sending 1.375ms servo signal high pulses (Center position)
waitcnt(clkfreq+cnt) 'Wait for 1 second (1.5ms high pulses continue to be generated by the other cog)
PUB laser_toggle(on)
dira[noparse][[/noparse]LASER]~~
outa[noparse][[/noparse]LASER] := on
DAT
'The assembly program below runs on a parallel cog and checks the value of the "position" variable in the main Hub RAM (which
' other cogs can change at any time). It then outputs a servo high pulse for the "position" number of system clock ticks and
' sends a 10ms low part of the pulse. It repeats this signal continuously and changes the width of the high pulse as the
' "position" variable is changed by other cogs.
org 'Assembles the next command to the first cell (cell 0) in the new cog's RAM
x_servo mov dira,XPin 'Set the direction of the "ServoPin" to be an output (and all others to be inputs)
LoopX rdlong HighTimeX,par 'Read the "position" variable (at "par") from Main RAM and store it as "HighTime"
mov counterX,cnt 'Store the current system clock count in the "counter" cell's address
mov outa,AllOnX 'Set all pins on this cog high (really only sets ServoPin high b/c rest are inputs)
add counterX,HighTimeX 'Add "HighTime" value to "counter" value
waitcnt counterX,LowTimeX 'Wait until "cnt" matches "counter" then add a 10ms delay to "counter" value
mov outa,#0 'Set all pins on this cog low (really only sets ServoPin low b/c rest are inputs)
waitcnt counterX,0 'Wait until cnt matches counter (adds 0 to "counter" afterwards)
jmp #LoopX 'Jump back up to the cell labled "Loop"
'Constants and Variables:
XPin long |< 5 '<------- This sets the pin that outputs the servo signal (which is sent to the white wire
' on most servomotors). Here, this "7" indicates Pin 7. Simply change the "7"
' to another number to specify another pin (0-31).
AllOnX long $FFFFFFFF 'This will be used to set all of the pins high (this number is 32 ones in binary)
LowTimeX long 1_600_000 'This works out to be a 10ms pause time with an 80MHz system clock. If the
' servo behaves erratically, this value can be changed to 1_600_000 (20ms pause)
counterX res 'Reserve one long of cog RAM for this "counter" variable
HighTimeX res 'Reserve one long of cog RAM for this "HighTime" variable
fit 'Makes sure the preceding code fits within cells 0-495 of the cog's RAM
DAT
org 'Assembles the next command to the first cell (cell 0) in the new cog's RAM
y_servo mov dira,YPin 'Set the direction of the "ServoPin" to be an output (and all others to be inputs)
LoopY rdlong HighTimeY,par 'Read the "position" variable (at "par") from Main RAM and store it as "HighTime"
mov counterY,cnt 'Store the current system clock count in the "counter" cell's address
mov outa,AllOnY 'Set all pins on this cog high (really only sets ServoPin high b/c rest are inputs)
add counterY,HighTimeY 'Add "HighTime" value to "counter" value
waitcnt counterY,LowTimeY 'Wait until "cnt" matches "counter" then add a 10ms delay to "counter" value
mov outa,#0 'Set all pins on this cog low (really only sets ServoPin low b/c rest are inputs)
waitcnt counterY,0 'Wait until cnt matches counter (adds 0 to "counter" afterwards)
jmp #LoopY 'Jump back up to the cell labled "Loop"
'Constants and Variables:
YPin long |< 0 '<------- This sets the pin that outputs the servo signal (which is sent to the white wire
' on most servomotors). Here, this "7" indicates Pin 7. Simply change the "7"
' to another number to specify another pin (0-31).
' servo behaves erratically, this value can be changed to 1_600_000 (20ms pause)
AllOnY long $FFFFFFFF 'This will be used to set all of the pins high (this number is 32 ones in binary)
LowTimeY long 1_600_000 'This works out to be a 10ms pause time with an 80MHz system clock. If the
' servo behaves erratically, this value can be changed to 1_600_000 (20ms pause)
counterY res 'Reserve one long of cog RAM for this "counter" variable
HighTimeY res 'Reserve one long of cog RAM for this "HighTime" variable
fit 'Makes sure the preceding code fits within cells 0-495 of the cog's RAM

Comments
This is adding the value of register 0 to counterX, not "0". Change it to:
As for choosing the pin, you have everything in place. What you want to do is change XPin in Spin before you start the cog.
This change the value of XPin in the hub, when the cog starts this is brought into cog memory.
You should also then be able to start two cogs using the same assembly by choosing the pin before you start them and giving them different parameter variables.
Sadly my original problem still exists, and I'm not sure why. Was wondering if anyone had any thoughts? The repeat 10 loop that is run first in the code works as expected, the second one doesn't. It basically does nothing. If you re-order the repeat 10 loops the other will work. I must be missing something just I'm not sure what. Also appears that the order of the cognew functions does not matter as well. Here is the updated code.
CON _xinfreq=5_000_000 _clkmode=xtal1+pll16x 'The system clock is set at 80MHz (this is recommended for optimal resolution) LASER = 26 VAR long x_position 'The assembly program will read this variable from the main Hub RAM to determine ' the servo signal's high pulse duration long y_position PUB Main Pin := |< 0 cognew(@servo,@y_position) Pin := |< 5 cognew(@servo,@x_position) laser_toggle(1) 'The new cog that is started above continuously reads the "position" variable as it's changed by the example Spin code below repeat 10 x_position:=96_000 'Start sending 1ms servo signal high pulses (80_000 * 1/(80MHz clock freq) = 1ms) waitcnt(clkfreq+cnt) 'Wait for 1 second (1ms high pulses continue to be generated by the other cog) x_position:=168_000 'Start sending 1.375ms servo signal high pulses (Center position) waitcnt(clkfreq+cnt) 'Wait for 1 second (1.5ms high pulses continue to be generated by the other cog) repeat 10 y_position:=70_000 waitcnt(clkfreq+cnt) y_position:=105_000 waitcnt(clkfreq+cnt) PUB laser_toggle(on) dira[noparse][[/noparse]LASER]~~ outa[noparse][[/noparse]LASER] := on DAT org 'Assembles the next command to the first cell (cell 0) in the new cog's RAM servo mov dira,Pin 'Set the direction of the "ServoPin" to be an output (and all others to be inputs) Loop rdlong HighTime,par 'Read the "position" variable (at "par") from Main RAM and store it as "HighTime" mov counter,cnt 'Store the current system clock count in the "counter" cell's address mov outa,AllOn 'Set all pins on this cog high (really only sets ServoPin high b/c rest are inputs) add counter,HighTime 'Add "HighTime" value to "counter" value waitcnt counter,LowTime 'Wait until "cnt" matches "counter" then add a 10ms delay to "counter" value mov outa,#0 'Set all pins on this cog low (really only sets ServoPin low b/c rest are inputs) waitcnt counter,#0 'Wait until cnt matches counter (adds 0 to "counter" afterwards) jmp #Loop 'Jump back up to the cell labled "Loop" 'Constants and Variables: Pin long |< 5 '<------- This sets the pin that outputs the servo signal (which is sent to the white wire ' on most servomotors). Here, this "7" indicates Pin 7. Simply change the "7" ' to another number to specify another pin (0-31). AllOn long $FFFFFFFF 'This will be used to set all of the pins high (this number is 32 ones in binary) LowTime long 1_600_000 'This works out to be a 10ms pause time with an 80MHz system clock. If the ' servo behaves erratically, this value can be changed to 1_600_000 (20ms pause) counter res 'Reserve one long of cog RAM for this "counter" variable HighTime res 'Reserve one long of cog RAM for this "HighTime" variable fit 'Makes sure the preceding code fits within cells 0-495 of the cog's RAM {Copyright (c) 2008 Gavin Garner, University of Virginia}Post Edited (blake_macho) : 3/17/2009 5:47:16 PM GMT
When you say it 'does nothing', does this mean that it does not execute, or the motors do not twitch, or ... ? If you do debug printing on each iteration of each repeat 10 loop, does it appear like the spin component is running as expected?
My ignorance here : is there a limit on how many res can be listed at the end of PASM code?
Cheers!
Paul Rowntree
Post Edited (TreeLab) : 3/17/2009 6:06:11 PM GMT
Thanks for your help.
I am wondering if the Pin definition below is overriding the pin assignment before the cognew statement.
'Constants and Variables:
Pin long |< 5 '<
This sets the pin that outputs the servo signal (which is sent to the white wire
Thanks for the help.
-Blake
Post Edited (blake_macho) : 3/23/2009 5:26:29 AM GMT
Here's why:
If VAR variable contents pre-initialized to 0 as seems to be the case by looking at the F8 output, you ended up
getting a very long wait value for your pulse since the value you ended up waiting for with waitcnt had already
passed by the time the instruction executed. If you use small values say <= 12 (3 instructions * 4 ticks per
instruction) or very large values, you would have the same result.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
--Steve
Propalyzer: Propeller PC Logic Analyzer
http://forums.parallax.com/showthread.php?p=788230