blake_macho
03-17-2009, 02:06 PM
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.
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[LASER]~~
outa[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
#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[LASER]~~
outa[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