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

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

1121314151618»

Comments

  • evanhevanh Posts: 16,345

    @RossH said:
    Let me know how this goes.

    Cool, random data is in the buffer now.

    Oh, I've found the problem with fwrite() too. I never knew about the distinction between items and bytes. I guess I'd always fluked it in the past. That and Flexspin treats them as the same so I'd accidentally got it wrong there and not known it.

  • evanhevanh Posts: 16,345

    Ouch, could be better.

     Buffer = 2 kB, ................................................................ Written 128 kBytes, duration 13508 ms, makes 9 kB/s
     Verified, ................................................................ Read 128 kBytes, duration 842 ms, makes 152 kB/s
    
     Buffer = 8 kB, ................ Written 128 kBytes, duration 13502 ms, makes 9 kB/s
     Verified, ................ Read 128 kBytes, duration 840 ms, makes 152 kB/s
    

    Also, I'm seeing an odd behaviour with text sent to the terminal. The writing portion oddly buffers the whole line before emitting it. While the verifying and read speed portions both emit in real time.

  • RossHRossH Posts: 5,564

    @evanh said:

    Also, I'm seeing an odd behaviour with text sent to the terminal. The writing portion oddly buffers the whole line before emitting it. While the verifying and read speed portions both emit in real time.

    Just a question of how much stuff is in the buffer at the time, I think. Add an fflush after each putchar to force it out - i.e.
    putchar('.'); fflush(stdout);

    Ross.

  • evanhevanh Posts: 16,345
    edited 2025-03-01 05:24

    Yeah, that works. But it's not needed for the same action during fread(). Which I see as strange.

    BTW: The second time through using the bigger file buffer is same behaviour - without fflush() the terminal doesn't emit until end of line for fwrite() portion, while for both fread() portions it emits immediately.

    Here's an updated version with more dots during the verifying portion.

  • evanhevanh Posts: 16,345

    I'm thinking fopen() in write mode must be changing something internal to char handling.

  • RossHRossH Posts: 5,564

    @evanh said:
    I'm thinking fopen() in write mode must be changing something internal to char handling.

    What's happening is that fread() automatically flushes all open line-buffered output streams - including stdout - but fwrite() does not.

    This appears to be in accordance with the C specification, which says (in part) ...

    Furthermore, characters are intended to be transmitted as a block to the host
    environment when a buffer is filled, when input is requested on an unbuffered stream, or
    when input is requested on a line buffered stream that requires the transmission of
    characters from the host environment. Support for these characteristics is
    implementation-defined ...

    Ross.

  • evanhevanh Posts: 16,345
    edited 2025-03-01 07:32

    Hehe, very good. It's allowed according the spec. - Which I've never read.

    "implementation-defined" means you can choose though. Is there a reason you decided to make reads and writes behave differently to each other?

  • RossHRossH Posts: 5,564

    @evanh said:
    Hehe, very good. It's allowed according the spec. - Which I've never read.

    "implementation-defined" means you can choose though. Is there a reason you decided to make reads and writes behave differently to each other?

    I would like to say it was a deliberate and conscious decision - but in fact I didn't write that code, I simply ported it for Catalina :)

    The original "stdio" code Catalina uses comes from the Amsterdam Compiler Kit.

  • evanhevanh Posts: 16,345
    edited 2025-03-01 09:37

    Good point. It would be insane to not use a kit.

    EDIT: Oh, wow, it's only fread() that auto-flushes. Any other time I have to manually do it, irrespective of fopen() mode or anything else. :(
    That's weird, why would fread() even bother? What's weirder is shouldn't writes be the ones to flush more?

  • RossHRossH Posts: 5,564

    @evanh said:
    Good point. It would be insane to not use a kit.

    EDIT: Oh, wow, it's only fread() that auto-flushes. Any other time I have to manually do it, irrespective of fopen() mode or anything else. :(
    That's weird, why would fread() even bother? What's weirder is shouldn't writes be the ones to flush more?

    The C standard says it is so that an fread() after an fwrite() that is intended to display a prompt on a terminal will write the prompt before it does read.

  • evanhevanh Posts: 16,345

    I don't get why that needs an exception. Why not the other way around also? I'm suspicious it's probably an ancient backwards compatibility thing.

  • RossHRossH Posts: 5,564
    edited 2025-03-01 22:03

    @evanh said:
    I don't get why that needs an exception. Why not the other way around also? I'm suspicious it's probably an ancient backwards compatibility thing.

    The other way around would mean that output streams could never be line-buffered

    Doing it this way around means writes can be line-buffered except when you do a read, in which case the output is flushed even if it is not a complete line (which is typical in the case of a terminal prompt).

    The only thing that is a little unexpected is that doing an fread() on an input stream flushes all line-buffered output streams - and the reason for that is that stdio does not know which stream is being used to output the prompt - e.g. when you read input from stdin you actually need to flush stdout to ensure the prompt will be displayed on the terminal before you do the input.

    The behaviour of your program is a consequence of that.

    Ross.

  • evanhevanh Posts: 16,345
    edited 2025-03-02 01:14

    @RossH said:
    The only thing that is a little unexpected is that doing an fread() on an input stream flushes all line-buffered output streams - and the reason for that is that stdio does not know which stream is being used to output the prompt - e.g. when you read input from stdin you actually need to flush stdout to ensure the prompt will be displayed on the terminal before you do the input.

    Is that a requirement by the spec though, or is it just implementation defined too?

    Separately, I would like to be able to switch off the line buffering of stdout. Or, even better, have libc built without line buffering at all.

    Interrupts aren't used for transmitting, right? That would be an excuse to have a buffer at least.

  • RossHRossH Posts: 5,564

    @evanh said:

    Is that a requirement by the spec though, or is it just implementation defined too?

    It's a requirement of the spec.

    Separately, I would like to be able to switch off the line buffering of stdout. Or, even better, have libc built without line buffering at all.

    Use setbuf() or setvbuf()

    Interrupts aren't used for transmitting, right? That would be an excuse to have a buffer at least.

    The Catalina kernel does not use interrupts unless threading is used.

    Ross.

  • evanhevanh Posts: 16,345

    Reading Linux man pages - setvbuf(stdout, NULL, _IONBF, 0); did the job. It's consistent now.
    Thank you for the help!

  • RossHRossH Posts: 5,564
    edited 2025-03-04 04:44

    Aha! Ker .... SPLAT!!! ...

    I finally found a nasty bug that has been annoying me for some time. It popped its head up nearly every time I was just about to do a release, and every time it did so I found a workaround for it - but I could not find the underlying cause.

    It turned out to be in my implementation of getenv(), which is a standard C function that reads environment variables. It only affected Propeller 2 C programs which used environment variables, or Lua programs (because Lua uses environment variables during initialization), and it also mostly affected programs that used XMM, because it could cause cache corruption during program start up - which made it difficult to find, because if the program started at all it generally worked fine.

    I have already uploaded the fix to GitHub - attached is a patch for non-GitHub users. The fix will also be included in the next release.

    Ross.

  • RossHRossH Posts: 5,564

    Catalina 8.5 has been released on GitHub and SourceForge

    This is a full release. It adds eLua support for using the Parallax WiFi module to make Remote Procedure Calls (RPCs) between propellers. Note that demo and test programs may compile for both the Propeller 1 and 2, but they have only currently been tested on a Propeller 2. Also, some of the WiFi functionality requires a firmware update to the Parallax WiFi module (the updated firmware is included in the release).

    Here is the relevant extract from the README.TXT

    RELEASE 8.5
    
    New Functionality
    -----------------
    
    1. Catalina now supports WiFi-based Remote Procedure Calls (RPCs) in addition 
       to ALOHA serial RPCs. These are now implemented alongside the ALOHA
       protocol in several eLua variants. It is possible to have just ALOHA
       services, just WiFi services, or a combination of both. All the existing
       ALOHA example programs have been updated to use either ALOHA or WiFi,
       and an example of using both in the same program is given in a new 
       'hybrid' example. See the document 'ALOHA from Lua' for more details.
    
    2. The binaries generated by compiling the ALOHA versions of eLua have been 
       renamed alua, aluax etc to be consistent with the new WiFi RPC versions
       of eLua (which are called rlua, rluax etc). No changes to functionality.
    
    3. The eLua programs now load a generic 'serial' module if Lua is compiled 
       with either the 2 port or 8 port serial plugin library (i.e. -lserial2 or 
       -lserial8). Lua programs can use the 'serial' module without needing to 
       know if it is using the 2 port serial or 8 port serial plugin. 
    
    4. Lua now includes a module ('wifi') that allows access to the C WiFi support
       functions. The module is loaded automatically if Lua is linked with the 
       'wifi' library (e.g. compiled with -lwifi).
    
    5. All the pre-compiled versions of the eLua demos have been removed, since 
       they will all need to be modified and recompiled to use the new WiFi RPC 
       capabilities.
    
    6. Base64 encode and decode routines have been added to the Catalina library.
       See include/base64.h for details.
    
    7. The buffer size of the 8 port serial plugin has been increased from 32
       bytes to 1024 bytes to accommodate the new WiFi RPC functionality. Since
       there are 16 such buffers (one for each direction of each port) this can
       make programs that use this plugin up to 16k larger. If this causes
       problems, the files target\p2\s8serial.t and source\lib\serial8\core.c
       both need to be modified, and the Catalina library must be recompiled.
    
    8. The WiFi definitions have been removed from the P2_MASTER and P2_SLAVE
       platform configuration files (i.e. P2MASTER.inc and P2SLAVE.inc) since 
       this interfered with the ALOHA serial functionality. Instead, two new
       platform configurations have been added - P2_WIFI_MASTER and P2_WIFI_SLAVE
       (i.e. P2WIFI_M.inc and P2_WIFI_S.inc) which can be used if both WiFi RPC 
       and ALOHA serial RPC capabilities are required. If only the WiFi RPC 
       capabilities are required, P2_WIFI can still be used.
    
    5. Catalyst now includes a new Lua script (script.lua) that can be used to 
       invoke any Catalyst script from the command line just by typing the script
       name, without having to say 'exec script'. See script.lua for more details.
    
    Other Changes
    -------------
    
    1. A significant bug in the implementation of getenv() has been fixed. The bug
       affected only Propeller 2 programs that used getenv(), and Lua programs
       (because Lua uses getenv() during initialization), and it also generally
       only affected XMM programs. The bug caused memory corruption, usually on 
       startup. Programs that started ok generally ran properly thereafter. A 
       previous workaround to this bug was to add calls to _align_sbrk() to move 
       the C heap to another location - this generally worked around the problem 
       but didn't solve it. These calls have now been removed, but the 
       _align_sbrk() function is still available for other purposes. Affected the 
       Propeller 2 only.
    
    

    I will support this release, but now that Catalina has all the building blocks I needed, I will be taking a break from Catalina development to do some real software development for a change :)

    Ross.

  • RossHRossH Posts: 5,564

    Catalina 8.5 contains an error in the files demos/eLua/example/COMMON.LUA and demos/eLua/hybrid/COMMON.LUA

    Both files contain an incorrect definition of the invoke function. The correct definition is:

    function invoke(f, x)
      return bs.deserializeN(svc.serial(INVOKE_SVC, bs.serialize(f, x), 100), 1)
    end
    

    Github has been updated. SourceForge users should edit the files manually (NOTE: don't just edit one and copy it over the other - the two files have differences).

    All users should use the Catalyst command exec rebuild to rebuild the binary versions of the files before executing them.

    Ross.

  • RossHRossH Posts: 5,564

    I just noticed my Patreon page had been unpublished because I had not added anything to it for so long. That's the problem with social media - you have to feed it constantly! :)

    So I have added a video about the new eLua/ALOHA WiFi RPC calls. I have also updated GitHub with the latest version, which you will need to execute the demo yourself. One minor bug fix (to wifi_POLL) and some enhancements to the eLua/ALOHA custom dispatcher, plus the new demo. SourceForge users will have to wait till I have time to do a full release - but in the meantime, check out the video :)

    The video is here.

    Ross.

  • RossHRossH Posts: 5,564

    @RossH said:

    The video is here.

    I just reviewed this video (which I did in haste to reinstate my Patreon account) and I realized it did not include a key point that I should have made - which is that the "Same Origin Policy" implemented in modern browsers means it is not possible to do what this program does (at least not in such a trivial program) by simply calling the Slave directly - the request for data from the Slave has to go back through the Master (i.e. to the "same origin"), which must then make a separate RPC call to the Slave to get the data.

    I will add a note under the video.

    Ross.

  • RossHRossH Posts: 5,564
    edited 2025-03-15 03:01

    I had a query about the commands I used in the video to open the two terminal windows. These commands start two instances of Catalina's Windows terminal emulator (comms) with appropriate options. My two Propellers were on COM ports 3 and 8, so I just cut and pasted the following commands:

    comms /com=3 /baud=230400 /fg=white /bg=dark_blue /mode=vt100 /wrap /autocronlf /settitle=master
    comms /com=8 /baud=230400 /fg=yellow /bg=dark_green /mode=vt100 /wrap /autocronlf /settitle=slave
    

    Normally, comms is not executed directly - it is typically started using payload by specify the -I option - e.g. payload -p3 -b230400 -Ivt100 - but that doesn't allow access to all the command line options that the program supports (such as setting the window colours and title).

    The comms documentation is in the Catalina release, but not in the documents folder. It is in source/comms/doc/Terminal Emulator.pdf

    Ross.

  • RossHRossH Posts: 5,564
    edited 2025-03-19 22:50

    I found a silly bug in one of the library functions that I use to support eLua. The affected file is source/lib/catalina/service.c

    I have updated GitHub with the new source, but just by sheer luck it does not affect any of the eLua demos included in the release, so I have not bothered to recompile the library - I expect to be issuing an updated full release soon, which will include that.

    In the meantime, you can rebuild the library yourself if you want. Update the source, open a Catalina command line window, go to to the source/lib directory and execute the build_all command there. On Linux (including the Raspberry Pi) you many need to re-install Catalina to /opt (see the file BUILD.TXT for more details).

    Ross.

    EDIT: Replacement file now attached.

  • RossHRossH Posts: 5,564
    edited 2025-03-24 22:59

    Catalina 8.5.1 has been released on GitHub and SourceForge.

    This is a full release. It adds some minor eLua enhancements. The main reason for the release is to recompile the Catalina library to incorporate the fix to the eLua service.c function _register_services(). There are no changes to any of the Catalina binaries in this release, so the GitHub binary assets for release 8.5 can also be used for this release.

    Here is the relevant extract from the README.TXT:

    RELEASE 8.5.1
    
    New Functionality
    -----------------
    
    1. Simplified eLua so that the extension does not need to be specified for 
       client and server Lua file names - eLua (and all its variants) will 
       now add the appropriate default extension if none is specified. 
    
       So, for example:
          elua client server
       is now the same as:
          elua client.lua server.lua
    
       and
          eluax client server
       is now the same as:
          eluax client.lux server.lux
    
    2. Added a null server (null.lua) to all the eLua demos, so it can be
       specified as the server when executing non-eLua programs. The null
       server does nothing except stop eLua from complaining about missing 
       tables and functions it expects to find in any eLua server. 
       For example:
    
          elua ex4 null
    
       Previously, eLua would load and execute whatever it found in server.lua 
       (or server.lux) which may have not been an eLua server, or it may have 
       been an eLua server that interfered with the non-eLua client program.
    
    3. Modified the ALOHA WiFi RPC dispatcher so that the IP addresses in the 
       "rpc_network" table need now only be configured in the Lua remote server
       (i.e. remote.lua). The change was to interpret any invalid IP address to 
       mean the local IP address should be used - so the IP address field can 
       simply be left as a null string (or "xxx.xxx.xxx.xxx") in all servers 
       except for the remote server.
    
       Of course, the SSID and PASSPHRASE still have to be configured in both 
       the remote server and local servers (e.g. server.lua or serverbg.lua). 
    
       Previously, all IP addresses needed to be configured in all servers, and so
       it was recommended that the "rpc_network" table be stored in common.lua. 
       While this is still possible, this change makes configuring WiFi/RPC ALOHA 
       programs more consistent with configuring Serial ALOHA programs.
    
    
    Other Changes
    -------------
    
    1. Fixed a bug in the eLua support function _register_services(), which was
       not setting the service lock correctly. This did not affect any of the
       eLua demo programs in the release, but may have led to lock-ups in other
       eLua programs. Affected the Propeller 2 only.
    

    Ross.

    EDIT: SourceForge now working!

  • RossHRossH Posts: 5,564
    edited 2025-03-26 01:28

    Okay! Another WiFi module arrived yesterday, so I finally had a spare one to use to test Catalina's WiFi support on a P1 (my other WiFi modules are currently deployed on various remote P2s!).

    The good news is that it works! :smile:

    The bad news is that to get it to work, I had to wind the communications with the WiFi module all the way down to 1200 baud! Not ideal :(

    I was not expecting that, and it needs further investigation. But in the meantime, here is what I did to make the WiFi module work with my C3:

    I installed the WiFi module on pins 0 .. 7 on the C3:

       pin 0 - PGM
       pin 1 - DBG
       pin 2 - ASC
       pin 3 - CTS
       pin 4 - RTS
       pin 5 - DO
       pin 6 - DI
       pin 7 - RES
    

    But of these, only DO and DI - plus 3.3v and ground, of course - are actually necessary.

    Then I configured the 4 port serial plugin by editing the appropriate section of /target/p1/Extras.spin to support two serial ports - port 0 at 1200 baud for WiFi module comms, and port 1 at 115200 baud for user interaction:

    #ifdef libserial4
      S4.Setup
      S4.AddPort(0,5,6,-1,-1,0,0,1200)
      S4.AddPort(1,31,30,-1,-1,0,0,115200)
      'S4.AddPort(2,rx,tx,cts,rts,threshold,mode,baud)
      'S4.AddPort(3,rx,tx,cts,rts,threshold,mode,baud)
    #endif
    

    Then in demos/wifi I modified the Propeller 1 wifi_DO_PIN() and wifi_DI_PIN() functions in each of the demo programs (e.g. testwifi.c):

    int wifi_DO_PIN() {
       return 5;
    }
    
    int wifi_DI_PIN() {
       return 6;
    }
    

    Then I compiled the program. I did it manually rather than using the build_all script, because that script defaults to building in LARGE mode, which also works on the C3, but it won't work on Propellers that lack suitable XMM RAM. So I did it manually so I could use COMPACT mode:

    catalina testwifi.c -lwifi -lci -lserial4 -O5  -C NO_HMI -C COMPACT -C C3
    

    ... and Bob's your father's brother! :smiley:

    I can now load the program into the C3 and see its output using a suitable payload command - and a web browser! For example, my C3 is on port 4, so I used:

    payload -i -p4 testwifi
    

    This program serves a web page and can also respond to WebSockets and TCP requests, and it comes in under 10k of code (or 15k if you omit the -C COMPACT option, which means it will use TINY mode).

    I could not get the WiFi Reset function working, so I have to power cycle the module manually each time. I will investigate that, and also why it only works at1200 baud. I will do this as I have time.

    Also, note that the Propeller 1 only supports basic WiFi functionality (e.g. the programs in demos/wifi) - but this is enough to have it serve a web page etc. The eLua ALOHA WiFi functionality (e.g. in demos/elua/aloha) is not yet supported on the Propeller 1, and may never be - the Propeller 1 when using XMM RAM is simply not fast enough for this to be useful.

    Ross.

  • RossHRossH Posts: 5,564
    edited 2025-03-26 01:24

    @RossH said:
    I could not get the WiFi Reset function working, so I have to power cycle the module manually each time. I will investigate that ...

    Found this one. An embarrassingly silly error in my Propeller 1 PASM code. Everything works as long as you don't use the wifi_RESET() function.

    Does not affect the Propeller 2.

    Have fixed in on GitHub. Will include the fix in the next release for SourceForge users.

    Ross.

  • RossHRossH Posts: 5,564
    edited 2025-03-27 21:10

    I found the other problem with the Propeller 1 WiFi support, which meant the serial comms with the WiFi module only worked at very low baud rates (i.e. 1200 baud). I now have it working at 115200 baud.

    The problem was in the 4 port serial plugin. This plugin had very small buffers (16 bytes tx and 64 bytes rx) because it originally tried to fit everything into cog RAM. It also had incorrect bit timings (it uses bit banging). So it only worked at low baud rates and/or when only a small number of bytes were being transmitted or received at a time.

    I now have a new version of the plugin that increases the buffer sizes to 256 bytes (for both tx and rx), but on the Propeller 1 this would make this plugin too large for some programs that I know use it, so while I will fix the bit timings on the existing one, instead of also changing the existing buffer sizes I will add a new version of the plugin with the larger buffer sizes.

    The new plugin will be enabled by linking with a new "extended" version of the 4 port serial library (i.e. -lserial4x instead of -lserial4). So this is the library you will need to use with the WiFi module on the Propeller 1:

    catalina program.c -lserial4    <-- use the old 4 port serial plugin, with 16/64 byte tx/rx buffers. Use for existing programs.
    catalina program.c -lserial4x   <-- use the new 4 port serial plugin, with 256/256 byte tx/rx buffers. Use for WiFi programs.
    

    Since this needs a new plugin and library, I will have do another full release. Soon :(

    Ross.

  • RossHRossH Posts: 5,564

    Catalina 8.5.2 has been released on GitHub and SourceForge.

    This is a full release. It adds some minor serial and WiFi enhancements. It includes some bug fixes and a new "extended" version of the 4 port serial plugin for the Propeller 1.

    All the WiFi programs in demos/wifi now work correctly on both the Propeller 1 and Propeller 2, including a version of Lua with WiFi support - wlua (on the Propeller 1 this program requires XMM RAM).

    Here is the relevant extract from the README.TXT:

    RELEASE 8.5.2
    
    New Functionality
    -----------------
    
    1. The build_all script and Makefile in demos/wifi now defaults to building
       all programs in COMPACT mode on the Propeller 1 and NATIVE mode on the
       Propeller 2, except for wlua and wluax, which are built in LARGE mode
       on the Propeller 1 and COMPACT mode on the Propeller 2. This can be
       overridden on the build_all command line.
    
    2. A new "extended" version of the 4 port serial plugin and library has been
       added for the Propeller 1 which has 256 byte rx and tx buffers for each 
       port. This  version is enabled by linking with the new libserial4x library 
       (e.g. by using the command -lserial4x line option option). Note that the 
       same include file (serial4.h) is used for the serial4 and serial4x plugins.
       The serial4x plugin is now used when building the demos/wifi programs for 
       the Propeller 1.
    
    Other Changes
    -------------
    
    1. Fixed bugs in the Propeller 1 WiFi core functions drvlow(), drvhigh(), 
       input() and output() which prevented (for example) the wiFi_RESET() 
       function working on the Propeller 1. Affected the Propeller 1 only.
    
    2. Fixed a bug in the 4 port serial plugin. The bit timing meant it would 
       only work at low baud rates (e.g. 1200 baud) and/or when only a small 
       number of characters was being transmitted and/or received at a time. 
       Affected the Propeller 1 only.
    
    3. Some definitions were left out of the 2, 4 & 8 port serial include files 
       (i.e. serial2.h, serial4.h, serial8.h) when the serial function names 
       were unified to accommodate the generic serial include file (serial.h).
       Affected the Propeller 1 and Propeller 2.
    
    4. The README.TXT file in demos/wifi has been updated with more detail on 
       configuring programs to use the WiFi functionality on the Propeller 1, 
       which is more complex than the same process on the Propeller 2, 
       particularly for the Lua demos (wlua and wluax).
    

    I hope this is the last release for a while! :(

    Ross.

Sign In or Register to comment.