Shop OBEX P1 Docs P2 Docs Learn Events
PNut/Spin2 Latest Version (v47 - Cooperative multitasking added to Spin2, up to 32 tasks) - Page 13 — Parallax Forums

PNut/Spin2 Latest Version (v47 - Cooperative multitasking added to Spin2, up to 32 tasks)

1101113151670

Comments

  • Cluso99Cluso99 Posts: 18,069
    edited 2020-04-16 04:52
    cgracey wrote: »
    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.
    Chip,
    I am really trying!

    To change the parameters to use $120-$12F instead of $1E0-$1EF is easy, and I can compile it easily too using the original pnut v32i.

    BUT, trying to compile it and call it using pnut v34R is impossible. First up, it ignores the ORGH $anywhere. I don't know (or have any confidence) that it compiled correctly. It certainly cannot be called from where is it located, since it ignores the ORGH $FCxxx and places it at hub $0 upwards which if course cannot be called in hubexec.

    I am just trying to work within stupid constraints. Surely, pnut should honor an ORGH $XXX.

    I have even considered creating the binary blob using pnut v32i (or fastspin) and then trying to load it within pnut v34R but I have no confidence in whether this will work or not. How the devil do you expect anyone to write hubexec code when they have no idea where it gets loaded into???

    It's not a simple matter of using relative code since there are many entry points into the hubexec code block. It was written this way because we did not have ROM space to put a table at the beginning.

    Currently, I feel that absolutely everything I've ever done on P1, and P2, is no longer usable. I am not willing to start over again. If I do that it certainly will not be on a P2.
  • cgraceycgracey Posts: 14,206
    Cluso99 wrote: »
    cgracey wrote: »
    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.
    Chip,
    I am really trying!

    To change the parameters to use $120-$12F instead of $1E0-$1EF is easy, and I can compile it easily too using the original pnut v32i.

    BUT, trying to compile it and call it using pnut v34R is impossible. First up, it ignores the ORGH $anywhere. I don't know (or have any confidence) that it compiled correctly. It certainly cannot be called from where is it located, since it ignores the ORGH $FCxxx and places it at hub $0 upwards which if course cannot be called in hubexec.

    I am just trying to work within stupid constraints. Surely, pnut should honor an ORGH $XXX.

    I have even considered creating the binary blob using pnut v32i (or fastspin) and then trying to load it within pnut v34R but I have no confidence in whether this will work or not. How the devil do you expect anyone to write hubexec code when they have no idea where it gets loaded into???

    It's not a simple matter of using relative code since there are many entry points into the hubexec code block. It was written this way because we did not have ROM space to put a table at the beginning.

    You could use ORGH $FC000 and then BYTEMOVE($FC000,@monitor, $4000). That way, it was compiled with the address that you want, so you can move it to where you want it to be.
  • AribaAriba Posts: 2,690
    Cluso

    This starts your rom monitor in a new cog (after a short delay to start the terminal):
      _clkfreq = 160_000_000
     
    PUB Start() | x
      waitms(1500)
      x := (clkfreq / 115200) << 16 + 7
      coginit(16, @init_cog, x)           'start rom-monitor in a new cog
      repeat
    
    DAT
    		org	0		   
    init_cog
    		mov	$1E0,ptra        'lmm_x = baudrate+bits
    		call	#\$FCAB8         'serial_init
    		mov	$1EF,##$FC000    'buffer addr
    		jmp	#\$FCD78         'start monitor
    

    Spin code certainly knows the hubadresses at runtime, it's just the PASM code that has not the right (absolute) addresses. But there is a constant offset to the absolute address. You should be able to use a longmove($4000,@hubcode,codesize) to move it at the position you want it to have, and then start it there.

    Andy
  • Cluso99Cluso99 Posts: 18,069
    cgracey wrote: »
    Cluso99 wrote: »
    cgracey wrote: »
    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.
    Chip,
    I am really trying!

    To change the parameters to use $120-$12F instead of $1E0-$1EF is easy, and I can compile it easily too using the original pnut v32i.

    BUT, trying to compile it and call it using pnut v34R is impossible. First up, it ignores the ORGH $anywhere. I don't know (or have any confidence) that it compiled correctly. It certainly cannot be called from where is it located, since it ignores the ORGH $FCxxx and places it at hub $0 upwards which if course cannot be called in hubexec.

    I am just trying to work within stupid constraints. Surely, pnut should honor an ORGH $XXX.

    I have even considered creating the binary blob using pnut v32i (or fastspin) and then trying to load it within pnut v34R but I have no confidence in whether this will work or not. How the devil do you expect anyone to write hubexec code when they have no idea where it gets loaded into???

    It's not a simple matter of using relative code since there are many entry points into the hubexec code block. It was written this way because we did not have ROM space to put a table at the beginning.

    You could use ORGH $FC000 and then BYTEMOVE($FC000,@monitor, $4000). That way, it was compiled with the address that you want, so you can move it to where you want it to be.

    OK, I'll give this a try tonight.
  • Cluso99Cluso99 Posts: 18,069
    Chip,
    Am I correct that no code can be compiled for hubexec unless it it moved to the address it is designed to run at?

    For example, if I have a piece of pasm code and I ORGH it with or without any address, I still must do a bytemove(dest, srce, len)?

    Because it seems that the code is placed in hub starting at $0 which of course is below $400 and therefore cannot be run as hubexec.
  • Attached is my current FemtoBasic version for P2. FemtoDongle2.spin (and SmartSerial.spin) compile with FastSpin on a Mac and the compiled binary seems to work. The "Used_With_PNut" folder has modified versions of the two source files. FemtoDongle2.spin2 mostly has "()" added in the declarations of parameterless methods. SmartSerial.spin2 is the problem. PNut doesn't recognize the method calls like "wxpin_", but does accept "wxpin". It doesn't recognize "dirh_" nor "dirh" or "_dirh". This may just be an incompatibility between FastSpin and PNut, but it's confusing me.
  • AribaAriba Posts: 2,690
    Mike

    Here is a Serial object, that works for PNUT and Fastspin. It's already named according your use ;)
    There is a testcode at begin which you can comment out to spare some bytes.

    Andy
  • Thanks Andy
  • cgraceycgracey Posts: 14,206
    edited 2020-04-17 00:14
    Mike Green wrote: »
    Attached is my current FemtoBasic version for P2. FemtoDongle2.spin (and SmartSerial.spin) compile with FastSpin on a Mac and the compiled binary seems to work. The "Used_With_PNut" folder has modified versions of the two source files. FemtoDongle2.spin2 mostly has "()" added in the declarations of parameterless methods. SmartSerial.spin2 is the problem. PNut doesn't recognize the method calls like "wxpin_", but does accept "wxpin". It doesn't recognize "dirh_" nor "dirh" or "_dirh". This may just be an incompatibility between FastSpin and PNut, but it's confusing me.

    Mike, I made lots of minor edits to your code and it is compiling now. Not sure if it works, though.

    These were the edits, in order of frequency:

    1) Adding "()" after method names
    2) Adding " : result " after method declarations where necessary
    3) Changing "=<" or "=>" to "<=" or ">="
    4) Changing "|<" to "decod"

    The compiled size is 7,096 bytes, plus 4,088 bytes for the interpreter.

    Here are the two files...

  • cgraceycgracey Posts: 14,206
    edited 2020-04-16 23:51
    Cluso99 wrote: »
    Chip,
    Am I correct that no code can be compiled for hubexec unless it it moved to the address it is designed to run at?

    For example, if I have a piece of pasm code and I ORGH it with or without any address, I still must do a bytemove(dest, srce, len)?

    Because it seems that the code is placed in hub starting at $0 which of course is below $400 and therefore cannot be run as hubexec.

    No, of course hubexec code can run where it sits. You just have to make it relatively-addressed and get the address to the start of it. I posted some examples of how to do this, but you seemed to want to run your code at a fixed address, so I suggested you just move it to where you want to run it, since you were not supporting relocation.
  • Cluso99Cluso99 Posts: 18,069
    Thanks Chip.
    Somewhere I have problems with my code not working as it should, but it's like looking for a needle in a haystack.
    I ended up making a really simple program (posted on the Spin2 Snippets thread) to flash an LED in hubexec code. Now I can proceed forward again.

    BTW What I need is for resident code to remain in hub between loading/running programs from SD. These programs will use CON Equates for the entry points into the pre-loaded resident code. The resident code will provide SD FAT32 file routines, Input/Output routines via a mailbox so that the actual I/O can be redirected to serial or to keyboard/screen. This is the basis of an OS which I did for the P1 many moons ago. I am trying to port this to the P2. This is why it is essential that I know where the code is located in hub.

    Anyway, with what I have now, I can place my code where I require it to be within hub. It is a shame that the ROM Monitor cannot be used as-is but I will reload it with new register usage.
  • Cluso99Cluso99 Posts: 18,069
    Chip,
    Here is my contrived example of calling hubexec residing in its' own OBJ module.
    Can you tell me how to call the routine _HubToggle in the OBJ module?
    Rather than having to declare _clkfreq and LED_p2eval again in the OBJ module, how do I declare them in the top module?
    CON
      _clkfreq      = 297_000_000		                    'set clock frequency
      LED_p2eval    = 56                                    ' P2EVAL Blue LED 0=ON
    
    OBJ
      ob : "Test-OBJ-12i"  
    
    PUB go()
    
        repeat
            PR0 := 10
            CALL(@ob._HubToggle)                            ' call Toggle LED
            WAITMS(4000)                                    ' 4s        
    
    and the OBJ
    CON
      _clkfreq      = 297_000_000		                    'set clock frequency
      LED_p2eval    = 56                                    ' P2EVAL Blue LED 0=ON
    
    PUB dummy()
    
    DAT             
                  orgh
    _hubToggle
    '              mov       PR0,#10                         ' spin pasm comms registers
    .loop         drvnot    #LED_p2eval                     ' flash P2EVAL blue led
                  waitx     ##_clkfreq/2                    ' 0.5s
                  djnz      PR0,#.loop
                  RET                                       ' return
    
  • Cluso

    Try this
    Use a obj as a common header file
    
    con
    	_clkfreq = config.sysclk
    
    OBJ
      ob : "Test-OBJ-12i"  
    config: "config"
    
    PUB go()
    
        repeat
            PR0 := 10
            CALL(ob.hubt())                  
            WAITMS(4000) 
    
    obj
    
    config: "config"
    
    PUB hubt():x
    	return @_hubToggle
    DAT             
                  orgh
    _hubToggle
    '              mov       PR0,#10                         ' spin pasm comms registers
    .loop         drvnot    #config.LED_p2eval                     ' flash P2EVAL blue led
                  waitx     ##config.sysclk/2                    ' 0.5s
                  djnz      PR0,#.loop
                  RET                                       ' return
    
    config.spin2
    con
    
    	LED_p2eval    = 56
    	sysclk = 297_000_000
    
    pub dummy()
    
    

  • cgraceycgracey Posts: 14,206
    Cluso, like Ozpropdev showed, you need to make a method to return the address of the PASM code:

    ClusoTop.spin2
    CON
      _clkfreq      = 297_000_000	'set clock frequency
      LED_p2eval    = 56            'P2EVAL Blue LED 0=ON
    
    OBJ
      ob : "ClusoObj"  
    
    PUB go()
      repeat
        PR0 := 10
        CALL(ob.HubToggle())        'call Toggle LED
        WAITMS(4000)                '4s
    

    ClusoObj.spin2
    CON
      _clkfreq      = 297_000_000	'set clock frequency
      LED_p2eval    = 56            'P2EVAL Blue LED 0=ON
    
    PUB HubToggle() : x
      return @_HubToggle
    
    DAT             
                  orgh
    _HubToggle
    .loop         drvnot    #LED_p2eval                     ' flash P2EVAL blue led
                  waitx     ##_clkfreq/2                    ' 0.5s
           _ret_  djnz      PR0,#.loop
    
  • evanhevanh Posts: 16,032
    Presumably it is safe to store the return value for reuse.

  • Cluso99Cluso99 Posts: 18,069
    edited 2020-04-17 06:58
    cgracey wrote: »
    Cluso, like Ozpropdev showed, you need to make a method to return the address of the PASM code:

    ClusoTop.spin2
    CON
      _clkfreq      = 297_000_000	'set clock frequency
      LED_p2eval    = 56            'P2EVAL Blue LED 0=ON
    
    OBJ
      ob : "ClusoObj"  
    
    PUB go()
      repeat
        PR0 := 10
        CALL(ob.HubToggle())        'call Toggle LED
        WAITMS(4000)                '4s
    

    ClusoObj.spin2
    CON
      _clkfreq      = 297_000_000	'set clock frequency
      LED_p2eval    = 56            'P2EVAL Blue LED 0=ON
    
    PUB HubToggle() : x
      return @_HubToggle
    
    DAT             
                  orgh
    _HubToggle
    .loop         drvnot    #LED_p2eval                     ' flash P2EVAL blue led
                  waitx     ##_clkfreq/2                    ' 0.5s
           _ret_  djnz      PR0,#.loop
    

    So what do I do when I have 25+ entry points? Surely I don;t need a method for every entry point?

    This is why we have "bloat" code on the PC. Are we now getting it on the P2 too???

    At least I can still compile a PASM only program with both pnut v34R and Fastspin. Both give me a listing sufficient to work out the fixed hub addresses. I just have to work out how to include the code into spin so I can move it to where I want it. Not easy tho :(
  • cgraceycgracey Posts: 14,206
    edited 2020-04-17 07:09
    Cluso, I would probably make a jump table:
    CON   #0,pasm0,pasm1,pasm2,pasm3	'enumerate your PASM routines by name
    
    PUB go()
      CallPasm(pasm0)
      CallPasm(pasm1)
      CallPasm(pasm2)
      CallPasm(pasm3)
    
    PRI CallPasm(index)
      pr0 := index
      CALL(@pasm)
    
    
    DAT	ORGH
    
    pasm	jmprel	pr0
    	jmp	#pasm0_
    	jmp	#pasm1_
    	jmp	#pasm2_
    	jmp	#pasm3_
    
    pasm0_	'<code>
    pasm1_	'<code>
    pasm2_	'<code>
    pasm3_	'<code>
    

    This is maybe necessary if you don't have the routines in the same file.

    If the routines are in the same file, you can just CALL them:
    PUB go()
      CALL(@pasm0)
      CALL(@pasm1)
      CALL(@pasm2)
      CALL(@pasm3)
    
    DAT	ORGH
    
    pasm0	'<code>
    pasm1	'<code>
    pasm2	'<code>
    pasm3	'<code>
    
  • kwinnkwinn Posts: 8,697
    @Cluso99: I wonder if it might be simpler to store jump vectors at a specific memory memory area somewhat like what was done with the 8080/Z80 for CPM.
  • cgraceycgracey Posts: 14,206
    edited 2020-04-18 11:20
    Today I took the Spin2 compiler, which is 13,600 lines of 80386 assembly, and converted the 2,270 lines containing all the equates and automatic symbols into Spin2 source. It's all data, no code, and compiles to 11KB. I want to get the parser working in Spin2, but I need all this data present for context. Here is the Spin2 source for this, so far.

    I added size overrides to BYTE/WORD/LONG expressions in DAT sections, so that you can generate data of a different size when needed. Good for symbol table data. This will be in the next release of PNut.exe:
    byte	"X_DDS_GOERTZEL_SINC1",0,	type_con,		long	$F007 << 16
    


  • cgracey wrote: »
    Today I took the Spin2 compiler, which is 13,600 lines of 80386 assembly, and converted the 2,270 lines containing all the equates and automatic symbols into Spin2 source. It's all data, no code, and compiles to 11KB. I want to get the parser working in Spin2, but I need all this data present for context. Here is the Spin2 source for this, so far.

    I added size overrides to BYTE/WORD/LONG expressions in DAT sections, so that you can generate data of a different size when needed. Good for symbol table data. This will be in the next release of PNut.exe:
    byte	"X_DDS_GOERTZEL_SINC1",0,	type_con,		long	$F007 << 16
    

    Nice! It sounds like you're well on the way to a self-hosting compiler. I assume that is your goal.

  • cgraceycgracey Posts: 14,206
    David Betz wrote: »
    cgracey wrote: »
    Today I took the Spin2 compiler, which is 13,600 lines of 80386 assembly, and converted the 2,270 lines containing all the equates and automatic symbols into Spin2 source. It's all data, no code, and compiles to 11KB. I want to get the parser working in Spin2, but I need all this data present for context. Here is the Spin2 source for this, so far.

    I added size overrides to BYTE/WORD/LONG expressions in DAT sections, so that you can generate data of a different size when needed. Good for symbol table data. This will be in the next release of PNut.exe:
    byte	"X_DDS_GOERTZEL_SINC1",0,	type_con,		long	$F007 << 16
    

    Nice! It sounds like you're well on the way to a self-hosting compiler. I assume that is your goal.

    Yes, but also as a replacement for the '386 code. I realized the other day that there is a contiguous group of bytecodes that are P2-hardware-specific, while the rest are hardware-agnostic. This means that only a basic bytecode interpreter is needed on any system to run non-hardware Spin2 code, like a compiler. I want to go down this road and get a feel for how fast and efficient this approach might be.
  • cgracey wrote: »
    David Betz wrote: »
    cgracey wrote: »
    Today I took the Spin2 compiler, which is 13,600 lines of 80386 assembly, and converted the 2,270 lines containing all the equates and automatic symbols into Spin2 source. It's all data, no code, and compiles to 11KB. I want to get the parser working in Spin2, but I need all this data present for context. Here is the Spin2 source for this, so far.

    I added size overrides to BYTE/WORD/LONG expressions in DAT sections, so that you can generate data of a different size when needed. Good for symbol table data. This will be in the next release of PNut.exe:
    byte	"X_DDS_GOERTZEL_SINC1",0,	type_con,		long	$F007 << 16
    

    Nice! It sounds like you're well on the way to a self-hosting compiler. I assume that is your goal.

    Yes, but also as a replacement for the '386 code. I realized the other day that there is a contiguous group of bytecodes that are P2-hardware-specific, while the rest are hardware-agnostic. This means that only a basic bytecode interpreter is needed on any system to run non-hardware Spin2 code, like a compiler. I want to go down this road and get a feel for how fast and efficient this approach might be.
    That sounds like a good plan. I'm looking forward to seeing the results.

  • David Betz wrote: »
    That sounds like a good plan. I'm looking forward to seeing the results.
    To elaborate on that more, I'll be interested to see how you implement things like symbol tables. I'm thinking you might end up expanding Spin2 to support dynamic creation of object instances so that you can, for example, create a linked list of symbol structures. I guess that would also require object pointers. Or maybe you'll just implement the symbol table as a big fixed-size array? Anyway, doing something of this scale will be a good test of the Spin2 language.

  • cgraceycgracey Posts: 14,206
    David Betz wrote: »
    David Betz wrote: »
    That sounds like a good plan. I'm looking forward to seeing the results.
    To elaborate on that more, I'll be interested to see how you implement things like symbol tables. I'm thinking you might end up expanding Spin2 to support dynamic creation of object instances so that you can, for example, create a linked list of symbol structures. I guess that would also require object pointers. Or maybe you'll just implement the symbol table as a big fixed-size array? Anyway, doing something of this scale will be a good test of the Spin2 language.

    Symbol tables are the first thing to code, then the parser, since it needs symbols.

    Yes, this should shake out any bugs and provide impetus for improvements.
  • cgracey wrote: »
    David Betz wrote: »
    David Betz wrote: »
    That sounds like a good plan. I'm looking forward to seeing the results.
    To elaborate on that more, I'll be interested to see how you implement things like symbol tables. I'm thinking you might end up expanding Spin2 to support dynamic creation of object instances so that you can, for example, create a linked list of symbol structures. I guess that would also require object pointers. Or maybe you'll just implement the symbol table as a big fixed-size array? Anyway, doing something of this scale will be a good test of the Spin2 language.

    Symbol tables are the first thing to code, then the parser, since it needs symbols.

    Yes, this should shake out any bugs and provide impetus for improvements.
    How do you plan to implement the Spin2 byte code interpreter to run on the PC? You might want to consider writing it in C so it can be ported to non-Windows systems easily.

  • cgraceycgracey Posts: 14,206
    David Betz wrote: »
    cgracey wrote: »
    David Betz wrote: »
    David Betz wrote: »
    That sounds like a good plan. I'm looking forward to seeing the results.
    To elaborate on that more, I'll be interested to see how you implement things like symbol tables. I'm thinking you might end up expanding Spin2 to support dynamic creation of object instances so that you can, for example, create a linked list of symbol structures. I guess that would also require object pointers. Or maybe you'll just implement the symbol table as a big fixed-size array? Anyway, doing something of this scale will be a good test of the Spin2 language.

    Symbol tables are the first thing to code, then the parser, since it needs symbols.

    Yes, this should shake out any bugs and provide impetus for improvements.
    How do you plan to implement the Spin2 byte code interpreter to run on the PC? You might want to consider writing it in C so it can be ported to non-Windows systems easily.

    It's going to be a short program, so it can be written in anything that works.
  • cgracey wrote: »
    David Betz wrote: »
    cgracey wrote: »
    David Betz wrote: »
    David Betz wrote: »
    That sounds like a good plan. I'm looking forward to seeing the results.
    To elaborate on that more, I'll be interested to see how you implement things like symbol tables. I'm thinking you might end up expanding Spin2 to support dynamic creation of object instances so that you can, for example, create a linked list of symbol structures. I guess that would also require object pointers. Or maybe you'll just implement the symbol table as a big fixed-size array? Anyway, doing something of this scale will be a good test of the Spin2 language.

    Symbol tables are the first thing to code, then the parser, since it needs symbols.

    Yes, this should shake out any bugs and provide impetus for improvements.
    How do you plan to implement the Spin2 byte code interpreter to run on the PC? You might want to consider writing it in C so it can be ported to non-Windows systems easily.

    It's going to be a short program, so it can be written in anything that works.
    I know you've posted the source code for the P2 byte code interpreter but do you have a document describing them?

  • This is an interesting development and I am hoping things work out well Chip. This is really called taking your own medicine now isn't it. :smile:
    I wonder how well Spin2 will deal with file parsing / string manipulation aspects of a compiler implementation. You'll want to develop some handy utility functions there I imagine. Being able to run Spin2 code on a non-P2 would be interesting too.
  • rogloh wrote: »
    This is an interesting development and I am hoping things work out well Chip. This is really called taking your own medicine now isn't it. :smile:
    I wonder how well Spin2 will deal with file parsing / string manipulation aspects of a compiler implementation. You'll want to develop some handy utility functions there I imagine. Being able to run Spin2 code on a non-P2 would be interesting too.
    You can already use Eric's spin2cpp to translate Spin2 to C and then compile it with a PC C compiler.

  • Chip, With PNutVr I'm getting an error with a call to AKPIN (Expression terms must return a single result). Your documentation of this call doesn't seem to imply that there is more than one result.
Sign In or Register to comment.