Searching \ for '[PIC]: please optimise me to 12 ?' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page: www.piclist.com/techref/microchip/devices.htm?key=pic
Search entire site for: 'please optimise me to 12 ?'.

Exact match. Not showing close matches.
PICList Thread
'[PIC]: please optimise me to 12 ?'
2002\08\20@134159 by Roman Black

flavicon
face
Hi assembler code gurus, I have a short piece of
asm for high speed PWM code, that currently takes
15 cycles. Preferably I would like it to be 12 cycles.
:o)

The PWM code must divide by 3, doing 2/3 the time
at Current 2, and 1/3 of the time at current 1.

At the moment it is 15 cycles total, 267 kHz.
I would like 12 cycles, 333 kHz.

This has been stumping me for an hour now, most
annoying. My problem is that I need to check for
any change in inputs on PORTA at some point during
the 12 cycles. The only solutions I have require
reading PORTA directly after writing PORTB, which
I don't like as it is only 62nS between the two
and i'm moving 100+ mA out PORTB...

So if anyone feels like a quickie challenge,
can this 15 cycle code be reduced to 12 cycle code
AND satisfy these:
* must be 8/4 cycles PWM.
* must have minimum 1 inst between write and read.
:o)
-Roman


       ;-------------------------------------------------
       ; PWM LOOP
       ; (the 2 target currents were set previously)

       ; what this function does is spend 2 time units at current2,
       ; and 1 time unit at current1.
       ; actual is 10 cycles at current2
       ; and 5 cycles at current 1

       ; this gives an average pwm current of 2/3 the way between
       ; current2 and current1.

       ; pwm frequency is 267 kHz. (16MHz resonator)

       ; also checks for any change in input pins in this loop!
       ;-------------------------------------------------
pwm_loop
                               ; first output current1 to motor
       movf current1,w         ; get currents and phase switching
       movwf PORTB             ; send to motor!

       nop                     ;
       nop                     ;
       nop                     ; (5 cycles)

       ;-------------------------
                               ; now output current2
       movf current2,w         ;
       movwf PORTB             ; send to motor!

       nop                     ; let ports settle
       nop                     ; + some delay

                               ; now test input pins
       movf PORTA,w            ; get pin values from port
       movwf inputs            ; store in var

       xorwf inputs_last,w     ; xor to compare new inputs with last values
       skpnz
       goto pwm_loop           ; z, inputs not changed, so keep looping
                               ; (10 cycles)
       ;-------------------------------------------------

--
http://www.piclist.com hint: PICList Posts must start with ONE topic:
[PIC]:,[SX]:,[AVR]: ->uP ONLY! [EE]:,[OT]: ->Other [BUY]:,[AD]: ->Ads


2002\08\20@140044 by Scott Dattalo

face
flavicon
face
On Wed, 21 Aug 2002, Roman Black wrote:

{Quote hidden}

You can rearrange the xor

                                ; now output current2
        movf current2,w         ;
        movwf PORTB             ; send to motor!

;       nop                     ; let ports settle
;       nop                     ; + some delay

    nop
    movf   inouts_last,w
    xorwf  PORTA,w
    movwf  diff
    skpz
     goto pwm_loop

Now in the 3 cycles spare in the above loop, change 2 of the nops
to

    movf   diff,w
    xorwf  inputs_last,f

making use of the A = (A ^ B) ^ B trick.

Is that clear? I doubt it...

What is your're trying to do?

Scott

--
http://www.piclist.com hint: PICList Posts must start with ONE topic:
[PIC]:,[SX]:,[AVR]: ->uP ONLY! [EE]:,[OT]: ->Other [BUY]:,[AD]: ->Ads


2002\08\20@144319 by Roman Black

flavicon
face
Scott Dattalo wrote:

{Quote hidden}

