Shop OBEX P1 Docs P2 Docs Learn Events
Does anyone see any inherent problems with this PASM code? — Parallax Forums

Does anyone see any inherent problems with this PASM code?

turbosupraturbosupra Posts: 1,088
edited 2012-07-03 06:56 in Propeller 1
I replaced a PASM waitpne with the first few lines of code below and I cannot get consistently accurate results now.

pstPtr6/pstPtr7 will print the cycles I expect to the pst, about 75% of the time, the other 25% it will either print a number smaller than 100 or it will print out a number roughly 2.9 times as big, but never 3 times as large. This seems to be consistent, even when I adjust the frequency going to the input pin.

What I'd like the code to do is test a pin for high and if it is high to go to #end but if the pin is low then the phsa should be done accumulating values for the previous pin high and I should be able to copy the number of cycles out of phsa, so if it is low I then check phsa to see if it is 0. If it isn't 0, I copy the cycles out and store them under highCycles and then set phsa to 0 to show that I've been there so that next time if the pin is low and phsa is 0, I pass by knowing I've already grabbed the cycles data.

I'm not sure what is causing the jitter though, as the routine is pretty simple so I have a feeling I may be missing something obvious. Thanks for reading.
                       'wait for pin == 0 pause cog until mask matches the second field
'                        waitpne mask, mask   
                        test    mask, ina WC, WZ' test pin to be equal to ina register
        if_c                    jmp     #end            ' if equal to to the register jmp to end and loop because you can't count the cycles until the pin is in the opposing state
        if_z                    mov     phsaT, phsa     ' if 0 or not equal to register pin is low, copy cycles measuring pin high to phsaT
                               
                                cmp     phsaT, #0 WC, WZ    ' compare phsaT to literal 0
        if_e                    jmp     #end            ' if equal to 0, it has already been checked, jmp to end
        if_ne                   mov     highCycles, phsa     ' copy cycles accumlated to highCycles
        if_ne                   mov     phsa, #0        ' clear low phase counter
        if_ne                   mov     risingEdgeCnt, cnt     ' store cnt value

