Shop OBEX P1 Docs P2 Docs Learn Events
Catalina - Page 4 — Parallax Forums

Catalina

124

Comments

  • RossHRossH Posts: 5,336

    @Ariba said:

    @Cluso99 said:

    @RossH said:
    In the early Propeller 1 days I tried to get vrious Propeller users to adopt common standard for memory management and inter-cog communications to help solve such inter-operability issue, but I soon figured out that trying to get any two Propeller developers to agree on anything was worse than herding cats! :)

    Ross.

    Nothing's changed :(

    IMO Flexprop has solved all the problems we had on the P1 with using the same driver for different languages. If you write your driver in Spin2 you can use it with PNUT, PropTool, flexSpin, flex-C and flexBasic.
    Also it's no longer necessary to always start a new cog for assembly code, often inline assembly can run in the same cog. And the smartpins also are a kind of standard for drivers, because they are built in in hardware and accessible from all the cogs.

    Andy

    Actually, most drivers are written mostly in pure PASM. It is only the interface code that is written in other languages. If Eric's tool can translate that code between languages then it solves the problem.

  • @RossH said:

    @ersmith said:

    @Rayman said:
    How does one use a PASM driver?

    Another approach that can work is converting the PASM driver from Spin to C using "spin2cpp --ccode".

    This looks like an interesting approach. Thanks for pointing it out. This would help enormously with the main part of the work, which is translating the Spin access functions to C. But the other part is that PASM drivers often make fairly arbitrary use of Hub RAM, which may have to be modified to work successfully with the language runtime and the other drivers.

    Actually in my experience most Spin drivers only use RAM that's defined in their DAT section -- otherwise they couldn't work together even in Spin!

    Hooking the drivers up to the language runtime is another matter. For many drivers it would be nice to have access via the usual language functions. One way to handle this is to provide a special version of open() that handles drivers. For example, most character I/O drivers provide txchar() and rxchar() methods (or the equivalent). In C you could hook these up to the runtime via something like:

       // spin_data is the DAT area for the driver
       FILE *f;
       spin_init(&spin_data, driver_init_args);  // initialize Spin driver
       f = fopen_driver(&spin_data, &spin_txchar, &spin_rxchar); // hook up to a FILE struct
       fprintf(f, "Hello, driver!\n");
    

    FlexBASIC has a facility similar to this. I haven't tried to add it to C yet, but if Catalina already does something like it then I'd be happy to follow your lead @RossH .

  • RaymanRayman Posts: 13,797

    Does Catalina for P2 have any msleep() or sleep() functions?
    Would be nice to have the same ones as FlexC, like _waitms(), etc...

    At least there's _waitx()

  • RaymanRayman Posts: 13,797

    I've made some progress getting a simple Spin2 VGA driver to work via Spin2Cpp.
    With the pin settings hard coded, can now get VGA video output.

    But, I had to remove the VAR section.
    It seems using a VAR section results in there being a structure that you have to pass to the created C function.
    However, for some reason, I can't find a way to make that work with Catalina.
    Could be that I don't understand C structure usage with pointers and references well enough.
    But, I think I tried everything and nothing worked...

    Also, Spin2Cpp doesn't seem to allow AUGS (yet, it says).
    And, using LOC results in a warning that code will have to be moved.

    Anyway, I seem to have video output and also the bird image.
    Only trouble is getting the pointer to the bird image to the driver.
    Haven't found a way to get that working yet.

  • RaymanRayman Posts: 13,797

    Does Catalina have a way of embedding a large binary file? (Such as a bitmap image).

    I know the usual way is to convert that to a text file, but I'm not a huge fan of that....

  • @Rayman : Typically you'd declare a global structure and then pass its address to the functions, like:

    #include "vgatext.h"
    
    vgatext myvars;
    ...
    vgatext_start(&myvars, pinbase);
    vgatext_str(&myvars,  "hello, world!");
    

    The AUGS and LOC will be problems only if relocation is required, which is typically if the PASM code contains direct references to DAT variables (with @). If the PASM uses the ptra parameter to find everything then I don't think there will be an issue.

  • RaymanRayman Posts: 13,797

    @ersmith Thanks, that does work. What tripped me up was trying to declare variables in the middle of the code. Forgot that doesn't work in ANSI C. Relocated to top of routine and now it compiles.

    Think it's actually working now!

  • RaymanRayman Posts: 13,797
    edited 2021-10-19 21:01

    Going back to original form of driver, I think I'm seeing an issue with COGINIT.
    If the Spin2 code is given cog #16 as a constant, then Spin2Cpp turns that into a "_cognew" and it works.
    But, if the cog# is in a variable, then it generates a "coginit" (without the underscore), which doesn't compile.
    Adding an underscore gets it to compile, but it doesn't work.

    Ok, looks like the Catalina version of coginit has the cog # as the last parameter instead of the first...

    Seems I can't figure out the Catalina version of coginit... The docs refer to test_spinc.c which has this: if (_coginit ((int)data>>2, (int)flash_led_array>>2, ANY_COG) == -1) {
    Not sure why these shifts are there...

    Amazingly, it actually works when the shifts are added... This is strange:
    self->cog = _coginit(p>>2,(int32_t)(((int32_t *)((uint32_t)&dat[0]>>2))), CogNumber) - 1;

  • RossHRossH Posts: 5,336

    @ersmith said:

    Actually in my experience most Spin drivers only use RAM that's defined in their DAT section -- otherwise they couldn't work together even in Spin!

    Yes, that's the problem. This works fine in Spin, where driver code typically expects to have direct access to statically allocated areas of Hub RAM. But it doesn't work so well if you want to do dynamic allocation of buffers etc.

  • RossHRossH Posts: 5,336

    @Rayman said:
    Does Catalina for P2 have any msleep() or sleep() functions?
    Would be nice to have the same ones as FlexC, like _waitms(), etc...

    At least there's _waitx()

    msleep is defined in propeller.h Perhaps we should also have added it to propeller2.h

  • RossHRossH Posts: 5,336
    edited 2021-10-19 21:34

    @Rayman said:
    Does Catalina have a way of embedding a large binary file? (Such as a bitmap image).

    I know the usual way is to convert that to a text file, but I'm not a huge fan of that....

    Yes - convert it to a text file! :)

    Catalina has a bindump utility that does that.

  • RossHRossH Posts: 5,336
    edited 2021-10-19 21:31

    @Rayman said:
    Going back to original form of driver, I think I'm seeing an issue with COGINIT.
    If the Spin2 code is given cog #16 as a constant, then Spin2Cpp turns that into a "_cognew" and it works.
    But, if the cog# is in a variable, then it generates a "coginit" (without the underscore), which doesn't compile.
    Adding an underscore gets it to compile, but it doesn't work.

    Ok, looks like the Catalina version of coginit has the cog # as the last parameter instead of the first...

    Seems I can't figure out the Catalina version of coginit... The docs refer to test_spinc.c which has this: if (_coginit ((int)data>>2, (int)flash_led_array>>2, ANY_COG) == -1) {
    Not sure why these shifts are there...

    Amazingly, it actually works when the shifts are added... This is strange:
    self->cog = _coginit(p>>2,(int32_t)(((int32_t *)((uint32_t)&dat[0]>>2))), CogNumber) - 1;

    The Propeller 1 used 14 bit addresses for coginit - i.e. it expected the addresses to be on long boundaries and did not use the bottom 2 bits. I probably should have hidden this from the C user!

  • RaymanRayman Posts: 13,797
    edited 2021-10-19 21:55

    Ok, thanks, that explains the shifts.
    It would be good to not see the shifts and also have the parameters in the same order as Spin2 and FlexC.

    Also, having the sleep functions added to propeller2.h would be great.

  • RossHRossH Posts: 5,336

    @Rayman said:
    Ok, thanks, that explains the shifts.
    It would be good to not see the shifts and also have the parameters in the same order as Spin2 and FlexC.

    Also, having the sleep functions added to propeller2.h would be great.

    @Rayman said:
    Ok, thanks, that explains the shifts.
    It would be good to not see the shifts and also have the parameters in the same order as Spin2 and FlexC.

    Also, having the sleep functions added to propeller2.h would be great.

    Catalina already had a _coginit(), so when @ersmith and I agreed on a common "propeller2.h" we agreed that we would use:

    _cogstart_PASM(cog, pgm, ptr)
    _cogstart_C(func, arg, stack_base, stack_size);
    
    

    If you want C compiler interoperability, these are what you should be using - i.e. use _cogstart_PASM() in place of _coginit().

    If @ersmith wants to add definitions for _sleep() and _msleep() to "propeller2.h" then I would be happy to do that.

    Ross.

  • RossHRossH Posts: 5,336

    @RossH said:

    @Rayman said:
    @RossH

    Is there a way to set the P2 clock to an arbitrary value?

    There are no C function to set the clock mode or frequency (you can fetch them but not change them). You can only do this in Catalina_platforms.inc, and it happens at initialization time. The main reason for this is that changing the clock run time breaks too many things - e.g. nearly all the driver plugins, because they would not know about the clock change. However, it does occur to me that it might be useful to add this capability for deeply embedded applications that do not use any plugins.

    Hmm. Clearly my memory is not what it used to be ... there is indeed a function to do this defined in "propeller2.h" ...

    _clkset(clkmode, clkfreq)
    
    

    ... along with macros to simplify using it ...

    /*
     * P2 32 Bit Clock Mode (see macros below to construct)
     *
     *      0000_000e_dddddd_mmmmmmmmmm_pppp_cc_ss
     *
     *   e          = XPLL (0 = PLL Off, 1 = PLL On)
     *   dddddd     = XDIV (0 .. 63, crystal divider => 1 .. 64)
     *   mmmmmmmmmm = XMUL (0 .. 1023, crystal multiplier => 1 .. 1024)
     *   pppp       = XPPP (0 .. 15, see macro below)
     *   cc         = XOSC (0 = OFF, 1 = OSC, 2 = 15pF, 3 = 30pF)
     *   ss         = XSEL (0 = rcfast, 1 = rcslow, 2 = XI, 3 = PLL)
     */
    
    // macro to calculate XPPP (1->15, 2->0, 4->1, 6->2 ... 30->14) ...
    #define XPPP(XDIVP) ((((XDIVP)>>1)+15)&0xF)  
    
    // macro to combine XPLL, XDIV, XDIVP, XOSC & XSEL into a 32 bit CLOCKMODE ...
    #define CLOCKMODE(XPLL,XDIV,XMUL,XDIVP,XOSC,XSEL) ((XPLL<<24)+((XDIV-1)<<18)+((XMUL-1)<<8)+(XPPP(XDIVP)<<4)+(XOSC<<2)+XSEL) 
    
    // macro to calculate final clock frequency ...
    #define CLOCKFREQ(XTALFREQ, XDIV, XMUL, XDIVP) ((XTALFREQ)/(XDIV)*(XMUL)/(XDIVP))
    

    I even included a program to test it ... demos\p2\test_p2_clock.c

    However, the warning given above still applies - i.e. actually using this function may stop some drivers from functioning correctly.

    Ross.

  • evanhevanh Posts: 15,126
    edited 2021-10-20 07:16

    @RossH said:
    However, the warning given above still applies - i.e. actually using this function may stop some drivers from functioning correctly.

    The way I've dealt with that is relaunch the relevant drivers upon each frequency change. As long as clkfreq system variable is both updated and used then no issue.

  • RossHRossH Posts: 5,336

    @evanh said:

    @RossH said:
    However, the warning given above still applies - i.e. actually using this function may stop some drivers from functioning correctly.

    The way I've dealt with that is relaunch the relevant drivers upon each frequency change. As long as clkfreq system variable is both updated and used then no issue.

    That's certainly one solution! :)

    The function to do this is available, but I'd still like to understand why you might need to change the clock frequency at run-time. Saving power is one I can think of, but in that case you would probably want to restore the original clock frequency when you needed to use the drivers anyway, rather than arbitrarily change it on-the-fly.

    Anyone have any other applications?

  • evanhevanh Posts: 15,126
    edited 2021-10-20 11:44

    For me it has been testing, both hardware and software cases. Trying multiple clock rates to log/observe the behaviour.

    I had been doing everything in assembly until this year. I've got interested in having it work with compiled testing as well. Inlining the test code means I can mix with others' work. The plan9 filesystem support is a good one. Only just seen that in action and like it already.

  • RaymanRayman Posts: 13,797
    edited 2021-10-20 12:14

    Don’t need to change on the fly… but there are some other freqs I like such as 297 and 300 MHz .. oh, and 250 MHz

    Be nice to have easy way to start with those.

  • RaymanRayman Posts: 13,797
    edited 2021-10-20 11:49

    @RossH Could be that FlexC syntax has changed now that Spin2 docs are published

    So there’d be commonality between languages…

  • ersmithersmith Posts: 5,900
    edited 2021-10-20 15:42

    @RossH said:
    Catalina already had a _coginit(), so when @ersmith and I agreed on a common "propeller2.h" we agreed that we would use:

    _cogstart_PASM(cog, pgm, ptr)
    _cogstart_C(func, arg, stack_base, stack_size);
    
    

    If you want C compiler interoperability, these are what you should be using - i.e. use _cogstart_PASM() in place of _coginit().

    Ah, right. I'll need to update spin2cpp to use those for P2.

    If @ersmith wants to add definitions for _sleep() and _msleep() to "propeller2.h" then I would be happy to do that.

    I have _waitsec(), _waitms() and _waitus() instead (which are the names used in Spin2 but with an underscore prepended).

  • RossHRossH Posts: 5,336

    @ersmith said:
    I have _waitsec(), _waitms() and _waitus() instead (which are the names used in Spin2 but with an underscore prepended).

    Ok. I'll add those to the next release. If you need them in the meantime, just add the following #defines to Catalina's "propeller2.h".

    #define   _waitus(usecs)  _waitx((usecs)*(_clockfreq()/1000000))
    #define   _waitms(msecs)  _waitx((msecs)*(_clockfreq()/1000))
    #define   _waitsec(secs)  _waitx((secs)*_clockfreq())
    
    

    These will be accurate enough for most purposes. Do you use a more accurate method?

    Ross.

  • evanhevanh Posts: 15,126

    Ouch! Not using the system variable!

  • @RossH said:

    @ersmith said:
    I have _waitsec(), _waitms() and _waitus() instead (which are the names used in Spin2 but with an underscore prepended).

    Ok. I'll add those to the next release. If you need them in the meantime, just add the following #defines to Catalina's "propeller2.h".

    #define   _waitus(usecs)  _waitx((usecs)*(_clockfreq()/1000000))
    #define   _waitms(msecs)  _waitx((msecs)*(_clockfreq()/1000))
    #define   _waitsec(secs)  _waitx((secs)*_clockfreq())
    
    

    These will be accurate enough for most purposes. Do you use a more accurate method?

    For waitms and waitsec I loop so that the waits can last longer than the 32 bit system clock rollover. Some users asked for this.

  • RossHRossH Posts: 5,336

    @evanh said:
    Ouch! Not using the system variable!

    If you are talking about the calls to _clockfreq(), Catalina translated this call to rdlong r0, #$14. I don't see how you could do much better than that. Or are you referring to something else?

    Ross.

  • evanhevanh Posts: 15,126

    Oh, sorry. That's good.

  • RossHRossH Posts: 5,336

    @ersmith > @ersmith said:

    @Rayman said:
    How does one use a PASM driver?

    Another approach that can work is converting the PASM driver from Spin to C using "spin2cpp --ccode".

    Hello Eric

    I've had a chance to have a play with your spin2cpp and I am impressed. I've not got anything working on the Propeller 2 yet, but I have on the Propeller 1. However, on the Propeller 1 we don't have a common "propeller.h" file agreed (as we do for "propeller2.h") and I doubt anyone would be impressed if we went and revised it now.

    So I have another suggestion. Here is an extract of what spin2cpp currently produces (this example is from processing FullDuplexSerial.spin):

    #include <propeller.h>
    
    ...
    
    #ifndef __FLEXC__
    #define waitcnt(n) _waitcnt(n)
    #define coginit(id, code, par) _coginit((unsigned)(par)>>2, (unsigned)(code)>>2, id)
    #define cognew(code, par) coginit(0x8, (code), (par))
    #define cogstop(i) _cogstop(i)
    #endif /* __FLEXC__ */
    
    

    Now, this doesn't quite work for Catalina "out of the box" because it is missing some definitions used in FullDuplexSerial.c - for example, the generated code uses _CNT and _clkfreq but Catalina's propeller.h file has no definitions of these. Instead, it has CNT and _clockfreq(). When I add these (plus a few other definitions), it works. But I don't want to have to do that every time, and I'm sure you don't want to have to modify spin2cpp every time we find a need for another new definition.

    So, instead of adding these as new hardcoded #defines in spin2cpp, I would suggest generating something like:

    #define __SPIN2CPP__
    #include <propeller.h>
    

    This would allow all current (and future) compiler constructors to detect that the context in which propeller.h is being used is for a program generated by spin2cpp, and any required definitions could be added (without affecting any existing programs that already use propeller.h).

    For instance, in Catalina's propeller.h I could add:

    #ifdef ___SPIN2CPP__
    #define _CNT CNT
    #define _clkfreq _clockfreq()
    #endif
    
    

    You could also remove the hardcoded stuff about FLEXC from spin2cpp.c and just update FlexC's propeller.h whenever there is a need to add a new #define. The same thing would work for propeller2.h of course.

    Let me know what you think.

    Ross.

  • RossHRossH Posts: 5,336

    @RossH said:
    I've not got anything working on the Propeller 2 yet ...

    @ersmith

    Ok, now I have an example working on the Propeller 2. This is a really impressive piece of work. I'm glad I came back to the Propeller just to see this.

    However, I have some of the same problem on the Propeller 2 as on the Propeller 1 - i.e. the generated code makes assumptions about things being defined that Catalina doesn't have (it generally does have them, but not by the same name). However, once we get that sorted it looks like this is going to be a good option for porting SPIN/PASM code to C ... ok, or to C++ for those who still haven't figured out what a terrible language that is :)

    I assume the Spin portions will be 100% portable, but I've started looking at spin2cpp itself to see what types of PASM can be successfully ported and what can't. (you probably already know all this). But for "well behaved" Spin/PASM programs (without yet quite knowing exactly what "well behaved" means!) I can see that it is going to be possible to automatically turn those into Catalina plugins with just a little additional work. It may even help implement a feature I had intended to add to Catalina at some point, which was to make all the plugins dynamically loadable instead of having to load them all at initialization time.

    Ross.

  • The function to do this is available, but I'd still like to understand why you might need to change the clock frequency at run-time.

    I've only ever done it once (for a DEF CON badge). If there was no IR interaction with other badges for 15 minutes (e.g., in the hour or two you get a nap at DEF CON), the badge would shutdown all cogs but one , and put that cog in RCSLOW mode. If IR is detected, the badge rebooted to normal mode.

  • RaymanRayman Posts: 13,797
    edited 2021-10-21 20:45

    Ok, after figuring a few things out, seems can use Spin2Cpp to convert the simple VGA driver (as is) to Ansi C (with just one after the fact change to coginit).

    Main things were getting the clock high enough (add "-C MHZ_260" to build settings).
    and, get coginit right in the .c driver file: //Note: Need to change coginit to _cogstart_PASM at end of this file

Sign In or Register to comment.