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

    You are right about the 1us. I'm using this to be able to fade between colors.

    If I turn on the red led, wait 333uS, then turn on the green led, wait 333uS, and then the blue led and wait 333uS and then loop again, i have a white color at about 1000Hz, with no flickering. If i then increment the pauseus 333 for red and decrement the pauseus 333 for blu the color shifts smooth from white to about orange.

    I use the pauseus command at 8Mhz, which has a shortest delay of 12us. In the fade cycle this results in that one (or two) led are almost off, but not completely. The last 12 cycles the led stay on for 12us, and in the last cycle it will turn off.

    It works perfect except for the last few cycles ....

  2. #2
    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

  3. #3
    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?

  4. #4
    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.

  5. #5
    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 ..

  6. #6
    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.

  7. #7
    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.

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