Shop OBEX P1 Docs P2 Docs Learn Events
HELP PLEASE ...Assembly code for counter not working — Parallax Forums

HELP PLEASE ...Assembly code for counter not working

CrescendoCrescendo Posts: 4
edited 2012-02-15 17:50 in Propeller 1
Hi,

We need to count the vibrations from a vibration sensor on an input pin on our Propeller board. We want to write the code in Assembly language (we already wrote it in Spin) so that one cog can keeping counting while we use the count number as a variable for another program in Spin language. We hope to decrease our lag time by doing this. However, we are having trouble with our Assembly code. We tried to write it based on our Spin code and this is what we have:

DAT

org 0
:loop movi ctra, #000 'bs2.COUNT_Start(Pin) --> reference to Spin code
movi ctra, Hash
mov frqa, #1
mov phsa, #0
rdlong Delay, #0 'bs2.Pause(Duration)
shr Delay, #2
mov Time, cnt
add Time, Delay
waitcnt Time, Delay
mov Vibes, phsa 'bs2.Count_Read
movi ctra, #000 'bs2.Count_ Stop
jmp #:loop

Vibes long
Pin long |<4
Hash long (010 << 26 ) | (1 << 23) | (0 << 9) | (4)
Delay res 1
Time res 1


The Spin code that this code is based on is below where "bs2" is from the object exchange http://obex.parallax.com/objects/30/ :

bs2.Start
bs2.COUNT_Start(4)
bs2.pause(100)
vibes := bs2.Count_Read
bs2.Count_Stop


Any help with our Assembly code would be greatly appreciated!!
Thank you.

