Shop OBEX P1 Docs P2 Docs Learn Events
Catalina - ANSI C and Lua for the Propeller 1 & 2 - Page 17 — Parallax Forums

Catalina - ANSI C and Lua for the Propeller 1 & 2

11213141517

Comments

  • RossHRossH Posts: 5,569
    edited 2025-01-10 07:28

    Something I've been meaning to do for a while ...

    The Lua compile command (luac) has a really annoying syntax, requiring you to constantly enter long-winded commands like luac -o xxx.lux xxx.lua - and you can't even have the Lua filename before the -o option or it spits the dummy.

    I was planning to rewrite it but decided to just add a clua wrapper instead. I just uploaded it to github, but for SourceForge users, it is also in the attached in zip file.

    Just put clua.lua on your Catalyst SD card (I put it in the bin directory) and now you can just say clua xxx (or try clua -? for help).

    Ross.

  • Is it possible to prevent "illegal statement termination" while compiling a function that the declaration of a variable is done after a statement?

  • RossHRossH Posts: 5,569
    edited 2025-01-17 12:13

    @FredBlais said:
    Is it possible to prevent "illegal statement termination" while compiling a function that the declaration of a variable is done after a statement?

    No. ANSI C does not allow declarations after statements, unless they appear in a new block.

    The simplest solution is to just move the offending declaration before any statements in the block.

    For example, the code:

    #include <stdio.h>
    void main() {
       printf("hello world\n");
       int i = 1;
       printf("i = %d\n", i);
    }
    
    

    will generate:

    hello.c:4: illegal statement termination

    The preferred solution wold be to simply move the declaration - i.e. change the code to:

    #include <stdio.h>
    void main() {
       int i = 1;
       printf("hello world\n");
       printf("i = %d\n", i);
    }
    

    However, sometimes this is not so easy (e.g. if the initialization of i requires values calculated later). So another solution (which is always possible) is to introduce a new block to make the declaration appear before any statements that need it - for example:

    #include <stdio.h>
    void main() {
       printf("hello world\n");
       {
          int i = 1;
          printf("i = %d\n", i);
       }
    }
    
    

    In this case, either solution will fix the problem.

    Ross.

  • I'm trying to compile the MicroBlocks VM for the Propeller 2 (https://microblocks.fun/), I fixed a lot of the illegal statement termination but now I'm stuck at the code below
    source code : https://bitbucket.org/john_maloney/smallvm/src/dev/vm/

        static void *jumpTable;
    
        // initialize jump table
        void jumpTable[] = {
            &&halt_op,                  // stop this task
            &&stopAll_op,               // stop all tasks except this one
            &&pushImmediate_op,         // true, false, and ints that fit in 8 bits [-64..63]
            &&pushLargeInteger_op,      // ints that fit in 24 bits
            &&pushHugeInteger_op,       // ints that need > 24 bits
            &&pushLiteral_op,           // string constant from literals frame
    ...
        suspend:
            // save task state
            task->ip = ip - (int16 *) task->code;
            task->sp = sp - task->stack;
            task->fp = fp - task->stack;
            return;
        RESERVED_op:
        halt_op:
        codeEnd_op:
            sendTaskDone(task->taskChunkIndex);
            task->status = unusedTask;
            if (unusedTask == tasks[taskCount - 1].status) taskCount--;
            goto suspend;
        noop_op:
        comment_op:
            POP_ARGS_COMMAND();
            DISPATCH();
        pushImmediate_op:
            STACK_CHECK(1);
            *sp++ = (OBJ) arg;
            DISPATCH();
    ...
    
  • Sorry for bothering you about this repeatedly, but is there a reason you still only support ANSI C when the rest of the world has moved on? Your compiler has lots of neat features, but I'm not using a language that forces me to declare variables up-front before I'm ready to assign real values to them, as it's really bad coding practice. Even the ancient DSP compilers they make me use at work at least attempt to support basic C99 features like declarations after statements; at this point, most of them are GCC-based and support all the current standards. When's the last time you did a survey of what compilers that are still relevant in 2025 don't support declarations after statements even as an optional feature?

  • RossHRossH Posts: 5,569
    edited 2025-01-17 23:22

    @FredBlais said:
    I'm trying to compile the MicroBlocks VM for the Propeller 2 (https://microblocks.fun/), I fixed a lot of the illegal statement termination but now I'm stuck at the code below
    source code : https://bitbucket.org/john_maloney/smallvm/src/dev/vm/

    That code appears to be using the GCC "labels as values" extension to create a computed goto, as described here .

    This is not standard C and would probably not compile with any other C compiler. Add the -pedantic option to gcc to detect all such instances - there may be others and you will need to fix them all.

    In this particular case, you can convert that code to a C switch statement. A fairly clear comparison of the two ways of building a VM in C is given here. The gcc extension makes the code more efficient, but it is not portable.

    Ross.

  • ersmithersmith Posts: 6,149

    @FredBlais Catalina is a great compiler, but restricted to the C89 dialect of C. To compile later C dialects you'll need to back-port to C89 (which usually isn't too hard) and/or use another compiler. For code that uses C++ or some compiler-specific features you'll have to use a different compiler completely. There are several for the P2; all have their pluses and minuses, and it might be worth posting a question on the general C/C++ forum here.

  • RossHRossH Posts: 5,569

    @Electrodude said:
    Sorry for bothering you about this repeatedly, but is there a reason you still only support ANSI C when the rest of the world has moved on? Your compiler has lots of neat features, but I'm not using a language that forces me to declare variables up-front before I'm ready to assign real values to them, as it's really bad coding practice. Even the ancient DSP compilers they make me use at work at least attempt to support basic C99 features like declarations after statements; at this point, most of them are GCC-based and support all the current standards. When's the last time you did a survey of what compilers that are still relevant in 2025 don't support declarations after statements even as an optional feature?

    Catalina was originally intended to meet my own need for a C compiler for the Propeller 1, for a project that I completed long ago. I keep Catalina going because there is still no other compiler for the Propeller (1 or 2) that does everything I want. And Catalina is so simple that whenever I do find something else I want to be able to do, I can just add it. I could not do that with any other compiler.

    But if GCC suits your needs better, use that.

    Ross.

  • ersmithersmith Posts: 6,149

    @RossH said:

    @Electrodude said:
    Sorry for bothering you about this repeatedly, but is there a reason you still only support ANSI C when the rest of the world has moved on? Your compiler has lots of neat features, but I'm not using a language that forces me to declare variables up-front before I'm ready to assign real values to them, as it's really bad coding practice. Even the ancient DSP compilers they make me use at work at least attempt to support basic C99 features like declarations after statements; at this point, most of them are GCC-based and support all the current standards. When's the last time you did a survey of what compilers that are still relevant in 2025 don't support declarations after statements even as an optional feature?

    Catalina was originally intended to meet my own need for a C compiler for the Propeller 1, for a project that I completed long ago. I keep Catalina going because there is still no other compiler for the Propeller (1 or 2) that does everything I want. And Catalina is so simple that whenever I do find something else I want to be able to do, I can just add it. I could not do that with any other compiler.

    For the specific issue of "declaring variables like C99": this is a nice convenience feature to have. It's very nice to be able to type

    for (int i = 0; i < n; i++)
    

    rather than having to go back and add a new variable i (or to try to remember what variable names are free in the current scope). It's absolutely not necessary, of course -- it adds nothing but some "syntactic sugar" -- but it does make your life a little bit easier. And of course it'll also make your life easier when you want to port programs from other compilers. Adding this to Catalina would be of benefit to you, personally, as well as to your users.

    It's rather like // comments, which are also a C99 feature (not in C89) and yet are supported by Catalina. They add no new capability to the language and are easily emulated by /* comments. But they're handy to have for various reasons.

    If changing the Catalina parser to handle in-line variable declarations is a huge pain, then of course it may not be worth it. You'll have to make that determination for yourself. I see that some other lcc forks (like Pelles C and lcc-win32) have done this, so possibly their code could be re-used.

  • @RossH said:

    @Electrodude said:
    Sorry for bothering you about this repeatedly, but is there a reason you still only support ANSI C when the rest of the world has moved on? Your compiler has lots of neat features, but I'm not using a language that forces me to declare variables up-front before I'm ready to assign real values to them, as it's really bad coding practice. Even the ancient DSP compilers they make me use at work at least attempt to support basic C99 features like declarations after statements; at this point, most of them are GCC-based and support all the current standards. When's the last time you did a survey of what compilers that are still relevant in 2025 don't support declarations after statements even as an optional feature?

    Catalina was originally intended to meet my own need for a C compiler for the Propeller 1, for a project that I completed long ago. I keep Catalina going because there is still no other compiler for the Propeller (1 or 2) that does everything I want. And Catalina is so simple that whenever I do find something else I want to be able to do, I can just add it. I could not do that with any other compiler.

    But if GCC suits your needs better, use that.

    Ross.

    Sorry, I'm not trying to be discouraging. I'm just saying that there's a few C99 features that I think you could probably add without too much difficulty that would make it a lot easier for people to compile modern code with your compiler. C is supposed to be easily portable, but that's lost nowadays on Catalina because it can't actually compile anything resembling modern C without first editing the code to be significantly less maintainable. On the other hand, since flexprop supports all the parts of modern C that people actually tend to use, I can just write normal, clean, modern C and test it on my laptop using x86-64 GCC and then compile the exact same code for either Propeller using flexprop and be confident that it will work correctly.

    Parallax needs better official tools, but more competing unofficial tools that are good is the second-best thing to that, and I think you're significantly hurting your own project by not allowing C99 declarations.

    GCC, which is great on architectures it properly supports, most certainly does not suit my needs better on the P1 because the implementation we have does an abysmal job of dealing with the P1's memory model, and I'm not aware of any complete native P2 ports.

  • RossHRossH Posts: 5,569
    edited 2025-01-18 23:04

    It really comes down to a choice of where I want to spend my time. I'd much prefer to be be spending my time building Propeller applications than compilers, but there still isn't a C compiler available (other then Catalina) than can do what I need it do do, so unfortunately I still have to spend more of my time time on the compiler itself than I would like. But I try to minimize that so I can maximize the time I can spend on applications.

    And most often these days, those applications are in Lua and not C anyway. Lua is a much more interesting language than C, and one better suited to self-hosted development. And it's a lot more fun besides. And I think the "fun" part is missing from a lot of Propeller development these days.

    I spend time on the actual C compiler only when I have to. For instance, when I find bugs in the code generator - but that is quite rare now. More often, it is because I find a need for some language feature that requires compiler support - a good example is the recently added "alloca" function. That can't be done any other way.

    Also, there is a bunch of stuff waiting to be added to Catalina that I would much rather spend my time on than syntactic sugar such as inline declarations, which adds no actual functionality and is fairly trivial to rectify when porting C code. About the only one that I agree would be a real "nice to have" is the ability to declare "for" loop variables inline ** - I might spend some time on that one day, once I have finished everything else I have on my "todo" list.

    For instance, at the moment, I am in the middle of adding WiFi support to Catalina, because I have an application for it. Is being able to declare "for" loop variables inline really more important than that? I suppose it might be to some people, but it is not to me.

    However, Catalina is 100% open source, and I am aware that other derivatives of LCC have added that particular enhancement. So anyone who wants to work on the parser (which is all that would be required to be modified in this particular case) is welcome to do so. You don't even need Catalina for this - it could be done on any LCC-based compiler and I promise to integrate the results into Catalina.

    Fair?

    Ross.

    ** However, don't forget that a "for" loop that includes an in-line declaration that won't work in C89 like:

    for (int i = 0; i < MAX; i++) {
       /* do stuff with i here */
    }
    

    Can be re-written as an equivalent one that will work in any variant of C:

    {
        int i;
        for (i = 0; i < MAX; i++) {
           /* do stuff with i here */
        }
    }
    
  • evanhevanh Posts: 16,368
    edited 2025-01-19 08:33

    I did puzzle over why I only recently saw that syntax. Now I know why, it's only modern C programs that would use it. I'd only ever learnt ANSI C myself. And even that was only up to as much as I needed at the time.

  • Hi,
    from my perspective of a "maker-user" of the language tools, I have the impression that while for language developers details of language naturally make big difference, for users like me their importance is very much less. Instead besides documentation libraries become much much more interesting!!! The reason is, that I need a week or more, if I have to rewrite or port a I2C device. (For example, I have bought keypads with MPR121, which could be very useful, if I would bring myself to start writing the code for Taqoz....) I have used libraries, which are very much beyond my understanding, I was not forced to try to understand them. So what I still think would give P2 a real boost, would be full blown easy direct support of Arduino libraries out of the box. If possible in the Arduino IDE. As far as I understand, this is just too much work for a non-payed project. (And probably not enough fun.) If this is not possible, then K&R Standard seems to be sufficient. There is good description of this available. I must admit, that I don't even know the differences between the different C (and C++) standards.

    @RossH I like your efforts about Lua! Yes, this language could be fun!
    If it is possible, it would be very interesting to see, for what and how you use it?
    Cheers Christof

  • RossHRossH Posts: 5,569
    edited 2025-01-20 00:20

    @"Christof Eb." said:

    @RossH I like your efforts about Lua! Yes, this language could be fun!
    If it is possible, it would be very interesting to see, for what and how you use it?
    Cheers Christof

    Yes, Lua is fun. My current project is probably a bit like the PLC project currently being discussed on another thread here - I want to build a distributed home/farm automation system for off-grid applications, consisting of a cluster of WiFi connected Propellers. And of course, they will all be programmed in Lua. I could use Arduinos - I even bought a couple to try - but I decided against them. They would be cheaper, but are not nearly as much fun!

    I used to work on large centralized control systems where a single computer managed thousands of I/O points. For applications like SCADA, power stations, fire control systems or building management. But these days we can dedicate more processing power per I/O point than we used to have available for the entire system. Also, those systems were very "dense", where each I/O unit typically had dozens or hundreds of I/O points. In the system I need, the I/O is very "sparse" - it may have just a few I/O points to monitor or control in each physical location - possibly even just one (e.g. a pump, a tank, a rain gauge, a solar inverter, a generator, a gate, an ultrasonic sensor etc). And these points will be widely distributed geographically.

    To connect the I/O units to the central computer we mostly used hardwired serial links (e.g. RS-422) for shorter distances and radio links for longer distances - but these days WiFi can do it more easily and cheaply over both short and long distances. A WiFi repeater can reach up to 5km (or so it says on the box - actually, I only need about 1km - that's the size of our property).

    The hardware components I can buy - my work is just the software. I now have nearly all the things I need. I can already use Lua to make remote procedure calls between a cluster of hardwired Propellers, and I'm working on replacing that with WiFi connectivity now.

    Sure, I could just buy the entire system "off the shelf" - but where's the fun in that?

    Ross.

  • @RossH said:

    In the system I need, the I/O is very "sparse" - it may have just a few I/O points to monitor or control in each physical location - possibly even just one (e.g. a pump, a tank, a rain gauge, a solar inverter, a generator, a gate, an ultrasonic sensor etc). And these points will be widely distributed geographically.

    That is an interesting project. Do you plan on documenting the progress in another thread/place possibly ?

    Maciek

  • RossHRossH Posts: 5,569

    @Maciek said:

    @RossH said:

    In the system I need, the I/O is very "sparse" - it may have just a few I/O points to monitor or control in each physical location - possibly even just one (e.g. a pump, a tank, a rain gauge, a solar inverter, a generator, a gate, an ultrasonic sensor etc). And these points will be widely distributed geographically.

    That is an interesting project. Do you plan on documenting the progress in another thread/place possibly ?

    Maciek

    Yes, I can do, once it advances enough to be distinct from just a Catalina update.

  • RossHRossH Posts: 5,569

    Catalina 8.4 has been released on GitHub and SourceForge

    This is a full release. It adds support for the Parallax WiFi module to both C and Lua. However, note that while the new functionality is intended to support both the Propeller 1 and Propeller 2, and all the demo and test programs compile for both, they have only currently been tested on a Propeller 2. Also, some of the functionality requires a firmware update to the WiFi module (the updated firmware is included in the release).

    Here is the relevant extract from the README.TXT

    RELEASE 8.4
    
    New Functionality
    -----------------
    
    1. Support has been added for the Parallax ESP8266 WiFi module. It will be
       supported on both the Propeller 1 and 2, but it has only currently been
       tested on the Propeller 2. A new library (libwifi) has been added, which 
       can be used by adding -lwifi to the Catalina command. Serial communication
       with the WiFi module must be done using the 2 or 8 port serial comms module
       (Propeller 2) or the 4 port serial comms module (Propeller 1). 
    
       To simplify using the WiFi module on the Propeller 2, a new platform 
       configuration file has been added (P2WIFI.inc) which is enabled by 
       defining the Catalina symbol P2_WIFI. It is generally the same as 
       P2EDGE.inc except that it assumes a WiFi module is installed on pins
       16 .. 23. So for the Propeller 2 you might use a command like:
    
          catalina -p2 testwifi.c -lc -lwifi -lserial2 -C P2_WIFI
    
       On the Propeller 1, the serial4 configuration must be specified in the 
       file "target/p1/Extras.spin" but there is no specific configuration of 
       the WiFI module in the Propeller 1 target files - instead, the pins etc 
       must be specified in the application program when the WiFi module is 
       initialized.
    
       So (for example) on the Propeller 1 Activity board, you might use a
       Catalina command like:
    
          catalina testwifi.c -lc -lwifi -lserial4 -C ACTIVITY
    
       Note that on the Propeller 1, if a WiFi program is too large to fit in the 
       Propeller 1 Hub RAM, you may need to add additional options to optimize 
       the program (-O5), use COMPACT mode (-C COMPACT), or use the EEPROM load 
       option (-C EEPROM).
    
       See the include file "include/wifi.h" and the example programs in the 
       "demos/wifi" folder, and the "README.TXT" file in that folder for more 
       details.
    
    2. To accommodate the use of different serial plugins with the WiFi module,
       the 2, 4 and 8 port serial libraries now all use the same names for their
       functions - i.e. names like "s_xxxx()" instead of "s2_xxxx()", "s4_xxxx()" 
       and "s8_xxxx()" (respectively). The previous names can still be used by 
       including the relevant serial header file (e.g. "include/serial2.h" which
       now include #defines like defining "s2_tx()" to be "s_tx()") or the new 
       general-purpose header file "include/serial.h" which detects which serial 
       plugin and library is in use and includes the relevant serial header file.
    
    3. On the Propeller 2, the default HMI option is now the SIMPLE serial
       interface, rather than TTY. The reason for this change is that on the 
       Propeller 2, the TTY HMI actually uses one port of the 2 port serial 
       plugin, which means that the default HMI option would no longer work 
       with the WiFi module and the serial2 plugin (it would lead to errors 
       about multiply defined symbols). To reinstate the previous behaviour, 
       just explicitly add -C TTY to the catalina command.
    
       Because a serial comms plugin must be loaded to communicate with the WiFi
       module, and all the serial comms plugins support at least two ports, the 
       WiFi programs typically use the first serial port (port 0) to do that, 
       and the second serial port (port 1) for user interactions. Therefore, it 
       is common for WiFi programs to not load any HMI plugins at all (specifying
       -C NO_HMI) and not use any stdio functions at all - this saves both Hub 
       RAM and cogs.
    
    Other Changes
    -------------
    
    1. The serial header files (tty.h, serial2.h, serial4.h and serial8.h) had
       some errors which may have resulted in syntax errors during a compilation
       if some of the definitions were used. Also, using the "cls" functions 
       (e.g. "s2_cls()" may have resulted in an error about an undefined symbol 
       (in this case "s2_char()").
    
    2. The tiny I/O library had a bug in the scanf and sscanf functions - if the 
       last specifier in the format string was %s and the string being scanned did 
       not have a white space at the end of it (and in particular, if the string 
       being scanned was terminated by a null) then the scanning did not stop at 
       the end of the string, and scanf and sscanf typically returned rubbish and
       may have corrupted memory.
    

    Although this release includes support for all the functionality currently offered by the Parallax WiFi module firmware, I am not entirely happy with it yet. I hope to add additional functionality in future releases, which may involve additional firmware changes.

    Ross.

  • RossHRossH Posts: 5,569
    edited 2025-02-19 22:07

    I intend Lua to be the preferred language for writing Catalina web applications, so it is probably worth putting the Lua demo program (testhttp.lua) here, to illustrate how easy it is to serve an interactive web page from Lua ...

    --
    -- Simple Lua HTTP test program.
    --
    -- Load the initial web page from http:xxx.xxx.xxx.xxx/prop in a browser, 
    -- then you can use the button to get a new value from the Propeller on 
    -- each click.
    --
    -- IMPORTANT: At least the SSID and PASSPHRASE (see below) will need to be 
    -- configured before this program can be run successfuly.
    --
    
    SSID          = "MyNetwork";
    PASSPHRASE    = "TellMeASecret";
    
    IP_RETRIES    = 30;    -- times to retry getting a valid IP address
    IP_RETRY_SECS = 3;     -- seconds between retries
    POLL_INTERVAL = 250;   -- milliseconds between polls
    USER_PORT     = 1;     -- port to use for user interaction
    
    -- define constants necessary for LISTEN calls
    TKN_HTTP   = 0xF7;
    TKN_WS     = 0xF6;
    TKN_TCP    = 0xF5;
    
    -- print string on USER_PORT
    local function print(str)
      serial.str(USER_PORT, str);
    end
    
    print("\nSimple Lua HTML Test\n\n");
    
    local result = 0;
    
    result = wifi.AUTO();
    if result ~= 0 then                                                          
       print("Initialization failed, result = " .. result .. "\n");
    end
    
    -- set mode to AP to force module off any current network
    if wifi.SET("wifi-mode", "AP") ~= 0 then
      print("SET failed\n");
    end
    
    -- set mode to STA+AP mode
    if wifi.SET("wifi-mode", "STA+AP") ~= 0 then
      print("SET failed\n");
    end
    
    -- join the network
    print("Joining " .. SSID .. " ...");
    if wifi.JOIN(SSID, PASSPHRASE) ~= 0 then
      print("failed.\n");
      os.exit(1);
    end
    
    local retries = 0;
    local ip_address = "";
    
    -- wait till we get a valid IP address
    while retries < IP_RETRIES do
      result,ip_addr = wifi.CHECK("station-ipaddr");
      if result == 0 and ip_addr ~= "0.0.0.0" then
        print("done.\n\n");
        print("Open a browser to http://" .. ip_addr .. "/prop\n\n");
        break;
      end
      propeller.sleep(IP_RETRY_SECS);
    end
    
    if ip_addr == "0.0.0.0" then
      os.exit(1);
    end
    
    -- listen for HTTP requests on /prop ...
    local prop_handle = 0;
    result,prop_handle = wifi.LISTEN(TKN_HTTP, "/prop");
    if result ~= 0 then
      print("LISTEN failed\n");
      os.exit(2);
    end
    
    -- listen for HTTP requests on /prop/val ...
    local val_handle = 0;
    result,val_handle = wifi.LISTEN(TKN_HTTP, "/prop/val");
    if result ~= 0 then
      print("LISTEN failed\n");
      os.exit(3);
    end
    
    -- value to send in response to "GET /prop" ...
    
    local get_prop = [[
      <!DOCTYPE html>
      <html>
        <body>
          <H1>Welcome to Catalina with WiFi support!</H1> 
          <H2>Get a Value from the Propeller</H2> 
          <p>Click Update to get a value from the Propeller. 
           Click again to get a new value each time:</p> 
          <button onclick="getFromProp()">Update</button>
          <p id="value">Waiting...</p>
          <script>
            function usePropReply(response) {
              var val = document.getElementById("value");
              val.innerHTML = "Value: " + response;
            }
    
            function getFromProp() {
              httpGet("/prop/val", usePropReply);
            }
    
            function httpGet(path, callback) {
              var req = new XMLHttpRequest();
              req.open("GET", path, true); 
              req.onreadystatechange = function() { 
                if (req.readyState == 4) 
                  if (req.status == 200) 
                    callback(req.responseText);
                  else 
                    callback("Waiting...");
              };
              req.send();
            }
          </script>
        </body>
      </html>
    ]];
    
    -- value to send in response to "GET /prop/val"
    local prop_val = 99;
    
    -- poll for events
    while true do
      local handle;
      local value;
    
      propeller.msleep(POLL_INTERVAL);
      result,event,handle,value = wifi.POLL(0);
      if event == "G" then
        print("GET\n");
        if value == prop_handle then
          result = wifi.SEND_DATA(handle, 200, #get_prop, get_prop);
        elseif value == val_handle then
          get_prop_val = tostring(prop_val);
          prop_val = prop_val + 1; -- increment it on each GET
          result = wifi.SEND_DATA(handle, 200, #get_prop_val, get_prop_val);
        else
          print("Uknown GET path\n");
        end
      end
    end
    

    You don't even need to compile the Lua program, just execute it with the Catalyst command:

    wlua testhttp.lua

    EDIT: updated test program - the call to wifi.PATH was unnecessary.

  • RossHRossH Posts: 5,569

    I've just pushed a minor tweak to release 8.4 to GitHub to change the way the WiFi enabled versions of Lua (i.e. wlua and wluax) are built. I decided that disabling the normal HMI functions by adding NO_HMI by default was a bit too harsh, since it makes it harder to develop and debug Lua WiFi programs. If the extra cog this saves really is required, then NO_HMI can be explicitly added to the build_all command.

    Ross.

  • RossHRossH Posts: 5,569
    edited 2025-02-27 21:47

    Seems I broke the P2MASTER.inc and P2SLAVE.inc platform support files when adding WiFi support.

    I have fixed them on GitHub - attached is a new version of the file for SourceForge users - just overwrite target/p2/P2MASTER.inc and _target/p2/P2SLAVE.inc_with the versions in the zip file.

    Ross.

  • RossHRossH Posts: 5,569
    edited 2025-02-28 05:42

    As part of adding WiFi support to Lua, I have been doing a lot of Lua development on the Propeller 2 itself recently, and (being lazy!) I had been thinking about extending Catalyst so you can execute scripts at the Catalyst prompt without having to enter exec script to do it (i.e. I want to be able to just type script). Then it dawned on me that since Catalyst can already execute Lua programs from the Catalyst command prompt, it already had this capability!

    For example, suppose you have a Catalyst script called rebuild which rebuilds your multi-file Lua program (e.g. all the example eLua programs have such a script). Then you would execute it at the Catalyst command prompt by entering:

    exec rebuild

    But if you just want to enter rebuild, you can do that too - just use the vi text editor to create the following one line Lua program:

    propeller.execute("exec rebuild");

    Save it as rebuild.lua. Now, at the Catalyst command prompt, just enter rebuild. We are using Catalyst to execute Lua (i.e. bin/lua.bin), which then executes a Lua program (i.e. rebuild.lua), which then executes another Lua program (i.e. bin/exec.lua) which then executes a Catalyst script (i.e. rebuild). Too easy! :)

    And of course, you can get more sophisticated if you need to. For example, if you have a script called my_script that accepts parameters, you just need a few more lines - e.g. save this as my_script.lua:

    function par(n)
      if arg[n] then
        return arg[n] .. " ";
      end                                                                           
      return "";                                                                 
    end                                                                             
    propeller.execute("exec my_script" .. par(1) .. par(2) .. par(3));
    

    You can now enter my_script with up to 3 parameters - e.g. my_script a or my_script a b c and everything works.

    This kind of thing is why I love Lua! :)

  • RossHRossH Posts: 5,569

    I found another issue with the WiFi stuff I added to the P2MASTER.inc and P2SLAVE.inc platform support files, so I have simply removed it (it isn't necessary in those files, which are only used for the ALOHA demo programs that use serial links, not WiFi).

    Github has been updated, and this post has also been updated with the new versions.

    Ross.

  • evanhevanh Posts: 16,368
    edited 2025-02-28 07:49

    I'm coming to terms with inline assembly - Chosen the first layout because it allows comments. No comments in assembly would be hanging myself.

    I've got a program compiling now. It runs. PS: It's my file read/write speed tester. :)

    First questions:

    • How to mount and unmount a SD card?
    • How do I get a "\n" to emit CR + LF pair?
  • RossHRossH Posts: 5,569

    @evanh said:
    I'm coming to terms with inline assembly - Chosen the first layout because it allows comments. No comments in assembly would be hanging myself.

    I've got a program compiling now. How do I get a "\n" to emit CR + LF pair?

    Not sure I understand. Can you not just specify "\r\n"?

    For Inline PASM, there is also the _PSTR() macro that can be used to to encode C strings (such as "\r\n"). See the Catalina Reference Manual.

    More information, or the actual code you are trying to use (which presumably fails) would be helpful.

    Ross.

  • evanhevanh Posts: 16,368
    edited 2025-02-28 08:35
     fopen() for writing failed!   errno = 0: Error 0
    
        errno = 0;
        fh = fopen(filename, "wb");
        if( !fh ) {
            printf(" fopen() for writing failed!   errno = %d: %s\r\n", errno, strerror(errno));
            exit(3);
        }
    

    EDIT: Ah, the filename is "/sd/speed1.bin". Forgot about the /sd path ... no, not fixed with filename changed to "speed1.bin"

    EDIT2: Oh, I need to use -lcx for linking. Getting there :)

  • evanhevanh Posts: 16,368
    edited 2025-02-28 09:05

    It writes now but only the first 1.5 kB of the first 2 kB buffer.

    Buffer = 2 kB,  fwrite() failed!  writes = 0   errno = 0: Error 0
    

    randfill() doesn't work either.

  • RossHRossH Posts: 5,569

    @evanh said:
    It writes now but only the first 1.5 kB of the first 2 kB buffer.

    Buffer = 2 kB,  fwrite() failed!  writes = 0   errno = 0: Error 0
    

    randfill() doesn't work either.

    Too late to tackle this tonight. Will try and find time tomorrow.

    Ross.

  • evanhevanh Posts: 16,368

    No problem.

  • RossHRossH Posts: 5,569

    @evanh said:
    It writes now but only the first 1.5 kB of the first 2 kB buffer.

    Buffer = 2 kB,  fwrite() failed!  writes = 0   errno = 0: Error 0
    

    randfill() doesn't work either.

    Ok - not looking at your PASM code, but just at the way it is loaded and executed, the first problem I can see is that your LUT code is being loaded but not executed

    See the section "Using the LUT Execution Macros" of the Catalina Reference Manual - the LUT_BEGIN and LUT_END macros load but do not actually execute the code. You need to add a LUT_CALL to execute it.

    For example:

    static uint32_t  randfill( uint32_t *addr, size_t size, uint32_t state )
    {
        LUT_BEGIN("0", "randfill", "$FACE0000");    // load into lutRAM
        PASM(
    "       shr _PASM(size), #2\n"
    "       wrfast  #0, _PASM(addr)\n"
    "       rep @.rend, _PASM(size)\n"
    "       xoro32  _PASM(state)\n"
    "       mov pa, 0-0\n"
    "       wflong  pa\n"
    " .rend\n"
        );
        LUT_END;
        LUT_CALL("randfill");
        return state;    // for potential continuation of psuedo random sequence
    }
    
    static size_t  randcmp( const uint32_t *addr, size_t size, uint32_t state )
    {
        LUT_BEGIN("0", "randcmp", "$FACE0001");    // load into lutRAM
        PASM(
    "       shr _PASM(size), #2\n"
    "       mov r0, #0\n"
    "       rdfast  #0, _PASM(addr)\n"
    "       rep @.rend, _PASM(size)\n"
    "       rflong  pa\n"
    "       xoro32  _PASM(state)\n"
    "       cmp pa, 0-0   wz\n"
    "   if_z    add r0, #4\n"
    " .rend\n"
        );
        LUT_END;
        return LUT_CALL("randcmp");
    }
    

    Let me know how this goes.

    Ross.

  • RossHRossH Posts: 5,569

    Carrying on from this post, I was thinking more about adding the capability to Catalyst to detect that the command being executed is a Catalyst script rather than a Lua program or a propeller binary, and take the appropriate action, but I have decided not to add that at the moment because I'm too busy with other stuff. Maybe later.

    Instead, I just wrote a generic Lua program that can do the job for any script without changes - all you have to do is name it appropriately:

    -- script.lua - Execute any Catalyst script without having to say "exec script".
    --
    --              E.g. to use it to execute "myscript" do the following:
    --                 cp script.lua myscript.lua
    --
    --              From then on you can just enter:
    --                 myscript
    --
    --              Parameters are also ok - e.g:
    --                 myscript a b c
    --
    
    function par(n)
      if arg[n] then
        return arg[n] .. " ";
      end
    end
    
    -- extract script name (i.e. the name of this file without ".LUA")
    command = string.match(par(0), "[%w_]+") .. " ";
    
    -- add parameters (until we run out)
    n = 1;
    while par(n) do
      command = command .. par(n);
      n = n + 1;
    end
    
    -- execute (silently) the script with parameters
    propeller.execute("@exec " .. command);
    

    Save the above as script.lua on your Catalyst SD card. To try it, you can use the example loop script provided (which demonstrates how to do looping in a Catalyst script). Enter the Catalyst command:

    cp script.lua loop.lua

    From now on, you don't have to say exec loop to demo the loop script. You can just say loop (or loop 5 etc). Just don't expect speed - the things I have to do to make looping work at all in Catalyst scripts means it is already painfully slow - but it works!

    This may all seem quite trivial - and it is - but the thing about Lua is that someone else has done all the hard work to make it a simple, clean and very flexible way to extend existing functionality.

    Ross.

Sign In or Register to comment.