SX/B SEROUT vs PBasic SEROUT

Bill ChennaultBill Chennault Posts: 1,198
edited 2011-02-03 - 12:06:57 in Microcontrollers
All--

I am working on a project involving an AP-16+. I would LIKE to control it with an SX using SX/B. However, I have just realized that SEROUT is vastly different between PBasic and SX/B.

PBasic: SEROUT pin, baudmode, data
SX/B: SEROUT pin, baudmode, value

There is a big difference between "data" and "value"! PBasic allows a list of variables, constants, expressions, and formatters as data. SX/B restricts data to a value between 0 - 255. Sending commands to the AP-16+ requires a PBasic SEROUT such as this:

SEROUT pin, baudmode, ["!AP16", Addr, "PW", "birdie", CR, 1] (Note the complex data argument.)

Is there a way to emulate that in SX/B? (Or, should I just use a Stamp?)

Thanks!

--Bill
You are what you write.

Comments

  • ZootZoot Posts: 2,226
    edited 2011-01-29 - 09:01:21
    There's nothing "complex" about your Pbasic version -- it just has lots of bytes. The real thing in SX/B is to *always* wrap your high level commands like shiftout and serout into subs or functions.... each high level command can generate a fair amount of code, and if you use 10 serouts in a row you'll fill up your codespace quickly. Then it is just a matter of getting the bytes to your SX/B sub...
    tmpB1 VAR Byte ' work space
    tmpB2 VAR Byte
    SER_OUT SUB 1                    ' send a byte via serial
    
    '-----
    Main:
    
    SER_OUT "!"
    SER_OUT "A"
    SER_OUT "P"
    SER_OUT "1"
    SER_OUT "6"
    SER_OUT Addr
    SER_OUT "P"
    SER_OUT "W"
    SER_OUT "b"
    SER_OUT "i"
    SER_OUT "r"
    SER_OUT "d"
    SER_OUT "i"
    SER_OUT "e"
    SER_OUT CR
    SER_OUT 1
    
    GOTO Main
    
    '-----
    SUB SER_OUT
      tmpB1 = __PARAM1 ' stash the value to serout
      SEROUT SerIO, OT38400, tmpB1
      ENDSUB
    
    

    Now that won't take insane amounts of space, but of course, you are wondering, "is there an even more efficient way?" Sure, but this is meant to be clear. If it were me, I would wrap the preamble and postamble (is that word?) for all the AP16 calls into yet another sub:
    DO
    AP16_PREAMBLE Addr
    SER_OUT "P"
    SER_OUT "W"
    SER_OUT "b"
    SER_OUT "i"
    SER_OUT "r"
    SER_OUT "d"
    SER_OUT "i"
    SER_OUT "e"
    AP16_POSTAMBLE
    LOOP
    
    
    SUB AP16_PREAMBLE
    tmpB2 = __PARAM1
    SER_OUT "!"
    SER_OUT "A"
    SER_OUT "P"
    SER_OUT "1"
    SER_OUT "6"
    SER_OUT tmpB2
     RETURN
    
    SUB AP16_POSTAMBLE
    SER_OUT 1
    SER_OUT CR
     RETURN
    
    '-----
    SUB SER_OUT
      tmpB1 = __PARAM1 ' stash the value to serout
      SEROUT SerIO, OT38400, tmpB1
      ENDSUB
    
    

    Now, *if it were me* I would set up the file names as "data" strings, and write one more sub that would let me pass just an index number (say 0-32) and then the sub would "look up" the data string for the wav file name, and write all the bytes for that filename. This would save even more code space and clean up my code visually quite a bit.

    Hope this helps....
    When the going gets weird, the weird turn pro. -- HST

    my site: 1uffakind.com
    create bitmap data tool: 1uffakind.com/robots/povBitMapBuilder.php
    resistor ladder tool: 1uffakind.com/robots/resistorLadder.php
    convert images to ascii art: 1uffakind.com/apptoys/convtoascii/
    MC6808/Hero-1 assembler: 1uffakind.com/apptoys/onlinecompilers/MC6800/
  • Bill ChennaultBill Chennault Posts: 1,198
    edited 2011-01-29 - 09:07:40
    Zoot--

    Yes. It helps a lot. Thank you very much!

    --Bill
    You are what you write.
  • Bill ChennaultBill Chennault Posts: 1,198
    edited 2011-01-31 - 19:03:26
    Zoot (and All)--

    The SX48/AP-16+ combination is working. But, I am trying to implement "phase iii" of Zoot's guidance using data statements in SX/B. So far, without success. Will you take a look at my code, which is all stolen and adapted from others (primarily, Zoot) and tell me what might be wrong? (I will eliminate the redundant calls later.) My immediate goal is to read the file names from data statements in SX/B. If I can do that, then I will implement the AP-16+ pre- and post- (Zoot, if you see it on the Internet, then it must be true) amble code.
    DEVICE SX48, OSCHS1
    FREQ 20_000_000
    SIO PIN RE.7 OUTPUT ' no ULN, SETUP = UP
    LED PIN RC.7 OUTPUT
    ' -----[ Constants ]-------------------------------------------------------
    Addr CON %0 ' both address jumpers out
    CR CON 13
    ' -----[ Variables ]-------------------------------------------------------
    tmpB1 VAR BYTE
    tmpB2 VAR Byte
    idx VAR Byte
    char VAR Byte
    AP_Status VAR Byte
    Playing VAR AP_Status.7 ' 0 = idle, 1 = playing
    ' =========================================================================
    PROGRAM Start
    ' =========================================================================
    ' -------------------------------------------------------------------------
    ' Program Code
    ' -------------------------------------------------------------------------
    ' -----[ Initialization ]--------------------------------------------------
    SER_OUT SUB 1 ' send a byte via serial
    GET_Status SUB 1
    Verify_Play SUB 0
    Start:
    SER_OUT "!"
    SER_OUT "A"
    SER_OUT "P"
    SER_OUT "1"
    SER_OUT "6"
    SER_OUT Addr
    SER_OUT "P"
    SER_OUT "W"
    SER_OUT "X"
    SER_OUT CR
    SER_OUT 1
    pause 500
    '**************************************************************************
    ' send filename . . . this is the piece of code I am trying to make work
    idx = 0
    do
    read filename + idx, char
    if char = 0 then exit
    SER_OUT char
    inc idx
    loop
    SER_OUT CR
    SER_OUT 1
    '**************************************************************************
    Verify_Play
    pause 500
    goto Start
    Preamble:
    data "!AP16", "0", CR, 0
    filename:
    data "birdie", CR, 0
    data "descrip", CR, 0
    data "file00", CR, 0
    data "file01", CR, 0
    data "file02", CR, 0 
    data "file03", CR, 0
    data "file04", CR, 0
    data "file05", CR, 0
    data "file06", CR, 0
    data "file07", CR, 0
    data "file08", CR, 0
    data "file09", CR, 0
    data "file10", CR, 0
    ' -------------------------------------------------------------------------
    SUB SER_OUT
    tmpB1 = __PARAM1 ' stash the value to serout
    SEROUT SIO, OT38400, tmpB1
    ENDSUB
    ' -------------------------------------------------------------------------
    SUB Get_Status
    pause 50
    SER_OUT "!"
    SER_OUT "A"
    SER_OUT "P"
    SER_OUT "1"
    SER_OUT "6"
    SER_OUT Addr
    SER_OUT "G"
    serin SIO, OT38400, AP_Status
    endsub
    ' -------------------------------------------------------------------------
    SUB Verify_Play
    Get_Status 0
    ' if AP_Status.7 then
    if Playing then
    do
    pause 25
    Get_Status 0
    loop until Playing = 0
    endif
    [FONT=Fixedsys][FONT=Arial]endsub[/FONT][/FONT]
    

    Thanks!

    --Bill
    ps Is there a way to avoid the "X" on an attached file? It's ugly. Additionally, my code listing is proportionately spaced. How do I fix it?
    You are what you write.
  • SXleeSXlee Posts: 47
    edited 2011-02-01 - 03:08:23
    In the SX/B help search for SEROUT look at the READ Example.

    Main: TX_STR "SX/B makes string output easy!" ' send inline string TX_STR CrLf ' send stored z-string TX_STR TestStr, 14 ' sub-string TX_STR CrLf TX_STR TestStr, 13, 16 ' sub-string at offset TX_STR CrLf TX_STR TestStr, 8, 31 TX_STR Version TX_STR CrLf TX_BYTE LF, 2 ' ========================================================================= ' User Data ' ========================================================================= TestStr: DATA "Parallax, Inc. SX/B Compiler Version 1.50", 0 Version: DATA "1.50", 0 CrLf: DATA CR, LF, 0 [/Code] Is this what you're looking for? [Code] ' ------------------------------------------------------------------------- ' Subroutine Declarations ' ------------------------------------------------------------------------- TX_BYTE SUB 1, 2 ' transmit byte TX_STR SUB 2, 4 ' transmit string ' ------------------------------------------------------------------------- ' Program Code ' ------------------------------------------------------------------------- ' ------------------------------------------------------------------------- ' Subroutine Code ' ------------------------------------------------------------------------- ' Use: TX_BYTE theByte {, count} ' -- transmit "theByte" at "Baud" on "SOut" ' -- optional "count" may be specified (must be > 0) SUB TX_BYTE tmpB1 = __PARAM1 ' save byte IF __PARAMCNT = 1 THEN ' if no count tmpB2 = 1 ' set to 1 ELSE ' otherwise tmpB2 = __PARAM2 ' get count IF tmpB2 = 0 THEN ' do not allow 0 tmpB2 = 1 ENDIF ENDIF DO WHILE tmpB2 > 0 ' loop through count SEROUT SOut, Baud, tmpB1 ' send the byte DEC tmpB2 ' decrement count LOOP ENDSUB ' ------------------------------------------------------------------------- ' Use: TX_STR [string | label] {, count {, offset }} ' -- "string" is an embedded string constant ' -- "label" is DATA statement label for stored z-String ' -- "count" is number of characters to send (0 is entire string) ' -- "offset" is offset from head of string (0 is head) SUB TX_STR tmpW1 = __WPARAM12 ' get offset+base tmpB3 = 0 ' do whole string IF __PARAMCNT >= 3 THEN ' count specified? tmpB3 = __PARAM3 ' -- yes, get count ENDIF IF __PARAMCNT = 4 THEN ' offset specified? tmpW1 = tmpW1 + __PARAM4 ' -- yes, update it ENDIF DO READ tmpW1, tmpB4 ' read a character IF tmpB4 = 0 THEN EXIT ' if 0, string complete TX_BYTE tmpB4 ' send character DEC tmpB3 ' update count IF tmpB3 = 0 THEN EXIT ' terminate if done INC tmpW1 ' point to next character LOOP ENDSUB [/Code] Can not see an "X" on you attached file. Try (Code)(/Code) not (CODE)(/CODE). hope it helps[Code]
    Main:
    TX_STR "SX/B makes string output easy!" ' send inline string
    TX_STR CrLf ' send stored z-string
    TX_STR TestStr, 14 ' sub-string
    TX_STR CrLf
    TX_STR TestStr, 13, 16 ' sub-string at offset
    TX_STR CrLf
    TX_STR TestStr, 8, 31
    TX_STR Version
    TX_STR CrLf
    TX_BYTE LF, 2

    ' =========================================================================
    ' User Data
    ' =========================================================================

    TestStr:
    DATA "Parallax, Inc. SX/B Compiler Version 1.50", 0

    Version:
    DATA "1.50", 0

    CrLf:
    DATA CR, LF, 0
    [/Code]
    Is this what you're looking for?
    ' ------------------------------------------------------------------------- ' Subroutine Declarations ' ------------------------------------------------------------------------- TX_BYTE SUB 1, 2 ' transmit byte TX_STR SUB 2, 4 ' transmit string ' ------------------------------------------------------------------------- ' Program Code ' ------------------------------------------------------------------------- ' ------------------------------------------------------------------------- ' Subroutine Code ' ------------------------------------------------------------------------- ' Use: TX_BYTE theByte {, count} ' -- transmit "theByte" at "Baud" on "SOut" ' -- optional "count" may be specified (must be > 0) SUB TX_BYTE tmpB1 = __PARAM1 ' save byte IF __PARAMCNT = 1 THEN ' if no count tmpB2 = 1 ' set to 1 ELSE ' otherwise tmpB2 = __PARAM2 ' get count IF tmpB2 = 0 THEN ' do not allow 0 tmpB2 = 1 ENDIF ENDIF DO WHILE tmpB2 > 0 ' loop through count SEROUT SOut, Baud, tmpB1 ' send the byte DEC tmpB2 ' decrement count LOOP ENDSUB ' ------------------------------------------------------------------------- ' Use: TX_STR [string | label] {, count {, offset }} ' -- "string" is an embedded string constant ' -- "label" is DATA statement label for stored z-String ' -- "count" is number of characters to send (0 is entire string) ' -- "offset" is offset from head of string (0 is head) SUB TX_STR tmpW1 = __WPARAM12 ' get offset+base tmpB3 = 0 ' do whole string IF __PARAMCNT >= 3 THEN ' count specified? tmpB3 = __PARAM3 ' -- yes, get count ENDIF IF __PARAMCNT = 4 THEN ' offset specified? tmpW1 = tmpW1 + __PARAM4 ' -- yes, update it ENDIF DO READ tmpW1, tmpB4 ' read a character IF tmpB4 = 0 THEN EXIT ' if 0, string complete TX_BYTE tmpB4 ' send character DEC tmpB3 ' update count IF tmpB3 = 0 THEN EXIT ' terminate if done INC tmpW1 ' point to next character LOOP ENDSUB [/Code] Can not see an "X" on you attached file. Try (Code)(/Code) not (CODE)(/CODE). hope it helps[Code]
    '
    ' Subroutine Declarations
    '

    TX_BYTE SUB 1, 2 ' transmit byte
    TX_STR SUB 2, 4 ' transmit string



    '
    ' Program Code
    '

    '
    ' Subroutine Code
    '

    ' Use: TX_BYTE theByte {, count}
    ' -- transmit "theByte" at "Baud" on "SOut"
    ' -- optional "count" may be specified (must be > 0)

    SUB TX_BYTE
    tmpB1 = __PARAM1 ' save byte
    IF __PARAMCNT = 1 THEN ' if no count
    tmpB2 = 1 ' set to 1
    ELSE ' otherwise
    tmpB2 = __PARAM2 ' get count
    IF tmpB2 = 0 THEN ' do not allow 0
    tmpB2 = 1
    ENDIF
    ENDIF
    DO WHILE tmpB2 > 0 ' loop through count
    SEROUT SOut, Baud, tmpB1 ' send the byte
    DEC tmpB2 ' decrement count
    LOOP
    ENDSUB
    '

    ' Use: TX_STR [string | label] {, count {, offset }}
    ' -- "string" is an embedded string constant
    ' -- "label" is DATA statement label for stored z-String
    ' -- "count" is number of characters to send (0 is entire string)
    ' -- "offset" is offset from head of string (0 is head)

    SUB TX_STR
    tmpW1 = __WPARAM12 ' get offset+base
    tmpB3 = 0 ' do whole string
    IF __PARAMCNT >= 3 THEN ' count specified?
    tmpB3 = __PARAM3 ' -- yes, get count
    ENDIF
    IF __PARAMCNT = 4 THEN ' offset specified?
    tmpW1 = tmpW1 + __PARAM4 ' -- yes, update it
    ENDIF
    DO
    READ tmpW1, tmpB4 ' read a character
    IF tmpB4 = 0 THEN EXIT ' if 0, string complete
    TX_BYTE tmpB4 ' send character
    DEC tmpB3 ' update count
    IF tmpB3 = 0 THEN EXIT ' terminate if done
    INC tmpW1 ' point to next character
    LOOP
    ENDSUB


    [/Code]
    Can not see an "X" on you attached file.
    Try (Code)(/Code) not (CODE)(/CODE).


    hope it helps
  • ZootZoot Posts: 2,226
    edited 2011-02-01 - 07:49:58
    Bill -- the TX_STR routine in the code sxlee posted is what you want (you may need to declare some extra variables). Note that it "reads" a character at a time, including "embedded strings". What's an embedded string? It's in the code, not in the data, and if you pass that "string" as a parameter to a routine, what is passed in the parameter is not a character, nor the string, but rather the "internal" address in codespace where the string starts. SX/B will automatically terminate such a string with a 0.

    I'm not sure I would use a version with an optional "count" param if you don't need it.

    In any case, in the example above:

    TX_STR "SX/B makes string output easy!" 
    
    

    Is "like" having data that reads like the following, and the address of the data is automatically passed by TX_STR:
    DATA "SX/B makes string output easy!",0
    
    

    So both of the following are functionally identical:
    TX_STR "SX/B makes string output easy!" 
    
    TX_STR SomeData
    SomeData:
    DATA "SX/B makes string output easy!",0
    

    For your project I would do the strings as data statements, because then you can use the address for whatever clip you want to play (use a lookup statement or if/then, etc) and have the appropriate string fed out.

    One comment, however, about your posted code that I don't quite get -- you "GOTO Start". I do not recommend this. The automatically inserted code that comes after "Start" in SX/B is initialization code that configures pins, clears memory, etc. Generally, you want a structure more like this:
    Start:
      ' automatically inserted init code, plus your own "startup" code
      someVar = 0
      someOtherVar = $FF
    
    Main: ' your main loop so that init code doesn't run every time
    
      ' do some stuff
      ' do more stuff
    
      GOTO Main
    
    '----- subroutines
    
    '---- data
    
    
    When the going gets weird, the weird turn pro. -- HST

    my site: 1uffakind.com
    create bitmap data tool: 1uffakind.com/robots/povBitMapBuilder.php
    resistor ladder tool: 1uffakind.com/robots/resistorLadder.php
    convert images to ascii art: 1uffakind.com/apptoys/convtoascii/
    MC6808/Hero-1 assembler: 1uffakind.com/apptoys/onlinecompilers/MC6800/
  • Bill ChennaultBill Chennault Posts: 1,198
    edited 2011-02-01 - 08:32:56
    SXlee and Zoot--

    I am studying your suggestions, now. Thank you for helping me.

    This is the first time I have used DATA statements in SX/B. They kinda remind me of cutting assembly code on an 8080. But, that was a LONG time ago and I wish I could remember more of it!

    We are right on the northern edge of the big storm in the mid-west. It is headed north and east. It looks like it will hammer KC. Sure is pretty, though. However, the view of the golf course is disappearing as the snow falls harder and harder . . .

    --Bill
    You are what you write.
  • Bill ChennaultBill Chennault Posts: 1,198
    edited 2011-02-01 - 09:14:54
    Zoot--

    I neglected to add that I will stick 'Main:' back in! I took it out because I FORGOT its importance and wanted to save listing space in my posted code segment. :)

    --Bill
    You are what you write.
  • SXleeSXlee Posts: 47
    edited 2011-02-01 - 11:52:46
    Bill, did you find the example?
  • Bill ChennaultBill Chennault Posts: 1,198
    edited 2011-02-01 - 17:34:50
    SXlee--

    I studied your examples. Is there another example which you think would help me?

    Progress is being made; I am successfully using DATA statements. I am not quite ready to beg for help. :)

    If there is another example, let me know where to begin my search.

    Thanks!

    --Bill
    You are what you write.
  • SXleeSXlee Posts: 47
    edited 2011-02-02 - 04:12:19
    Hi Bill,
    they are not my examples.
    I got the example In the SX/B help, (SX-Key Editors / "SX/B Help")
    I search for "SEROUT",
    and got the "READ Example", and posted some of it here for you.

    A good place to begin your search is the (SX-Key Editors / "SX/B Help"), there's a lot of good stuff in there.


    For you or anyone that don't have the same version of the "SX/B Help" or can not fined the "READ example",
    here it is:
    ' ------------------------------------------------------------------------- ' Program Description ' ------------------------------------------------------------------------- ' ' This program demonstrates the use of strings in an SX/B program. As of ' version 1.4, the SX/B READ instruction can accept a variable base and ' offset. These values may be created by the compiler by specifying the ' label of a stored z-string, or by using an inline string constant. ' ' The subroutine TX_STR accepts the base and offset values of a stored or ' inline string and will transmit them to a connected terminal -- the ' construction of the subroutine allows the string to cross SX page ' boundaries. ' ------------------------------------------------------------------------- ' Device Settings ' ------------------------------------------------------------------------- DEVICE SX28, OSCXT2, TURBO, STACKX, OPTIONX FREQ 4_000_000 ID "READ_STR" ' ------------------------------------------------------------------------- ' IO Pins ' ------------------------------------------------------------------------- SOut PIN RA.0 OUTPUT ' serial output ' ------------------------------------------------------------------------- ' Constants ' ------------------------------------------------------------------------- Baud CON "T9600" ' use with MAX232/USB2SER CR CON 13 ' carriage return LF CON 10 ' line feed ' ------------------------------------------------------------------------- ' Variables ' ------------------------------------------------------------------------- tmpB1 VAR Byte ' subroutine work vars tmpB2 VAR Byte tmpB3 VAR Byte tmpB4 VAR Byte tmpW1 VAR Word ' ========================================================================= PROGRAM Start ' ========================================================================= ' ------------------------------------------------------------------------- ' Subroutine Declarations ' ------------------------------------------------------------------------- TX_BYTE SUB 1, 2 ' transmit byte TX_STR SUB 2, 4 ' transmit string ' ------------------------------------------------------------------------- ' Program Code ' ------------------------------------------------------------------------- Start: PLP_A = %0001 ' pull-up unused pins PLP_B = %00000000 PLP_C = %00000000 Main: TX_STR "SX/B makes string output easy!" ' send inline string TX_STR CrLf ' send stored z-string TX_STR TestStr, 14 ' sub-string TX_STR CrLf TX_STR TestStr, 13, 16 ' sub-string at offset TX_STR CrLf TX_STR TestStr, 8, 31 TX_STR Version TX_STR CrLf TX_BYTE LF, 2 PAUSE 1000 GOTO Main ' ------------------------------------------------------------------------- ' Subroutine Code ' ------------------------------------------------------------------------- ' Use: TX_BYTE theByte {, count} ' -- transmit "theByte" at "Baud" on "SOut" ' -- optional "count" may be specified (must be > 0) SUB TX_BYTE tmpB1 = __PARAM1 ' save byte IF __PARAMCNT = 1 THEN ' if no count tmpB2 = 1 ' set to 1 ELSE ' otherwise tmpB2 = __PARAM2 ' get count IF tmpB2 = 0 THEN ' do not allow 0 tmpB2 = 1 ENDIF ENDIF DO WHILE tmpB2 > 0 ' loop through count SEROUT SOut, Baud, tmpB1 ' send the byte DEC tmpB2 ' decrement count LOOP ENDSUB ' ------------------------------------------------------------------------- ' Use: TX_STR [string | label] {, count {, offset }} ' -- "string" is an embedded string constant ' -- "label" is DATA statement label for stored z-String ' -- "count" is number of characters to send (0 is entire string) ' -- "offset" is offset from head of string (0 is head) SUB TX_STR tmpW1 = __WPARAM12 ' get offset+base tmpB3 = 0 ' do whole string IF __PARAMCNT >= 3 THEN ' count specified? tmpB3 = __PARAM3 ' -- yes, get count ENDIF IF __PARAMCNT = 4 THEN ' offset specified? tmpW1 = tmpW1 + __PARAM4 ' -- yes, update it ENDIF DO READ tmpW1, tmpB4 ' read a character IF tmpB4 = 0 THEN EXIT ' if 0, string complete TX_BYTE tmpB4 ' send character DEC tmpB3 ' update count IF tmpB3 = 0 THEN EXIT ' terminate if done INC tmpW1 ' point to next character LOOP ENDSUB ' ========================================================================= ' User Data ' ========================================================================= TestStr: DATA "Parallax, Inc. SX/B Compiler Version 1.50", 0 Version: DATA "1.50", 0 CrLf: DATA CR, LF, 0 [/Code][Code]
    '
    ' Program Description
    '
    '
    ' This program demonstrates the use of strings in an SX/B program. As of
    ' version 1.4, the SX/B READ instruction can accept a variable base and
    ' offset. These values may be created by the compiler by specifying the
    ' label of a stored z-string, or by using an inline string constant.
    '
    ' The subroutine TX_STR accepts the base and offset values of a stored or
    ' inline string and will transmit them to a connected terminal -- the
    ' construction of the subroutine allows the string to cross SX page
    ' boundaries.

    '
    ' Device Settings
    '

    DEVICE SX28, OSCXT2, TURBO, STACKX, OPTIONX
    FREQ 4_000_000
    ID "READ_STR"

    '
    ' IO Pins
    '

    SOut PIN RA.0 OUTPUT ' serial output

    '
    ' Constants
    '

    Baud CON "T9600" ' use with MAX232/USB2SER
    CR CON 13 ' carriage return
    LF CON 10 ' line feed

    '
    ' Variables
    '

    tmpB1 VAR Byte ' subroutine work vars
    tmpB2 VAR Byte
    tmpB3 VAR Byte
    tmpB4 VAR Byte
    tmpW1 VAR Word

    ' =========================================================================
    PROGRAM Start
    ' =========================================================================

    '
    ' Subroutine Declarations
    '

    TX_BYTE SUB 1, 2 ' transmit byte
    TX_STR SUB 2, 4 ' transmit string

    '
    ' Program Code
    '

    Start:
    PLP_A = %0001 ' pull-up unused pins
    PLP_B = %00000000
    PLP_C = %00000000

    Main:
    TX_STR "SX/B makes string output easy!" ' send inline string
    TX_STR CrLf ' send stored z-string
    TX_STR TestStr, 14 ' sub-string
    TX_STR CrLf
    TX_STR TestStr, 13, 16 ' sub-string at offset
    TX_STR CrLf
    TX_STR TestStr, 8, 31
    TX_STR Version
    TX_STR CrLf
    TX_BYTE LF, 2
    PAUSE 1000
    GOTO Main

    '
    ' Subroutine Code
    '

    ' Use: TX_BYTE theByte {, count}
    ' -- transmit "theByte" at "Baud" on "SOut"
    ' -- optional "count" may be specified (must be > 0)

    SUB TX_BYTE
    tmpB1 = __PARAM1 ' save byte
    IF __PARAMCNT = 1 THEN ' if no count
    tmpB2 = 1 ' set to 1
    ELSE ' otherwise
    tmpB2 = __PARAM2 ' get count
    IF tmpB2 = 0 THEN ' do not allow 0
    tmpB2 = 1
    ENDIF
    ENDIF
    DO WHILE tmpB2 > 0 ' loop through count
    SEROUT SOut, Baud, tmpB1 ' send the byte
    DEC tmpB2 ' decrement count
    LOOP
    ENDSUB
    '

    ' Use: TX_STR [string | label] {, count {, offset }}
    ' -- "string" is an embedded string constant
    ' -- "label" is DATA statement label for stored z-String
    ' -- "count" is number of characters to send (0 is entire string)
    ' -- "offset" is offset from head of string (0 is head)

    SUB TX_STR
    tmpW1 = __WPARAM12 ' get offset+base
    tmpB3 = 0 ' do whole string
    IF __PARAMCNT >= 3 THEN ' count specified?
    tmpB3 = __PARAM3 ' -- yes, get count
    ENDIF
    IF __PARAMCNT = 4 THEN ' offset specified?
    tmpW1 = tmpW1 + __PARAM4 ' -- yes, update it
    ENDIF
    DO
    READ tmpW1, tmpB4 ' read a character
    IF tmpB4 = 0 THEN EXIT ' if 0, string complete
    TX_BYTE tmpB4 ' send character
    DEC tmpB3 ' update count
    IF tmpB3 = 0 THEN EXIT ' terminate if done
    INC tmpW1 ' point to next character
    LOOP
    ENDSUB

    ' =========================================================================
    ' User Data
    ' =========================================================================

    TestStr:
    DATA "Parallax, Inc. SX/B Compiler Version 1.50", 0

    Version:
    DATA "1.50", 0

    CrLf:
    DATA CR, LF, 0
    [/Code]
  • Bill ChennaultBill Chennault Posts: 1,198
    edited 2011-02-02 - 08:38:42
    SXlee (and All)--

    I've studied that example. It is a good example of using the READ/DATA statements. But, what I am trying to do is slightly more complex. (At least, it is to me!)

    What I would like to do--or rather what my "mission" has morphed into--is READ multiple, 0-terminated strings, like this . . .
    [FONT=Courier New]Data_Area:[/FONT]
    [FONT=Courier New]data "this is a string", 0[/FONT]
    [FONT=Courier New]data "Here is another example", 0[/FONT]
    [FONT=Courier New]data "I would like to read multiple DATA strings", 0[/FONT]
    

    The current problem concerns my inability to address the second string. I can read the first string a byte at a time. However, I cannot read the next string. I have a byte-sized offset variable that points to the first and then successive bytes in the string. It works well until the second string at which point it SEEMS to be reset to 0, thus making READ string+offset re-read the first string beginning with byte 0. This is all in a loop which tests the current character for 0 (not "0"), calls a sub-routine which performs SEROUT, and increments the offset variable. (I seem to lose the value of the offset variable after the loop is exited upon reading 0.)

    I'm still testing. I sure appreciate you watching this thread. There are a few more things I need to pin down/clean up in my code before I can ask intelligent (for me, anyway) questions.

    Maybe by just WRITING this it will cause me to think about what I am doing wrong. We'll see.

    --Bill
    You are what you write.
  • ZootZoot Posts: 2,226
    edited 2011-02-02 - 09:06:46
    Bill -- seriously, post your whole program, preferably as an attachment, so we can see all the pieces.

    For addressing multiple strings, remember that the start address of each needs to be referenced OR you need to make sure all strings are the exact same length. In the case of wav files on an SD card, I would go with the latter, and give all my wavs 14 character filenames including the .wav -- this would give me "blocks" of string datasets that are all 16 characerters (14 characters for the filename + 1 CR + 1 "zero" terminator. Then I could call each string to send by using a number from 0-x and multiplying by 16 to get the address, e.g.
    addr VAR Word
    char VAR Byte
    tmpB1 VAR Byte
    tmpB2 VAR Byte
    
    FOR tmpB1 = $0 TO $2 ' I only have 3 data strings below
       tmpB2 = tmpB1
       SWAP tmpB2 ' move low nib to high nib as these are 16 byte blocks
    do_again:
       READ file_names + tmpB2, char
       SER_OUT char
       INC tmpB2
       IF tmpB2 < 16 THEN do_again ' and this line, but both work as checks
       IF char <> 0 THEN do_again ' you don't need both this line
    NEXT
    
    ' technically, with known block sizes you do NOT need the 0 terminator, which would free up a byte filename characters. 
    ' you also could dispense with the CR and just run that as part of the main code that sends the string (since your peripheral
    ' always requires the CR, you don't really need to code it into data.
    
    file_names:
    DATA "file567890.wav", CR, 0 '  @file_names + $00
    DATA "file567890.wav", CR, 0 '  @file_names + $10
    DATA "file567890.wav", CR, 0 '  @file_names + $20
    ' etc
    
    

    Now, if you want variable length strings, that's fine, but you need an extra step where you have a table that is the addresses....then you read the "address" by an index number (like above) then load a read address with the "read" address of the start of the string.
    When the going gets weird, the weird turn pro. -- HST

    my site: 1uffakind.com
    create bitmap data tool: 1uffakind.com/robots/povBitMapBuilder.php
    resistor ladder tool: 1uffakind.com/robots/resistorLadder.php
    convert images to ascii art: 1uffakind.com/apptoys/convtoascii/
    MC6808/Hero-1 assembler: 1uffakind.com/apptoys/onlinecompilers/MC6800/
  • Bill ChennaultBill Chennault Posts: 1,198
    edited 2011-02-02 - 09:46:29
    Zoot--

    I wonder if my concept of referencing the start address of each string is incorrect? Assumption #1: I THOUGHT all I had to do was reference the start address of the 0 byte of the first string and then add an offset for each ensuing byte of the ENTIRE DATA "block." My included code illustrates my take on this.

    The AP-16+ is an 8.3 machine. So, couldn't I just use a byte variable to point to the next character as long as the total number of characters <= 255 (and Assumption #1 is also correct)?

    If Assumption #1 is incorrect, then we have found my error. The following listing is simple, really. Especially since it has been seen before as posted by the real authors from whom I stole, merged and then mangled it.
    [FONT=Courier New]DEVICE   SX48, OSCHS1[/FONT]
    [FONT=Courier New]FREQ   20_000_000[/FONT]
    [FONT=Courier New]SIO             PIN     RE.7 OUTPUT             ' no ULN, SETUP = UP[/FONT]
    [FONT=Courier New]' -----[ Constants ]-------------------------------------------------------[/FONT]
    [FONT=Courier New]Addr            CON     %0                      ' both address jumpers out[/FONT]
    [FONT=Courier New]CR  CON 13[/FONT]
    [FONT=Courier New]' -----[ Variables ]-------------------------------------------------------[/FONT]
    [FONT=Courier New]tmpB1  VAR BYTE[/FONT]
    [FONT=Courier New]tmpB2   VAR  Byte[/FONT]
    [FONT=Courier New]idx  VAR Byte[/FONT]
    [FONT=Courier New]char  VAR Byte[/FONT]
    [FONT=Courier New]AP_Status VAR Byte[/FONT]
    [FONT=Courier New]Playing        VAR     AP_Status.7            ' 0 = idle, 1 = playing[/FONT]
    [FONT=Courier New]' -----[ Declare Sub-routines ]--------------------------------------------[/FONT]
    [FONT=Courier New]SER_OUT  SUB  1                    ' send a byte via serial[/FONT]
    [FONT=Courier New]GET_Status SUB 1[/FONT]
    [FONT=Courier New]Verify_Play SUB 0[/FONT]
    [FONT=Courier New]' =========================================================================[/FONT]
    [FONT=Courier New]PROGRAM Start[/FONT]
    [FONT=Courier New]' =========================================================================[/FONT]
    [FONT=Courier New]Start:[/FONT]
    [FONT=Courier New]' -------------------------------------------------------------------------[/FONT]
    [FONT=Courier New]' Program Code[/FONT]
    [FONT=Courier New]' -------------------------------------------------------------------------[/FONT]
    [FONT=Courier New]Main:[/FONT]
    [FONT=Courier New]idx = 0[/FONT]
    [FONT=Courier New]ReEnter:[/FONT]
    [FONT=Courier New]' send reset . . .[/FONT]
    [FONT=Courier New]SER_OUT "!"[/FONT]
    [FONT=Courier New]SER_OUT "A"[/FONT]
    [FONT=Courier New]SER_OUT "P"[/FONT]
    [FONT=Courier New]SER_OUT "1"[/FONT]
    [FONT=Courier New]SER_OUT "6"[/FONT]
    [FONT=Courier New]SER_OUT Addr[/FONT]
    [FONT=Courier New]SER_OUT "P"[/FONT]
    [FONT=Courier New]SER_OUT "W"[/FONT]
    [FONT=Courier New]SER_OUT "X"[/FONT]
    [FONT=Courier New]SER_OUT CR[/FONT]
    [FONT=Courier New]SER_OUT 1[/FONT]
    [FONT=Courier New]pause 500[/FONT]
    [FONT=Courier New]' send preamble . . .[/FONT]
    [FONT=Courier New]SER_OUT "!"[/FONT]
    [FONT=Courier New]SER_OUT "A"[/FONT]
    [FONT=Courier New]SER_OUT "P"[/FONT]
    [FONT=Courier New]SER_OUT "1"[/FONT]
    [FONT=Courier New]SER_OUT "6"[/FONT]
    [FONT=Courier New]SER_OUT Addr[/FONT]
    [FONT=Courier New]SER_OUT "P"[/FONT]
    [FONT=Courier New]SER_OUT "W"[/FONT]
    [FONT=Courier New]'**************************************************************************[/FONT]
    [FONT=Courier New]' send filename . . . this is the piece of code I am trying to make work[/FONT]
    [FONT=Courier New]' currently, it will only read the the first data statement[/FONT]
    [FONT=Courier New]do[/FONT]
    [FONT=Courier New]read filename + idx, char' read a character at filename+idx[/FONT]
    [FONT=Courier New]if char = 0 then exit'     if char 0, then exit do loop[/FONT]
    [FONT=Courier New]SER_OUT char'              output the character[/FONT]
    [FONT=Courier New]inc idx'                   increment pointer idx[/FONT]
    [FONT=Courier New]loop[/FONT]
    [FONT=Courier New]SER_OUT CR[/FONT]
    [FONT=Courier New]SER_OUT 1[/FONT]
    [FONT=Courier New]'**************************************************************************[/FONT]
    [FONT=Courier New]Verify_Play[/FONT]
    [FONT=Courier New]pause 500[/FONT]
    [FONT=Courier New]goto ReEnter[/FONT]
    [FONT=Courier New]'************ DATA ********************************************************[/FONT]
    [FONT=Courier New]filename:[/FONT]
    [FONT=Courier New]data "sfx00", 0[/FONT]
    [FONT=Courier New]data "sfx02", 0[/FONT]
    [FONT=Courier New]'************ Subroutines**************************************************[/FONT]
    [FONT=Courier New]' -------------------------------------------------------------------------[/FONT]
    [FONT=Courier New]SUB SER_OUT[/FONT]
    [FONT=Courier New]tmpB1 = __PARAM1 ' stash the value to serout[/FONT]
    [FONT=Courier New]SEROUT SIO, OT38400, tmpB1[/FONT]
    [FONT=Courier New]ENDSUB[/FONT]
    [FONT=Courier New]' -------------------------------------------------------------------------[/FONT]
    [FONT=Courier New]SUB Get_Status[/FONT]
    [FONT=Courier New]pause 50[/FONT]
    [FONT=Courier New]SER_OUT "!"[/FONT]
    [FONT=Courier New]SER_OUT "A"[/FONT]
    [FONT=Courier New]SER_OUT "P"[/FONT]
    [FONT=Courier New]SER_OUT "1"[/FONT]
    [FONT=Courier New]SER_OUT "6"[/FONT]
    [FONT=Courier New]SER_OUT Addr[/FONT]
    [FONT=Courier New]SER_OUT "G"[/FONT]
    [FONT=Courier New]serin SIO, OT38400, AP_Status[/FONT]
    [FONT=Courier New]endsub[/FONT]
    [FONT=Courier New]' -------------------------------------------------------------------------[/FONT]
    [FONT=Courier New]SUB Verify_Play[/FONT]
    [FONT=Courier New]Get_Status 0[/FONT]
    [FONT=Courier New]if Playing then[/FONT]
    [FONT=Courier New]do[/FONT]
    [FONT=Courier New]pause 25[/FONT]
    [FONT=Courier New]Get_Status 0[/FONT]
    [FONT=Courier New]loop until Playing = 0[/FONT]
    [FONT=Courier New]endif[/FONT]
    [FONT=Courier New]endsub[/FONT]  
    

    --Bill
    You are what you write.
  • ZootZoot Posts: 2,226
    edited 2011-02-02 - 10:52:27
    Yes, what you have should work. If you want to just "set and forget" the "pointer" to the character in your data lists, then you can also use a Word and no offset and just keep the full address handy for your routine. This would let you do more than 256 bytes worth, if your list grows.
    When the going gets weird, the weird turn pro. -- HST

    my site: 1uffakind.com
    create bitmap data tool: 1uffakind.com/robots/povBitMapBuilder.php
    resistor ladder tool: 1uffakind.com/robots/resistorLadder.php
    convert images to ascii art: 1uffakind.com/apptoys/convtoascii/
    MC6808/Hero-1 assembler: 1uffakind.com/apptoys/onlinecompilers/MC6800/
  • Bill ChennaultBill Chennault Posts: 1,198
    edited 2011-02-02 - 15:45:55
    Zoot and SXlee and All--

    I struggled with the code some more to no avail. The listing above is still my "best" effort.

    In execution, the AP-16+ plays "sfx00" 13 times. It never plays the next file, "sfx02". Perhaps, I am handling the AP-16+ incorrectly. Maybe JonnyMac might chime in. He already labored to overcome a previous stupido on my part with the AP-16+.

    I should add that the AP-16+ Stamp Demo code works fine for me using either a BS2 or a BS2p40.

    --Bill
    You are what you write.
  • ZootZoot Posts: 2,226
    edited 2011-02-02 - 16:24:00
    See attached.

    For one, I moved the AP16 reset stuff into the start section, so it only runs once. You can change it when/if everything else works, but I don't think you need to send that every time.

    Then I found the bug -- sorry I should've seen this earlier. Your do...read...ser_out...loop increments idx (read offset variable) AFTER the exit is evaluated, so on the final char (0), it will be in the wrong spot next time around and will just keep exiting.

    If you still have problems, definitely check simple stuff -- correct oscillator and feedback (parallel) resistor across osc1 and osc2, etc. You could also try communicating with the AP16 at 2400 baud, get it working, then try higher baud.
    When the going gets weird, the weird turn pro. -- HST

    my site: 1uffakind.com
    create bitmap data tool: 1uffakind.com/robots/povBitMapBuilder.php
    resistor ladder tool: 1uffakind.com/robots/resistorLadder.php
    convert images to ascii art: 1uffakind.com/apptoys/convtoascii/
    MC6808/Hero-1 assembler: 1uffakind.com/apptoys/onlinecompilers/MC6800/
  • SXleeSXlee Posts: 47
    edited 2011-02-03 - 03:21:00
    Hi Bill,
    In execution, the AP-16+ plays "sfx00" 13 times. It never plays the next file, "sfx02".

    if char = 0 then exit' if char 0, then exit do loop [/Code] [Code] filename: data "sfx00", 0 '( the output will be "sfx" if send no "0" ) data "sfx02", 0 '( the output will be "sfx" if send no "0" and exit ) data "sfx102", 0 '( the output will be "sfx1" if send no "0" and exit ) [/Code] So it mast play "sfx" 13 times.[Code]
    if char = 0 then exit' if char 0, then exit do loop
    [/Code]
    filename: data "sfx00", 0 '( the output will be "sfx" if send no "0" ) data "sfx02", 0 '( the output will be "sfx" if send no "0" and exit ) data "sfx102", 0 '( the output will be "sfx1" if send no "0" and exit ) [/Code] So it mast play "sfx" 13 times.[Code]
    filename:
    data "sfx00", 0 '( the output will be "sfx" if send no "0" )
    data "sfx02", 0 '( the output will be "sfx" if send no "0" and exit )
    data "sfx102", 0 '( the output will be "sfx1" if send no "0" and exit )
    [/Code]
    So it mast play "sfx" 13 times.
  • Shawn LoweShawn Lowe Posts: 601
    edited 2011-02-03 - 07:29:59
    You know, Bill, I don't see any demo code on EFX-TEK for a Prop-SX. Perhaps you might want to post on their forums to see what Jon suggests to do to handle the EOL character issue.
  • Bill ChennaultBill Chennault Posts: 1,198
    edited 2011-02-03 - 10:44:05
    Zoot and SXlee and Shawn Lowe--

    Thank you all for helping me! :) Now, I can move on to the overall project.

    Zoot, it works perfectly now, as you know! (I was close, but "close" doesn't cut it in this game.)

    I appreciate all the time all of you spent thinking about this for me.

    --Bill
    You are what you write.
  • ZootZoot Posts: 2,226
    edited 2011-02-03 - 10:45:56
    Cool beans!

    P.S.
    data "sfx00", 0 '( the output will be "sfx" if send no "0" )

    The "0" in "sfx00" is not 0 binary (i.e. it is not %0000_0000), it is ASCII character "0". Check your ASCII chart. This is why 0 term strings work -- the 0 index position in ASCII is not a "character" in the sense of "0-9" or "abc".
    When the going gets weird, the weird turn pro. -- HST

    my site: 1uffakind.com
    create bitmap data tool: 1uffakind.com/robots/povBitMapBuilder.php
    resistor ladder tool: 1uffakind.com/robots/resistorLadder.php
    convert images to ascii art: 1uffakind.com/apptoys/convtoascii/
    MC6808/Hero-1 assembler: 1uffakind.com/apptoys/onlinecompilers/MC6800/
  • Shawn LoweShawn Lowe Posts: 601
    edited 2011-02-03 - 12:06:57
    Zoot wrote: »
    Cool beans!

    P.S.



    The "0" in "sfx00" is not 0 binary (i.e. it is not %0000_0000), it is ASCII character "0". Check your ASCII chart. This is why 0 term strings work -- the 0 index position in ASCII is not a "character" in the sense of "0-9" or "abc".
    Ahhhh, OK! Helps with my confusion, thanks!
Sign In or Register to comment.