Why does this phsa assembly code not work?
godzich
Posts: 74
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:
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):
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
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
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...
Christian
BTW, how do I attach code snipplets here int this forum - embedded into the text (using monospace font)?
-Phil
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.
Are you sure? A - B and A - |B| are two different things in my book ... and so is the flag behaviour.
I think he was referring to the first program, where temp is already the absolute value.
-Phil
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?).
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
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
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).
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
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
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