Shop OBEX P1 Docs P2 Docs Learn Events
flexspin compiler for P2: Assembly, Spin, BASIC, and C in one compiler - Page 76 — Parallax Forums

flexspin compiler for P2: Assembly, Spin, BASIC, and C in one compiler

17374767879122

Comments

  • ke4pjw wrote: »
    I wonder if there could be any optimization that could be done at compile time to determine if only one pin is being used or not.

    If the pin is a constant than the compiler will use the old (single instruction) form of readpin(pin). But that will only work for constant pin values.
  • evanhevanh Posts: 15,916
    ersmith wrote: »
    ...
    The flexspin compiled version looks like:
    _mypinread
            test    arg01, #32 wz
     if_ne  mov     _var01, outb
     if_e   mov     _var01, outa
            mov     result1, _var01
            shr     result1, arg01
            shr     arg01, #6
            zerox   result1, arg01
    _mypinread_ret
            ret
    
    Which would be the same number of instructions except for the "ret" at the end; one of these days I'll have to add an optimization pass to get rid of ret when possible.
    The use of _var01 seems extraneous too.

  • RaymanRayman Posts: 14,648
    Is there a way to have the preprocessor work with a Spin2 file that is included in a c program?

    I have a USB driver as part of a c code and it has the basepin defined like this:
    '------------------------------------------------------------------------------
    ' P2-ES USB Host (Master) x 2 Accessory Board I/O group base pin:
            USB_BASEPIN = 16'12'16 ' + offsets for ES-64006 Serial Host board
    '------------------------------------------------------------------------------
    

    But, I'd like to have all of the pin definitions in a separate file...
  • JRoarkJRoark Posts: 1,215
    edited 2021-01-17 20:09
    Is there a way in FlexBASIC to determine what type of variable was passed to a function? Consider this scenario:
    FUNCTION Foo(x as any) as integer
       if x was an uinteger... (do stuff)
       if x was an integer... (do more stuff)
       if x was a string... (do different stuff)
       if x was a single... (do other different stuff)
       if x was a byte... (do still other different stuff)
    END FUNCTION
    
    How can I get there from here?
  • ersmithersmith Posts: 6,053
    edited 2021-01-17 20:26
    Rayman wrote: »
    Is there a way to have the preprocessor work with a Spin2 file that is included in a c program?

    I have a USB driver as part of a c code and it has the basepin defined like this:
    '------------------------------------------------------------------------------
    ' P2-ES USB Host (Master) x 2 Accessory Board I/O group base pin:
            USB_BASEPIN = 16'12'16 ' + offsets for ES-64006 Serial Host board
    '------------------------------------------------------------------------------
    

    But, I'd like to have all of the pin definitions in a separate file...

    I'm not quite sure what you're asking for here. But FlexProp allows #include in a Spin2 file, if that's what you wanted. It won't automatically pass along a #include from a C file to objects included with __struct using, you'll have to explicitly put the #include in those objects.
  • JRoark wrote: »
    Is there a way in FlexBASIC to determine what type of variable was passed to a function? Consider this scenario:
    FUNCTION Foo(x as any) as integer
       if x was an uinteger... (do stuff)
       if x was an integer... (do more stuff)
       if x was a string... (do different stuff)
       if x was a single... (do other different stuff)
       if x was a byte... (do still other different stuff)
    END FUNCTION
    
    How can I get there from here?

    No, variables don't have any type information associated with them. An "any" variable is just 32 bits of data, untyped.

    Now, *maybe* something like this could be added to the generic function system. It's likely that, whatever you wanted to do there, a generic function would match it better:
    Any(T) FUNCTION Foo(x as T) as integer
    ...
    END FUNCTION
    
    There's currently no way to do anything with type T inside Foo, except to declare variables of that type, but possibly we could add some limited testing for what kind of thing T is.

    Could you give me a more concrete example of what you'd like to do?
  • JRoarkJRoark Posts: 1,215
    edited 2021-01-17 20:59
    @ersmith A real world example: I'm noodling about making a replacement for STR$() that is sensitive to the type of variable passed to it. For speed, if the variable is an integer, then we branch internally to a loop that avoids the need for floating point, but if the variable is a float, then we branch to a different, slower (float-based) handler.

    Currently the programmer has to decide whether to use STR$() or StrInt$(). This isn't onerous but it seems to me it would be better to make a version of STR$() that "just works" and let it determine which pathway is needed. FWIW, the speed trade-off is about 7.5x between the integer-only solution and the floating-point solution.

    If this cant be easily done without tearing-up the carpet, then I'll move on. :)

    EDIT: Maybe its better to modify STR$() to add a second, optional parameter to tell it what to do:
    FUNCTION Str$(num as any, intFlag = 0 as integer) as string
       if intFlag=0 then
          (call internal float-based handler)
       else
          (call internal integer-based handler)
       end if
    END FUNCTION
    
    Not particularly elegant, and it'll be slow on integers if you give it the traditional syntax, but for those who can RTFM, adding that second argument will speed things up.
  • Cluso99Cluso99 Posts: 18,069
    Rayman wrote: »
    Is there a way to have the preprocessor work with a Spin2 file that is included in a c program?

    I have a USB driver as part of a c code and it has the basepin defined like this:
    '------------------------------------------------------------------------------
    ' P2-ES USB Host (Master) x 2 Accessory Board I/O group base pin:
            USB_BASEPIN = 16'12'16 ' + offsets for ES-64006 Serial Host board
    '------------------------------------------------------------------------------
    

    But, I'd like to have all of the pin definitions in a separate file...

    The #INCLUDE is the best and easiest way, using a CON section. But pnut and PropTool do not support #INCLUDE :(

    You can also make it an OBJ and reference it as xxx.pinxx
  • JRoark wrote: »
    @ersmith A real world example: I'm noodling about making a replacement for STR$() that is sensitive to the type of variable passed to it. For speed, if the variable is an integer, then we branch internally to a loop that avoids the need for floating point, but if the variable is a float, then we branch to a different, slower (float-based) handler.

    I think, if you're very careful about the algorithm, you might be able to code it as:
    Any(T) FUNCTION Str$(num as T) as string
       ' write code to convert num to string here
       ' the code cannot assume num is integer, but if it is
       ' integer then all the operations will be integer only
    END FUNCTION
    

    The tricky part is writing the body of the function so it will work for either floats or integers. I think you'd want to generate the integer portion backwards (dividing by 10 until the value is < 1), then generate the fractional part (if any) by multiplying by 10 until the value is 0 or until some cut-off is reached. The fractional part will always be 0 for integers, of course, so that won't impede the performance much at all for the integer only case.

  • RaymanRayman Posts: 14,648
    edited 2021-01-18 18:33
    Thanks for the mouse help, all.
    But, I now see that the 2020 version of the @garryj mouse/kb driver takes the usb pin numbers as inputs. I switched to that and all better now.
  • JRoarkJRoark Posts: 1,215
    edited 2021-01-19 01:49
    I think, if you're very careful about the algorithm, you might be able to code it as:
    Any(T) FUNCTION Str$(num as T) as string
       ' write code to convert num to string here
       ' the code cannot assume num is integer, but if it is
       ' integer then all the operations will be integer only
    END FUNCTION
    

    I’ll definitely take a shot at this! But I gotta admit... it was pretty funny that you managed to say that first part with a straight face knowing my code comments tend to include things like “hold my beer!” :)
  • RaymanRayman Posts: 14,648
    ersmith wrote: »
    There's documentation on the SD card file system now in general.pdf:
    So for example to change to using pins 0-3 for these you would add `-DPIN_MISO=0 -DPIN_MOSI=1 -DPIN_SS=2 -DPIN_CLK=3` to the command line.

    @ersmith Any chance this could be done via defines in the code instead of on the command line?

    It'd be more convenient to tie all my pin settings to one "basepin" setting...

  • ersmith wrote: »
    ke4pjw wrote: »
    Possible bug in flexprop spin2 compiler:
    It'll be fixed in the next release of the compiler, although alas this fix will come at a performance cost for the common case of reading a single pin.

    For now, you can use the replacement function below (it should work in PNut/PropTool as well):
    pub mypinread(x) : y
      y := (x & $20) ? outb : outa
      y >>= x       ' implicitly relies on only bottom 5 bits being used
      x >>= 6       ' now x has number of pins to use
      y := y ZEROX x
    
    Eric, I have a question and a comment.

    Does this bug also exist for pinwrite? I haven't been able to check it on a test harness yet :)

    Also, I had to modify your code to get it to read:
    pub mypinread(x) : y
      y := (x & $20) ? inb : ina
      y >>= x       ' implicitly relies on only bottom 5 bits being used
      x >>= 6       ' now x has number of pins to use
      y := y ZEROX x
    


    As always, thank you sir!

    --Terry
  • Rayman wrote: »
    ersmith wrote: »
    There's documentation on the SD card file system now in general.pdf:
    So for example to change to using pins 0-3 for these you would add `-DPIN_MISO=0 -DPIN_MOSI=1 -DPIN_SS=2 -DPIN_CLK=3` to the command line.

    @ersmith Any chance this could be done via defines in the code instead of on the command line?

    It'd be more convenient to tie all my pin settings to one "basepin" setting...

    Unfortunately no, that's not really possible.

    The "correct" solution is to make the SD access functions parameters to the fat file system, to that it could be made not only pin independent but also device agnostic. Someday I'd like to do that, unless someone beats me to it.
  • ke4pjw wrote: »
    Does this bug also exist for pinwrite? I haven't been able to check it on a test harness yet :)
    No, pinwrite should already be able to handle multiple pins.
    Also, I had to modify your code to get it to read:
      y := (x & $20) ? inb : ina
    
    Aargh! Thanks for catching this typo. It's in the 5.0.8-beta too, unfortunately -- I'll fix it before the final release.

    Cheers,
    Eric
  • @ersmith

    I'm using flexbasic on the P2 and have finally figured how to use the smartpin D/A.
    So now I want to output an audio file.
    I need to store about 10 seconds of 8 bit audio at 10KHz so about 100 Kbyte.
    I could load the data via a serial port into a predefined ubyte array, or somehow 'load' a pc file into hub ram.
    If I use serial I 'think' I would need another serial port on the prop so that I don't reset the prop while changing serial device.
    I have no idea how to 'import' or 'include' a binary file into hub ram, but that would seem to be the simplest solution.
    Hope you can help

    Dave
  • @tritonium I'm not Eric, but I did spend the night at a Holiday Inn Express once.

    Have you considered putting it on an SD card so you can read it in directly from that? This would give you the ability to store files far larger than P2 memory, and you could have multiple sounds at your fingertips. FlexBASIC supports a really simple interface with the SD. If you need some example code to get you started, holler at me.
  • If you make a simple Spin2 object with just the minimum stuff in it and then add a FILE directive with a label. Then you can include that object in your BASIC or C source and it will get compiled in and you can access it directly from the label.
  • tritoniumtritonium Posts: 543
    edited 2021-01-22 23:11
    Hi JRoark and Roy Eltham.

    Thanks for your taking the time to help but-

    I will get an sd card working one of these days, but the way I do things is to write my own utilities and copy and paste them in as necessary. Bit banging is straight forward but the smart pins are baffling to me. I searched everywhere for D/A examples but could not get then to work in Flexbasic. Eventually I almost accidentally got it to work by mixing commands.
    I could make a big aschii hex file of the audio data and copy and paste into the code as an array as you might a font but there must be a way to directly load an array with binary data without resorting to serial code.
    I don't know how to use spin- I'm strictly a 'Basic' kind of guy.
    Resorting to libraries is a last resort for me- the challenge is to get it going using simple code. Somehow bolting libraries into code or copy pasting others code is not appealing to me. I have no end 'product' in mind just to amuse myself pottering around.
    I like to read the code of others and learn what needs to be done, but then write my own code when I think I know what to do.
    This may seem rediculous to you guys.

    From the FlexBasic manual
    Include files
    A .bas file may also be included with the #include directive. [i][b]
    This places all of the code in the included file directly into the main file,
    as if it had been typed in by the user[/b][/i]. The downside of this is that there is
    no namespace protection, and any test code outside of sub and function will be executed. 
    To avoid this, use #ifdef TEST or something similar around such code.
    

    That seems to imply that I can do-
    dim shared as ubyte audio(100_000)= {_
    #include "audio_file.txt"_
    {
    

    However it also says it has to be a .bas file..
    I am about to try that but don't feel confident..

    Dave

  • I think™ what you want is

    asm shared
    audio byte
    file "audio_file.raw"
    end asm
    
  • tritoniumtritonium Posts: 543
    edited 2021-01-22 23:34

    Hi Wuerful_21

    re

    I think™ what you want is

    asm shared
    audio byte
    file "audio_file.raw"
    end asm

    The doc's say-
    An asm shared block declares some assembly code and/or data that exists outside of any function. Such code must be explicitly executed with a cpu directive.

    and
    CPU Used to start a subroutine running on another CPU.

    Thanks but; Sorry- I don't get it.. another cpu?

    Dave

  • In this case the ASM SHARED is just used because it allows defining data with Spin DAT syntax. No code, no CPU.
  • @Tritonium The #INCLUDE directive has a caveat or two, including that it needs to stand alone, ie, it cant follow anything else as an argument, or in the way you have typed it. It will however faithfully insert another file inline, but it has to be a .BAS file. If that .BAS file was a single, huge array definition and its associated data, it should work.

    I think Wuerfel's suggestion will also get you there, but I need to get to my compiler laptop to see if this works.

    In truth, every time I've needed to read-in data, I've done it via the SD card, but I understand where you are coming from.
  • ersmithersmith Posts: 6,053
    edited 2021-01-23 00:11
    @tritonium
    #include "foo.txt" literally copies the contents of "foo.txt" into the source code, not into the final compiled data. So it won't do what you want.

    Roy was correct that you could use Spin2's FILE directive to include binary data, but as Wuerfel_21 points out there's an even easier option, which is to use "asm shared". You can use asm shared to declare data (the docs are a bit out of date):
    asm shared
    myblock
         file "somefile.bin"
    end asm
    
    declares a variable "myblock" of type "ubyte" which will contain all of the data from "somefile.bin".

    EDIT: note that "myblock" is of type "ubyte", so only the first byte of it is easily accessible. To get at all of the data you'll need to use a pointer. See an example below.
  • Another option is to convert your data to ASCII and include it with "data" statements, or as an initialized array. These would be more "portable" solutions if you want your BASIC code to run elsewhere, but they're not as easy as the asm shared.
  • Whoops! My mistake. You cannot directly use labels from the assembly code in BASIC, you have to use a pointer. Makes it slightly more awkward, but something like the following should work:
    asm shared
    mydata
       file "somedata.bin"
    end asm
    
    dim p as ubyte ptr
    
    p = @mydata   ' get a pointer to mydata
    for i = 0 to 7    ' print the first 8 bytes of the file
      print p(i)
    next i
    
  • tritoniumtritonium Posts: 543
    edited 2021-01-23 01:01
    Thanks Eric and everyone.

    That's given me something to get my teeth into tomorrow.

    This dates back to BBC micro days when I made a race countdown announcer to start model yacht races with a handheld box, internal speaker and Z8 cpu and 128Kbyte eprom for code and data. It replaced the tape recorder they used which was unreliable and clumsy to use. I used the BBC micro to sample the audio and break down into single words and bits of words which I joined in the program to make sentences bangs and bells. I thought I would do it all in a single cpu see how small I could make it. Back in those days people didn't believe there was no tape involved- digital audio was not widely known. Surprisingly for the low sample rate and data size it sounded really good- at least as good as the tape recorder it replaced.
    These days using SD audio readers on ebay for a few pounds the whole thing becomes trivial but after finding the audio data on an old floppy I thought I would revisit this and remind myself how I sounded back then :)

    Dave
  • Hi

    Just to let you know that Eric's solution works beautifully. :smiley:

    Thanks again for your help.

    Dave
  • @ersmith

    I'm having this error when I enable debug in Raspberry Pi:
    "/home/pi/Downloads/flexprop/bin/flexspin" -2 -l -D_BAUD=230400 -O1 -g -I "/home/pi/Downloads/flexprop/include" "/home/pi/Documents/encoder_test_program.spin2"
    Propeller Spin/PASM Compiler 'FlexSpin' (c) 2011-2021 Total Spectrum Software Inc.
    Version 5.0.8 Compiled on: Jan 23 2021
    Unable to open file `libsys/fmt.c': No such file or directory
    encoder_test_program.spin2
    child process exited abnormally
    Finished at Sat Jan 23 13:29:43 2021

    Is there a fix or something I should install to have that file available?
  • jrullan wrote: »
    @ersmith

    I'm having this error when I enable debug in Raspberry Pi:
    "/home/pi/Downloads/flexprop/bin/flexspin" -2 -l -D_BAUD=230400 -O1 -g -I "/home/pi/Downloads/flexprop/include" "/home/pi/Documents/encoder_test_program.spin2"
    Propeller Spin/PASM Compiler 'FlexSpin' (c) 2011-2021 Total Spectrum Software Inc.
    Version 5.0.8 Compiled on: Jan 23 2021
    Unable to open file `libsys/fmt.c': No such file or directory
    encoder_test_program.spin2
    child process exited abnormally
    Finished at Sat Jan 23 13:29:43 2021

    Is there a fix or something I should install to have that file available?

    What's in your /home/pi/Downloads/flexprop/include directory? There should be a subdirectory called "libsys", and inside that a file called "fmt.c".

    I notice your directory is "Downloads/flexprop". Did you install by downloading a file? Or did you build with "make install"? If the latter, you do have to specify the directory you want to install to -- it defaults to $HOME/flexprop, so to put it somewhere else do:
    make install INSTALL=/home/pi/Downloads/flexprop
    
Sign In or Register to comment.