Comments

  • Mark_TMark_T Posts: 1,981
    edited 2012-07-01 13:37
    Can you clean up the code, nearly every instruction has a condition yet this seems unnecessary with the conditional jmps (to non-existent label).

    You also test both for zero and carry flags after the first test instruction which doesn't make sense - are you trying to test for zero and non-zero? carry records the parity under the mask, unless you actually want to record the parity make things clear by using Z or NZ. Is the mask a single bit or can it be more than one bit?

    Why is the waitpne not used? What are you trying to achieve? What is the signal going to the pin and what results are you expecting to observe?
  • turbosupraturbosupra Posts: 1,088
    edited 2012-07-01 14:30
    Hi Mark,

    I am not using waitpeq/waitpne because I need to have functionality within the loop where the cog is not paused. The entire code is about 1400 lines so I didn't want to post everything and cause unnecessary confusion with all of the extra lines of code.

    Psuedo code line by line would read
    test if pinmask == ina (test of pin is high)
    if equal jump to end (this will indirectly loop to restart which is the beginning of the loop)
    if not equal copy phsa to phsaT
    
    compare phsaT to literal 0
    if equal  jump to end (this will indirectly loop to restart which is the beginning of the loop)
    if not equal copy phsa to highCycles
    if not equal clear phsa
    if not equal copy cnt to risingEdgeCnt
    
                            test    mask, ina WC, WZ' test pin to be equal to ina register
    if_c                    jmp     #end            ' if equal to to the register jmp to end and loop because you can't count the cycles until the pin is in the opposing state
    if_z                    mov     phsaT, phsa     ' if 0 or not equal to register pin is low, copy cycles measuring pin high to phsaT
                           
                            cmp     phsaT, #0 WC, WZ    ' compare phsaT to literal 0
    if_e                    jmp     #end            ' if equal to 0, it has already been checked, jmp to end
    if_ne                   mov     highCycles, phsa     ' copy cycles accumlated to highCycles
    if_ne                   mov     phsa, #0        ' clear low phase counter
    if_ne                   mov     risingEdgeCnt, cnt     ' store cnt value
    
    
  • ericballericball Posts: 774
    edited 2012-07-01 17:17
    Your pseudocode doesn't match your PASM. Why are you using if_c jmp #end after the test mask, in a instead of if_z? You also don't need some of the instructions.
                   test    mask, ina    wz ' test pin to be equal to ina register
        if_nz      mov     phsaT, phsa  wz ' if 0 or not equal to register pin is low, copy cycles measuring pin high to phsaT
        if_z       jmp     #end            ' if equal to 0, it has already been checked, jmp to end
                   mov     highCycles, phsa     ' copy cycles accumlated to highCycles
                   mov     phsa, #0        ' clear low phase counter
                   mov     risingEdgeCnt, cnt     ' store cnt value
    
    One of the powers of PASM is you can chain condition codes. So here I chain the test & mov in a virtual OR equivalent to
    if ( mask == ina ) OR ( ( phsaT := phsa ) == 0 ) goto end
    
  • turbosupraturbosupra Posts: 1,088
    edited 2012-07-01 20:15
    Hi Eric,

    Thanks for the code, that was educational! I tried it and it appears to be working like my other code.

    I am still seeing "jitter" where phsa and phsb are either <100 cycles or 2.x greater than what they should be. Any thoughts on that?
  • Mark_TMark_T Posts: 1,981
    edited 2012-07-02 06:11
    How do you know what it "should be" - what is your signal source and how have you determined that the "jitter" isn't present in it?
  • ericballericball Posts: 774
    edited 2012-07-02 09:47
    I realized last night that test (aka AND) sets C based on odd parity. Therefore if mask only contains a single 1 then C will be an ==. So the correct PASM is:
                   test    mask, ina    wc ' test pin to be equal to ina register
        if_nc      mov     phsaT, phsa  wz ' if 0 or not equal to register pin is low, copy cycles measuring pin high to phsaT
        if_z_or_c  jmp     #end            ' if equal to 0, it has already been checked, jmp to end
                   mov     highCycles, phsa     ' copy cycles accumlated to highCycles
                   mov     phsa, #0        ' clear low phase counter
                   mov     risingEdgeCnt, cnt     ' store cnt value
    
  • turbosupraturbosupra Posts: 1,088
    edited 2012-07-02 09:54
    The reason I feel I know what I should be seeing is because I don't see jitter on the scope, it works as expected with the waitpeq/waitpne commands and another propeller is the one generating the signal as well as timing its own cycles and displaying them for me. I still may be overlooking something though and am open to suggestions as to how to narrow this down.
  • turbosupraturbosupra Posts: 1,088
    edited 2012-07-02 11:14
    Thanks Eric, now I'll have to figure out this jitter. It turns out using waitpeq ruins my entire project and would basically make it unusable.

    I have taken out all code in the entire pasm loop but the test command (I'm looping at ~96 cycles in pasm) and I'm still seeing the jitter (both high and low) so I'm going to try something other than test as I'm not sure what else to do.


    ericball wrote: »
    I realized last night that test (aka AND) sets C based on odd parity. Therefore if mask only contains a single 1 then C will be an ==. So the correct PASM is:
                   test    mask, ina    wc ' test pin to be equal to ina register
        if_nc      mov     phsaT, phsa  wz ' if 0 or not equal to register pin is low, copy cycles measuring pin high to phsaT
        if_z_or_c  jmp     #end            ' if equal to 0, it has already been checked, jmp to end
                   mov     highCycles, phsa     ' copy cycles accumlated to highCycles
                   mov     phsa, #0        ' clear low phase counter
                   mov     risingEdgeCnt, cnt     ' store cnt value
    
  • turbosupraturbosupra Posts: 1,088
    edited 2012-07-03 06:10
    Either there is an issue with how I'm using the test command in a way that it wasn't designed to be used, or something else is happening as I'm still getting erroneous values when checking the phsa and phsb counters. It's right at least 75% of the time but not always. The code is pretty simple so I think it's either a register flag isn't being handled correctly or I can't use it this way.

    Is there a command that I can write that clears register flags so that they cannot carry over to the next if_registerflag? Almost like a break? maybe mov 0, 0 ?
  • turbosupraturbosupra Posts: 1,088
    edited 2012-07-03 06:56
    Ok, I got the erroneous high values sorted, but not the erroneous low values.

    Could it be that there is some sort of delay in the frqa to phsa accumulation so that after I detect a pin state transition and I copy the values of phsa to a variable, frqa then loads <100 cycles to phsa which are present the next time I loop through? Is this inherent to the test command?
Sign In or Register to comment.