Shop OBEX P1 Docs P2 Docs Learn Events
How can you check a specific pin number inside of a cogs ina register in PASM? — Parallax Forums

How can you check a specific pin number inside of a cogs ina register in PASM?

turbosupraturbosupra Posts: 1,088
edited 2012-05-22 19:49 in Propeller 1
Hello,

With spin, I would write temp := ina[6]

With PASM, I'm able to view all of the pins with "mov pinsState, ina" and then writing pinsState but I'm not sure how to do a cmp to 1010111100000000000000000[size=+2]1[/size]000000 ?

I'd like to do:
cmp pinsState, #1 or cmp pinsState, #0

Is this possible?
«1

Comments

  • tonyp12tonyp12 Posts: 1,951
    edited 2012-05-11 13:35
    'INA read-only register and thus should only be used in the instruction’s source operand'

    try this:
    mov ina,ina 'copy to shadow
    and ina,_mypin wz
    if_z ...
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2012-05-11 13:58
    A quicker way:
            test    my_pin,ina wz
            ...
    my_pin  long    1 << pin_number
    

    -Phil
  • turbosupraturbosupra Posts: 1,088
    edited 2012-05-11 14:04
    Ah, thank you Tony.

    And if I wanted to check for that pin being low, then
                            mov     ina, ina
                            andn     ina, camPwmMonitorPinMask WZ
    if_e                    mov     highCycles, phsa     
    
  • JonnyMacJonnyMac Posts: 9,195
    edited 2012-05-11 14:07
    I think this is a cleaner way to go:
    test    camPwmMonitorPinMask, ina       wz
            if_z            mov     highCycles, phsa
    
  • turbosupraturbosupra Posts: 1,088
    edited 2012-05-11 14:12
    Hi Phil,

    I've never used test before and am trying to wrap my head around it
    test	camPwmMonitorPinMask, ina WZ, WC
    if_e
    
    
    in this case is the same as
    test	00000000000000000000000001000000, 10101111000000000000000001000000 WZ, WC
    if_e
    

    How would this work with testing the pin being low?


    A quicker way:
            test    my_pin,ina wz
            ...
    my_pin  long    1 << pin_number
    

    -Phil
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2012-05-11 14:14
    Since you're testing only one pin, just do a test for zero. If the pin is low, the Z flag will be set, as a result of the wz.

    -Phil
  • Duane DegnDuane Degn Posts: 10,588
    edited 2012-05-11 14:30
    This is one of many reasons I wish the examples in the Propeller Manual used binary number examples. It's really hard to see what's happening with dec or hex numbers when the operator is working on the individual bits.

    I'm sure I'm not the only one with many bit operation examples translated into binary.

    Sorry, Brad and others for the OT (but not too much so) rant.
  • turbosupraturbosupra Posts: 1,088
    edited 2012-05-11 14:45
    Thank you all for the replies


    Explanation
    TEST is similar to AND except it doesn’t write a result to Value1; it performs a bitwise AND of the values in Value1 and Value2 and optionally stores the zero-result and parity of the result in the Z and C flags.
    If the WZ effect is specified, the Z flag is set (1) if Value1 AND Value2 equals zero. If the WC effect is specified, the C flag is set (1) if the result contains an odd number of high (1) bits.

    JonnyMac wrote: »
    I think this is a cleaner way to go:
    test    camPwmMonitorPinMask, ina       wz
            if_z            mov     highCycles, phsa
    

    test against a low to then move high cycles
    test 00000000000000000000000001000000, 10101111000000000000000000000000 WZ, WC
    if_z mov highCycles, phsa
    ' if they AND to 0, Z is set to 1

    I understand how this AND works, because the only one that is high in the pin mask is pin 6 and I guess test sets Z to 1 because no 1's are returned from the AND operation?


    A quicker way:
            test    my_pin,ina wz
            ...
    my_pin  long    1 << pin_number
    

    -Phil

    test against a high to then move low cycles
    test 00000000000000000000000001000000, 10101111000000000000000001000000 WZ
    if_nz mov lowCycles, phsb
    ' if they AND to 1, Z is set to 0


    And with this one, if it is ANDed together, there is a single 1 from the AND operation, so test sets the Z flag to 0?

    Do I have it?
  • turbosupraturbosupra Posts: 1,088
    edited 2012-05-11 14:48
    No need to apologize, as I agree ... and the propeller manual is the bane of my existence sometimes. If it weren't for the people on this forum I would be still trying to figure out DIRA in spin :-D. As annoyed as I get at Parallax sometimes for the lack of examples in the manual, or Parallax classroom style example objects to download/manipulate and figure out how they work, I'm inversely that thankful to all of the helpful people on this forum.

    Duane Degn wrote: »
    This is one of many reasons I wish the examples in the Propeller Manual used binary number examples. It's really hard to see what's happening with dec or hex numbers when the operator is working on the individual bits.

    I'm sure I'm not the only one with many bit operation examples translated into binary.

    Sorry, Brad and others for the OT (but not too much so) rant.
  • jazzedjazzed Posts: 11,803
    edited 2012-05-11 14:58
    test bitmask, ina wc ' far more intuitive and flexible especially for serial to parallel conversions - making bytes one bit at a time.
  • turbosupraturbosupra Posts: 1,088
    edited 2012-05-11 16:33
    If the WC effect is specified, the C flag is set (1) if the result contains an odd number of high (1) bits.
    odd bits/C=1
    even bits/C=0

    So if a bit from ina is high, all the bits below are ANDed together and 1 of them results in an odd number of bits (1)

    0000000000000000000000000[size=+2]1[/size]000000 (pin mask)
    ANDed
    1010111100000000000000000[size=+2]1[/size]000000
    =
    0000000000000000000000000[size=+2]1[/size]000000
    C=1


    and if a bit is low, all the bits are ANDed together and 0 of them result in an odd number of bits (0)
    0000000000000000000000000[size=+2]1[/size]000000 (pin mask)
    ANDed
    1010111100000000000000000[size=+2]0[/size]000000
    =
    0000000000000000000000000[size=+2]0[/size]000000
    C=0



    I take it this is best used when testing a single pin?


    jazzed wrote: »
    test bitmask, ina wc ' far more intuitive and flexible especially for serial to parallel conversions - making bytes one bit at a time.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2012-05-11 16:36
    turbosupra wrote:
    I take it this is best used when testing a single pin?
    Yes, that's usually the case. The utility of the even/odd thing comes into play, for example, when testing the parity of sent or received data.

    -Phil
  • kuronekokuroneko Posts: 3,623
    edited 2012-05-11 17:06
    turbosupra wrote: »
    I take it this is best used when testing a single pin?
    Define best! While it's probably the most common form you may not be able to use the carry flag at the time so the zero flag will do just fine.
  • JonnyMacJonnyMac Posts: 9,195
    edited 2012-05-11 17:21
    I used the Zero flag in my example because you're wanting to check if the pin is low (0 if read digitally). Don't get wrapped around the axle about the value of the Zero flag, treat it as true or false when used in the context I suggested.
  • turbosupraturbosupra Posts: 1,088
    edited 2012-05-19 18:37
    Hello everyone,

    I can't figure out what I'm doing wrong here?

    The binary value of pinReadMask is 00000000000000000000001000000000
    I can see pstPtr16 oscillating between 1 and 0 and I've set the counters up as shown below.

    highCycles is always 0 and lowCycles is at least doing something, does the format at least look correct?

    highCycles should read ~66500
    lowCycles should read ~200000
                            test    pinReadMask, ina WZ               ' test if pin is high or low
    if_z                    mov     highCycles, phsa
    if_z                    wrlong  one, pstPtr16
    if_z                    wrlong  highCycles, pstPtr13
    
                            test    pinReadMask, ina WC
    if_c                    mov     lowCycles, phsb
    if_c                    mov     phsb, #0                       ' clear high phase counter
    if_c                    wrlong  zero, pstPtr16
    if_c                    wrlong  lowCycles, pstPtr14
    
    
                            mov     ctra, POS_DETECT                ' ctra measures high phase
                            add     ctra, pinReadMask
                            mov     frqa, #1
                            
                            mov     ctrb, NEG_DETECT                ' ctrb measures low phase
                            add     ctrb, pinReadMask
                            mov     frqb, #1
     
    
    
  • kuronekokuroneko Posts: 3,623
    edited 2012-05-19 19:55
    Test and waitpxx take pin masks (|< n), the counter setup requires pin numbers (n).
    movs    ctra, #pin
            movi    ctra, #%0_01000_000        ' POS detect
    
            test    mask, ina wc
    
    mask    long    |< pin
    
  • turbosupraturbosupra Posts: 1,088
    edited 2012-05-20 17:52
    Thank you very much Kuroneko, I will make that change tomorrow and see if I can get it working : )
  • turbosupraturbosupra Posts: 1,088
    edited 2012-05-21 12:37
    I'm still failing at this, I've been at this for so long, I'm not sure which way is up now. I can however see pstPtr16 oscillating back and forth between zero and one.

    pinRead is 22, pinReadMask is 00000000010000000000000000000000
    pin is 26, pinMask is 00000100000000000000000000000000


    POS_DETECT long %01000 << 26
    NEG_DETECT long %01100 << 26


    I would like to read the high cycles when the pin goes low, and the low cycles when the pin goes high, but without a wait command as well as then clear the high cycles when the pin is low and clear the low cycles when the pin is high, again without any wait commands.

    I've reread what everyone has written a bunch of times and to me, the code below should work based on my understanding, and it is not.

    initialize
                           
    
                            mov     pinMask, #1                     ' create mask from pin #
                            rdlong  pin, pinAddrPtr 
                            shl     pinMask, pin
                            mov     dira, pinMask
    
                            mov     pinReadMask, #1                     ' create mask from pin #
                            rdlong  pinRead, pinReadAddrPtr 
                            shl     pinReadMask, pinRead
                            mov     ina, pinReadMask 
    
                            mov     ctra, pinRead
                            mov     ctra, POS_DETECT                ' ctra measures high phase                        
                            mov     frqa, #1
    
                            mov     ctrb, pinRead
                            mov     ctrb, NEG_DETECT                ' ctrb measures low phase                       
                            mov     frqb, #1
     
                            mov     phaseState, phaseOne
    

                            test    pinReadMask, ina WC               ' test for low
    if_nc                   mov     highCycles, phsa
    if_nc                   mov     phsb, #0
    if_nc                   wrlong  one, pstPtr16
    if_nc                   wrlong  highCycles, pstPtr14
    
                            test    pinReadMask, ina WC            ' test for high
    if_c                    mov     lowCycles, phsb
    if_c                    mov     phsa, #0                       ' clear high phase counter
    if_c                    wrlong  zero, pstPtr16
    if_c                    wrlong  lowCycles, pstPtr15
    
    
    
  • kuronekokuroneko Posts: 3,623
    edited 2012-05-21 16:59
    Do you have some test code for this? That said, ctrb is detecting low and you clear it when you (manually) detect low (nc)?
  • turbosupraturbosupra Posts: 1,088
    edited 2012-05-21 17:49
    Hi,

    Thanks for the reply and pointing out that I'm clearing on the wrong 1/2 of the cycle, I've changed that to what is reflected below but it still isn't working? I've also changed the initialize code to reflect the following.
    mov     ctra, #pinRead
    mov     ctrb, #pinRead
    

    I have my full object with lots of pasm and lots of debugging/commenting. Would you rather me create something simple?

    What I would like to do is:

    when pin == 1, copy phsb to lowCycles, then clear phsb
    when pin == 0, copy phsa to highCycles, then clear phsa

    Does my code look close if I switch to
                            test    pinReadMask, ina WC               ' test for low
    if_nc                   mov     highCycles, phsa
    if_nc                   mov     phsa, #0
    if_nc                   wrlong  one, pstPtr16
    if_nc                   wrlong  highCycles, pstPtr14
    
                            test    pinReadMask, ina WC            ' test for high
    if_c                    mov     lowCycles, phsb
    if_c                    mov     phsb, #0                       ' clear high phase counter
    if_c                    wrlong  zero, pstPtr16
    if_c                    wrlong  lowCycles, pstPtr15
    
    
    

    Let me know if you'd like me to try to build some simple object. Thanks!
  • kuronekokuroneko Posts: 3,623
    edited 2012-05-21 18:03
    turbosupra wrote: »
    ... pointing out that I'm clearing on the wrong 1/2 of the cycle, I've changed that to what is reflected below but it still isn't working?
    Depending on how fast your loop runs consider the following: You detect high and read/clear/report the relevant counter. The second half isn't relevant yet (still high) so is skipped. Then you detect high again ... the NEG DETECT counter is still idle (hasn't seen a low yet) so you report 0 which may hide your previous result if the display code isn't fast enough. Hard to say without seeing the complete code. Just post it as is.
  • turbosupraturbosupra Posts: 1,088
    edited 2012-05-21 18:13
    I believe you are right and what you are describing is happening (big surprise there :-D )

    Here is the object itself, if you need the entire project, please let me know.

    Thank you again.

    Here is what the pst is seeing (as a general example, the numbers are changing with each refresh)

    Pst14: 2786
    Pst15: 4528
    Pst16: 1

    kuroneko wrote: »
    Depending on how fast your loop runs consider the following: You detect high and read/clear/report the relevant counter. The second half isn't relevant yet (still high) so is skipped. Then you detect high again ... the NEG DETECT counter is still idle (hasn't seen a low yet) so you report 0 which may hide your previous result if the display code isn't fast enough. Hard to say without seeing the complete code. Just post it as is.
  • turbosupraturbosupra Posts: 1,088
    edited 2012-05-21 18:37
    I tried this ... all aboard the failboat : ) . This ina register was so easy in spin, but it is killing me in PASM!
                            cmp     pinReadState, waitForLow WC, WZ
    if_e                    jmp     #low
    
                            cmp     pinReadState, waitForHigh WC, WZ
    if_e                    jmp     #high
                         
    
    low
                            test    pinReadMask, ina WC, WZ               ' test for low
    if_z                    mov     highCycles, phsa
    if_z                    mov     phsa, #0
    if_z                    wrlong  one, pstPtr16
    if_z                    wrlong  highCycles, pstPtr14
    if_z                    mov     pinReadState, waitForHigh        
    
    high
                            test    pinReadMask, ina WC, WZ            ' test for high
    if_c                    mov     lowCycles, phsb
    if_c                    mov     phsb, #0                       ' clear high phase counter
    if_c                    wrlong  zero, pstPtr16
    if_c                    wrlong  lowCycles, pstPtr15
    if_c                    mov     pinReadState, waitForLow
    
  • kuronekokuroneko Posts: 3,623
    edited 2012-05-21 19:54
    Keep it simple. You have the basic idea right but execution lacks a little :) The example below samples a square wave generated by a different cog. High and low times are written to hub memory where they are picked up by a simple display loop.
    CON
      _clkmode = XTAL1|PLL16X
      _xinfreq = 5_000_000
    
      pin = 16
    
    OBJ
      serial: "FullDuplexSerial"
      
    VAR
      long  storage[2]
      long  stack[32]
      
    PUB null
    
      serial.start(31, 30, %0000, 115200)
      cognew(pulse, @stack{0})
      cognew(@entry, @storage{0})
      waitcnt(clkfreq*3 + cnt)
      serial.tx(0)
    
      repeat
        serial.hex(storage{0}, 8)
        serial.tx(32)
        serial.hex(storage[1], 8)
        serial.tx(13)
        waitcnt(clkfreq/2 + cnt)
    
    PRI pulse
    
      dira[pin]~~
      ctra := constant(%0_00100_000 << 23 | pin)
      repeat
        frqa := $00000100
        waitcnt(clkfreq*2 + cnt)
        frqa := $00000080
        waitcnt(clkfreq*2 + cnt)
      
    DAT             org     0
    
    entry           add     pulse_h, par
                    add     pulse_l, par
    
                    movs    ctra, #pin
                    movi    ctra, #%0_01000_000             ' POS
                    movs    ctrb, ctra
                    movi    ctrb, #%0_01100_000             ' NEG
    
                    mov     frqa, #1
                    mov     frqb, #1
    
    loop            [COLOR="blue"]cmp     edge, #1 wz[/COLOR]                     ' rising edge test?
        [COLOR="blue"]if_z[/COLOR]        [COLOR="orange"]test    mask, ina wc[/COLOR]                    ' Y
        [COLOR="blue"]if_z[/COLOR]_[COLOR="#FFA500"]and_c[/COLOR]  mov     phsb, phsb                      ' sample
        [COLOR="blue"]if_z[/COLOR]_[COLOR="#FFA500"]and_c[/COLOR]  wrlong  phsb, pulse_l                   ' report
        [COLOR="blue"]if_z[/COLOR]_[COLOR="#FFA500"]and_c[/COLOR]  mov     phsb, #0                        ' clear
        [COLOR="blue"]if_z[/COLOR]_[COLOR="#FFA500"]and_c[/COLOR]  xor     edge, #1                        ' next is falling edge
    
                    [COLOR="blue"]cmp     edge, #0 wz[/COLOR]                     ' falling edge test?
        [COLOR="blue"]if_z[/COLOR]        [COLOR="#FFA500"]test    mask, ina wc[/COLOR]                    ' Y
        [COLOR="blue"]if_z[/COLOR]_[COLOR="#FFA500"]and_nc[/COLOR] mov     phsa, phsa                      ' sample
        [COLOR="blue"]if_z[/COLOR]_[COLOR="#FFA500"]and_nc[/COLOR] wrlong  phsa, pulse_h                   ' report
        [COLOR="blue"]if_z[/COLOR]_[COLOR="#FFA500"]and_nc[/COLOR] mov     phsa, #0                        ' clear
        [COLOR="blue"]if_z[/COLOR]_[COLOR="#FFA500"]and_nc[/COLOR] xor     edge, #1                        ' next is rising edge
    
    '               other in-loop code
    
                    jmp     #loop
                    
    
    edge            long    0
    mask            long    |< pin
    pulse_h         long    0
    pulse_l         long    4
    
                    fit
    
    DAT
    
    Generated output. Note that there are occasional transitions visible because the frequency change doesn't happen in sync with the square wave.
    00800000 00800000
    00800000 00800000
    00800000 00800000
    01000000 00DA41D0
    01000000 01000000
    01000000 01000000
    00EA7638 01000000
    00800000 00800000
    00800000 00800000
    00800000 00800000
    00800000 008C1A68
    01000000 01000000
    01000000 01000000
    01000000 01000000
    
  • turbosupraturbosupra Posts: 1,088
    edited 2012-05-21 20:06
    I would bet my execution lacks a lot :) ... but I'm thankful to have this forum and users that are as generous as yourself to parse through my code

    I was able to get this to work a few minutes ago, but it was discovered through attrition. I'll be using your code to learn more about this, as I obviously have a huge gaping hole in my PASM knowledge when it comes to checking a pins input state. I want to make sure my head is completely wrapped around this, before moving to the next code that I have to write. Believe it or not, I'm pretty much an ADC/DAC away from testing this out in the car!

    I was told that you could not do a conditional condition, such as

    cmp x, y
    if_e cmp, x, z

    Is that incorrect? I see that you've done that with cmp/test, is it special with the test operation or can you do as I've written above?


    Thank you again for the help.
                            cmp     pinReadState, waitForLow WC, WZ
    if_e                    jmp     #low
    
                            cmp     pinReadState, waitForHigh WC, WZ
    if_e                    jmp     #high
                         
    
    low
                            test    pinReadMask, ina WC, WZ               ' test for low, and if low
    if_z                    mov     highCycles, phsa
    if_z                    mov     phsa, #0
    if_z                    wrlong  one, pstPtr16
    if_z                    wrlong  highCycles, pstPtr14
    if_z                    mov     pinReadState, waitForHigh
    if_nz                   jmp     #phases    
    
    
    high
                            test    pinReadMask, ina WC, WZ            ' test for high, and if high
    if_c                    mov     lowCycles, phsb
    if_c                    mov     phsb, #0                       ' clear high phase counter
    if_c                    wrlong  zero, pstPtr16
    if_c                    wrlong  lowCycles, pstPtr15
    if_c                    mov     pinReadState, waitForLow
    
    
    phases
    
  • kuronekokuroneko Posts: 3,623
    edited 2012-05-21 20:25
    turbosupra wrote: »
    I was told that you could not do a conditional condition, such as

    cmp x, y
    if_e cmp, x, z

    Is that incorrect? I see that you've done that with cmp/test, is it special with the test operation or can you do as I've written above?
    Don't see why it can't be done/used. The thing is that the second compare may introduce a flag condition which is incompatible with the first one, e.g.
    cmp     x, y wz
    if_e    cmp     x, z wz
    if_e    jmp     #label
    
    In this case the branch may be taken if x == y but can still be cancelled with x <> z. So the final branch condition would be x == y AND x == z. If that's not what you want then you have to restructure your code.

    What's the branch condition in this case?
    cmp     x, y wz
    if_e    cmp     x, z wz
    if_ne   jmp     #label
    
  • kuronekokuroneko Posts: 3,623
    edited 2012-05-21 20:33
    Before you get confused by this:
    if_z_and_c  mov     [COLOR="blue"]phsb[/COLOR], phsb                      ' sample
        if_z_and_c  wrlong  [COLOR="blue"]phsb[/COLOR], pulse_l                   ' report
        if_z_and_c  mov     phsb, #0                        ' clear
    
    The counter is considered inactive at this point. The phase register can't be written directly to hub (shadow/counter) so we have to copy it first to a location which can be used in the destination slot (shadow or regular register). The final move affects both, counter and shadow register. An equivalent sequence would be:
    if_z_and_c  mov     [COLOR="orange"]temp[/COLOR], phsb                      ' sample
        if_z_and_c  wrlong  [COLOR="orange"]temp[/COLOR], pulse_l                   ' report
        if_z_and_c  mov     phsb, #0                        ' clear
    
  • turbosupraturbosupra Posts: 1,088
    edited 2012-05-22 06:44
    kuroneko wrote: »
    Don't see why it can't be done/used. The thing is that the second compare may introduce a flag condition which is incompatible with the first one, e.g.
    cmp     x, y wz
    if_e    cmp     x, z wz
    if_e    jmp     #label
    
    In this case the branch may be taken if x == y but can still be cancelled with x <> z. So the final branch condition would be x == y AND x == z. If that's not what you want then you have to restructure your code.

    Ok, so in PASM you can do if && if, or if || if? I did not know that, but that will be handy.

    What's the branch condition in this case?
    cmp     x, y wz
    if_e    cmp     x, z wz
    if_ne   jmp     #label
    

    I like puzzles! I believe it would be if x=y but x!=z, jump to #label? My question is, if x!=y, does it satisfy the if_ne also? If that is true, how would you handle that, with a jump, or is there something a little cleaner/universal like a break?
  • kuronekokuroneko Posts: 3,623
    edited 2012-05-22 06:54
    turbosupra wrote: »
    Ok, so in PASM you can do if && if, or if || if? I did not know that, but that will be handy.
    Not as such (as you would in SPIN) it's just a logical expression written in PASM. Then again, it's rather late here so maybe we refer to the same thing. Who knows?
    turbosupra wrote: »
    I believe it would be if x=y but x!=z, jump to #label?
    You mean x == y AND x <> z? If so, not quite (one out of three). Just take it one step at a time. You have 4 input conditions (x <> y, x == y, x <> z, x == z) what happens for each pairing?
  • turbosupraturbosupra Posts: 1,088
    edited 2012-05-22 07:23
    What's the branch condition in this case?
    cmp     x, y wz
    if_e    cmp     x, z wz
    if_ne   jmp     #label
    

    Ok, I'm not sure yet if I'm looking at this correctly, because I'm still unclear if these are always evaluated conditionally/together, or they can be evaluated separately line by line? If the second comparison is always evaluated only if the first comparison is equal, then I believe I have the below correct. It's like a 2 digit binary equation : )

    x==y / x!=z := true
    x==y / x==z := false
    x!=y / x!=z := false
    x!=y / x==z := false
Sign In or Register to comment.