Embedded Strings in your Code Space


Closed Thread
Results 1 to 40 of 50

Hybrid View

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


    Did you find this post helpful? Yes | No

    Default

    That's great Michael, glad you liked it. And it's good to have willing particpants around.

    And, if you wanted more macro's... then I'm sure to make you happy today.

    Oh boy, where to start.... I guess I'll start at the end result.

    What this does is to allow the strings to be sent to up to 7 different "Destinations". Those destinations can be easily defined like this.
    Code:
    @  Make_Destination  HSER, _HSER_Send
    This creates a Destination named "HSER", and everytime the program needs to send a character, it will call the _HSER_Send subroutine.

    Each destination needs it's own subroutine to actually send the data. The character is placed in the temp variable before calling it. Here's one for HSER.
    Code:
    HSER_Send:
         While PIR1.4 = 0 : Wend
         TXREG = temp 
    return
    To make another Destination for the LCD, is just as easy...
    Code:
    @  Make_Destination  LCD,  _LCD_Send
    
    LCD_Send:
        LCDOUT temp
    Return
    Now when using the SendStr macro, you can tell it which destination you want it to go to.

    @ SendStr "This is a string", HSER
    @ SendStr "1 for the LCD", LCD

    You can even combine them to send the data to multiple Destinations.

    @ SendStr "This is a string", HSER + LCD

    Destination #8 is reserved for a CR,LF option that can be used like this...

    @ SendStr "This is a string", HSER + CRLF

    Of course, here's the one you were after...
    Code:
    @  Make_Destination  I2C,  _I2C_Send
    
    I2C_Send:
         ' However you need to do it here...
    RETURN
    In order to make this work, I ripped up your code pretty bad. Sorry!

    For instance, I got rid of the whole Pushing and Popping stuff. I hated to do that, but at least it solves the interrupt problem. The TBLPTR is now loaded from the SendStr macro so that it doesn't need to use the stack to get the address. Major changes to the prntSTR section too. It had all the USART stuff in there that had to come out. The Make_Destination and Director macro's are the real difference that allows the data to be re-directed. I'm sure there will be some questions on them, but for now I'll let you try to figure it out first.

    Here's the whole thing.
    Code:
    SER2_TX      VAR  PORTE.0
    SER2_Baud    CON  396
    TRISB.6 = 1   ' Set USART TX pin to Output
    
    temp         var  byte
    Destination  VAR  BYTE
    
    @CRLF = 0x080    ; Reserve destination #8 for CR,LF after string
    
    '--[ Initialise USART for specified baud rate at current OSC speed ]------------
    asm
    USART_Init  macro  Baud
        clrf    TXSTA, 0
    _SPBRG = (OSC * 1000000) / 16 / Baud - 1     ; calc SPBRG @ High baud rate
        if _SPBRG > 255                          ; if SPBRG is too high
    _SPBRG = (OSC * 1000000) / 64 / Baud - 1     ; calc for Low baud rate
            bcf   TXSTA, BRGH, 0                 ; Set BRGH to Low Speed
            if _SPBRG > 255
    _SPBRG = 255
            endif
        else                                     
            bsf   TXSTA, BRGH, 0                 ; Set BRGH to High Speed
        endif
        bsf     TXSTA, TXEN, 0                   ; Set Transmit Enable bit
        movlw   _SPBRG          
        movwf   SPBRG, 0                         ; load the calulated SPBRG
        movlw   B'10010000'                      ; enable USART
        movwf   RCSTA, 0
        endm
    ENDASM
    
    ;----[Make_Destination]---- Compile Time Only - Does not use any Code space ----
    ASM
    DestinationCount = 0                              ; Global
    
    Make_Destination  macro Nam, Sub
    Nam = 1 << DestinationCount                       ; Generate a unique ID
    Destination#v(DestinationCount) = Sub             ; Save Subroutines Address
    DestinationCount += 1                             
        endm
    ENDASM
    
    ;----[SendStr] -----------------------------------------------------------------
    ASM
    SendStr  macro Astring, Dest
      local TheStringData, BypassData
        goto   BypassData                             ; Jump over the data
    TheStringData    
        data   Astring,0                              ; Place String Data here
    BypassData
        MOVE?CB   Dest, _Destination
        MOVE?CB   low TheStringData, TBLPTRL          ; Load the address of 
        MOVE?CB   low (TheStringData >> 8), TBLPTRH   ;  TheStringData into
        MOVE?CB   low (TheStringData >> 16), TBLPTRU  ;      TABLPTR
        L?CALL    prntSTR
        if (Dest && CRLF) > 0
            L?CALL  _Send_CRLF
        endif
        endm
    ENDASM
    
    ;----[ This macro will call each of the specified Destinations in sequence ]----
    ASM    
    Director  macro
      local counter
    counter = 0
          while counter < DestinationCount
              btfsc  _Destination, counter
              CALL   Destination#v(counter)
    counter += 1          
          endw
        endm    
    ENDASM
    
    
    ;---[ These define the Destinations that will be called to output each byte ]---
    ;                                                     There is currently a  
    ;                    Name, _Subroutine                MAXimum of 7 destinations
    @  Make_Destination  HSER, _HSER_Send
    @  Make_Destination  SER2, _SER2_Send
    @  Make_Destination  LCD,  _LCD_Send
    @  Make_Destination  I2C,  _I2C_Send
    
    
    Main:
    @ USART_Init 19200
    @ SendStr "This is a string", HSER + CRLF
    @ SendStr "yet another string again", (HSER  + SER2 + CRLF)
    @ SendStr "and one more time!", I2C
    @ SendStr "1 for the LCD", LCD
    
    Done:
       Goto Done
    
    ;-------------------------------------------------------------------------------
    HSER_Send:
         While PIR1.4 = 0 : Wend
         TXREG = temp 
    return
    
    ;-------------------------------------------------------------------------------
    SER2_Send:
        SEROUT2  SER2_TX, SER2_Baud, [temp]
    Return
    
    ;-------------------------------------------------------------------------------
    LCD_Send:
        LCDOUT temp
    Return
    
    ;-------------------------------------------------------------------------------
    I2C_Send:
         ' However you need to do it here...
    RETURN
    
    ;----[prntStr]------------------------------------------------------------------
    ASM
    ;--- TBLPTR should be pointing to 1st character in string before calling -------
    prntSTR
    Next_Char
        tblrd   *+              ; table read and post increment TBLPTR
        movff   TABLAT,_temp    ; fetch character from message string
        bra     Test_EOM        ; go test for EOM character
    Continue                    ; If not EOM then...
        Director                ; Send the byte to each specified destination
        bra     Next_Char       ; fetch next message character from table
    Test_EOM
        movlw   .0              ; check for EOM character
        cpfseq  _temp,W         ; compare temp with w, if temp = 0 then end			
        bra     Continue        ; no EOM, so continue
        return                  ;finished with message, return to caller
    endasm
    
    ;---[Send Carriage Return, Line feed to the dest's specified in last SendStr]---
    Send_CRLF:
        temp = 13
        @ Director
        temp = 10
        @ Director
    RETURN
    
    end
    Note that prntSTR and Send_CRLF must be at the end of the program for the Director to work properly.

    Well, have fun, and I hope this is closer to what you were looking for.

    Best regards,
    Darrel

  2. #2
    mytekcontrols's Avatar
    mytekcontrols Guest


    Did you find this post helpful? Yes | No

    Default

    And, if you wanted more macro's... then I'm sure to make you happy today.
    Wow! Am I ever! It'll keep me quite busy this week trying it out in my application.

    In order to make this work, I ripped up your code pretty bad. Sorry!

    For instance, I got rid of the whole Pushing and Popping stuff. I hated to do that, but at least it solves the interrupt problem.
    I have no problem at all with this. At the time it was the only way I knew how to start heading in the direction I wanted to go. Perhaps it'll still be of use to someone, since there doesn't appear to be too much info out on the net showing actual application of this 18F series ability.

    Major changes to the prntSTR section too. It had all the USART stuff in there that had to come out.
    As you probably saw in my last code post, I had already ripped this out and gone ahead and used your USART initialize macro.

    The Make_Destination and Director macro's are the real difference that allows the data to be re-directed. I'm sure there will be some questions on them, but for now I'll let you try to figure it out first.
    Yes I do have questions, but I'll hold off until I have had ample time to digest it. And perhaps I wont if my brain can take it all in.

    Well, have fun, and I hope this is closer to what you were looking for.
    This is EXACTLY (and more) what I was looking for!
    Thanks so very, very much,

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


    Did you find this post helpful? Yes | No

    Default

    Here's my own version. Not as brilliant as all the above but allow to send String and numeric value. Have fun!
    [html]
    ' ///////////////////////////////////|\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
    ' Embedded String and Data handling
    ' =================================
    ' Steve Monfette
    ' Mister E Enr
    '
    ' This program show how to use/define/send a combination of String and Data
    ' to a PC terminal or else @9600 bauds.
    '
    ' We can still use HSEROUT and do the same thing, of course but the
    ' following use another approach wich :
    ' 1. Allow to modify one or all string/data in a snap when needed.
    ' 2. Call a string many time only by calling his name with the macro.
    ' That is still more code efficient than if you create and use
    ' a specific SUBROUTINE.
    '
    ' Also, if you compare this method to the use of multiple HSEROUT,
    ' you'll notice a slight difference in the size of the generated code.
    '
    ' This program could also be usefull to send string/data to various device
    ' like I2C, LCD,...
    ' ///////////////////////////////////|\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

    @ errorlevel 0,-207 ' avoid anoying MPASM error message
    ' -- found label after column 1 --

    ' PIC Definition
    ' ==============
    ' Done with an old & dusty PIC16F877 @ 20MHZ
    '
    DEFINE LOADER_USED 1
    DEFINE OSC 20

    ' Hardware define
    ' ===============
    '
    TRISC=%10111111

    ' Serial Comm definition
    ' ======================
    '
    RCSTA=$90 ' Enable USART, continuous receive
    TXSTA=$24 ' Enable transmit, BRGH=1
    SPBRG=129 ' 9600 Bauds

    ' Variable definition
    ' ===================
    '
    Char var byte ' Character to be read/send
    SAddr var word ' String adress pointer

    ' Software initialisation
    ' =======================
    '
    clear ' set all variable to 0
    goto Start ' Skip any Macro And string Definition

    ' String Definition
    ' =================
    ' String must be defined as follow
    ' <label> dt <data>,0
    '
    ' could also be
    ' <label> dt <data>
    ' dt <data>
    ' .........
    ' dt <data>,0
    '
    ' Any String must be NULL terminated. Can contain text and numeric value
    '
    asm

    s1 dt "String #1",13,10,0

    s2 dt "String #2",13,10
    dt "********************",13,10,0

    s3 dt "String #3",13,10,0

    s4 dt "String #4..... THE LAST ONE",13,10,0

    endasm

    ' Macro Definition
    ' ================
    '
    ' SendString:
    ' ===========
    ' This send the according string via USART
    ' Format:
    ' =======
    ' SendString <StringName>
    '
    asm
    SendString macro StringLabel
    CHK?RP _SAddr ; Reach the right BANK of SAddr
    MOVE?CW StringLabel,_SAddr ; Store address of StringLabel in SAddr
    L?CALL SendIt ; Send the string.
    endm
    endasm
    @SendIt
    Readcode SAddr, char ' Read character
    if Char then ' if not NULL, send it
    ASM
    MOVE?BB _Char,TXREG ; Load TXREG with Char
    IsFull
    BIT?GOTO 0, PIR1, 4, IsFull ; Loop while TXREG is full
    ; The above is the same as
    ; IF PIR1.4=0 THEN GOTO IsFull
    ;
    INCF _SAddr,1 ; Point to the next character
    GOTO SendIt ; Do it again
    ENDASM
    endif
    return


    ' /////////////////////////////////|\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
    Start:
    ' /////////////////////////////////|\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
    '
    ' Here we will send our data by using the above macro
    '
    @ SendString s1 ; Send string with label 's1'
    @ SendString s2 ; Send string with label 's2'
    @ SendString s3 ; Send string with label 's3'
    @ SendString s4 ; Send string with label 's4'
    pause 1500 ; wait a little bit
    goto Start ; do it again
    [/html]
    Last edited by mister_e; - 27th August 2005 at 17:58.
    Steve

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

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


    Did you find this post helpful? Yes | No

    Default

    Hi Steve,

    While I don't see any advantages over the previous examples, it does present a few problems that weren't there before.

    They are the same problems I came across when writing the strings program I pointed out in the 2nd post of this thread.

    By using the "dt" directive, it uses twice as much code space by only storing 1 byte per word. The "da" directive is much more efficient. It packs two 7-bit characters in each word.

    Also, when using the MOVE?CW macro inside another macro, it makes it so that all string data has to be placed at the beginning of the program. If you place the string data after the SendString command that's trying to use it, you will get a "Address label duplicate or defferent in second pass" error.

    John Barrat figured out how to get around that problem with this macro. It compiles to the exact same thing as the MOVE?CW, but because of which "Pass" it gets compiled on, it can find an address either before or after the code that uses it.

    Code:
    '------------GetAddress Macro - Location insensitive -------------------------
    ASM
    GetAddress macro Label, Wout       ; Returns the Address of a Label as a Word
        CHK?RP Wout
        movlw low Label
        movwf Wout
        movlw High Label
        movwf Wout + 1
        endm
    ENDASM
    I think, once you fix those 2 things, you'll have something that looks just like my Strings prog. See second post.
    <hr>
    I do like this though
    Code:
        @ errorlevel 0,-207 ' avoid anoying MPASM error message 
                            ' -- found label after column 1 --
    Sure makes things look better when you can indent labels.
    <br>
    DT

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


    Did you find this post helpful? Yes | No

    Default

    Yep i understand it... the only thing... HOW TO use DA to send numeric Value, say 13,10 or else 8 bits value with the string???

    I tried the \ option... doesn't seems to work as i want. well i can miss something really stupid/easy... once again.

    BUT it works with dt. BUT i agree with you, i take 2 time the needed space.
    Steve

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

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


    Did you find this post helpful? Yes | No

    Default

    "DA" works fine with anything under 128, so 10,13 isn't a problem.
    Code:
       da  "Danger Will Robinson",13,10,0
    But you're right. Unless you are using an 18F part, if you want 8-bit data, it will take 2x the code space.
    Last edited by Darrel Taylor; - 27th August 2005 at 20:45.
    DT

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


    Did you find this post helpful? Yes | No

    Default

    mmm i already tried the above... MIIIIIIIIP doesn't work. GOT YA... for the first time in my life... probably the last too

    We must send a 14 bit pack stuff... as it's suppose to!

    So i just found that
    Code:
    @ da "This is a string....",0x068a,0
    the above will send cr+lf.

    Sounds like
    Code:
    CR con 13
    LF con 10
    CRLF var WORD
    
    CRLF.HighByte=CR
    CRLF=CRLF>>1
    CRLF.LOWBYTE=CRLF.LowByte | LF
    it works... just harder to figure out. BAH could be worst. And BTW, a 18F will be more appropriate for that.

    About the String placement... you're right. As i figure to place all string at the top, it shouldn't be a problem. All the string together. Make it easy if some modification have to be done.
    Last edited by mister_e; - 27th August 2005 at 21:14.
    Steve

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

Similar Threads

  1. Minimizing code space
    By Tobias in forum mel PIC BASIC Pro
    Replies: 2
    Last Post: - 30th May 2009, 07:25
  2. How much code space do PBP statements use.
    By Darrel Taylor in forum Code Examples
    Replies: 5
    Last Post: - 13th February 2009, 21:31
  3. Loop with two motor and 2 sensors
    By MrRoboto in forum mel PIC BASIC
    Replies: 4
    Last Post: - 8th December 2008, 23:40
  4. Making Program Code Space your playground...
    By Melanie in forum Code Examples
    Replies: 15
    Last Post: - 19th July 2008, 08:26
  5. Please help with storing strings in codespace
    By g-hoot in forum mel PIC BASIC Pro
    Replies: 3
    Last Post: - 16th May 2008, 01:02

Members who have read this thread : 1

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