Comments

  • CircuitsoftCircuitsoft Posts: 1,166
    edited 2012-02-12 15:18
    Crescendo wrote: »
    Hi,

    We need to count the vibrations from a vibration sensor on an input pin on our Propeller board. We want to write the code in Assembly language (we already wrote it in Spin) so that one cog can keeping counting while we use the count number as a variable for another program in Spin language. We hope to decrease our lag time by doing this. However, we are having trouble with our Assembly code. We tried to write it based on our Spin code and this is what we have:
    DAT
    
                    org       0      
    :loop         movi     ctra, #000                'bs2.COUNT_Start(Pin)  --> reference to Spin code
                    movi     ctra, Hash
                    mov      frqa, #1
                    mov      phsa, #0
                    rdlong   Delay, #0                        'bs2.Pause(Duration)
                    shr      Delay, #2
                    mov      Time, cnt
                    add      Time, Delay
                    waitcnt  Time, Delay                       
                    mov      Vibes, phsa                     'bs2.Count_Read  
                    movi     ctra, #000                  'bs2.Count_ Stop
                    jmp      #:loop
    
    Vibes      long
    Pin        long    |<4
    Hash       long    (010 << 26 ) | (1 << 23) | (0 << 9) | (4)
    Delay      res     1
    Time       res     1
    


    The Spin code that this code is based on is below where "bs2" is from the object exchange http://obex.parallax.com/objects/30/ :
        bs2.Start
        bs2.COUNT_Start(4)
        bs2.pause(100)
        vibes := bs2.Count_Read
        bs2.Count_Stop              
    

    Any help with our Assembly code would be greatly appreciated!!
    Thank you.
    Just adding CODE tags to make it easier to read.
  • JonnyMacJonnyMac Posts: 9,197
    edited 2012-02-12 15:45
    Once you've captured the count you have to write it to the hub (using wrlong) so that your Spin code can access it. And if your Spin counter is working, why not just launch that into its own cog? Easy to do and saves you the trouble of converting to PASM.

    [Edit] Here's how:

    Create a variable and a stack for the counter cog:
    var
    
      long  vibes
      long  cstack[32]
    


    Then launch the method that handles the counting. Note that I mark these methods as private as an indicator that they're call-and-return type methods. You'll see that inside the code it runs in a loop and can never escape, hence you cannot call it normally, you must launch it with cognew
    cognew(counter(CNTR_PIN, 100, @vibes), @cstack)
    


    Here's the counter method. Remember, this is launched into its own cog so you cannot read its phsa register directly.
    pri counter(pin, ms, pntr) | t                                  ' launch with cognew
    
      phsa := 0
      frqa := 1
      ctra := (%01010 << 26) | pin                                  ' count positive edges on pin
    
      t := cnt
      repeat
        waitcnt(t += (clkfreq / 1000) * ms)                         ' let count accumulate
        long[pntr] := phsa                                          ' report to hub
        phsa := 0                                                   ' reset
    


    After launching your hub variable will be updated with the counts on the selected pin at the rate you specify. For very high frequency signals you may still have to convert to PASM; this code is closer to what you want than using the BS2 object.


    [Edit 2] Here's how to do the same thing in PASM.
    var
    
      long  cpin
      long  vibes
      
      
    dat
    
                            org     0
    
    counter                 mov     t1, par                         ' start of variables
                            rdlong  cp, t1                          ' read counter pin
                            add     t1, #4
                            mov     cpntr, t1                       ' save count result address   
                            rdlong  delaytix, t1                    ' read loop timing
    
                            mov     t1, #0
                            wrlong  t1, cpntr                       ' clear delay from result var
    
                            mov     frqa, #1                        ' set to count positive edges
                            mov     phsa, #0
                            mov     t2, POS_EDGE
                            or      t2, cp
                            mov     ctra, t2
    
                            mov     ctimer, delaytix                ' start timer
                            add     ctimer, cnt
    
    ctrloop                 waitcnt ctimer, delaytix                ' let timing window expire
                            mov     t1, phsa                        ' capture count
                            mov     phsa, #0                        ' restart count
                            wrlong  t1, cpntr                       ' update hub result                                     
                            jmp     #ctrloop
    
    ' --------------------------------------------------------------------------------------------
    
    POS_EDGE                long    %01010 << 26
    
    cp                      res     1                               ' counter pin
    cpntr                   res     1                               ' pointer to count result
    
    delaytix                res     1                               ' loop delay in ticks
    ctimer                  res     1                               ' loop timer
    
    t1                      res     1                               ' work vars
    t2                      res     1
    
                            fit     496
    


    You launch the PASM code like this:
    cpin := CNTR_PIN
      vibes := clkfreq / 1000 * 100
      cognew(@counter, @cpin)
    


    Note that this counts on a specific order of variables and the delay timing is passed in the vibes variable to the PASM code. Once the delay is read by the PASM code this variable is cleared in prep for counts on the pin.
  • ChrisGaddChrisGadd Posts: 310
    edited 2012-02-12 21:01
    First of all, it doesn't look like your counter is ever being turned on. The instruction movi ctra, #000 turns the counter off, and the following line moves the nine low bits of hash, which unless I'm mistaken is %0_00010_001_00000000_000000_000_00100 into ctra. The nine low bits sets the counter mode to %0_00000_100, which is still turned off.

    It looks like you're trying to use PLL single-ended mode with divide by 64 (counter mode 0_00010_001) with an output on pin 4. If that's the case you would either use a regular mov instruction: mov ctra, Hash or piece it together as in: movi ctra,#%0_00010_001 and movs ctra,#%00100. That gets the clock ticking, but you need to enable an output pin: mov dira,#%1000. I don't really see how that's useful for counting though. Seems to me counter modes 0_01010_000 (posedge detector) or 0_01110_000 (negedge detector) would be better suited.

    You're loading a delay from memory location 0, which contains the clock frequency (typically 80_000_000) which shifted right twice is a 250ms delay.

    And lastly a nitpicky detail, it's better to load your delay into the register and add the current cnt, than to load the cnt and add the delay. mov Time,Delay then add Time,cnt. This makes sure you the most recent value of cnt.
    ... actually it looks like you're starting the counter mov phsa,#0 quite a few cycles before you get the delay established. Ideally, you'd get the delay read in and prepared first, and then zero phsa and wait out the delay.
              movi          ctra,#%0_01010_000                    ' Set ctra to count positive edges
              movs          ctra,#1<<4                            ' Count on pin 4
              mov           frqa,#1                               ' Increment phsa by 1 for each positive edge detected
              rdlong        time,Delay_address                    ' Load the time delay
              shr           time,#2                               '  and divide it by 4
    :loop
              mov           delay,time                            ' Load the time delay
              add           delay,cnt                             ' Add the current cnt
              mov           phsa,#0                               ' Clear phsa
              waitcnt       delay,#0                              ' Wait out the time delay
              mov           Vibes,phsa                            ' Make a copy of phsa
              wrlong        Vibes,Count_address                   ' Store the count in hub memory
              jmp           #:loop                                
    
  • JonnyMacJonnyMac Posts: 9,197
    edited 2012-02-13 10:47
    Attached is a test program for the PASM code I posted above. One of my favorite aspects of the Propeller is that one cog can be used to provide test input for another -- no outside hardware required.
  • kuronekokuroneko Posts: 3,623
    edited 2012-02-13 16:07
    JonnyMac wrote: »
    You'll see that inside the code it runs in a loop and can never escape, hence you cannot call it normally, you must launch it with cognew.
    In that case you're missing a repeat ...
  • JonnyMacJonnyMac Posts: 9,197
    edited 2012-02-13 16:36
    Whoops, that's what I get for typing code into the forums. I actually ran the PASM version, so I know it works.
  • CrescendoCrescendo Posts: 4
    edited 2012-02-15 17:50
    Thank you all for your prompt and valuable input. Mr. McPhalen, we have been improving our code according to your suggestions, and will inform you about our progress.
Sign In or Register to comment.