Actually it is. You store the new pins in an XORed
form. :o) But there is a problem that your code below
still takes 9 cycles (once goto is included).

       ;-------------------------
                               ; now output current2
       movf current2,w         ;
       movwf PORTB             ; send to motor!
      nop
      movf   inputs_last,w
      xorwf  PORTA,w
      movwf  diff
      skpz
      goto pwm_loop


> What is your're trying to do?

This is supposed to:
* output byte 2 to PORTB for 8 cycles exact
* output byte 1 to PORTB for 4 cycles exact
as a form of PWM that is modulating between
2 values of PORTB, weighted so that one is output
for exactly twice as long as the other.

Somethere in there I need to see if any PORTA
pins have changed, and if so exit with the new
PORTA values in "inputs". The variable "inputs_last"
must not be destroyed.
-Roman

--
http://www.piclist.com hint: PICList Posts must start with ONE topic:
[PIC]:,[SX]:,[AVR]: ->uP ONLY! [EE]:,[OT]: ->Other [BUY]:,[AD]: ->Ads


2002\08\20@145741 by Brendan Moran

flavicon
face
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

> Actually it is. You store the new pins in an XORed
> form. :o) But there is a problem that your code below
> still takes 9 cycles (once goto is included).
>
>         ;-------------------------
>                                 ; now output current2
>         movf current2,w         ;
>         movwf PORTB             ; send to motor!
>        nop
>        movf   inputs_last,w
>        xorwf  PORTA,w
>        movwf  diff
>        skpz
>        goto pwm_loop
>
>
> > What is your're trying to do?

So drop the NOP

- --Brendan
- ---
"Rejection out of hand of all but one's favoured alternative may cost
you dearly in one way or another." -Russell McMahon

-----BEGIN PGP SIGNATURE-----
Version: PGPfreeware 6.5.8 for non-commercial use <http://www.pgp.com>

iQA/AwUBPWKQ3gVk8xtQuK+BEQJ7LACgmTSQFS4ZDKpoNUvcH/9sOp1yakMAoI81
7l/S5ZxWG/yh7NSLD+ytI7Xt
=hPKq
-----END PGP SIGNATURE-----

--
http://www.piclist.com hint: PICList Posts must start with ONE topic:
[PIC]:,[SX]:,[AVR]: ->uP ONLY! [EE]:,[OT]: ->Other [BUY]:,[AD]: ->Ads


2002\08\20@152033 by Olin Lathrop

face picon face
> The only solutions I have require
> reading PORTA directly after writing PORTB, which
> I don't like as it is only 62nS between the two

Where did you get this from.  If I remember right (maybe I don't), output
data is latched at the end of an instruction and input data is sampled at
the start of an instruction.  Therefore there is no time at all between the
output from one instruction and the input received by the next.  Your 62nS
seems to be one Q cycle, but I thought there were 0 Q cycles between the
two.  Of course this doesn't apply if you're writing one port and reading
from another.

{Quote hidden}

Switching to 20MHz would be the equivalent of running this loop at 12.8
instructions or 313KHz.

>
>         ; also checks for any change in input pins in this loop!
>         ;-------------------------------------------------
> pwm_loop
>                                 ; first output current1 to motor
>         movf current1,w         ; get currents and phase switching
>         movwf PORTB             ; send to motor!

Why do you need such high PWM frequency if you are driving a mechanical
system like a motor.  Most motors don't "see" frequencies past 100Hz or so,
certainly a motor will average 1KHz nicely.  At 300KHz you're just
increasing the RF
harmonic content.

Also, what are the bit values of CURRENT1 and CURRENT2?  Are they only off
by one bit, by all bits?

{Quote hidden}

values
>         skpnz
>         goto pwm_loop           ; z, inputs not changed, so keep looping
>                                 ; (10 cycles)
>         ;-------------------------------------------------

Why store the port A value to INPUTS?  Can't the code after this loop fetch
port A itself?


*****************************************************************
Embed Inc, embedded system specialists in Littleton Massachusetts
(978) 742-9014, http://www.embedinc.com

--
http://www.piclist.com hint: PICList Posts must start with ONE topic:
[PIC]:,[SX]:,[AVR]: ->uP ONLY! [EE]:,[OT]: ->Other [BUY]:,[AD]: ->Ads


2002\08\20@153701 by Scott Dattalo

face
flavicon
face
On Wed, 21 Aug 2002, Roman Black wrote:
>
> Actually it is. You store the new pins in an XORed
> form. :o) But there is a problem that your code below
> still takes 9 cycles (once goto is included).

