Embedded Strings in your Code Space


Closed Thread
Page 1 of 2 12 LastLast
Results 1 to 40 of 50
  1. #1
    mytekcontrols's Avatar
    mytekcontrols Guest

    Default

    Thanks for the heads up on the PDS. I'll check go check it out. Although on the current project I extremely doubt I'll be jumping ship (... I can almost see the shore as we speak). However on another project, It might certainly be a consideration. How is the optimization of the code it produces?

    Also as I said in my previous post, reliability plays a key role in my choice of programming tools. I tend to stick to what works, and usually find work arounds for minor ommisions. Case in point; the lack of string handling ability in PBP I quickly resolved by taking a different approach. At first I was stumped at not being able to set up a string variable that I could later pass to an I2C routine. Of course the solution came in the form of using lookup tables as shown below (printascii would go to a separate print routine for output, in my case a specialized I2C routine).

    For y=0 To 255
    Gosub mesghello
    If ascii = Null Then exit
    Gosub printascii
    Next y

    mesghello: Lookup y,["hello world",Null],ascii
    Return

    In my 6502 assembler days, I used a routine that would pop the return address off the stack, increment it by 1 to pick up the start of the ascii data to be sent, send the data, and then modify the RTS to return directly following the ascii data (next example).

    jsr printascii
    .byte "hello world",Null
    -- rentry point upon return from printascii routine --

    Much simpler, and some what more readable when looking at the source code (the messages appear where used, and not in a later table). However for messages that would be reused several times through out a program, the table approach is preferred in order to save code space. Unfortunately I haven't figured out a similar method that would work either within PBP or as an @asm script (can't pop the stack as far as I know).

    I ran a suggestion by the makers of PBP about the possibility of including something like the LCDOUT command maybe in the form "BYTEOUT var{,item...} example:

    ascii var byte[255]

    BYTEOUT ascii,"hello world",Null
    Gosub print ascii


    printascii:
    For y=0 To 255
    If ascii[y] = Null Then Return
    Gosub sendascii ' send character by whatever method desired
    Next y
    Return

    This would yield something similar to the 6502 assembly example.

    Anyway getting back to the original topic so to speak; picnaut thanks again for your sugestion about PDS.

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


    Did you find this post helpful? Yes | No

    Default

    mytekcontrolsm,

    Using a Lookup for strings can use up a huge amount of code. And I believe I may have the solution you're looking for.

    How to store and retrieve strings in Code Space

    Another person that I helped out a while back had his 877 completely maxed out with Lookups for strings to be displayed on an LCD. After converting them to the STRINGS in CODE format, it only took up 1.5K words. Leaving 6.5K for more program. We were both amazed.

    And, I too will not be Jumping ship anytime soon. PBP is just to good.

    Darrel

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


    Did you find this post helpful? Yes | No

    Default

    Nice job Darrel, and thanks for the excellent resource. I've used several of
    your routines on various projects.

    Here's something similar for the 18F series.
    Code:
    DEFINE LOADER_USED 1
    DEFINE OSC 4
    
    ptr_pos	VAR BYTE
    temp	VAR BYTE
    x	VAR BYTE
    
    Main:
       CALL USART_Init
       ptr_pos = 0
       CALL Start
       ptr_pos = 16
       CALL Start
       ptr_pos = 48
       CALL Start
       ptr_pos = 176
       CALL Start
    
    Done:
       GOTO Done
        
    ASM
    _USART_Init
       movlw   B'00100100'   ;initialize USART
       movwf   TXSTA	 ;8-bit, Async, High Speed
       movlw   .25           ;value for 9600 bps @ 4MHz
       movwf   SPBRG	 ;set SPBRG for 9600 bps @ 4MHz
       movlw   B'10010000'   ;enable USART
       movwf   RCSTA
       return
    
    ;----Lookup & send text messages--------------------------
    _Start
       movlw   UPPER msg_table
       movwf   TBLPTRU
       movlw   HIGH msg_table
       movwf   TBLPTRH
       movlw   LOW msg_table
       movwf   TBLPTRL
       movf    _ptr_pos,W	;prt_pos must hold message address
       addwf   TBLPTRL,F
       clrf    WREG
       addwfc  TBLPTRH,F
       addwfc  TBLPTRU,F
    
    Next_Char
       tblrd   *+
       movff   TABLAT,_temp
       bra     Test_EOM      ;test for EOM character
    	
    Continue
       movf	  _temp,W	 ;move temp to w
       movwf  TXREG		 ;send it
       btfss  TXSTA,TRMT	 ;wait for data TX
       goto   $-2
       bra	  Next_Char      ;fetch next message character from table
    	
    Test_EOM
       movlw  "~"            ;check for EOM character
       cpfseq  _temp, 1	 ;compare temp with w, if temp = ~ then end			
       bra     Continue      ;no EOM, so continue
       movlw   "\r"		 ;move data into TXREG
       movwf   TXREG	 ;send carriage return
       btfss   TXSTA,TRMT	 ;wait for data TX
       goto    $-2	
       movlw   "\n"		 ;move data into TXREG
       movwf   TXREG	 ;send line feed
       btfss   TXSTA,TRMT	 ;wait for data TX
       goto    $-2
       return                ;finished with message, return to caller
    ENDASM
    
    ASM
    msg_table	; Message strings
       data	" Message #1~    ";Message #1 starts at msg_table 0
       data	" Message #2~    ";Message #2 starts at msg_table 16, etc,
       data	" Message #3~    ";32
       data	" Message #5~    ";48
       data	" Message #6~    ";64
       data	" Message #7~    ";80
       data	" Message #8~    ";96
       data	" Message #9~    ";112
       data	" Message #10~   ";128
       data	" Message #11~   ";144
       data	" Message #12~   ";160
       data	" Message #13~   ";176
    ENDASM
    Regards,

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

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


    Did you find this post helpful? Yes | No

    Default

    Now there's an endorsement I can be proud of.

    Thanks Bruce!

  5. #5
    mytekcontrols's Avatar
    mytekcontrols Guest


    Did you find this post helpful? Yes | No

    Smile I like it!

    Thanks Darrel and Bruce for your great examples. I would have to say I like Darrel's approach the best, since it seems less cryptic as to what the messages are (i.e; you can give them meaningfull names). Also I like the idea that they can be located anywhere in the program (kinda like my 6502 example). However I am using an 18F252 for my project, and apparently this approach wont work with a 16 bit processor. Any ideas how this could be changed?

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


    Did you find this post helpful? Yes | No

    Default

    Code:
    ' Text message addresses w/specific names
    Intro CON 0
    PumpOn CON 16
    PumpOFF CON 32 ' etc,,
    
       ptr_pos = Intro     ' print intro message
       CALL Start
       ptr_pos = PumpON ' print pump on message, etc,,,
       CALL Start
    You now have meaningful names for your strings. It's not that cryptic once
    you've played with it a bit. The 18F series are easier to code in .asm than
    16F parts.

    Make your strings as long as you like. That was just a quick/simple example.

    I don't have an example for placing strings all over code space since I would
    never do that. PBP library functions & my app code get first pick. Huge
    chunks of text messages get the left-overs at the bottom...;o]
    Regards,

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

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


    Did you find this post helpful? Yes | No

    Default Strings updated.

    Hi again Michael,

    I guess it was about time anyhow. Haven't updated it since 2003.

    I've modified the Strings program to be able to work with 16-bit devices.

    Between Bruce's example and the new one, I'm sure you'll get what you need.

    It's still in the same place ... How to store and retrieve strings in Code Space

    Best regards,
       Darrel

  8. #8
    mytekcontrols's Avatar
    mytekcontrols Guest


    Did you find this post helpful? Yes | No

    Question I would like to use Bruce's message table code, but...

    Hi Bruce,

    I have been studying your code that you posted here on doing message tables from assembly code, and quite frankly I am baffled by parts of it. This wouldn't be problem if I could use it as is, but I really need to have the pointer increments to be by 1 (i.e.; 0,1,2,3,4,5,6, ect.).

    Here are some snippits of your code with some questions I have next to them. If you get a chance can you please explain what is going on?

    Code:
    ; This section appears to be locating the message table, but Im not
    ; really sure specifically what is going on especially with the first part
    ; where you are moving Upper msg_table into TBLPTRU
    ; (what is UPPER? I've used HIGH and LOW before, but never UPPER).
    ; TBLPTR is obviously short for Table Pointer.
    
       movlw   UPPER msg_table 
       movwf   TBLPTRU
       movlw   HIGH msg_table
       movwf   TBLPTRH
       movlw   LOW msg_table
       movwf   TBLPTRL
    
    ; Now here we seem to be adding an offset into the message table using
    ; the same pointers we previously set to what I am asuming is the base
    ; address of our message table. This is where the beginning of a particular
    ; message resides within the table (correct?). Now here comes the questions
    ; of particular interest to me; does the fact that your pointers are in 16 byte
    ; increments mean that each message string can only be up to 16 bytes long?
    ; Or can the pointer be changed to any increment desired?
    
      movf    _ptr_pos,W	;prt_pos must hold message address
       addwf   TBLPTRL,F
       clrf    WREG
       addwfc  TBLPTRH,F
       addwfc  TBLPTRU,F
    
    ; Ok now that we have our index to a message set, we can begin retrieving
    ; the characters one by one, until we see the EOM character "~". What is
    ; tblrd   *+ or more specifically *+ (is this doing a read and then increment?)
    ; Oh and what is "goto   $-2" doing? (specifically $-2).
    
    Next_Char
       tblrd   *+
       movff   TABLAT,_temp
       bra     Test_EOM      ;test for EOM character
    	
    Continue
       movf	  _temp,W	 ;move temp to w
       movwf  TXREG		 ;send it
       btfss  TXSTA,TRMT	 ;wait for data TX
       goto   $-2
       bra	  Next_Char      ;fetch next message character from table
    	
    ; This part is fairly obvious, although there are some more of those $-2
    ; which I don't understand the purpose of, and what does "\r"
    ; and "\n" do? Actually to be more specific since I can see your comments,
    ; what my question really is; what or how does moving a literal of "\r" into
    ; W actually move the data (which I assume is a character from the table).
    
    Test_EOM
       movlw  "~"            ;check for EOM character
       cpfseq  _temp, 1	 ;compare temp with w, if temp = ~ then end			
       bra     Continue      ;no EOM, so continue
       movlw   "\r"		 ;move data into TXREG
       movwf   TXREG	 ;send carriage return
       btfss   TXSTA,TRMT	 ;wait for data TX
       goto    $-2	
       movlw   "\n"		 ;move data into TXREG
       movwf   TXREG	 ;send line feed
       btfss   TXSTA,TRMT	 ;wait for data TX
       goto    $-2
       return                ;finished with message, return to caller
    If I was better versed in the assembly aspects of the 18F series I could probably figure this out on my own, but I only recently began working with this series of PIC chips.

    Any help you can offer is appreciatted.
    Thanks,

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


    Did you find this post helpful? Yes | No

    Default

    Hi Michael,

    Download the PICmicro® 18C MCU Family Reference Manual... or just the chapters you need from here;

    http://www.microchip.com/stellent/id...GE&nodeId=2054

    There's a whole section on table read/write with detailed explanations that should answer every question you have.

    Much easier than me re-typing it all. If you have questions after reading section 8 let me know.
    Regards,

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

  10. #10
    mytekcontrols's Avatar
    mytekcontrols Guest


    Did you find this post helpful? Yes | No

    Lightbulb Another approach...

    Hi Darrel - Hi Bruce,

    Darrel I checked out your new message table code for 16 bit pics. Very Nice!

    Bruce I read up on the info you linked me to, and I have a pretty good grasp of what you are doing in your code. I also figured out that the GOTO $-2 is just a slick way to skip backwards without having to use a labeled reference.

    Well of course after getting my brain filled with a bit more knowledge I decided to try my hand at writing yet another variation on message string handling, but not without problems (and a smoking head). Check out this code:
    Code:
    DEFINE LOADER_USED 1
    DEFINE OSC 40               ' change to suit oscillator speed
    DEFINE HSER_RCSTA 90h
    DEFINE HSER_TXSTA 20h
    DEFINE HSER_BAUD 19200      ' change to suit baud rate
    
    message var byte[40]
    stringsize var byte
    x var byte
    temp var byte
    Clr
    
    Main:
        Call getSTR
    @ data "This is a string",0
        Gosub putSTR
    
    '    Call getSTR
    '@ data "yet another string again",0
    '    Gosub putSTR
    Done:
       Goto Done
    
    putSTR:
        For x = 0 To (stringsize-1)
        temp = message[x]
        Hserout [temp]
        Next x
        Hserout [$0D,$0A]       ; send carriage return + line feed
        stringsize = 0          ; reset for next message
        Return    
    
    asm
    _getSTR
        LFSR    FSR0,_message   ; set message array base address
    
    ;copy return address to TBLPTR and then pop it off the stack
        movf    TOSU,W
        movwf   TBLPTRU
        movf    TOSH,W
        movwf   TBLPTRH
        movf    TOSL,W
        movwf   TBLPTRL
        POP
    
    ;TBLPTR should now be pointing to 1st character in string
    Next_Char
        tblrd   *+              ; table read and post increment TBLPTR
        movf    TABLAT,W        ; retrieve character to W register
        movwf   POSTINC0        ; xfer to message array and increment FSR
        incf    _stringsize,F   ; keep track of message string size
        movf    TABLAT,W        ; Is character = 0?
        bnz     Next_Char       ; If not, then get next character			
    
    ;use incremented value of TBLPTR as new return address (push it)
        movf   TBLPTRU,W
        movwf   TOSU
        movf   TBLPTRH,W
        movwf   TOSH
        movf   TBLPTRL,W
        movwf   TOSL
        PUSH
        return                  ;finished with message, return to caller
    endasm
    It's more of a variation of what Darrel's code does. Only I wanted to try using the POP and PUSH functions on the PIC18F to allow me to have embedded message strings (this is a pet peeve of mine). Anyway if you run the code as is (leave the 2nd message string commented out) everything works great. However if you try to use more then one message (uncomment the 2nd message string) then all hell breaks loose, and you end up with garbled messages and a runaway processor.

    Any ideas what I am doing wroung?

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


    Did you find this post helpful? Yes | No

    Default

    Well.. that certainly is a creative approach. I guess you did do some
    reading ehh..;o]

    Initialize your stringsize variable before you start incrementing it.

    Move the PUSH up to the entry point of the section "before" modifying
    TOS.

    See how this works.
    Code:
    DEFINE LOADER_USED 1
    DEFINE OSC 40               ' change to suit oscillator speed
    DEFINE HSER_RCSTA 90h
    DEFINE HSER_TXSTA 20h
    DEFINE HSER_BAUD 19200      ' change to suit baud rate
    
    message var byte[40]
    stringsize var byte
    stringsize = 0      ; <-- initialize to zero here. Don't wanna incf if it's not
    x var byte          ; starting at zero
    temp var byte
    Clr
    
    Main:
        Call getSTR
    @ data "This is a string",0
        Gosub putSTR
    
        Call getSTR
    @ data "yet another string again",0
        Gosub putSTR
    Done:
       Goto Done
    
    putSTR:
        For x = 0 To (stringsize-1)
        temp = message[x]
        Hserout [temp]
        Next x
        Hserout [$0D,$0A]       ; send carriage return + line feed
        stringsize = 0          ; reset for next message
        Return    
    
    asm
    _getSTR
        LFSR    FSR0,_message   ; set message array base address
    
    ;copy return address to TBLPTR and then pop it off the stack
        movf    TOSU,W
        movwf   TBLPTRU
        movf    TOSH,W
        movwf   TBLPTRH
        movf    TOSL,W
        movwf   TBLPTRL
        POP
    
    ;TBLPTR should now be pointing to 1st character in string
    Next_Char
        tblrd   *+              ; table read and post increment TBLPTR
        movf    TABLAT,W        ; retrieve character to W register
        movwf   POSTINC0        ; xfer to message array and increment FSR
        incf    _stringsize,F   ; keep track of message string size
        movf    TABLAT,W        ; Is character = 0?
        bnz     Next_Char       ; If not, then get next character			
    
    ;use incremented value of TBLPTR as new return address (push it)
        PUSH ; <--- moved up to here
        movf   TBLPTRU,W
        movwf   TOSU
        movf   TBLPTRH,W
        movwf   TOSH
        movf   TBLPTRL,W
        movwf   TOSL
        ; PUSH
        return                  ;finished with message, return to caller
    endasm
    Regards,

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

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


    Did you find this post helpful? Yes | No

    Default

    This is getting interesting, and now I have a few new ideas too.

    But, I think We've gone past melanie's original post of "Which PBP Compiler are you using?". So I've SPLIT it into a new thread "Embedded Strings in your Code Space". In the "mel PIC BASIC Pro" forum.

    Sorry if it caused any confusion.

    More from me soon,
    &nbsp;&nbsp;&nbsp;Darrel

  13. #13
    mytekcontrols's Avatar
    mytekcontrols Guest


    Did you find this post helpful? Yes | No

    Thumbs up It works!!!!

    Thanks Bruce, it works great!

    And now here it is utilizing your RS232 code:
    Code:
    DEFINE LOADER_USED 1
    DEFINE OSC 40               ' change to suit oscillator speed
    
    temp var byte
    
    Main:
       CALL USART_Init
    
        Call prntSTR
    @ data "This is a string",0
    
        Call prntSTR
    @ data "yet another string again",0
    
        Call prntSTR
    @ data "and one more time!",0
    
    Done:
       Goto Done
    
    asm
    _USART_Init
        movlw   B'00100100'     ; initialize USART
        movwf   TXSTA           ; 8-bit, Async, High Speed
        movlw   .129            ; value for 19200 bps @ 40MHz
        movwf   SPBRG           ; set SPBRG for 19200 bps @ 40MHz
        movlw   B'10010000'     ; enable USART
        movwf   RCSTA
        return
    
    _prntSTR
    ;copy return address to TBLPTR and then pop it off the stack
        movf    TOSU,W
        movwf   TBLPTRU
        movf    TOSH,W
        movwf   TBLPTRH
        movf    TOSL,W
        movwf   TBLPTRL
        POP
    
    ;TBLPTR should now be pointing to 1st character in string
    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...
        movf    _temp,W         ; move character into TXREG and...
        movwf   TXREG           ; send it!
        btfss   TXSTA,TRMT      ; has it been transmitted?
        goto    $-2             ; If not, keep checking
        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
        movlw   "\r"            ; move carriage return into TXREG and...
        movwf   TXREG           ; send it!
        btfss   TXSTA,TRMT      ; has it been transmitted?
        goto    $-2             ; If not, keep checking	
        movlw   "\n"            ; move line feed into TXREG and...
        movwf   TXREG           ; send it!
        btfss   TXSTA,TRMT      ; has it been transmitted?
        goto    $-2             ; If not, keep checking
    
    ;use incremented value of TBLPTR as new return address (push it)
        PUSH
        movf   TBLPTRU,W
        movwf   TOSU
        movf   TBLPTRH,W
        movwf   TOSH
        movf   TBLPTRL,W
        movwf   TOSL
        return                  ;finished with message, return to caller
    endasm
    This is real sweet, because all you have are 2 lines of code to send a message, and without any limitations as to how many or where they are located (assuming it fits in the program space).

    Well this is what I wanted in the first place, all it took was a bit of head scratching and some terrific help from you and Darrel. Heck until I started reading through the PIC18F reference material, I had assumed that there was no way to PUSH and POP a PIC chip (BTW, that is a great link to all kinds of good information).

    Next: Do the same thing for an LCD. Anyone got some good LCD asm code and an LCD to try it on?

    (yet another challenge for some brave soul)

    EDIT: Opps!! Darrel I guess you'll have to move this as well... Sorry

    see ya,
    Last edited by mytekcontrols; - 1st July 2005 at 05:04.

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


    Did you find this post helpful? Yes | No

    Default

    You know.. I just noticed from your earlier example that Clr wasn't returning
    an error. So just out of curiosity, I tried this.

    PBP v2.46, MPASM v4.01. Compiled for 18F452.
    Code:
    DEFINE LOADER_USED 1
    DEFINE OSC 20
    
    ptr_pos	VAR BYTE
    temp	VAR BYTE
    x       VAR BYTE
    Yahoo           '
    NoWay          '
    YeahSoWhat  ' <-- none of this returns an error..?
    
    Main:
        High 0
        pause 1000
        low 0
        pause 1000
        goto Main
    Anyone else get an error returned with this?
    Regards,

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

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


    Did you find this post helpful? Yes | No

    Default

    Any single word lines in PBP automaticaly become a Label. Even though they don't show up in MicroCode Studio until they have a colon ":" after them.

    So it should have been CLEAR. But it won't show up as an error if it's not.

    DT

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


    Did you find this post helpful? Yes | No

    Default

    I guess the move went well, it seems to still be notifying us, and replies are going to the new thread. That's the first time I've split a thread, so I wasn't sure.

    Back to the topic, this isn't quite what I had thought of earlier, but the code changed since then. I haven't had a chance to try it yet, but it does compile.

    So assuming everything is working, I wanted to add one thing that gets you closer to that 1 line "embedded message strings" that you're looking for.

    Here's a simple macro that should do the same thing that you have now, but only takes 1 line (of PBP code) to do it. It needs to be before Main:
    Code:
    ASM
    SendStr  macro Astring
        call _prntSTR
        data Astring,0
        endm
    ENDASM
    Now in the "Main" code, it'll look like this...
    Code:
    Main:
       CALL USART_Init
    
    @ SendStr "This is a string" 
    @ SendStr "yet another string again"
    @ SendStr "and one more time!"
    OR, of course it could also be...
    Code:
    ASM
      SendStr "This is a string" 
      SendStr "yet another string again"
      SendStr "and one more time!"
    ENDASM
    Darrel
    Last edited by Darrel Taylor; - 1st July 2005 at 06:29.

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


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by Darrel Taylor
    Any single word lines in PBP automaticaly become a Label. Even though they don't show up in MicroCode Studio until they have a colon ":" after them.

    So it should have been CLEAR. But it won't show up as an error if it's not.

    DT
    Interesting. I never noticed that one before until looking at where he had
    Clr instead of clear.
    Regards,

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

  18. #18
    mytekcontrols's Avatar
    mytekcontrols Guest


    Did you find this post helpful? Yes | No

    Default

    Great job Darrel! It just keeps getting better and better.

    Here is the tested version of the code incorporating your changes:
    Code:
    DEFINE LOADER_USED 1
    DEFINE OSC 40       ' change to suit oscillator speed
    setSPBRG con 129    ' 19200 baudrate w/ 40Mhz OSC
                        ' (change to suit requirements)
    
    temp var byte       ' temporary storage for character
    
        Goto main
    ' Send String Macro (must be located prior to Main)
    ASM
    SendStr  macro Astring
        call _prntSTR
        data Astring,0
        endm
    ENDASM
    
    '=======================================
    Main:
       CALL USART_Init  ' initialize hardware USART
    
    ' send messages through RS232
    ' format #1
    @ SendStr "This is a string" 
    @ SendStr "yet another string again"
    @ SendStr "and one more time!"
    
    ' format #2
    ASM
      SendStr "This is a string" 
      SendStr "yet another string again"
      SendStr "and one more time!"
    ENDASM
    
    Done:
       Goto Done        ' loop forever
    
    '=======================================
    
    ' USART initialization and print string code (locate anywhere)
    asm
    _USART_Init
        movlw   B'00100100'     ; initialize USART
        movwf   TXSTA           ; 8-bit, Async, High Speed
        movlw   _setSPBRG       ; pass constant to SPBRG to
        movwf   SPBRG           ; determine baudrate to be used
        movlw   B'10010000'     ; enable USART
        movwf   RCSTA
        return
    
    _prntSTR
    ;copy return address to TBLPTR and then pop it off the stack
        movf    TOSU,W
        movwf   TBLPTRU
        movf    TOSH,W
        movwf   TBLPTRH
        movf    TOSL,W
        movwf   TBLPTRL
        POP
    
    ;TBLPTR should now be pointing to 1st character in string
    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...
        movf    _temp,W         ; move character into TXREG and...
        movwf   TXREG           ; send it!
        btfss   TXSTA,TRMT      ; has it been transmitted?
        goto    $-2             ; If not, keep checking
        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
        movlw   "\r"            ; move carriage return into TXREG and...
        movwf   TXREG           ; send it!
        btfss   TXSTA,TRMT      ; has it been transmitted?
        goto    $-2             ; If not, keep checking	
        movlw   "\n"            ; move line feed into TXREG and...
        movwf   TXREG           ; send it!
        btfss   TXSTA,TRMT      ; has it been transmitted?
        goto    $-2             ; If not, keep checking
    
    ;use incremented value of TBLPTR as new return address (push it)
        PUSH
        movf   TBLPTRU,W
        movwf   TOSU
        movf   TBLPTRH,W
        movwf   TOSH
        movf   TBLPTRL,W
        movwf   TOSL
        return                  ;finished with message, return to caller
    endasm
    So now we have a single line RS232 messaging system that will work properly, assuming you don't use any interrupts in the rest of your code (that's right, this will probably fail with interrupts enabled).

    Now to get the interrupt compatible version we'll need an efficient way to disable global interrupts when doing the stack manipulations. Since there are 2 levels of interrupts (GIEL and GIEH) possible on an 18 series pic it's a little more complicated. Before I dive into this does anyone have a good suggestion or example code?

    Thanks,

  19. #19
    mytekcontrols's Avatar
    mytekcontrols Guest


    Did you find this post helpful? Yes | No

    Smile Now before somebody thinks we're going crazy...

    If you look at the last code example you may be asking yourself "Hey isn't that the same thing as HSEROUT ["This is a string"]?"

    Well... yes it is, sort of. What I really see to be accomplished here, has more to do with creating the framework for a customizable message string handling Function, then just mimicing an already available PicBasic Pro function. For testing purposes, it is just easier to send it out unaltered through the RS232 port. Ulimately, it will hopefully evolve into a great way to send either message strings, data, or both to any device you wish. While at the same time doing it in a way that is more like a built-in PicBasic Pro function.

    A great example of what this could be used for, is imagine that you are interfaced to a device that would accept message strings via RS232, but always requires special commands to precede the message. Using what has already been developed here, all that would be required is to add these commands within the printSTR code (same as what was done for the carriage return and linefeed). Then every time you send a message such as @ SendStr "This is a string" the pre commands would be automatically sent as well.

    Even better still, imagine if you were interfaced to several different devices or gateways, each one having special communication requirements (I2C, SPI, One-Wire, RS232, ect.). Every protocol could concievably be supported within the printSTR code, thereby allowing you to broadcast simultaneously to all devices via the single line SendStr function. Pretty cool huh!

    We are only scratching the surface as to the possibilities.
    Last edited by mytekcontrols; - 1st July 2005 at 19:29. Reason: Just had another thought

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


    Did you find this post helpful? Yes | No

    Default

    Hiya Michael,

    And for my next installment of things you can change with the program you already have working ....

    Sometimes I go crazy with the macro's. But I kinda like this one.
    Code:
    '--[ 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
    Now to initialize the USART all you have to do is this...
    Code:
    @ USART_Init 19200
    It should work with any OSC setting and any valid baud rate.

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

    >> Ulimately, it will hopefully evolve into a great way to send either message strings, data, or both to any device you wish.

    I've also got some MAJOR changes that allow you to do the above quote. Haven't tested them completely yet, but they look promising.

    Best regards,
    &nbsp;&nbsp;&nbsp;Darrel

  21. #21
    mytekcontrols's Avatar
    mytekcontrols Guest


    Did you find this post helpful? Yes | No

    Thumbs up I love your Macros, please keep them coming

    I've also got some MAJOR changes that allow you to do the above quote. Haven't tested them completely yet, but they look promising.
    Hey Darrel, I really think we got you hooked on this :-)
    Which is perfectly fine by me, and will surely be fun to see what's in store.

    Any good ideas on the best way to deal with the interrupt disable issue? I was reading up on this a bit, and it seems like some approaches could cause latency problems. I am also not 100% sure of which parts of the stack manipulation are no no's while an interrupt is occuring (in otherwords, is it only during the PUSH, or POP or both).

    My particular interest will be to implement the "printSTR" in an I2C format, since a video chip I am working with requires this. It also has fussy timing requirements that appear to lower than even the standard device speed. to top it off I have 2 chips on board, so I am using independant clock lines and a shared SDA, since they both have identical addresses. Presently I have everything working with a custom PicBasic Pro I2C routine, but I suspect I'll need to implement this as an ASM routine if it is to be incorporated into the "printSTR" routine. Unless your MAJOR changes would allow for this.

    BTW: I like the USART routine, it makes it very easy which we all love.

  22. #22
    mytekcontrols's Avatar
    mytekcontrols Guest


    Did you find this post helpful? Yes | No

    Default Here's the latest code version

    Darrel this incorporates your USART macro (works great):
    Code:
    DEFINE LOADER_USED 1    ' use for Boot Loader
    DEFINE OSC 40   ' change to suit oscillator speed
    
    '============================================
    ' Equates
    '============================================
    
    temp var byte   ' temporary storage for character
    
        Goto main   ' skip around Macros
    
    '============================================
    ' Macros
    '============================================
    ' Send String Macro (must be located prior to Main)
    ASM
    SendStr  macro Astring
        call _prntSTR
        data Astring,0
        endm
    ENDASM
    
    ' USART Initialization Macro (must be located prior to Main)
    ' [ Initialize 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
    
    '============================================
    ' Main Program
    '============================================
    Main:
    @ USART_Init 19200  ; set RS232 baudrate
    
    ' send messages through RS232
    ' format #1
    @ SendStr "This is a string" 
    @ SendStr "yet another string again"
    @ SendStr "and one more time!"
    
    ' format #2
    ASM
      SendStr "This is a string" 
      SendStr "yet another string again"
      SendStr "and one more time!"
    ENDASM
    
    Done:
       Goto Done        ' loop forever
    
    '============================================
    ' String Extraction and Print Routines
    '============================================
    ' print string code (locate anywhere)
    ASM
    _prntSTR
    ;copy return address to TBLPTR and then pop it off the stack
        movf    TOSU,W
        movwf   TBLPTRU
        movf    TOSH,W
        movwf   TBLPTRH
        movf    TOSL,W
        movwf   TBLPTRL
        POP
    
    ;TBLPTR should now be pointing to 1st character in string
    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...
        movf    _temp,W         ; move character into TXREG and...
        movwf   TXREG           ; send it!
        btfss   TXSTA,TRMT      ; has it been transmitted?
        goto    $-2             ; If not, keep checking
        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
        movlw   "\r"            ; move carriage return into TXREG and...
        movwf   TXREG           ; send it!
        btfss   TXSTA,TRMT      ; has it been transmitted?
        goto    $-2             ; If not, keep checking	
        movlw   "\n"            ; move line feed into TXREG and...
        movwf   TXREG           ; send it!
        btfss   TXSTA,TRMT      ; has it been transmitted?
        goto    $-2             ; If not, keep checking
    
    ;use incremented value of TBLPTR as new return address (push it)
        PUSH
        movf   TBLPTRU,W
        movwf   TOSU
        movf   TBLPTRH,W
        movwf   TOSH
        movf   TBLPTRL,W
        movwf   TOSL
        return                  ;finished with message, return to caller
    ENDASM

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

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

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

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

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

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

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

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


    Did you find this post helpful? Yes | No

    Default

    mmm, another solution...
    Code:
    String1 da "My string",13,10,"blah blah",13,10,125,126,127,0
    Just modify a little bit the StringOut Sub
    Code:
    StringOut:  ' Send the string out via Hserout
        Readcode Addr, TwoChars       ' Get the 14 bit packed characters
        Char = TwoChars >> 7          ' Separate first char
        if Char then                  ' Look for Null char, Stop if found
           hserout [Char]             ' Send first char
           endif
    
        Char = TwoChars & $7F         ' Separate second char
        if Char then                  ' Look for Null char, Stop if found
           hserout [Char]             ' Send the second char
           Addr = Addr + 1            ' Point to next two characters
           goto StringOut	          ' Continue with rest of the string
           endif
    return
    that way it works. BUT it don't take all the advantage of the 14 BIT pack stuff. It's just more readable the the previous.
    Last edited by mister_e; - 27th August 2005 at 21:21.
    Steve

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

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


    Did you find this post helpful? Yes | No

    Default

    Hmmmpf,

    Apparently, none of them are right.

    With mine, it puts 00's in front of each byte (13,10), that will cause the send routine to terminate early.

    With the 0x068a, if there's an ODD number of characters in the string, it will pad the string with a 00, again causing the send routine to terminate early.

    So there doesn't seem to be a way to add CRLF on the end of a string with "DA".

    Your program seems to have an advantage after all. My apologies.
    <br>
    DT

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


    Did you find this post helpful? Yes | No

    Default

    How dare you fix my program while I'm still posting that you were right!

    Ha ha, Good job!
    <br>
    DT

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


    Did you find this post helpful? Yes | No

    Default

    OK as i will probably never happen again, i'll write the date/month/year in my notebook with the note
    once in my life, i beat Mr Darrel Taylor
    THE Canadian 1
    United State 0
    Just kidding Darrel I learn a lot from all of your previous posts.

    Keep up the good work !!!
    Steve

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

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


    Did you find this post helpful? Yes | No

    Default

    Oh shoot,

    Still has that "Padding the string" problem.

    Code:
    010D   26F9 1073 3A72 00255 String1 da "My string",13,10,"blah blah",13,10,125,126,127,0
           34EE 3380 000D
           000A 316C 30E8
           1062 3661 3400
           000D 000A 007D
           007E 007F 0000
    Sendstring still terminates early if the string has an ODD number of charaters.

    Almost there.

    P.S.
    THE Canadian 0.99
    <br>
    Last edited by Darrel Taylor; - 27th August 2005 at 22:02.
    DT

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


    Did you find this post helpful? Yes | No

    Default

    Maybe this...
    Code:
    StringOut:  ' Send the string out via Hserout
        Readcode Addr, TwoChars       ' Get the 14 bit packed characters
        IF TwoChars <> 0 then
            Char = TwoChars >> 7      ' Separate first char
            if Char then              ' Look for Null char, Don't send if found
               hserout [Char]         ' Send first char
            endif
    
            Char = TwoChars & $7F     ' Separate second char
            if Char then              ' Look for Null char, Don't send if found
               hserout [Char]         ' Send the second char
           endif
           Addr = Addr + 1            ' Point to next two characters
           goto StringOut	          ' Continue with rest of the string
        ENDIF
    return
    DT

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


    Did you find this post helpful? Yes | No

    Default

    hmmpff... is it me or
    Code:
        IF TwoChars <> 0 then
    is unecesary since we check both character anyway???
    Steve

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

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


    Did you find this post helpful? Yes | No

    Default

    But it has to stop sometime.

    When you add a final ,0 to the end of the line, DA generates a 0x0000 word. So only if the whole word is 0 will it consider it the end of the "string".

    Any other 0 characters within the "string" are ignored.
    <br>
    DT

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


    Did you find this post helpful? Yes | No

    Default

    Got it..
    Code:
    StringOut:  ' Send the string out via Hserout
        Readcode Addr, TwoChars       ' Get the 14 bit packed characters
        IF TwoChars then
            Char = TwoChars >> 7      ' Separate first char
            if Char then              ' Look for Null char, Don't send if found
               hserout [Char]         ' Send first char
            endif
    
            Char = TwoChars & $7F     ' Separate second char
            if Char then              ' Look for Null char, Don't send if found
               hserout [Char]         ' Send the second char
           endif
           Addr = Addr + 1            ' Point to next two characters
           goto StringOut	          ' Continue with rest of the string
        ELSE
            Addr=Addr+1
            Goto StringOut
        ENDIF
    return
    Steve

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

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


    Did you find this post helpful? Yes | No

    Default

    NARGH forget the above. It depend on the previous and the next string... wich doesn't happen with my first version with DT...mmm
    Steve

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

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


    Did you find this post helpful? Yes | No

    Default

    Forgotten
    DT

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