PNut/Spin2 Latest Version (v34z - Lots of DEBUG display stuff)

191012141534

Comments

  • Instead of using $1E0+, use $1D8..$1DF. The $1E0+ registers get overwritten by the interpreter, while the others are untouched.
  • Cluso99Cluso99 Posts: 16,660
    edited 2020-04-13 - 09:31:22
    cgracey wrote: »
    Instead of using $1E0+, use $1D8..$1DF. The $1E0+ registers get overwritten by the interpreter, while the others are untouched.
    Ouch! This is what I asked originally a few posts ago.

    This means the ROM Monitor/Debugger is not usable from spin2 as they use $1E0-$1EF :(

    Also we cannot use the ROM SD routines either as they use $1C0-$1DF :(

    Otherwise, all those routines that are all callable by user programs - print char(s), hex, dump cog/lut/hub in formatted columns, load cog/lut/hub, read char, and read string from the serial port, but can be intercepted at a single common read and a single common write hub instruction, and calling the monitor itself, are all not usable from spin.
    '' +--------------------------------------------------------------------------+
    '' | Cluso's LMM_SerialDebugger for P2    (c)2013-2018 "Cluso99" (Ray Rodrick)|
    '' +--------------------------------------------------------------------------+
    ''  xxxxxx : xx xx xx xx ... <cr>  DOWNLOAD:  to cog/lut/hub {addr1} following {byte(s)}
    ''  xxxxxx - [xxxxxx] [L] <cr>     LIST:      from cog/lut/hub {addr1} to < {addr2} L=longs
    ''  xxxxxx G <cr>                  GOTO:      to cog/lut/hub {addr1}
    ''  Q <cr>                         QUIT:      Quit Rom Monitor and return to the User Program
    ''  Lffffffff[.]xxx<cr>            LOAD:      Load file from SD
    ''  Rffffffff[.]xxx<cr>            RUN:       Load & Run file from SD
    ''  <esc><cr>                      TAQOZ:     goto TAQOZ
    '' +--------------------------------------------------------------------------+
    ''   LMM DEBUGGER - CALL Modes...(not all modes supported)
    '' +--------------------------------------------------------------------------+
      _MODE         = $F << 5                       ' mode bits defining the call b8..b5 (b4..b0 are modifier options)
      _SHIFT        = 5                             ' shr # to extract mode bits
      _HEX_         = 2 << 5                        ' hex...
        _REV_               = 1 << 4                '   - reverse byte order
        _SP                 = 1 << 3                '   - space between hex output pairs
       '_DIGITS             = 7..0 where 8->0       '   - no. of digits to display
      _LIST         = 3 << 5                        ' LIST memory line (1/4 longs) from cog/hub
        _ADDR2              = 1 << 4                ' 1= use lmm_p2 as to-address
        _LONG_              = 1 << 1                ' 1=display longs xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
      _TXSTRING     = 4 << 5                        ' tx string (nul terminated) from hub
      _RXSTRING     = 5 << 5                        ' rx string
        _ECHO_              = 1 << 4                '    - echo char
        _PROMPT             = 1 << 3                '    - prompt (lmm_x)
        _ADDR               = 1 << 2                '    - addr of string buffer supplied
        _NOLF               = 1 << 1                '    - strip <lf>
      _MONITOR      = 7 << 5                        ' goto rom monitor
    '' +--------------------------------------------------------------------------+
    
  • Once debugging is implemented, the last 16KB of RAM will be used, overwriting what is left of the ROM image. Those ROM routines you wrote could be made into objects, so that if they are needed, they could be included into applications. They would take the same amount of memory, but not in a fixed area.
  • JonnyMacJonnyMac Posts: 7,005
    edited 2020-04-13 - 19:11:27
    @cgracey In the world of "It would be nice to have..." I would ask for this:
      term.str("This is a plain string.")
    
    ...instead of...
      term.str(string("This is a plain string."))
    
    This may create a complication because we don't need to zero-terminate and create a return address when the string is defined in a DAT section, and if we want to add control characters then string() still has a place.
      term.str(string("This is a string with a CR added to the end.", 13))
    
    Still, just defining a string constant in quotes would be nice, especially since I've added formatted string output to my serial code so I can do things like this:
      term.fstr3(string("%2d   $%2x    $%2x \r"), ++count, slaveid >> 1, slaveid)
    
    It would be nice to not have to type in string().
  • ElectrodudeElectrodude Posts: 1,432
    edited 2020-04-13 - 19:17:38
    How about adding support for the backslash-escaped control characters common in many other languages?
    term.str("This is a plain string.\r") ' Carriage return
    term.str("This is a plain string.\x13") ' Hexadecimal carriage return
    term.str("\"yields falsehood when preceded by its quotation\" yields falsehood when preceded by its quotation.\r") ' String constant contains escaped quotes which compile to quote characters
    

    Could you make a new operator, such as .. , which would be a sort of compile-time string concatenation operator? E.g.:
    term.str("This is a plain string." .. 13)
    
  • JonnyMacJonnyMac Posts: 7,005
    edited 2020-04-13 - 20:38:44
    How about adding support for the backslash-escaped control characters common in many other languages?
    I did -- I put them into my jm_serial.spin2 library. It cannot do escaped double quotes (because of the way the compiler works), so I use \q for that. FWIW, I'd rather have a library deal with escape codes/character and formatted strings than to build that into the compiler.

    This is a comment section for documentation for what I've implemented. It's certainly not 100% compatible with printf() in C, but it's enough for creating nicely formatted output to the terminal and devices like LCDs.
    con { formatted strings }
    
    {{
        Escaped characters
    
          \\          backslash char
          \%          percent char
          \q          double quote
          \b          backspace
          \t          tab (horizontal)
          \n          new line (vertical tab)
          \r          carriage return
          \nnn        arbitrary ASCII value (nnn is decimal)
    
        Formatted arguments
    
          %w.pf       print argument as decimal width decimal point
          %[w[.p]]d   print argument as decimal
          %[w[.p]]x   print argument as hex
          %[w[.p]]o   print argument as octal
          %[w[.p]]q   print argument as quarternary
          %[w[.p]]b   print argument as binary
          %[w]s       print argument as string
          %[w]c       print argument as character (
    
                      -- w is field width
                         * positive w causes right alignment in field
                         * negative w causes left alignment in field
                      -- %ws aligns s in field (may truncate)
                      -- %wc prints w copies of c
                      -- p is precision characters
                         * number of characters to use, aligned in field
                           -- prepends 0 if needed to match p
                           -- for %w.pf, p is number of digits after decimal point
    }}
    


    You mean \x0D, right?
    term.str("This is a plain string.\x13") ' Hexadecimal carriage return
    
  • If we don't allow characters < 32 (space), but rely on \decimal, then two or more characters within quotes could trigger a string compilation:

    term.str("This is a z-string.\13", other, parameter)

    The compiler could resolve "\13" to byte value 13. Maybe for cases of decimal values after \, we could just take care of them, while leaving \notdecimals intact, and compile them verbatim.

    What to do about single-character strings, though? They just look like a byte value ("A" = 65).
  • I thought that the Spin2 way to avoid having to write term.str(string("stuff")) is to write:
      send := @term.tx  ' method for sending one character
      send("this is a plain string")
    
    rather than providing a term.str method.
  • ersmith wrote: »
    I thought that the Spin2 way to avoid having to write term.str(string("stuff")) is to write:
      send := @term.tx  ' method for sending one character
      send("this is a plain string")
    
    rather than providing a term.str method.

    Yes, SEND works like that, but if you just want to declare strings and return pointers, we currently need to use STRING.

    Maybe everyone needs to take a look at SEND. It's described in the docs.
  • @cgracy I think you said that Spin2 compiles to relocatable code. How would I load and run a Spin2 object from another non-Spin2 program? What is required to setup the environment? I'm making a self-hosted BASIC interpreter and it would be nice to be able to call Spin2 code from BASIC.
  • David Betz wrote: »
    @cgracy I think you said that Spin2 compiles to relocatable code. How would I load and run a Spin2 object from another non-Spin2 program? What is required to setup the environment? I'm making a self-hosted BASIC interpreter and it would be nice to be able to call Spin2 code from BASIC.

    There are a few hard-coded addresses in the interpreter, currently. I need to make those relative and then the interpreter can be relocated anywhere. Not ready, yet.
  • Chip,
    You missed this bug in my post a few back...

    Next, after spin code, this DAT ORGH $4000 is set to hub $1000 and not $4000 (ie code is placed into hub at $1000)
    ''============[ HUB VARIABLES ]=================================================                                    
    DAT             
                    orgh    $4000
    str_fun         byte    "Fun with P2 ROM v010",13,10,0
    str_msg         byte    "More P2 fun...",13,10,0
                    alignl                                                                                                     
    ''---------------------------------------------------------------------------------------------------
    
  • Cluso99 wrote: »
    Chip,
    You missed this bug in my post a few back...

    Next, after spin code, this DAT ORGH $4000 is set to hub $1000 and not $4000 (ie code is placed into hub at $1000)
    ''============[ HUB VARIABLES ]=================================================                                    
    DAT             
                    orgh    $4000
    str_fun         byte    "Fun with P2 ROM v010",13,10,0
    str_msg         byte    "More P2 fun...",13,10,0
                    alignl                                                                                                     
    ''---------------------------------------------------------------------------------------------------
    

    ORGH doesn't really matter in Spin2. With no address, it just uses $400. There's no telling where it will wind up after compilation. You can always get the address in Spin2, though, by @str_fun or @str_msg.

    You can ORGH $FC000 if you want and it will compile any absolute addresses to that range, but if you want to use those absolute addresses assembled into the instructions, you'd need to move the code at runtime to $FC000.
  • cgracey wrote: »
    Cluso99 wrote: »
    Chip,
    You missed this bug in my post a few back...

    Next, after spin code, this DAT ORGH $4000 is set to hub $1000 and not $4000 (ie code is placed into hub at $1000)
    ''============[ HUB VARIABLES ]=================================================                                    
    DAT             
                    orgh    $4000
    str_fun         byte    "Fun with P2 ROM v010",13,10,0
    str_msg         byte    "More P2 fun...",13,10,0
                    alignl                                                                                                     
    ''---------------------------------------------------------------------------------------------------
    

    ORGH doesn't really matter in Spin2. With no address, it just uses $400. There's no telling where it will wind up after compilation. You can always get the address in Spin2, though, by @str_fun or @str_msg.

    You can ORGH $FC000 if you want and it will compile any absolute addresses to that range, but if you want to use those absolute addresses assembled into the instructions, you'd need to move the code at runtime to $FC000.

    I used ORGH $4000 but it placed the code at $1000.

    Do you really mean we cannot force the compiler to put code in hub where we want it?

    If so, this is really being short-sighted :( :( :( :( :(

    I have just been redoing the SDcard and Serial Monitor/Debugger so I can put it precisely where I require it. I've stopped now as I am about to give up on P2 entirely!
  • Cluso99 wrote: »
    cgracey wrote: »
    Cluso99 wrote: »
    Chip,
    You missed this bug in my post a few back...

    Next, after spin code, this DAT ORGH $4000 is set to hub $1000 and not $4000 (ie code is placed into hub at $1000)
    ''============[ HUB VARIABLES ]=================================================                                    
    DAT             
                    orgh    $4000
    str_fun         byte    "Fun with P2 ROM v010",13,10,0
    str_msg         byte    "More P2 fun...",13,10,0
                    alignl                                                                                                     
    ''---------------------------------------------------------------------------------------------------
    

    ORGH doesn't really matter in Spin2. With no address, it just uses $400. There's no telling where it will wind up after compilation. You can always get the address in Spin2, though, by @str_fun or @str_msg.

    You can ORGH $FC000 if you want and it will compile any absolute addresses to that range, but if you want to use those absolute addresses assembled into the instructions, you'd need to move the code at runtime to $FC000.

    I used ORGH $4000 but it placed the code at $1000.

    Do you really mean we cannot force the compiler to put code in hub where we want it?

    If so, this is really being short-sighted :( :( :( :( :(

    I have just been redoing the SDcard and Serial Monitor/Debugger so I can put it precisely where I require it. I've stopped now as I am about to give up on P2 entirely!

    As objects get packed together, there is no control over where ANYTHING winds up. You need to make your PASM code use relative addressing within itself. Branches are already relative, but to get the address of data structures in PASM, you need to use LOC, which will convert their relative address into an absolute address for you. That's why we have LOC. Hubexec code can be anywhere and still run if you'll make a few simple mods to your code.

    If anything about that doesn't make sense, post your code in question here and I'll show you what needs to be done.
  • Chip,
    I give up :(
  • Cluso99 wrote: »
    Chip,
    I give up :(

    You're still alive, so there's still hope.
  • Spin1 is all relative and we get by...
    Never thought of it as a problem.
  • Cluso99 wrote: »
    Chip,
    I give up :(

    Maybe you just need to give up complicating things.

    If you want a monitor write it in Spin as an object, so everyone can easy incorporate it in his project.

    If you want to use your ROM code, start it in a new cog with hubexec, so the spin interpreter will not affect your registers.

    Do you know a compiler that allows to place code at fixed absolute adresses? You will get big gaps or overwritten code and combining code from different sources will be a pain.

    Andy
  • cgracey wrote: »
    Hubexec code can be anywhere and still run if you'll make a few simple mods to your code.

    Is there anything to stop anyone modding spin2_interpreter.spin2, to prevent buffers conflicting with other code?
  • TonyB_ wrote: »
    cgracey wrote: »
    Hubexec code can be anywhere and still run if you'll make a few simple mods to your code.

    Is there anything to stop anyone modding spin2_interpreter.spin2, to prevent buffers conflicting with other code?

    What do you mean?
  • Not sure if TonyB meant this, but my question is:

    When I compile my spin2 source, is the spin2_interpreter.spin2 source compiled new and linked to my code, or is the interpreter fixed in a binary blob, and the interpreter source is just for reference?

    Andy
  • cgraceycgracey Posts: 13,077
    edited 2020-04-14 - 18:05:20
    Ariba wrote: »
    Not sure if TonyB meant this, but my question is:

    When I compile my spin2 source, is the spin2_interpreter.spin2 source compiled new and linked to my code, or is the interpreter fixed in a binary blob, and the interpreter source is just for reference?

    Andy

    The interpreter is a binary blob which is embedded into the compiler.
  • cgracey wrote: »
    Ariba wrote: »
    Not sure if TonyB meant this, but my question is:

    When I compile my spin2 source, is the spin2_interpreter.spin2 source compiled new and linked to my code, or is the interpreter fixed in a binary blob, and the interpreter source is just for reference?

    Andy

    The interpreter is a binary blob which is embedded into the compiler.

    Although given that the compiler is written in assembly, it's probably not exactly hard to figure out where it's at and replace it with some modified version if one feels the need for that.
  • Wuerfel_21 wrote: »
    cgracey wrote: »
    Ariba wrote: »
    Not sure if TonyB meant this, but my question is:

    When I compile my spin2 source, is the spin2_interpreter.spin2 source compiled new and linked to my code, or is the interpreter fixed in a binary blob, and the interpreter source is just for reference?

    Andy

    The interpreter is a binary blob which is embedded into the compiler.

    Although given that the compiler is written in assembly, it's probably not exactly hard to figure out where it's at and replace it with some modified version if one feels the need for that.

    For that to work, I would need to make it an external file. I'm using an .exe compressor on the PNut.exe program to keep it small.
  • Chip,
    I've spent considerable time trying to compile my monitor code into hub so that it can be used by everyone from spin and pasm.

    But, because I cannot call the current ROM monitor from spin, I am flying blind to see what in the hell is going wrong. I coded the ROM monitor so that all programs could call it to get going.

    So, since you are not willing to compromise, Can you build me a version of pnut that keeps $1E0-$1E0 free so that I can use the monitor to debug my replacement code? I can then build a loadable hub version that all can incorporate as an object.
  • I've been trying to compile FemtoDongle with PNut now that I have it partly working compiling with FastSpin. I'm using "SmartSerial.spin" for serial I/O. I tried compiling it all with PNut version "r". I was surprised that I had to add "()" to the declaration for every parameterless method. Once I got that done, several of the I/O method calls in "SmartSerial" would not compile ... all ending with "_". Once I removed the trailing "_", some compiled, but "dirh_" would not, no matter whether it had a "_" somewhere or not. I did change the file extensions to ".spin2". Suggestions?
  • Mike Green wrote: »
    I've been trying to compile FemtoDongle with PNut now that I have it partly working compiling with FastSpin. I'm using "SmartSerial.spin" for serial I/O. I tried compiling it all with PNut version "r". I was surprised that I had to add "()" to the declaration for every parameterless method. Once I got that done, several of the I/O method calls in "SmartSerial" would not compile ... all ending with "_". Once I removed the trailing "_", some compiled, but "dirh_" would not, no matter whether it had a "_" somewhere or not. I did change the file extensions to ".spin2". Suggestions?

    Mike, I'm not sure what's wrong. Could you please post a .zip with your files into this thread so I can look at it?
  • Cluso99 wrote: »
    Chip,
    I've spent considerable time trying to compile my monitor code into hub so that it can be used by everyone from spin and pasm.

    But, because I cannot call the current ROM monitor from spin, I am flying blind to see what in the hell is going wrong. I coded the ROM monitor so that all programs could call it to get going.

    So, since you are not willing to compromise, Can you build me a version of pnut that keeps $1E0-$1E0 free so that I can use the monitor to debug my replacement code? I can then build a loadable hub version that all can incorporate as an object.

    Cluso99, is there a reason you can't make your monitor use $120..$12F, or anything below? I don't think it will be very simple for me to do what you're asking. I'd have to make a lot of edits to my tools and there are probably some gotcha's lurking in the effort. Your monitor has free use of $000..$131.
  • I just updated finished FLOW CONTROL section of the Spin2 docs at the top of this thread.

    I think, aside from examples, there's not much left to document. It's at 47 pages now.
Sign In or Register to comment.