Shop OBEX P1 Docs P2 Docs Learn Events
Why does this phsa assembly code not work? — Parallax Forums

Why does this phsa assembly code not work?

godzichgodzich Posts: 74
edited 2010-10-07 08:42 in Propeller 1
Hi,

I'm running a 6-channel (center-symmetric) PWM using the following WORKING prop asm code. This routine is called repeatedly, just after the loop has finished:
            
Entry              mov     loopcnt, loops                'loop for 2048 times 
                   mov     phsa, value                     'set phase register to -50_000
               
:PWMLoop           abs     temp, phsa                     
                   subabs  PWM1, temp      nr, wc            
                   muxnc   outa, LeftRed       
                   subabs  PWM2, temp      nr, wc
                   muxnc   outa, LeftGrn       
                   subabs  PWM3, temp      nr, wc 
                   muxnc   outa, LeftBlu                           
                   subabs  PWM4, temp      nr, wc                                                
                   muxnc   outa, RightRed      
                   subabs  PWM5, temp      nr, wc 
                   muxnc   outa, RightGrn      
                   subabs  PWM6, temp      nr, wc 
                   muxnc   outa, RightBlu
                   djnz    loopcnt, #:PWMLoop                   'jump back


Yes I know - the routine would also work if the subabs are replaced by just sub. However, I would like to run the code using only 52 clocks (instead of 56), by using the routine written as follows (removing the "abs tepm, phsa" from within the loop):
Entry              mov     loopcnt, loops         'loop for 2047 times - at least
                   mov     phsa, value              'set phase register to -50000
             
:PWMLoop           subabs  PWM1, phsa      nr, wc       
                   muxnc   outa, LeftRed       
                   subabs  PWM2, phsa      nr, wc
                   muxnc   outa, LeftGrn       
                   subabs  PWM3, phsa      nr, wc 
                   muxnc   outa, LeftBlu                           
                   subabs  PWM4, phsa      nr, wc                                                
                   muxnc   outa, RightRed      
                   subabs  PWM5, phsa      nr, wc 
                   muxnc   outa, RightGrn      
                   subabs  PWM6, phsa      nr, wc 
                   muxnc   outa, RightBlu
                   djnz    loopcnt, #:PWMLoop               'jump back


However, referring to phsa within the loop does not work (gives erroneous pwm output). I know that phsa should not be used in read-modify-write instructions, but here it is just used as the source! Why does the first version work, but not this other? The trick I use to produce center-symmetric pwm - is to use a PWM phase counter (phsa) that runs from -50_000 to +50_000, and compare its absolute value agains the current PWM value at every PMWx. This works completely well in the first example!!!

Please, can someone direct me or educate me, what I am doing wrong. Any help is higly appreciated. I'm still learning prop asm...

Cheers

Christian

