Simple asm delay ?


Closed Thread
Results 1 to 23 of 23

Hybrid View

  1. #1
    Join Date
    Apr 2006
    Location
    GearSweaterMountain, The Netherlands
    Posts
    52


    Did you find this post helpful? Yes | No

    Default

    Google came up with an interesting piece of code.
    I did some tests and it seems to do the trick.

    If called using "@ wait 0" it delays 1uS,
    if called using "@ wait 1" it delays about 2,5uS,
    if called using "@ wait 2" it delays about 3uS.

    Code:
    asm
    shortwait macro del  ; used by main wait macro
        if (del>3) && (del<8) 
            call del7+(7-(del)) 
        endif 
        if del <4 
            if del>=2 
                goto $+1
            endif
            if ((del) & 1) == 1
                nop
            endif
        endif
        endm
    endasm
    
    asm
    wait macro del 
    ;    if (del)<0 error 'negative delay' 
    ;    endif 
        if (del)>=8 
            movlw ((del)-8) /4 
            call delay
            shortwait ((del-8) % 4) 
        else
            shortwait (del)
         endif
        endm
    
    delay  
        addlw 0xff 
        skpnc 
        goto delay
        return
     
    del7 goto del5      ; 7 cycle delay
    del6 goto del4      ; 6 cycle delay
    del5 nop            ; 5 cycle delay
    del4 return         ; 4 cycle delay
    ENDasm
    So, the delay is not the problem anymore.
    However, when called from picbasic like :
    Code:
    led1 var word
    led2 var word
    
    led1 = 2
    led2 = 2
    
    start:
    
    GPIO = %01
    @ wait _led1
    GPIO = %10
    @ wait _led2
    
    goto start
    The delay is about 33uS instead of 2. I understand that the delay would be longer, but 30uS extra ??

    Can someone, please, point me in the right direction ?
    Last edited by ultiblade; - 12th November 2009 at 13:18. Reason: Typo

  2. #2
    Join Date
    Nov 2005
    Location
    Bombay, India
    Posts
    969


    Did you find this post helpful? Yes | No

    Default

    Once you start counting instruction cycles, you will realize how they all add up to get you to the 30uS extra that you see. A call takes 2 cycles, a return another 2, and so on.

    I am a bit curious about your application and how you achieve colour fading. According to what you have shown here, you seem to be lighting the leds one behind the other with a fixed pause in between. I do not know why you have it that way, but, I would think it would be better to have them work in tandem unless you want just 1 led on at a time.

    Why not use 3 PWM channels one per colour to control the intensity of each?
    Now, the refresh rate for all the channels will be the same, but, the on-time for each led will be decided by its on-time variable.

    Would this work for you?

  3. #3
    Join Date
    Apr 2006
    Location
    GearSweaterMountain, The Netherlands
    Posts
    52


    Did you find this post helpful? Yes | No

    Default

    Hi Jerson,

    I understand your questions, let me explain some more :

    I drive 3 powerled's directly from the mains using a led driver board. These led's are switched by FET's, each on it's own channel. The driver board itself is about 10x10mm, a pic with 3 pwm channels in a SO8 package is just not available. Everything larger won't fit the enclosure.

    The driver cannot drive 2 or 3 led's at once, that's why i'm switching between the three. Doing so at a total delay (led1 delay + led2 delay + led3 delay)=1000Hz + some overhead.

    Pauseus does it's work, and all is fading smoothly. Except for the first start of a color. This sticks to 12us. When a fade is started, the color that is being faded in does not start at 1 or 2 us but starts with an initial delay of 12uS.

    Hope this makes my problem somewhat clearer ...

    I did count the instruction cycles, i even did a cross comparison of the asm files, the one using a number @ wait 0 and the one using @ wait _ledRED both files are exactly the same and have the exact same length ! I played around with the variables, changed them to byte's, putting them in bank0 ....

    Why would changing from a numeric value to a numeric value stored in a variable result in an overhead of 30uS, i just don't understand.

  4. #4
    Join Date
    Apr 2006
    Location
    GearSweaterMountain, The Netherlands
    Posts
    52


    Did you find this post helpful? Yes | No

    Default

    Small update :

    Declaring the variables as:

    ledRED VAR WORD BANK0

    Does reduce the total delay somewhat, the shortest delay (0) now results in 20uS ..

  5. #5
    Join Date
    Nov 2005
    Location
    Bombay, India
    Posts
    969


    Did you find this post helpful? Yes | No

    Default

    Try declaring your variable as BYTE instead of word. It will shave more time from the 20uS.

  6. #6
    Join Date
    Nov 2005
    Location
    Bombay, India
    Posts
    969


    Did you find this post helpful? Yes | No

    Default

    Assuming you have TMR0 (8 bit timer) free, you can try this code

    Code:
    AsmDelay macro  delayus
          movlw  0FFh-delayus    ; delayus to overflow                          1T
          movwf  TMR0                                                                            1T
          bcf        INTCON, T0IF    ; clear the timer0 Overflow flag          1T
          btfss     INTCON, T0IF    ; wait till it overflows                          1T/2T
          goto      $-1                   ; back to the btfss                              2T
      
          endm
    The minimum delay you will achieve will be 4T cycles or roughly 2uS at 8MHz.


    The way to use it would be
    Code:
          GPIO = %01
          @ AsmDelay 12
          GPIO = %10
          @ AsmDelay 24
    I hope this takes you closer to your goal. The code is just a concept, you may have to correct it. One important point you should note - the maximum delay will be 255uS
    Last edited by Jerson; - 12th November 2009 at 18:00.

  7. #7
    Join Date
    Jul 2003
    Posts
    2,405


    Did you find this post helpful? Yes | No

    Default

    Try this.
    Code:
    asm
    DelayCycles macro ncy ; ncy can be from 1 up to 256
      local n
    n set   (ncy)   ; assign ncy value to label n
    
      while n > 2   ; inserts goto $+1 while n > 2
        goto $+1    ; burn 2 cycles
    n   set   n - 2 ; n = n - 2
      endw
                    ; handle left-overs
      while n > 0   ; 1 nop for odd numbers
        nop         ; burn 1 cycle
    n   set   n - 1 ; n = n - 1
      endw
      endm
    endasm
    
    Main:
      HIGH 0
      @ DelayCycles 1  ; adds 1 nop
      LOW 0
      @ DelayCycles 5  ; adds 2 x goto $+1 and 1 x nop
      GOTO Main
    Regards,

    -Bruce
    tech at rentron.com
    http://www.rentron.com

Similar Threads

  1. 16F628A - Stops if release power switch.
    By dene12 in forum General
    Replies: 16
    Last Post: - 14th February 2009, 07:57
  2. Old and beyond help ?
    By DavidFMarks in forum mel PIC BASIC Pro
    Replies: 46
    Last Post: - 11th December 2008, 15:23
  3. RF Transmitter
    By et_Fong in forum mel PIC BASIC Pro
    Replies: 4
    Last Post: - 27th October 2005, 16:34
  4. Memory Space of the PIC16F84...
    By Tear in forum mel PIC BASIC Pro
    Replies: 7
    Last Post: - 1st July 2005, 19:55
  5. Problem with saving to EEPROM...
    By Tear in forum mel PIC BASIC Pro
    Replies: 5
    Last Post: - 1st July 2005, 00:10

Members who have read this thread : 0

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts