Making PBP code more modular


Closed Thread
Results 1 to 31 of 31

Hybrid View

  1. #1
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default

    WOW, this is very surprising. Nobody uses Includes???

    I can't imagine NOT using them.

    Reasons for my thinking. :

    -- Version Control -- Back when I wasn't using Includes, I'd have the same routine Cut&Pasted into several different programs. While working on one of them I'd have a brainstorm and figure out a better way to do it. Now all the other programs are either stuck with the old version, or I'd have to go back through every program I've written in the past to update their in-line code. Ugg.

    -- Thought Grouping -- As in Melanie's modularized list, Typically any variables, aliases etc. will be placed at the top of the program. But more than likely, the routines in question will be buried deep in the middle of the program, completely isolated from all the other things that go with it. By using Include files, you can keep things grouped together so that you always know what variables or other subroutines are needed to be able to use the said routine.

    -- Ease of use -- If I need an interrupt driven clock or a buffered UART routine. All I need to do is type in 1 or 2 lines. No cut&paste, no variable searching, nothing. Just boom, there it is.

    I always wondered when I wrote an include file for sombody else, why they would take it apart and paste it in 4 different places in their own program. Just doesn't make sense to me. And seemed rude to me at the time.
    But apparently, everybody would do the same thing.

    ----------------

    And, about those "Magic Numbers", don't like 'em
    Do you know how many problems on both the List and the forum have been tracked down to Magic Numbers. The newbie just cut&pastes the code we give them without having a clue how it works. They spend a week trying to figure out why the Code doesn't work, and it turns out to be that T1CON=%00001001 should have been T1CON=%00000001 or something similar.

    Granted, doing it all in one shot saves instruction cycles, and code space. But it sure can cause problems when sharing your code in public forums.

    Best regards,
       Darrel Taylor

    P.S. scroll down to the bottom of the page and click on the vB Code link. There are several ways to format your posts.

  2. #2
    Join Date
    Feb 2003
    Location
    Delaware
    Posts
    30


    Did you find this post helpful? Yes | No

    Default To each his own.

    Darrel,

    I guess that I just never got into the habit of using includes. I almost always have an assembly language ISR at the begining of my programs and I could probably make different ones up with different features and then just include them. But I guess I just never took the time to make sure it would work properly so I don't trust it. I might try it on my next program. If I do I will post a follow up.

    As for magic numbers...I am not sure you follow. A magic number is a nicely named constant that allows you to more easily control your code parameters from one place. Magic numbers make your code easier for newbies to understand because the numbers are given meaningful names.

    Your example of
    T1CON=%00000001

    might look like this
    'CONSTANTS and MAGIC NUMBERS
    TMR1_ON = %00000001 'constant to plug into T1CON to start timer
    TMR1_OFF = %00000000 'constant to plug into T1CON to stop timer
    Some really nice code goes here!
    Main:
    T1CON = TMR_ON 'start timer1
    Some more code.
    T1CON = TMR_OFF 'stop timer1
    goto main

    I usually don't do it this way. I usually alias the register bit and set it equal to 0 or 1.

    TMR1_enable = T1CON.0 'set TMR1_enable to start clr to stop.
    TMR1_enable = 1 'start timer 1
    TMR1_enable = 0 'stop timer 1

    A better example of magic numbers would be
    'Constants--------------------
    buffer_size = 16 'This is how big the buffer is (in chars).
    'Variables----------------------
    buffer var byte[buffer_size] 'This is were the serial in characters go.


    I think that these examples show that magic numbers can make it easier to make changes to your code and they make your code easier to read.

    What do you think?

    Regards,

    Joe.

  3. #3
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default

    I think the same thing applies there too. If TMR1_ON = %00000001, and the next person is trying to use an external crystal on timer1. It can cause problems.

    Apparently I do things different than everyone else, but I try to do things in as Low Level as possible when controling SFR's.

    This is also where Includes can come in handy.
    In that file you can have predefined macro's that give good names to common functions. For the above example it might look like this...
    Code:
    ASM
    TMR1_ON  macro
        bsf  T1CON, TMR1ON
        endm
    
    TMR1_OFF  macro
        bcf  T1CON, TMR1ON
        endm
    ENDASM
    Along with many other Timer related macro's.

    Then in the main program, you no longer need to worry about what registers, and what bit's need to be in a Magic Number or an Aliased variable. Just call the macro like this...
    Code:
    @  TMR1_ON
    
    '-- OR --
    
    @  TMR1_OFF
    As a side benefit, those macros only take 1 instruction cycle, instead of the 2 required to copy a constant to a byte variable.

    I don't think the buffer_size example applies here because it's not a bitwise operation. It's a whole number that still requires a constant. (CON, not =)

    Darrel
    Last edited by Darrel Taylor; - 27th July 2005 at 00:37.

  4. #4
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default

    OR ---

    Here's another version that allows you to work with Timers 0-3
    Code:
    ASM
    TMR_ON  macro T
        if (T==0)
            bsf  T0CON, TMR0ON
        else
            if (T==1)
                bsf  T1CON, TMR1ON
            else
                if (T==2)
                    bsf T2CON, TMR2ON
                else
                    if (T==3)
                        bsf T3CON, TMR3ON
                    endif
                endif
            endif
        endif
        endm
    
    TMR_OFF  macro T
        if (T==0)
            bcf  T0CON, TMR0ON
        else
            if (T==1)
                bcf  T1CON, TMR1ON
            else
                if (T==2)
                    bcf T2CON, TMR2ON
                else
                    if (T==3)
                        bcf T3CON, TMR3ON
                    endif
                endif
            endif
        endif
        endm
    ENDASM
    This still only takes 1 instruction cycle but allows you to select which timer is being used.
    Code:
    @  TMR_ON  1
    @  TMR_ON  3
    @  TMR_OFF 0
    After awhile, your include files start to define your own personal language. No longer stuck with the standard commands that are defined in the PBP compiler. You'll spend a lot less time looking at the datasheets, and more looking at your program.

    Best regards,
       Darrel
    Last edited by Darrel Taylor; - 27th July 2005 at 01:09.

  5. #5
    forgie's Avatar
    forgie Guest


    Did you find this post helpful? Yes | No

    Default includes for assembly macros

    Now this is more like what includes make sense for (in my mind)..... Peripheral control macros. You could make a file that contains all the macros for one uC (e.g. 18f452.pbp). Every time you use a peripheral, you make a macro and add it to the uCs peripheral macro file. I was going to make another post asking about how to do assembly macros (I too want my own command set to make things tidier) but seeing your example shows me what I need to know.

    Only one question: is there any way to make a macro in asm, then put PBP code inside the macro? (I guess I could go and pick the PBP-ASM files apart to find the ASM macros that PBP uses and use them, but if I don't have to I won't waste my time)

    So, for example, is there some way to write, say an LCD command macro that uses LCDOUT?
    so that
    LCDCMD Clear, Line1, Right
    would have the effect of
    LCDOUT $FE, $01, $FE, $80, $FE, $14

    (BTW I already have constants representing all those commands anyway, but it would be nice to not have to enter the them all in this way)

  6. #6
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default

    You might want to try making includes NOT processor specific. Otherwise you go back to that multiple version problem again. If you need a new file for every chip you use, you'll be writing include files for ever.
    is there any way to make a macro in asm, then put PBP code inside the macro?
    Sure, you can pop in and out of asm whenever you want, but passing arguments can be a little trickier. Let's go back to the first example
    Code:
    ASM
    TMR1_ON  macro
        bsf  T1CON, TMR1ON
        endm
    
    TMR1_OFF  macro
        bcf  T1CON, TMR1ON
        endm
    ENDASM
    This could also be done this way
    Code:
    ASM
    TMR1_ON  macro
        ENDASM
        T1CON.0 = 1     ' PBP statement in a macro
        ASM
        endm
    
    TMR1_OFF  macro
        ENDASM
        T1CON.0 = 0
        ASM
        endm
    ENDASM
    But, as you can see, it's harder to read that way, but will compile to the exact same thing.
    so that LCDCMD Clear, Line1, Right would have the effect of LCDOUT $FE, $01, $FE, $80, $FE, $14
    Let's try the LCD thing with PBP statements too. This may not be the most efficient way to handle the LCD, but it does answer the specific question...
    Code:
    Clr       CON    1  system
    Home      CON    2  system
    Line1     CON    4  system
    Line2     CON    8  system
    Line3     CON   16  system
    Line4     CON   32  system
    CurOFF    CON   64  system
    CurBlink  CON  128  system
    CurUL     CON  256  system
    
    ASM
    LCDCMD  macro  options
        if (options & Clr) > 0      ; Clear Screen
            ENDASM
            LCDOUT  $FE, $01
            ASM
        endif
        if (options & Home) > 0     ; Home Cursor
            ENDASM
            LCDOUT  $FE, $02
            ASM
        endif
        if (options & Line1) > 0    ; Move to Line 1
            ENDASM
            LCDOUT  $FE, $80
            ASM
        endif
        if (options & Line2) > 0    ; Move to Line 2
            ENDASM
            LCDOUT  $FE, $C0
            ASM
        endif
        if (options & Line3) > 0    ; Move to Line 3
            ENDASM
            LCDOUT  $FE, $90         ; may be $94 on some displays
            ASM
        endif
        if (options & Line4) > 0    ; Move to Line 4
            ENDASM
            LCDOUT  $FE, $D0         ; may be $D4 on some displays
            ASM
        endif
        if (options & CurOFF) > 0   ; Turn Off Cursor
            ENDASM
            LCDOUT  $FE, $0C
            ASM
        endif
        if (options & CurBlink) > 0 ; Blinking Cursor
            ENDASM
            LCDOUT  $FE, $0F
            ASM
        endif
        if (options & CurUL) > 0    ; Underline Cursor
            ENDASM
            LCDOUT  $FE, $0E
            ASM
        endif
        endm
    ENDASM
    Then to use the macro you can do it this way...
    Code:
    @ LCDCMD Clr + CurBlink       ; Clear screen and turn on blinking cursor
    '-- OR --
    @ LCDCMD Clr + Line2 + CurOFF ; Clr screen, Move to Line2 and turn off cursor
    Any of the options can be combined together, and only the options you use will actually create code.

    HTH,
       Darrel
    Last edited by Darrel Taylor; - 27th July 2005 at 08:51.

  7. #7
    Join Date
    Sep 2004
    Location
    montreal, canada
    Posts
    6,898


    Did you find this post helpful? Yes | No

    Default

    Many thanks Darrel for this tutorial about the Macro. I guess it could be interesting to place a post in the FAQ or Code example on that AND how to work with the internal PBP macro also work... you know those MOVE?CB etc...

    I could start it myself but... oooooh... you're really better than me to explain those

    Well just an idea!
    Last edited by mister_e; - 27th July 2005 at 16:53.
    Steve

    It's not a bug, it's a random feature.
    There's no problem, only learning opportunities.

Similar Threads

  1. PBP Extensions, What are they?
    By PJALM in forum PBP Extensions
    Replies: 9
    Last Post: - 28th September 2021, 12:26
  2. PBP code to read R/C signal from receiver
    By malc-c in forum mel PIC BASIC Pro
    Replies: 9
    Last Post: - 28th October 2009, 22:51
  3. Making Program Code Space your playground...
    By Melanie in forum Code Examples
    Replies: 15
    Last Post: - 19th July 2008, 09:26
  4. 4 Chanel Dmx512 ready assembly code to PBP ?
    By syscoder in forum mel PIC BASIC Pro
    Replies: 10
    Last Post: - 22nd March 2007, 00:55
  5. convert code "c" lcd graphic to pbp
    By nicolasronan in forum mel PIC BASIC Pro
    Replies: 2
    Last Post: - 19th June 2006, 16:49

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