Shop OBEX P1 Docs P2 Docs Learn Events
Can't get SUB command to work in assembly - newbie — Parallax Forums

Can't get SUB command to work in assembly - newbie

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!!!
{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

  • ErNaErNa Posts: 1,752
    edited 2016-02-14 21:02
    waitcnt L1counter,0 'Wait until "cnt" matches "counter" then add a 10ms delay to "counter" value

    shouldn't this be waitcnt L1counter, #0 'Wait until "cnt" matches "counter" then add a 10ms delay to "counter" value
  • No, I don't think so. It 'waitcnt L1counter,0' will wait till CNT = L1counter, then moves 0 into L1counter.
  • ElectrodudeElectrodude Posts: 1,657
    edited 2016-02-14 21:52
    Jermcb wrote: »
    No, I don't think so. It 'waitcnt L1counter,0' will wait till CNT = L1counter, then moves 0 into L1counter.

    '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.
  • ErNaErNa Posts: 1,752
    This is a beginners pitfall, I was a specialist in this. Remember: the prop is a register machine. So by default, all the parameters are pointers to registers. If you which to use a literal, you have to tell this explicitely by marking the value with a "#"
  • Wow! Thank you. I knew it was going to be a newbie mistake!!

    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?)
  • Jermcb wrote: »
    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.
  • Thank you!
Sign In or Register to comment.