Making PBP code more modular


+ Reply to Thread
Results 1 to 31 of 31
  1. #1
    forgie's Avatar
    forgie Guest

    Question Making PBP code more modular

    Hi there,
    I've been using PBP on and off for a few years, now semi-professionally. I'm interested in what coding techniques people use to keep their PBP code modular and portable (i.e. the way that you code using C for a PC)...... or should I be using a C compiler to satisfy my desire for modular code? I find that things become unwieldy and messy when I start splitting projects into multiple files, as far as variable/pin declarations go.

    I don't want to start the tired old BASIC vs C flamewar here, I just want to know if anyone else uses multiple files for their PBP projects in a way that is properly modular/portable as well as being very readable.

    Any code examples/tips/tricks/whatever would be appreciated.

    Thanks,
    Nick Forge

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

    Default

    Personnaly, i never use Include in my code, i prefer to see everything in my face. I have several routine that i built and i just copy/paste them in my code.
    Steve

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

  3. #3
    Join Date
    Feb 2004
    Location
    Germany
    Posts
    762

    Default

    I agree with Steve,

    I have a number of SUBs I use on many projects.

    When I started I used to include them.
    But today, I cut and paste them into my projects for better readability.
    That way I have everything at a glance.
    (No need to look at different files)

    It is no real problem to write modular code in PBP.
    agreed, VARs are global,
    but with some creativity you can write modular and readable code
    and minimize RAM usage.
    regards

    Ralph

    _______________________________________________
    There are only 10 types of people:
    Those who understand binary, and those who don't ...
    _______________________________________________



  4. #4
    forgie's Avatar
    forgie Guest

    Default

    I just feel much more comfortable having 6 files of around 50-100 lines each, each file having a specific task to complete, rather then having one monolithic 400-500 line file. Maybe I just have to break out of the PC programming (C) mentality, where you try and hide code away somewhere else (inside a module) once it is finished and debugged - this is perhaps one of the reasons for the "PBP /= Professional quality" attitude that many have: on a PC one always strives for modular, portable code 100% of the time. On a PIC, by the very nature of the beast that isn't always possible.

    Do you guys follow PC convention in so far as removing 'magic numbers' from your code and using constants to control registers? By this I mean saying something like:

    SLEEP_PORTE CON %00000101
    WAKE_PORTE CON %00000010
    ~

    Sleep:
    PORTE = SLEEP_PORTE
    Sleep
    PORTE = WAKE_PORTE
    Return

    This gives you a convenient place up the top where you can define the PORT states for each 'program state'. Just to give an idea of where I'm coming from.... maybe I need to completely reset my perspective on this whole issue. (Could someone please pull the MCLR attached to my mentality to ground?)

  5. #5
    Join Date
    Jul 2003
    Posts
    2,358

    Default

    I've written many programs, the biggest almost six and a half thousand lines (that's a 200kb .BAS file which reated a 8Mb .LST by MPASM!!!)... Like the other replies, I never use include files, but my programs stick to a very rigid and repeatable format... so it is 'modularised' in that form...

    1. Define Configuration Fuses
    2. Define Hardware (usually sequential in Port order)
    3. Define EEPROM (in address order)
    4. Define RAM (always in alphabetical order)
    5. Define Constants (always in alphabetical order)
    6. Subroutines (always in alphabetical order)
    7. Hardware Initialisation
    8. Main Program Loop
    9. Interrupt Handlers (always in alphabetical order)
    10. Error Handlers (always in alphabetical order)

    I don't redefine things that are already included by PBP... ie things like TRISB or OPTION_REG, but I will use the same Label Names as are in the Datasheet and am consistant to use the same variable, hardware or constant names across all my programs if they are doing the same job. Once I have a routine for a particular function (ie reading a keypad or ADC), that routine is replicated EXACTLY and I don't reinvent the wheel. Changes like Timeout values are always predefined constants. Section 2 in my program structure (Hardware Definition) will reassign the pins so that my Keypad routine for example will still work without change or worry regardless of the PIC or PCB layout.

    Keeping to a consistant structure allows me to create programs quickly, with the minimum or errors, allows me find what I'm looking for and best of all, allows me to refamiliarise myself with the program easily, when it needs to be revisted several months down the road. Life is too short, if you have a formula that works, flog it for all that it's worth... (here we go, back to whips and things again)...

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

    Default Magic numbers and aliases.

    I write a bit of software and I very seldom use includes. I follow a routine similar to Melanie's in that I tend to structure all of my programs the same way, pretty much as Melanie described. One differance, I usually write my ISR in assembly and stick it at the very top. I also define magic numbers (constants) for things like timer preloads and initial variable states. I also use aliases to define registers. This way my code looks the same, regardless of PIC, because I try and use the same names. I too find that I cut and paste routines when writing code.

    All in all code portablity is pretty good but remember we are talking about micros. I mean, its not like you are gonna run your PBP code on an AVR! Now that would be portable!

    Regards,

    Joe.

  7. #7
    forgie's Avatar
    forgie Guest

    Default I've taken your advice and....

    Following the PBP experts lead I went through the task of converting my 7 files project into a single, big momma file. In the process it has helped me tidy up alot of my PBP coding style as well as variable naming. It's taken me a while to adjust to a different style of indenting (and the visual appearance of PBP code is so different to C style code it's really hard to find it readable without doing a hell of a lot of it):

    If oranges = apples Then
    Do something
    Endif

    vs

    If (oranges = apples) {
    Do something;
    }

    Overall I am much more happy with PBP as a language since forcing myself to do it the 'hard' way. I can see perfectly well why C-experienced PC-programming people don't take to it, but I think it's perfectly up to the task that it has in front of it (programming pics, not multimedia software packages).

    Thanks for the tips guys,
    Nick

    EDIT: damn these auto-formatting forums.... the guys who wrote the code must have thought they were being so clever. oh well i hope you get the picture of what i tried (and failed) to show. if not.... well it doesn't really matter, does it?
    Last edited by forgie; - 26th July 2005 at 21:00.

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

    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.

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

    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.

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

    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.

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

    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.

  12. #12
    forgie's Avatar
    forgie Guest

    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)

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

    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.

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

    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.

  15. #15
    forgie's Avatar
    forgie Guest

    Default

    Thanks heaps for the info, Darrel, much appreciated.

    With the LCD example, I was actually thinking more along the lines of how would one get a macro that can handle a list of arguments, like LCDOUT does. It's by no means a necessity, the workarounds are very easy, it would just be nice luxury to have in the world of coding.

    Is it possible to do for loops in macros? e.g. make a macro called LCDRIGHT x which moves the cursor right x spaces, and define it using a for loop? Sorry, I don't know how to display code on this forum, so I can't write down the code for what I'm thinking of.

    Anyway,
    Thanks heaps for the info,
    Nick

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

    Default

    Forgie,

    to display code you must use those VbCode... really easy to use and explain Here
    Steve

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

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

    Default

    Quote Originally Posted by forgie
    With the LCD example, I was actually thinking more along the lines of how would one get a macro that can handle a list of arguments, like LCDOUT does.
    Well, I thought that's what it does. It takes a list of arguments, but instead of using commas, it uses the Plus sign instead.

    Take a look at this thread Embedded Strings in your Code Space
    It has some more examples of passing parameters with macro's.

    But really, the main problem is that MPASM always has to have the exact number of parameters supplied to a macro. So a single macro can't accept 2 parameters on 1 use and 5 on another. PM has that ability, but I don't like making programs that only work with PM since you can't use it with the 18F's

    Quote Originally Posted by forgie
    Is it possible to do for loops in macros? e.g. make a macro called LCDRIGHT x which moves the cursor right x spaces, and define it using a for loop?
    Yes, you can do that. But keep in mind that every time you use a macro, it duplicates the entire code at the place where it is used. So, big macro's that are used several times can eat up a lot of code space. There are ways around that too, but it's not for the scardy cats. For instance, consider this example as an alternative to the LCDRIGHT idea. It allows you to move the cursor anywhere on the screen using either constants or byte variables. Using the constant version would look like this
    Code:
    @ LCDCUR?C 1,5  ; Row, Col
    Which would move the cursor to Row1, Colomn5.

    Or, using the byte variable version would be like this
    Code:
    Row  VAR BYTE  system
    Col  VAR BYTE  system
    
    Row = 2
    Col = 10
    @ LCDCUR?B  Row, Col
    Here's the macros for them. They are self optimising, so that no code is generated unless you actually use them. The main parts of the routine are actually subroutines that can be "called", and the macros you use in the main program simply place the parameters in Temp variables so that the "called" routine can access them. This way it only uses a few words each time you use one of the macro's.
    Code:
    This code has been removed, please see a couple posts down for the revision.
    Should have tested it first. Doh!
    I just threw this together last night in anticipation of your next question, so if you actually try it, and have problems, let me know.

    Best regards,
       Darrel
    Last edited by Darrel Taylor; - 28th July 2005 at 08:42.

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

    Default

    Quote Originally Posted by mister_e
    ... 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...!
    Yeah, probably would..., but I don't know, something about the FAQ section scares me.

    If you choose a topic, then your supposed to answer all the frequently asked questions about that topic. It's like you're supposed to know everything about it, and you don't want to miss anything because nobody's going to write an FAQ that conflict's with you're FAQ.

    Coupled with the fact that, I don't know Everything about Anything. It's just not a good fit for me.

    But actually, I've tried to write something for the macro's in PBP 3 times now. Then when I read it back afterwards, it never seems to get the point across. Not even close.

    I do think it's worthwhile to laud the abilities of INCLUDE macro's. Especially since nobody seems to use them. So maybe it's time for a new approach.

    Hmmm, what could it be .... scratch, scratch ...

    DT

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

    Default

    OK, so that last example was terrible. Should have tested it first.

    Here's a better one that shows more of how to use PBP statements in macro's. It's also a little easier to see how the "self optimization" works. (this time I tested it)
    Code:
    <b>DEFINE  </b></font><b>LCDCOLS 16  </b><font color="#0000FF"><b><i>; can be 8, 16, 20, 24 or 40
                        ; but 20 is the only one that matters in this routine
    </i></b></font><b>LCD_Row   </b><font color="#008000"><b>VAR BYTE </b></font><b>system
    LCD_Col   </b><font color="#008000"><b>VAR BYTE </b></font><b>system
    
    </b><font color="#008000"><b>ASM
        </b></font><font color="#000080">ifndef LCDCOLS
            #define LCDCOLS 16    </font><font color="#0000FF"><b><i>; Default to 16 Columns
        </i></b></font><font color="#000080">endif
    
    MoveCursorExpanded = 0
    
    
    </font><font color="#0000FF"><b><i>; --- Move cursor to new location ---(inputs are LCD_Row and LCD_Col)-----------
    </i></b></font><font color="#000080">Expand_MoveCursor  macro
      local  OverCode
        goto      OverCode
    MoveCursorExpanded = 1
    MoveCursor
        if LCDCOLS == 20          </font><font color="#0000FF"><b><i>; if using a 4x20 display
            </i></b></font><font color="#008000"><b>ENDASM
                LOOKUP </b></font><b>LCD_Row</b>,[<b>$80</b>,<b>$80</b>,<b>$C0</b>,<b>$94</b>,<b>$D4</b>],<b>LCD_Row
            </b><font color="#008000"><b>ASM
        </b></font><font color="#000080">else                      </font><font color="#0000FF"><b><i>; if NOT using a 4x20 display
            </i></b></font><font color="#008000"><b>ENDASM
                LOOKUP </b></font><b>LCD_Row</b>,[<b>$80</b>,<b>$80</b>,<b>$C0</b>,<b>$90</b>,<b>$D0</b>],<b>LCD_Row
            </b><font color="#008000"><b>ASM
        </b></font><font color="#000080">endif
        </font><font color="#008000"><b>ENDASM
            </b></font><b>LCD_Row </b>= <b>LCD_Row </b>+ (<b>LCD_Col </b>- <b>1</b>)
            <font color="#008000"><b>LCDOUT </b></font><b>$FE</b>, <b>LCD_Row  </b><font color="#0000FF"><b><i>; Send the command
        </i></b></font><font color="#008000"><b>ASM
        </b></font><font color="#000080">return
    OverCode
        endm
    
    </font><font color="#0000FF"><b><i>; --- Move LCD cursor to  Row, Column using constants --------------------------
    </i></b></font><font color="#000080">LCDCUR?C  macro  Row, Col
        if MoveCursorExpanded == 0
            Expand_MoveCursor
        endif
        MOVE?CB   Row, LCD_Row
        MOVE?CB   Col, LCD_Col
        L?CALL    MoveCursor
        endm
    
    </font><font color="#0000FF"><b><i>; --- Move LCD cursor to  Row, Column using Byte variables ---------------------
    </i></b></font><font color="#000080">LCDCUR?B  macro  Row, Col
        if MoveCursorExpanded == 0
            Expand_MoveCursor
        endif
        MOVE?BB   Row, LCD_Row
        MOVE?BB   Col, LCD_Col
        L?CALL    MoveCursor
        endm
    
    </font><font color="#008000"><b>ENDASM
    </b></font>
    Using them is still the same
    Code:
    <font color="#000080">@ LCDCUR?C 1,5          </font><font color="#0000FF"><b><i>; Move to Row1 Column5
      </i></b></font><font color="#008000"><b>LCDOUT </b></font><font color="#FF0000">&quot;R1C5&quot;         </font><font color="#0000FF"><b><i>; Display something
    
    '-- OR --
    
    </i></b></font><b>Row  </b><font color="#008000"><b>VAR BYTE  </b></font><b>system
    Col  </b><font color="#008000"><b>VAR BYTE  </b></font><b>system
    
    Row </b>= <b>2
    Col </b>= <b>10
    </b><font color="#000080">@ LCDCUR?B  Row, Col    </font><font color="#0000FF"><b><i>; Move to Row2 Column10
      </i></b></font><font color="#008000"><b>LCDOUT </b></font><font color="#FF0000">&quot;R2C10&quot;        </font><font color="#0000FF"><b><i>; Display something</i></b></font>
    Last edited by Darrel Taylor; - 29th July 2005 at 09:43.
    DT

  20. #20
    forgie's Avatar
    forgie Guest

    Default Very helpful - but....

    ....haha I still have a tricky question for the masters around here..... is it possible to write a macro to accept arguments like this:

    <code>
    lcdline1 "this is line 1"
    lcdline2 "this is line 2"
    </code>

    where "lcdline1 X" is equivalent to "lcdout $FE, $80, X".... with the small catch that X can be anything from a string to a list of arguments (basically it can be anything that lcdout can take as an arg). I'm thinking that this is impossible - I assume its the compiler that converts LCDOUT args and strings into seperate ASM statements - since it's not the assembler that's doing the parsing from a list of args, or a string, to a number of individual ASM statements.

    BTW this is something that I would actually use, but it's only for extreme convenience and 'luxury' - it's always nicer to be able to write the highest level control/interface sections of a program in incredibly high-level, easy to understand language and syntax.

  21. #21
    Join Date
    Jul 2003
    Posts
    2,358

    Default

    http://www.picbasic.co.uk/forum/showthread.php?t=1999

    I would draw your attention to Darrels link to his website in one of the early posts.

  22. #22
    Join Date
    May 2004
    Location
    NW France
    Posts
    3,578

    Wink

    Hi, Mel

    just Take that as an info for our friend Forgie....

    http://www.elabtronics.com/products_cat_CoreChart.htm

    That's modular !!!

    Alain

    PS : No comments about gadgets ... Next step could be the voice or cerebral activity recognition compiler.
    But what about the programmer snoring ??? must the compiler write a "sleep" line or wake up our friend from his dreams ???

    Alain
    Last edited by Acetronics2; - 31st July 2005 at 17:21.

  23. #23
    forgie's Avatar
    forgie Guest

    Default

    Thanks for the macro examples Darrel, much appreciated.
    I guess there's still two things that irritate me:

    Assembly macros (and hiding them in an include file if you want to) are a great way to do your own simple 'custom instructions'..... but if you have a big block of complex code that has many indentations, the restriction of having to put the "@ MYMACRO" statement at column 1 is very annoying. Perhaps PBP could have a command called MACRO? Where you could write MACRO MYMACRO to run an asm macro that you've previously defined? This would make the code much, much more readable. Even changing the way PBP interprets the '@' symbol would fix it, if you made PBP interpret the start of the ASM line where the '@' symbol is.... that way you could put @ MYMACRO after three tabs and keep your pretty, readable code.

    The second is local variables. I'm sorry, but I still can't quite be satisfied with the modularity of PBP until there are proper local variables implemented somehow. The implementation might be difficult to write, granted, but without local variables, you have to keep track of every variable that every little subrouting uses, and make sure that different subs don't use an already in-use 'counter1' or 'temp3' or whatever. Does anyone else find this annoying? With local variables, all of a sudden 'true modularity' becomes a reality, and you can copy a subroutine that say, does a math function, without worrying about variable naming or anything like that, because they're all local to that sub.

    Just my thoughts.....

  24. #24
    Join Date
    Jul 2003
    Posts
    2,358

    Default

    > but without local variables, you have to keep track of every variable that every little subrouting uses...

    I'm sure I've used @ beyond the first column... but @ has to be the first character encountered on the line. How far along the line PBP finds it, is I think not relevant. To be fair, I've not tried it with MPASM, but certainly with PM several Tab-Stops still finds it working.

    The luxury of 'Local Variables' was extended to you first in Compilers or Interpreters that have access to near limitless resources. It's almost impossible to run out of RAM in a Visual Basic program for example - if you are the most wasteful shoddy programmer on the planet, how much RAM can you use? 100kb out of some 256Mb (or more) avaiable to you? This is not the case with most PICs, and certainly not the case with the 12F or 10F series! A couple of dozen variables and suddenly you're in deep trouble. So variables HAVE to be reused. So document your subroutines - it'll only take a minute. Indicate in a comment header at the start, what the entry variables should be, what the exit variables are, and the names of any working variables or other subroutines used internally. You only need to add this documentation once, and it's there for life. You can pick-up that subroutine in six months time and you KNOW where you stand.

    > must the compiler write a "sleep" line or wake up our friend from his dreams ???

    Hey, I always write my best code when I'm asleep. It's remembering what I wrote next morning that's the problem...

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

    Default

    You're welcome forgie!

    The @ symbol in col 1 is more of a MicroCode Studio problem.

    If the @ is in any other column, MCS won't highlight it as an ASM statement. It still compiles just fine in both PM and MPASM no matter how far it's indented. But, it can sure be confusing.<br><br>
    DT

  26. #26
    forgie's Avatar
    forgie Guest

    Default

    Thanks Darrel, you are correct - I use MCS and I didn't even try compiling with tabs before the @ symbols - but I just indented all my @ statements and of course it compiles and works fine.

    With the local variables - of course resources are limited, and the concept of local variables wouldn't be appropriate (or would they?) in a number of situations. What I'm thinking is this: you have different types of vars that you define as such:

    <code>
    SUB MY_SUB
    i VAR LOCAL BYTE
    temp VAR LOCAL WORD
    x VAR WORD
    .....
    RETURN
    END SUB
    </code>

    The 'LOCAL' VARs would be reallocated for each SUB. When programming, you would have to ensure that your LOCAL vars can lose their value whenever a GOSUB is used. Other variables defined locally will be have their own allocation. Given that the 18f452 has 1500 bytes of memory surely some other people would find this useful?

    Perhaps you could solve all memory problems by using memory addresses (pointers) as arguments for SUBS:

    <code>
    ..
    GOSUB MY_SUB(a, b, c)
    ..


    SUB MY_SUB(WORD x, WORD y, BYTE d)
    i VAR LOCAL BYTE
    temp VAR LOCAL WORD
    .....
    x = i + y
    ....
    RETURN
    END SUB
    </code>

    Then PBP would just have to make all those vars point to the same address. And perhaps spit out a type-check warning if you pass a byte where a word is expected or whatever.

    Would anyone else find this to make PBP a much more pleasurable and professional compiler?

    Please, please respond with criticism if you disagree with my comments, as that's the only way that I will see the reasons why it isn't a good idea....

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

    Default

    OK, so the head scratching worked a little.

    As another example of why I feel that INCLUDE files and Macros's are two of the most usefull features of PicBasic Pro.

    Here's an example of an INCLUDE file that uses a single macro to generate some pretty neat BARgraphs. Just Include the file, and away you go.

    LCD BARgraphs
    http://www.picbasic.co.uk/forum/showthread.php?p=12475
    <br>
    Last edited by Darrel Taylor; - 9th September 2005 at 22:23.
    DT

  28. #28
    mytekcontrols's Avatar
    mytekcontrols Guest

    Thumbs up I like it! I like it! Hey Mikey likes it!

    Hi Darrel,

    I haven't been on this board in a while (busy doing some contract work --- gotta make money). I see besides writing a great LCD routine you have been enhancing your posts as well (I especially liked the video presentation). And hey it all looked great under FireFox.

    Keep up the great work,
    Michael

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

    Default

    Thanks Mikey,

    I think it took longer to figure out how to post it, than it did to write it in the first place. Thanks for noticing.
    And, thanks for the Firefox update. I always wonder if I'm getting that part right or not.

    I hope that contract work is PIC related.
    <br>
    DT

  30. #30
    Join Date
    May 2004
    Location
    NW France
    Posts
    3,578

    Wink

    Nice and useful ... Despite it keeps users from undestanding LCD use and special characters ...

    New " pseudo-problem threads" in sight ...

    Thanks for that nice work , Darrel
    Last edited by Acetronics2; - 11th September 2005 at 09:40.
    ************************************************** ***********************
    Why insist on using 32 Bits when you're not even able to deal with the first 8 ones ??? ehhhhhh ...
    ************************************************** ***********************
    IF there is the word "Problem" in your question ...
    certainly the answer is " RTFM " or " RTFDataSheet " !!!
    *****************************************

  31. #31
    mytekcontrols's Avatar
    mytekcontrols Guest

    Smile Whew!! Finally back to writing PBP code again

    Darrel,
    I hope that contract work is PIC related
    Yes it was, but unfortunately it wasn't done in PBP. Actually it is a ressurection of pic assembly code I wrote back in 1998, with some minor changes to adapt it to newer hardware.
    If you are interested, here is a link to what I was doing: www.mytekcontrols.com/specialproducts/
    What had originally started out as a contract proposal, changed into an actual product instead. This allowed me to retain the rights to sell it to anyone, and kept it more affordable for the buyer since they weren't paying for the full engineering time (it gets spread out over several unit sales --- hopefully).

    Now I am back to working on my main project (StampVue), which has an OS written in PBP. In fact this morning I just got an Auto Baud Detect PBP routine to work for it, which I'll be posting some sample code in an appropriate forum within the next couple of days.

    I'll need to do some catching up on your macro escapades. Which I can see from other posts, you've been busy as well.

    I hope all is well with you,

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

Posting Permissions

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