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

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

17576788081123

Comments

  • RaymanRayman Posts: 14,762

    Thanks. The code is all C, except for the curses part, which I've converted from C++ to C.


    I think I've fixed the problem by making these problem windows static. Well, defined on the heap, but only once, to the maximum size ever needed.

    Seems to have fixed the issue.


    It looked like there was some kind of leakage before. It was as if free was mostly, but not completely working. Every call to inventory ate some memory and eventually it runs out.


    Anyway, all better now. :)

  • tritoniumtritonium Posts: 543
    edited 2021-02-01 22:11

    Hi


    @ersmith - I have an interesting one for you :) on prop2


    I wrote a simple bit of code to test lighting a string (8) of leds :-



    const ledpin7=24 

    const ledpin0=31


    ledcount

    do

    loop


    '----------------- SUB -----------------


    sub ledcount  

    dim as ulong num,dlay,tsec

    tsec=clkfreq/10


    num=0

    direction(ledpin7,ledpin0) = output

    dlay=getcnt()+tsec

    do

    output(ledpin7,ledpin0)= not(num)

    waitcnt dlay

    dlay+=tsec

    num+=1

    loop

    end sub


    '-----------------


    needed to pass values of the pins in the cpu command (to make this code work in another cog) so:


    const ledpin7=24 

    const ledpin0=31 


    ledcount(ledpin7,ledpin0)

    do

    loop


    '------------------- SUB -------------------------------

    sub ledcount(hp,lp)

    dim as ulong num,dlay,tsec


    tsec=clkfreq/10

    num=0

    direction (hp,lp) = output

    dlay=getcnt()+tsec

    do

    output(hp,lp)= not(num)

    waitcnt dlay

    dlay+=tsec

    num+=1

    print lp,hp

    loop

    end sub

    '=================================================

    Well this did not work- no led activity at all!

    It took a while before I realised I had the hi-lo order in the calling code back to front- but that should only have just reversed the order of the leds.

    So I re-ordered the 31,24 order and it worked as expected. After some more testing it seems that using the reversed order but on fewer leds the code then ran but the bits were shifted ie calling the sub with (21,26) then leds on pins 31 down to 26 count correctly; just shifted up 5 bits.

    I haven't found a combination of pins numbers to use all 8 leds.


    Wodya think?


    Dave

  • JRoarkJRoark Posts: 1,215
    edited 2021-02-01 21:54

    @tritonium

    Are you maybe getting tripped-up with how OUTPUT works? It's a bitfield. This video shows the code below producing output on 8 leds with I incrementing from 0 to 255. LSB on left, MSB on right. (Note: my LED driver is active low so the FOR/NEXT loop is backwards, but you get the idea)


    ledcount(31,24)

    '-----------------

    sub ledcount(hp,lp)

       dim i as ulong

       direction (hp,lp) = output

       do

          for i = 255 to 0 step -1

             output(hp,lp)= i

             pauseMS(100)

             print lp,hp, i

          next i

       loop

    end sub


    To illuminate all of the LEDS, you can output 0xFF. Or am I misunderstanding the question?


    EDIT: I cant upload a video. The forum has a 10 meg limit and doesn't like the file type. :(


    EDIT2: Run this code and see what your LEDs do:


    direction(31,24) = output

    do

       output(31,24) = &h0

       pauseMS(500)

       output(31,24) = &h55

       pauseMS(500)

       output(31,24) = &hAA

       pauseMS(500)

       output(31,24) = &hFF

       pauseMS(500)

    loop

  • Hi @JRoark


    Thanks but- the code works fine if NOT placed into a subroutine. It works both forward and backward. hi-lo and lo-hi

    Its not the bit order, but where the bits get placed. When passing (hp-lp) into a subroutine it expects the bit numbers in that order ie hp=31, lp=24 if I am to get the count out oriented correctly. That works correctly.

    However passing hp=24, lp=31 screws up not the bit order but the bit placement. Instead of using the correct pins (24 to 31) but displaying the led's in the reverse order, it actually moves the pin numbers themselves- ie, pins other than the ones specified get used. In the extreme case using pin 31 I think it must try to use port B and nothing is displayed.

    So if I ask it to use pins hp=21, lp=26 then it actually 'uses' pins 31 to 26 (incorrect) but counting backwards(correct)

    Its difficult to explain. I hope that is clearer.

    This ONLY happens in a subroutine when the pin numbers are passed.

    Using global variables it works.

    Dave

  • @tritonium Gotcha. I get it now. Let me go fiddle with that a bit. I love a good mystery!

  • RaymanRayman Posts: 14,762

    @ersmith Pure assembly code should work the same in Propeller Tool as with Fastspin, right? I haven't done pure assembly for a while, so maybe I forgot something...


    This Space Invaders code works on Prop Tool, but apparently not with FastSpin...

  • tritoniumtritonium Posts: 543
    edited 2021-02-01 23:19

    Hello again

    I stated 'using global variables it works'

    nope, Ive just realised it only works if the pins are constants and used as global values

    Passing pin numbers to a sub as variables does not work if sent lo-hi, instead of hi-lo.

    I think that is because Eric hard codes the patterns and inserts then into the assembler code with no calculations done in the code if constants are used.

    I 'think' its the way that Eric's assembler code works out the bit patterns.

    I've looked at the listing file and the code to get the bits to the correct port and in the right place is quite involved.

    I've tried adding comments in the listing file to explain to myself what's happening but I have to decode some of the mnemonics.


    Dave

  • @tritonium Thanks for the bug report, it's definitely using the wrong pin for the shift when the pins are given as variables in the "wrong" (lo, hi) order. For now you should always make sure to give it in (hi,lo) order. The assembly is a bit messy, but you can see what's going wrong if you have it output C code with spin2cpp; it always uses the second of the pins for the shift, when in fact it should be using the smaller of the two pins. I'll try to fix this in the next release.

    (The case where the pins are constant is handled differently, at compile time, and I think that comes out correctly as a result.)

  • @Rayman : The 8080 games emulator code is using ASMCLK, which is a funny macro not supported by FlexProp.

  • Hi Eric


    Yep, I've been looking at the listing file and the use of constants produces very different code.

    I doubt I would be bothering with the P2 if it wasn't for FlexBasic.

    Thanks for your tireless work- its appreciated.

    Dave

  • RaymanRayman Posts: 14,762
    edited 2021-02-02 01:49

    @ersmith Thanks! That was indeed the problem... Maybe the presence of that label could issue a warning?


    I've tried to convert this from pure assembly to Spin2, but doesn't seem to work... The VGA driver is running, but showing static junk instead of Space Invaders...

    The .._RJA2 version works as pure assembly, the _RJA3 version is attempt at Spin2 version, but doesn't work...

    I'm sure I'm missing something obvious...

  • JRoarkJRoark Posts: 1,215
    edited 2021-02-02 02:02

    @tritonium @ersmith

    I'm a little late to the game, but here is a truth table of sorts for the following code:

    ledcount(14,21) '<--- change to any pin range, see the Truth Table below
    
    '-----------------
    sub ledcount(hp,lp)
    direction(hp,lp) = output
    
    do
       output(hp,lp) = &h0
       print "00"
       pauseMS(3000)
       output(hp,lp) = &hFF
       print "FF"
       pauseMS(3000)
    loop
    end sub
    

    Here is the truth table. The first column is the calling values, the second column is the result of outputing a "00h:, and the last column is outputing a "FFh":

    '                  Send "00" Send "FF"
    '                 HHHH_HHHH   LLLL_LLLL
    ' -------------------------------------
    'ledcount(24,31) = LHHH_HHHH   HHHH_HHHH
    'ledcount(23,30) = LLHH_HHHH   HHHH_HHHH
    'ledcount(22,29) = LLLH_HHHH   HHHH_HHHH
    'ledcount(21,28) = LLLL_HHHH   HHHH_HHHH
    'ledcount(20,27) = LLLL_LHHH   HHHH_HHHH
    'ledcount(19,26) = LLLL_LLHH   HHHH_HHHH
    'ledcount(18,25) = LLLL_LLLH   HHHH_HHHH
    'ledcount(17,24) = LLLL_LLLL   HHHH_HHHH
    'ledcount(16,23) = HLLL_LLLL   HHHH_HHHH
    'ledcount(15,22) = HHLL_LLLL   HHHH_HHHH
    'ledcount(14,21) = HHHL_LLLL   HHHH_HHHH
    'ledcount(13,20) = HHHH_LLLL   HHHH_HHHH
    'ledcount(12,19) = HHHH_HLLL   HHHH_HHHH
    'ledcount(11,18) = HHHH_HHLL   HHHH_HHHH
    'ledcount(10,17) = HHHH_HHHL   HHHH_HHHH
    'ledcount(9,16)  = HHHH_HHHH   HHHH_HHHH
    

    PS: I HATE this damn editor! AGH!!!

  • @Rayman ,

    I tried a while ago to run space invaders and saw it would not work with flexprop. The clock never changes and is always at 20mhz for spin2.

    Mike

  • @JRoark

    Yes can confirm using ledcount(17,24) gives the result you would expect from ledcount(24,31)
    Well done Shirlock- I like your method of testing.
    Dave

  • @iseries , @Rayman : You guys are talking about trying space invaders with flexspin, aren't you getting a compile error on the ASMCLK? Do you have an older version of flexspin? I added an error for ASMCLK back in 5.0.3.

  • RaymanRayman Posts: 14,762

    I don't remember getting an error message, but maybe I didn't notice, or I had an old version, I'll check.

    But, I've already gotten past that and the assembly only version runs fine with FlexSpin.

    Current problem is that I haven't been able to make it work when I add "PUB main()" to make it Spin2 and not pure assembly...

  • RaymanRayman Posts: 14,762
    edited 2021-02-03 01:34

    Code I'm working on uses sscanf() but this doesn't seem to work with FlexSpin C...
    Or, maybe I'm doing something wrong. (I had to look up what sscanf is...)

    Anyway, the code I'm trying to use looks like this:
    (void) sscanf(buf,"%d x %d\n", &lines, &cols);

    This causes the P2 to reboot...
    So, I tried adding this to simple_ls.c for testing and it gives some strange error on sscanf() line:

    int main()
    {
        ////RJA:  Testing
        int lines, cols;
        char* s = "25 x 80";
        char* f = "%d x %d\n";
        sscanf(s,f, &lines, &cols);
        printf("lines=%d, cols=%d",lines,cols);
    
  • @Rayman: yep, there's definitely a bug in the sscanf code. I'm sure that used to work, so it crept in recently. I'll try to get a fix soon. In the meantime, I'm afraid you'll have to work around it by using strtol() or some other way to read the values from the string.

  • RaymanRayman Posts: 14,762

    @ersmith Thanks for looking at this! I can get by without it for now...

    I noticed something with Plan 9... This game I'm working on saves and restores to file about 54 kB. I think if this were done using a buffer the speed would be OK. But, this code reads one long at a time and it takes forever (Ok, about 2 minutes or so). When I switch to uSD it's about 2 seconds. I imaging this is because the uSD is using a 512 byte read buffer.

    It's not a priority at all, but would it be possible in the future to add a read ahead buffer on the P2 side for Plan 9? Or, would that not help?

  • RaymanRayman Posts: 14,762

    Trying to figure out if this is bug in this code or FlexC...

    Code has a structure with a pointer to a function that gets executed sometimes.
    There came a time in the program when the value of this pointer was NULL.
    When NULL function is called, the P2 reboots...

    Here's the line that does this and above it is how I'm getting around it.

            if (*wire->d_func != NULL) //RJA added this to keep from crashing
                (*wire->d_func)(wire->d_arg);
    

    But, I don't know what is supposed to happen in C if you call a function this way with NULL...

  • But, I don't know what is supposed to happen in C if you call a function this way with NULL...

    Calling a null function is undefined behavior. Although most platforms will crash in one way or another.

  • @Rayman: the plan 9 file system already has a buffer, but all the host communication is happening at serial speed, which defaults to 230400 (i.e. very slow). Have you tried increasing the baud rate to 2000000 via _setbaud(2000000) (and passing the appropriate arguments to loadp2)?

  • And as @Wuerfel_21 pointed out, calling a NULL pointer can do anything at all. On the P2 it restarts the program (because the program starts at 0).

  • RaymanRayman Posts: 14,762
    edited 2021-02-03 23:14

    Ok thanks.

    Btw I did increase baud already ...
    Guess that’s just how it is.

  • RaymanRayman Posts: 14,762

    @ersmith said:
    And as @Wuerfel_21 pointed out, calling a NULL pointer can do anything at all. On the P2 it restarts the program (because the program starts at 0).

    I think I saw that this didn't clear the heap as it ran out of memory after this reboot. Can this be?

  • RaymanRayman Posts: 14,762

    @ersmith Minor issue... Flex C didn't like the printf with multiple lines of text in the print_instructions() function of the attached.

    I had to declare that text as a char* and then do printf on it to make it work.

    c
    c
  • @Rayman said:
    @ersmith Minor issue... Flex C didn't like the printf with multiple lines of text in the print_instructions() function of the attached.

    I had to declare that text as a char* and then do printf on it to make it work.

    I saw that as well and just broke print_instructions() into 2 functions and it compiled. Glad someone was able to diagnose to a better conclusion!

  • @Rayman said:

    @ersmith said:
    And as @Wuerfel_21 pointed out, calling a NULL pointer can do anything at all. On the P2 it restarts the program (because the program starts at 0).

    I think I saw that this didn't clear the heap as it ran out of memory after this reboot. Can this be?

    Yes. Do not rely on anything related to calling a NULL pointer. The memory will be messed up afterwards.

  • Might help to make the init code not re-entrant (i.e. overwrite first instruction with a jump into an error handler). IDK what that error handler would actually do though that'd be appropriate in all situations. What is done currently for other error cases? (divide by zero and whatnot)

  • @Wuerfel_21 said:
    Might help to make the init code not re-entrant (i.e. overwrite first instruction with a jump into an error handler). IDK what that error handler would actually do though that'd be appropriate in all situations. What is done currently for other error cases? (divide by zero and whatnot)

    Most error cases just set errno. Overwriting the first instruction with a jump to itself might be a good solution, it would cause a hang instead of a restart. I've thought of turning on an LED or something, but that could cause trouble for users who are using the pins for something other than LEDs.

Sign In or Register to comment.