<snip>

Maybe I don't follow. This is what I meant:

pwm_loop

                               ; first output current1 to motor
       movf current1,w         ; get currents and phase switching
       movwf PORTB             ; send to motor!

       movf  diff,w            ;
       xorwf inputs_last       ;

       ;-------------------------
                               ; now output current2
       movf current2,w         ;
       movwf PORTB             ; send to motor!

;        nop                     ; let ports settle
;        nop                     ; + some delay

       movf  inputs_last,w     ; now test input pins
       xorwf PORTA,w
       movwf diff

       skpnz
        goto pwm_loop          ; z, inputs not changed, so keep looping
       ;-------------------------------------------------

That has the 4/8 cycle requirement.  There's a trick to squeeze in another
instruction and still meet the timing. It's probably obvious, so I won't
bother mentioning it. :)

Scott

--
http://www.piclist.com hint: PICList Posts must start with ONE topic:
[PIC]:,[SX]:,[AVR]: ->uP ONLY! [EE]:,[OT]: ->Other [BUY]:,[AD]: ->Ads


2002\08\20@161032 by Eric Bohlman

picon face
8/20/02 12:36:50 PM, Roman Black <spam_OUTfastvidTakeThisOuTspamEZY.NET.AU> wrote:

>So if anyone feels like a quickie challenge,
>can this 15 cycle code be reduced to 12 cycle code
>AND satisfy these:
>* must be 8/4 cycles PWM.
>* must have minimum 1 inst between write and read.

If we can assume that the inputs variable is only accessed outside the loop (i.e. *not* by any
interrupt handler that could be activated during the loop):

>pwm_loop
>                                ; first output current1 to motor
>        movf current1,w         ; get currents and phase switching
>        movwf PORTB             ; send to motor!
>
>        nop                     ;
>        nop                     ;
>        nop                     ; (5 cycles)

Drop that last nop.

>
>        ;-------------------------
>                                ; now output current2
>        movf current2,w         ;
>        movwf PORTB             ; send to motor!
>
>        nop                     ; let ports settle
>        nop                     ; + some delay

Drop that last nop.

>                                ; now test input pins
>        movf PORTA,w            ; get pin values from port
>        movwf inputs            ; store in var

Drop the movwf
>
>        xorwf inputs_last,w     ; xor to compare new inputs with last values
>        skpnz
>        goto pwm_loop           ; z, inputs not changed, so keep looping
>                                ; (10 cycles)
>        ;-------------------------------------------------

And add (now we're outside the loop):

xorwf inputs_last,w
movwf inputs

--
http://www.piclist.com hint: PICList Posts must start with ONE topic:
[PIC]:,[SX]:,[AVR]: ->uP ONLY! [EE]:,[OT]: ->Other [BUY]:,[AD]: ->Ads


2002\08\21@065839 by Roman Black

flavicon
face
Sorry Scott, you were indeed right with your code!
I did understand the xor storage of the dif and the
recovery associated.
Thanks again! :o)
-Roman


Scott Dattalo wrote:
{Quote hidden}

--
http://www.piclist.com hint: The list server can filter out subtopics
(like ads or off topics) for you. See http://www.piclist.com/#topics


2002\08\21@070930 by Roman Black

flavicon
face
Brendan Moran wrote:
{Quote hidden}

Whoops! Me stupid! Sorry Scott and Brendan etc, in my
rush to criticize I forgot that the PORTA read is NOT
the next instruction after the nop.

