Can't get SUB command to work in assembly - newbie
Jermcb
Posts: 8
in Propeller 1
Hi All,
I am trying to learn to use the propeller chip.
I have some code from the object exchange. It is controlling 3 RC servo motors. I was looking at the output and noticed that the time base of the signal changes based on the duration of the 'ON' pulse. So I wanted to modify it to have a constant 10mS or 20mS period that is not dependant on the 'ON' pulse.
So I created a register 'L1PulseDuration' that I use to sum all 3 servo's 'ON' period. Then I wanted to subtract it from the Period register 'L1LowTime'. (Which I move into 'L1counter2' before I do the subtraction because I don't want to over write the 'L1LowTime' register.)
However, as soon as I enable the line in the DAT block with the 'SUB' command, I get no output on any of the Servo pins. (I get the first pulse then it is low for 10 seconds or so, then I get one pulse again. And so on.) I have pasted the code below, and marked the line that is giving me issues with comments ' Here lies the problem'.
1) Can anyone help me out here? I have no idea why this would not work. Especially if it works if I comment out the line with the subtraction. I have no idea how to even look at the values of 'L1PulseDuration' and 'L1counter2' because I don't know how to debug the problem...
Can someone let me know what is wrong. My suspicion is that L1PulseDuration is larger than L1counter2, but that should not be the case because L1counter2 should be 1_600_000 and L1PulseDuration should only be (3*180_000).
2) Also, How can I see the value of L1PulseDuration int he Main spin routine. I also have a serial function that I can stream the data to my computer with, but I don't know how to read the value...
Thank you in advance!!!
I am trying to learn to use the propeller chip.
I have some code from the object exchange. It is controlling 3 RC servo motors. I was looking at the output and noticed that the time base of the signal changes based on the duration of the 'ON' pulse. So I wanted to modify it to have a constant 10mS or 20mS period that is not dependant on the 'ON' pulse.
So I created a register 'L1PulseDuration' that I use to sum all 3 servo's 'ON' period. Then I wanted to subtract it from the Period register 'L1LowTime'. (Which I move into 'L1counter2' before I do the subtraction because I don't want to over write the 'L1LowTime' register.)
However, as soon as I enable the line in the DAT block with the 'SUB' command, I get no output on any of the Servo pins. (I get the first pulse then it is low for 10 seconds or so, then I get one pulse again. And so on.) I have pasted the code below, and marked the line that is giving me issues with comments ' Here lies the problem'.
1) Can anyone help me out here? I have no idea why this would not work. Especially if it works if I comment out the line with the subtraction. I have no idea how to even look at the values of 'L1PulseDuration' and 'L1counter2' because I don't know how to debug the problem...
Can someone let me know what is wrong. My suspicion is that L1PulseDuration is larger than L1counter2, but that should not be the case because L1counter2 should be 1_600_000 and L1PulseDuration should only be (3*180_000).
2) Also, How can I see the value of L1PulseDuration int he Main spin routine. I also have a serial function that I can stream the data to my computer with, but I don't know how to read the value...
Thank you in advance!!!
{Learn Spin programming} CON _clkmode = xtal1 + pll16x 'Standard clock mode * crystal frequency = 80 MHz _xinfreq = 5_000_000 VAR long position1, position2, position3 'The assembly program will read these variables from the main Hub RAM to determine ' the high pulse durations of the three servo signals PUB Main position1:=40_000 'Start sending 2.25ms servo signal high pulses to servomotor 1 (CCW position) position2:=50_000 'Start sending 1.375ms servo signal high pulses to servomotor 2 (Center position) position3:=180_000 'Start sending 0.5ms servo signal high pulses to servomotor 3 (CW position) L1p1:=@position1 'Stores the address of the "position1" variable in the main Hub RAM as "p1" L1p2:=@position2 'Stores the address of the "position2" variable in the main Hub RAM as "p2" L1p3:=@position3 'Stores the address of the "position3" variable in the main Hub RAM as "p3" cognew(@Entry1,0) repeat position1:=180_000 position2:=180_000 position3:=180_000 DAT '--------------------------------------------------------------------------------------------------------------------------------- '--------------------------------------------------------------------------------------------------------------------------------- ' 3 servos 1 '--------------------------------------------------------------------------------------------------------------------------------- '--------------------------------------------------------------------------------------------------------------------------------- Entry1 org 'Assembles the next command to the first cell (cell 0) in the new cog's RAM L1Loop mov L1PulseDuration,0 ' Clear timer counter mov dira,L1ServoPin1 'Set the direction of the "ServoPin1" to be an output (and all others to be inputs) rdlong L1HighTime,L1p1 'Read the "position1" variable from Main RAM and store it as "HighTime" add L1PulseDuration,L1HighTime 'Add first high time to counter mov L1counter,cnt 'Store the current system clock count in the "counter" cell's address mov outa,L1AllOn 'Set all pins on this cog high (really only sets ServoPin1 high b/c rest are inputs) add L1counter,L1HighTime 'Add "HighTime" value to "counter" value waitcnt L1counter,0 'Wait until cnt matches counter (adds 0 to "counter" afterwards) mov outa,#0 'Set all pins on this cog low (really only sets ServoPin1 low b/c rest are inputs) mov dira,L1ServoPin2 'Set the direction of the "ServoPin2" to be an output (and all others to be inputs) rdlong L1HighTime,L1p2 'Read the "position2" variable from Main RAM and store it as "HighTime" add L1PulseDuration,L1HighTime 'Add first high time to counter mov L1counter,cnt 'Store the current system clock count in the "counter" cell's address mov outa,L1AllOn 'Set all pins on this cog high (really only sets ServoPin2 high b/c rest are inputs) add L1counter,L1HighTime 'Add "HighTime" value to "counter" value waitcnt L1counter,0 'Wait until cnt matches counter (adds 0 to "counter" afterwards) mov outa,#0 'Set all pins on this cog low (really only sets ServoPin2 low b/c rest are inputs) mov dira,L1ServoPin3 'Set the direction of the "ServoPin3" to be an output (and all others to be inputs) rdlong L1HighTime,L1p3 'Read the "position3" variable from Main RAM and store it as "HighTime" add L1PulseDuration,L1HighTime 'Add first high time to counter mov L1counter,cnt 'Store the current system clock count in the "counter" cell's address mov outa,L1AllOn 'Set all pins on this cog high (really only sets ServoPin3 high b/c rest are inputs) add L1counter,L1HighTime 'Add "HighTime" value to "counter" value waitcnt L1counter,0 '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 ServoPin3 low b/c rest are inputs) mov L1counter,cnt 'Store the current system clock count in the "counter" cell's address mov L1counter2,L1LowTime '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' '' Here lies the problem VVVVVVVVVVVVVVVVVVVVVV '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' sub L1counter2,L1PulseDuration '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' '' Here lies the problem ^^^^^^^^^^^^^^^^^^^^^^^^^ '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' add L1counter,L1counter2 'Add "HighTime" value to "counter" value waitcnt L1counter,0 '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 ServoPin3 low b/c rest are inputs) jmp #L1Loop 'Jump back up to the cell labled "Loop" 'Constants and Variables: L1ServoPin1 long |< 0 '<------- This sets the pin that outputs the first servo signal (which is sent to the white ' wire on most servomotors). Here, this "6" indicates Pin 6. Simply change the "6" ' to another number to specify another pin (0-31). L1ServoPin2 long |< 1 '<------- This sets the pin that outputs the second servo signal (could be 0-31). L1ServoPin3 long |< 2 '<------- This sets the pin that outputs the third servo signal (could be 0-31). L1p1 long 0 'Used to store the address of the "position1" variable in the main RAM L1p2 long 0 'Used to store the address of the "position2" variable in the main RAM L1p3 long 0 'Used to store the address of the "position2" variable in the main RAM L1AllOn long $FFFFFFFF 'This will be used to set all of the pins high (this number is 32 ones in binary) L1LowTime 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) L1PulseDuration long 0 ' This is the perioed the high pulse goes on for, to accurately get 20mS Period L1PulseDurRead long 0 L1counter res 'Reserve one long of cog RAM for this "counter" variable L1counter2 res 'Reserve one long to calculate the low time L1HighTime 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
shouldn't this be waitcnt L1counter, #0 'Wait until "cnt" matches "counter" then add a 10ms delay to "counter" value
'waitcnt L1counter,0' will wait until the system counter equals L1counter, and then will add the value contained in register 0 into L1counter. In your case, register 0 contains the instruction "mov L1PulseDuration,0", which equals $A0BC5000 and not 0. I agree with ErNa that you want #0 and not 0.
You have this same problem in several other places. Your first instruction, "mov L1PulseDuration,0", should be "mov L1PulseDuration,#0".
You need a # in front of all immediate literal constants. # sets a bit in the instruction which tells the Prop to use that value and not the value stored in the register with that address for its source value.
I put the # in front of my literal 0's and now it works well.
I am still curious about my second question though... If this was another problem and I wanted to see what value the 'L1PulseDuration' was set to, how could I get that value in my main spin routing to pass it on to my serial port?
(I understand it is in the cog ram and the spin program will be in the hub ram. But how do I transfer the updated value across?)
Right now, you have registers like L1p1 and such that you poke pointers into before cognew'ing your PASM code. You then use these pointers as the source field of rdlong instructions. Make some more variables just like those ones, but use wrlong with them instead. Then, have your Spin code display the values in those variables. If necessary, you can have one to use as a flag to indicate when data is ready.