Comments

  • ericballericball Posts: 774
    edited 2010-10-04 11:49
    Could the difference be PHSA changing during the loop? Also, how are you controlling PHSA? (i.e. limiting it to +50_000)?
  • godzichgodzich Posts: 74
    edited 2010-10-04 11:56
    Hi,

    Thanks for your fast reply!

    Since my PWMx required value changes is chucks of 56 - no - there is no time for the phsa to advance more than 56 counts during these 14 instructions (14 x 4 = 56). Frqa is set to #1. PHSA gets loaded at the beginning of each looping of 2048 times, as shown. The final value is very close to the opposite, as intended...

    This really puzzles me...
    ericball wrote: »
    Could the difference be PHSA changing during the loop? Also, how are you controlling PHSA? (i.e. limiting it to +50_000)?

    Christian


    BTW, how do I attach code snipplets here int this forum - embedded into the text (using monospace font)?
    Hmm... don't bother - I found it already :)
    
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2010-10-04 12:58
    godzich wrote:
    However, referring to phsa within the loop does not work (gives erroneous pwm output).
    Christian, when you say you get erroneous pwm output, can you elaborate? Your second version cannot be expected to match the first exactly, since phsa is advancing during the loop. Are you seeing errors that exceed the differences expected?

    -Phil
  • kuronekokuroneko Posts: 3,623
    edited 2010-10-04 17:11
    godzich wrote: »
    Since my PWMx required value changes is chucks of 56 - no - there is no time for the phsa to advance more than 56 counts during these 14 instructions (14 x 4 = 56). Frqa is set to #1. PHSA gets loaded at the beginning of each looping of 2048 times, as shown. The final value is very close to the opposite, as intended...

    2048*13*4 = 106496 (-50k..+56k), I'd say that's slightly out of range. Regardless, as Phil already mentioned, the second version only differs in that phsa is live during the loop. Not what I'd call a noticable difference. Even your first example goes beyond +50k (+64k) so it's most likely something else.
    godzich wrote: »
    Yes I know - the routine would also work if the subabs are replaced by just sub.
    Are you sure? A - B and A - |B| are two different things in my book ... and so is the flag behaviour.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2010-10-04 18:31
    Kuroneko,

    I think he was referring to the first program, where temp is already the absolute value.

    -Phil
  • kuronekokuroneko Posts: 3,623
    edited 2010-10-04 19:44
    I think he was referring to the first program, where temp is already the absolute value.

    Good point (and the comment is below the first example). Serves me right for taking it out of context :)

    But that is most likely the problem, now that I see it spelled out. The carry flag is inverted if the argument to subabs is negative. So half the time your conditions are wrong. Looks like you're stuck with 56 cycles (is it really that important?).
  • godzichgodzich Posts: 74
    edited 2010-10-05 12:58
    I finally found also the explanation for my trouble in the prop help files.

    There it says about SUBABS like this:

    If the source is negative - then C is the inverse of unsigned carry!

    Wonder if the propeller manual has an omission here?

    So you are totally right with this, I cannot use the SUBABS as I inteded, I have to calculate the ABS value as in my first version, and then just do plain SUB's within the loop. Since my timing is critical, I tried to squeeze one instruction from the loop. But that seems not to be possible...

    My original version works just fine. The initial value for phsa is (-2048*56/2-13) = -57357
    This gives me a perfectly center-aligned PWM with 2048 levels (including fully off and fully on). Increasing the PWM value adds the width of the PWM pulse, at both edges, one side at a time.

    Thank you all for your professional comments. A great forum -and members !!!

    Cheers,

    Christian
    kuroneko wrote: »
    Good point (and the comment is below the first example). Serves me right for taking it out of context :)

    But that is most likely the problem, now that I see it spelled out. The carry flag is inverted if the argument to subabs is negative. So half the time your conditions are wrong. Looks like you're stuck with 56 cycles (is it really that important?).
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2010-10-05 13:40
    godzich wrote: »
    I finally found also the explanation for my trouble in the prop help files. There it says about SUBABS like this: If the source is negative - then C is the inverse of unsigned carry! Wonder if the propeller manual has an omission here?
    It's in the latest downloadable version of the manual (although it's missing from the explanation) but not in the printed version.

    attachment.php?attachmentid=74209&stc=1&d=1286310411

    But the "corrected" manual is still wrong -- somewhere. In the truth table, it shows subabs 3, -3 as having the carry set. But 3 + -3 (i.e. 3 + $ffff_fffd) yields an unsigned carry, and inverting that produces C=0.

    The inverse of the unsigned carry for D+S when S is negative is the same as the unsigned borrow for D-|S|. So I'm not sure why there has to be a distinction if that's the correct explanation for how the instruction works.

    -Phil
    774 x 777 - 42K
  • kuronekokuroneko Posts: 3,623
    edited 2010-10-05 18:07
    But the "corrected" manual is still wrong -- somewhere. In the truth table, it shows subabs 3, -3 as having the carry set. But 3 + -3 (i.e. 3 + $ffff_fffd) yields an unsigned carry, and inverting that produces C=0.

    The truth table is correct. Carry is set as for sub a, |b| but inverted if b was negative, i.e. subabs'ing -4..3 from 2 will give you a carry vector of %00110001 (LSb is for 3).
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2010-10-05 19:52
    Kuroneko,

    Thanks. So it's the footnote, "If S is negative, C = the inverse of unsigned carry (for D+S)," that's wrong.

    Why do I get the feeling that this was not the intended behavior but was discovered after it was too late to fix it? Unless I'm overlooking the problem it was designed to solve, the carry behavior doesn't seem very useful.

    -Phil
  • godzichgodzich Posts: 74
    edited 2010-10-06 04:46
    Hi,

    Strange, I got the same feeling that this is not how Chip originally had thought this C bit to behave in this opcode. Surely the C-bit is less usable this way around -at least in my case - maybe also in other cases. I wish this sentence "If S is negative, C = the inverse of unsigned carry (for D+S)" would have been included in the explanation part - it would have saved me from some hours of frustration. Maybe it can be added to the next release of the manual? This would deserve to also be added into the "caveats" section in the excellent Propeller tips & tricks document!!!

    Christian

    Kuroneko,

    Thanks. So it's the footnote, "If S is negative, C = the inverse of unsigned carry (for D+S)," that's wrong.

    Why do I get the feeling that this was not the intended behavior but was discovered after it was too late to fix it? Unless I'm overlooking the problem it was designed to solve, the carry behavior doesn't seem very useful.

    -Phil
  • kuronekokuroneko Posts: 3,623
    edited 2010-10-07 05:21
    @Christian: Is it important that the on-phase for all LEDs(?) is centered in relation to each other? Otherwise you might get away with doubling the PWM# values and run phsa from 0..2*range.
    before:
    
    __--------__|__--------__
    ____----____|____----____
    ___------___|___------___
    
    after:
    --------____|--------____
    ----________|----________
    ------______|------______
    
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2010-10-07 08:42
    Kuroneko,

    For certain kinds of loads, you sometimes want the centered PWM. It's not so much for keeping the different channels centered w.r.t. each other but for preventing phase shifts in each one when the duty cycle changes.

    -Phil
Sign In or Register to comment.