So it seems to be done, with Scott's solution needing
no work and only two extra cycles upon exit to give
the required "inputs" variable. I can live with that.
:o)
-Roman

--
http://www.piclist.com hint: The list server can filter out subtopics
(like ads or off topics) for you. See http://www.piclist.com/#topics


2002\08\21@071345 by Roman Black

flavicon
face
Thanks Eric, that's a newie and in some ways neater
than Scott's! Although it still requires the 2 inst
recovery afterward and still gets 1 inst grace between
the write and read. Unless someone gets it to less
than 2 insts recovery and/or more than 1 inst grace
I will go with this method I think. :o)
-Roman



Eric Bohlman wrote:
{Quote hidden}

--
http://www.piclist.com hint: The list server can filter out subtopics
(like ads or off topics) for you. See http://www.piclist.com/#topics


2002\08\21@075126 by Roman Black

flavicon
face
Olin Lathrop wrote:
>
> > The only solutions I have require
> > reading PORTA directly after writing PORTB, which
> > I don't like as it is only 62nS between the two
>
> Where did you get this from.  If I remember right (maybe I don't), output
> data is latched at the end of an instruction and input data is sampled at
> the start of an instruction.  Therefore there is no time at all between the
> output from one instruction and the input received by the next.  Your 62nS
> seems to be one Q cycle, but I thought there were 0 Q cycles between the
> two.  Of course this doesn't apply if you're writing one port and reading
> from another.

No I don't think the write and read occur at the
same point in time. Page 23 of the 16C84 datasheet
shows the timing, the write occurs at the end of
the 4th clock and read occurs at the end of the
1st clock. :o)


> Switching to 20MHz would be the equivalent of running this loop at 12.8
> instructions or 313KHz.

This obvious point did not escape me, <grin> but
the design calls for low parts cost so a 16MHz
resonator it was.

> Why do you need such high PWM frequency if you are driving a mechanical
> system like a motor.  Most motors don't "see" frequencies past 100Hz or so,
> certainly a motor will average 1KHz nicely.  At 300KHz you're just
> increasing the RF
> harmonic content.

It is actually for feeding an RC integrator to get
a DC voltage out. Higher freq gives less ripple
voltage and the difference from 15 cycles to 12
cycles is significant with no increase in parts
cost. :o)


> Also, what are the bit values of CURRENT1 and CURRENT2?  Are they only off
> by one bit, by all bits?

Unfortunately no, they vary in differing ways although
sometimes are only 1bit different.
-Roman

--
http://www.piclist.com hint: The list server can filter out subtopics
(like ads or off topics) for you. See http://www.piclist.com/#topics


2002\08\21@090826 by Bob Ammerman

picon face
Roman:

This version does give you an extra instruction between the output and the
input:


loop:
   movf      current1,W
   movwf   PORTB
   goto      $+1
   movf      current2,W
   movwf   PORTB
   nop
   movf      inputs_last,W
   xorfwf    PORTA,W
   skpnz
   goto       loop
   xorwf     inputs_last,W
   movwf    inputs

(sorry for the repeat on the send, but your comments indicated you hadn't
seen this)

Bob Ammerman
RAm Systems

--
http://www.piclist.com hint: The list server can filter out subtopics
(like ads or off topics) for you. See http://www.piclist.com/#topics


2002\08\21@133011 by Roman Black

flavicon
face
Bob Ammerman wrote:
{Quote hidden}

Sorry Bob, I did miss your post, and I have been
getting a lot in the wrong time sequence too.

I thought Eric was the first who posted this
solution, or was it you? Yours uses the $+1
2-cycle trick, saving one memory word also.
:o)
-Roman

--
http://www.piclist.com hint: The list server can filter out subtopics
(like ads or off topics) for you. See http://www.piclist.com/#topics


More... (looser matching)
- Last day of these posts
- In 2002 , 2003 only
- Today
- New search...