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

Catalina 2.9

1246715

Comments

  • potatoheadpotatohead Posts: 10,261
    edited 2011-02-09 22:04
    Dr_A: Very impressive indeed! I'm going to have a play when I complete the task I'm on right now. :)
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-02-09 22:09
    Thanks Ross. Looking through the Basic Stamp manual, I think some of the things relate to pins and maybe we need to look at some more catalina drivers.

    Turn a pin on and off. I've pondered the latch solution, but it is so inherently tied up with memory access and the core of catalina that I think it may not be the right answer. I'm thinking more of an SPI interface using the 4 pins dedicated to the SD card and adding more SPI chips. A bit like the C3 does. Though that still is going to possibly clash with SD card access. Hmm.

    For the basic stamp user, I think the best example code might be a few lines to turn a led on and off.

    Just in relation to that, is there an equivalent of PAUSE(100) in catalina?

    Another thing I guess are a few more inbuilt drivers. I would dearly love to have the dual serial port code as part of catalina, and then I could use the second serial port. Indeed, attaching the second serial port to a picaxe or basic stamp may actually be the simplest way to get multiple pins in and out, and analog I/O.
  • RossHRossH Posts: 5,548
    edited 2011-02-09 22:26
    potatohead wrote: »
    Yes I would say the same. IMHO, the differentiator for me is whether or not there are meta-tasks, and where the intent of the program is embodied.

    With LMM, whether it's one instruction, or a few, or 8, whatever, the center of attention isn't the kernel running in the COG.

    You're a hard man to convince :smile: I will have to give the subtleties in your post some thought - but in the meantime here's another thought experiment to ponder:

    What if there were no "kernel" at all? Just a PASM program which, when loaded, immediately started executing from location 200. If it ever gets to location 400 (or if the program ever jumped out of the range 200 - 400), it instead calls a function that overwrites locations 200 to 400 with the next 200 instructions and starts executing those instead.

    No kernel. No LMM primitives. No PC. No SP. No specific registers at all! Just one function that loads 200 instructions at a time. Or 300. Or 400.

    Native execution? Or not?

    Ross.
  • RossHRossH Posts: 5,548
    edited 2011-02-09 22:30
    Dr_Acula wrote: »
    Thanks Ross. Looking through the Basic Stamp manual, I think some of the things relate to pins and maybe we need to look at some more catalina drivers.

    Turn a pin on and off. I've pondered the latch solution, but it is so inherently tied up with memory access and the core of catalina that I think it may not be the right answer. I'm thinking more of an SPI interface using the 4 pins dedicated to the SD card and adding more SPI chips. A bit like the C3 does. Though that still is going to possibly clash with SD card access. Hmm.

    For the basic stamp user, I think the best example code might be a few lines to turn a led on and off.

    Just in relation to that, is there an equivalent of PAUSE(100) in catalina?

    Another thing I guess are a few more inbuilt drivers. I would dearly love to have the dual serial port code as part of catalina, and then I could use the second serial port. Indeed, attaching the second serial port to a picaxe or basic stamp may actually be the simplest way to get multiple pins in and out, and analog I/O.

    There's no problem with pins - Catalina offers C equivalents to all low-level Prop functions - e.g. _outa() to set pins, or _ina() to read them. See catalina_cog.h. There is also a _waitcnt() function to implement pauses (and ther is an msleep() macro that uses this defined in catalina_icc.h).

    Ross.
  • potatoheadpotatohead Posts: 10,261
    edited 2011-02-09 23:00
    (...and I apologize for stuffing this in here --was just thinking about virtual machines a lot lately because I'm using a batch of them right now to simulate a rather messy managed data environment on my laptop).

    Ok, so you are going to split hairs! Good.

    IMHO, your thought example is a overlay. The primary task is embodied in the PASM segments. If there is no kernel, there really isn't any supervisory meta-task, which indicates overlay.

    In that scenario, the PASM would have to be coded in such a way as to insure that the various segments handle their own affairs, and know when to launch the meta-code needed to fetch and hand control to the other segments. The supervisory function is the developer. Overlay.

    I find myself thinking about whether or not it's possible to supervise as a boundary between the techniques. 200 instruction chunks means very coarse interaction with the meta-task responsible for large model code. That's hard to characterize as anything but a overlay.

    There is your boundary as to "when" right there!

    Seems to me, the need for pseudo-opcodes contributes to that. With a 200 instruction block, it's really ugly not to use the native PASM instructions, so then there three basic paths:

    1. Do not use them, defaulting to managed instructions instead, meaning code must execute in 200 instruction blocks. Ugly and very coarse. This is supervised code, not practical, but not a overlay either.

    2. Do use them, and have them behave as native PASM does, meaning the developer must supervise this to insure that flow eventually results in the other overlays or blocks of PASM get fetched and executed. One model could be where a COG is to offer lots of services. A small portion waits, fetches, executes, then returns to wait again. Or, it's just a long program, broken into chunks that each understand what other chunks could be loaded and why. This is overlay, in that the developer is in charge of how it all comes together, and the flow of things is specific to the code needed, though the technique is repeated in concept, as I defined above.

    3. Do use them, but do not use them in the traditional sense. A branch would always branch to handler code that manages that branch, returning execution to the PASM after supervising said execution. That could be general purpose, as it operates in a structured and repeatable way not requiring the intervention of the developer to realize and most importantly, the code would not be useful without the kernel, or supervisor, or simply resident bits.

    Case number 2 could be useful without the connecting bits, and that crosses the boundary, making case 2 overlay, case 3 virtual or supervised code.

    I think I just expanded my scope of definition some. If the code could run stand alone, not requiring the kernel, it's going to make the case for being a overlay. If it can't execute without that supervisor, meta-code, then it's not a overlay, and in that case, the meta-tasks contained in the supervisor must be contributory and enabling, not primary just because of the order of things in that case.
  • RossHRossH Posts: 5,548
    edited 2011-02-10 01:07
    potatohead wrote: »
    Ok, so you are going to split hairs! Good.
    Just trying to establish where you draw the line between "native" (or "direct") and "non-native" (or "supervised") execution Obviously the line has to be drawn somewhere, or no PASM program larger than 496 longs in size could ever be regarded as being "native". If that were the case then there is little scope for further discussion.
    potatohead wrote: »
    IMHO, your thought example is a overlay.

    Mine too - but just to clarify - do you mean that you accept this is essentially "native" execution? - i.e. the overlay technique is primarily being used to circumvent the 496 instruction limit?
    potatohead wrote: »

    Seems to me, the need for pseudo-opcodes contributes to that. With a 200 instruction block, it's really ugly not to use the native PASM instructions, so then there three basic paths:

    1. Do not use them, defaulting to managed instructions instead, meaning code must execute in 200 instruction blocks. Ugly and very coarse. This is supervised code, not practical, but not a overlay either.

    2. Do use them, and have them behave as native PASM does, meaning the developer must supervise this to insure that flow eventually results in the other overlays or blocks of PASM get fetched and executed. One model could be where a COG is to offer lots of services. A small portion waits, fetches, executes, then returns to wait again. Or, it's just a long program, broken into chunks that each understand what other chunks could be loaded and why. This is overlay, in that the developer is in charge of how it all comes together, and the flow of things is specific to the code needed, though the technique is repeated in concept, as I defined above.

    3. Do use them, but do not use them in the traditional sense. A branch would always branch to handler code that manages that branch, returning execution to the PASM after supervising said execution. That could be general purpose, as it operates in a structured and repeatable way not requiring the intervention of the developer to realize and most importantly, the code would not be useful without the kernel, or supervisor, or simply resident bits.

    Case number 2 could be useful without the connecting bits, and that crosses the boundary, making case 2 overlay, case 3 virtual or supervised code.

    I think I just expanded my scope of definition some. If the code could run stand alone, not requiring the kernel, it's going to make the case for being a overlay. If it can't execute without that supervisor, meta-code, then it's not a overlay, and in that case, the meta-tasks contained in the supervisor must be contributory and enabling, not primary just because of the order of things in that case.

    I see what you're saying, but there are more cases than that. Perhaps I have not have explained my thought experiment well enough (actually, it's no longer just a thought experiment - I just wrote most of the code!). What I'm proposing is basically case number 2 - mostly "unmanaged" but with a single support function which gets executed automatically whenever the overlaid code attempts to execute outside the overlay range - and all that function does is blindly load in another 200 instructions for execution. No "kernel", no "primitives". Perhaps you would argue there is one primitive - i.e. the overlay load function - but of course you need that function to do overlays at all!

    I maintain that this case should also be categorized as "native" code execution (using overlays). But then if I understand your differentiation correclty, adding even one "psuedo opcode" - or a trivial supervisor function - turns this into "non-native" (or "supervised") code. But this means that pjv's multithreaded PASM solution is also "non-native" code - and I think he would be surprised to hear that!

    The upshot of all this is that I could quite easily turn Catalina into a "native" C compiler. But the results would run much more slowly, and the executables would be much larger, than the current "LMM" C compiler. So while it might be interesting as an exercise, I certainly have no intention of doing so!

    But what I will do is point people who demand a "native" C compiler for the Propeller to this thread!

    Ross.
  • potatoheadpotatohead Posts: 10,261
    edited 2015-07-01 22:35
    I'm not sure PJV would be surprised, if supplied with this discussion. Would be interesting to hear his contribution. And you are right too. There are more cases, though I think the coarse breakdown is enough for the discussion. I wish I knew enough to define more cases, but that's why I'm here! Love this stuff, and watching you and Dr_A and others build out this bigger model always has me thinking.

    :) By all means do invite them. I don't see "power" being linked to native, as everything costs something. People want a big COG, but that would cost them other things, which they also want. Another discussion.

    Frankly, I think LMM and it's supervisory capability is potent. The scale of Prop I means it's a bit of a PITA, and it makes running in the COG compelling, but at the scale of Prop II, it won't be seen in the same negative way, and it's a known thing now, not some discovery that wasn't realized early on.

    On that chip, for example, a perfectly reasonable video driver could be written that way, with the COG actually providing specialized services, or instructions, necessary for that task. Going to be interesting, IMHO. Several larger programs, each running from a LMM COG, each able to leverage some aspect of it... It's the same model now, only in a much larger memory space. Maybe people won't really ***** about 2K, once they see where it's all gonna go. And Chip is a smart cookie indeed :)

    Many virtual solutions use a supervisor, because native execution is necessary to actually perform the task in a way that makes sense. I find that we get this option in a micro-controller very interesting.

    Thanks for entertaining that diversion.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-02-10 05:28
    There's no problem with pins - Catalina offers C equivalents to all low-level Prop functions - e.g. _outa() to set pins, or _ina() to read them. See catalina_cog.h. There is also a _waitcnt() function to implement pauses (and ther is an msleep() macro that uses this defined in catalina_icc.h).

    This is great! It means we can take different syntaxes and work with them. eg I think sleep(); worked with tinyc, but you could change that to pause() or whatever, and then change that to the c command. I might get back to you in a day or two for some more details.

    Next little project is to take the XMM model and move it back to a smaller model. I've taken a shotgun approach and just put in every .h file I could find. But it might be worth thinking about a smaller model that uses less .h files.

    In particular, I wonder about taking the Basic Stamp and trying to emulate it in C/Basic. If you are doing such a thing, you might be very interested in code that does things like puts a pin high, waits a second, sets it low etc. But at the same time, maybe not so interested in displaying on a vga monitor, or an sd card. So for a minimalist approach, a number of .h files might not be needed. Maybe you don't even need stdio.

    The real motivation for this is to fit all the code into a propeller that has no external memory, and also has a large number of uncommitted pins. In other words, make this attractive to the Basic Stamp and Picaxe and Arduino group. Later, those people may want more code space, displays etc. A really cool thing about the BCX code is you can hybridise C and Basic. An Arduino user might for instance put $CCODE around their entire program and write it all in C. Or use the odd Basic syntax here and there. But a Basic Stamp user might write most of it in Basic. But use the odd C code here and there. This really does open up the code to both user groups, and, I think, neatly sidesteps the "my language is better than yours" debate.

    So my absolute minimalist "Hello World" does not even output "Hello World". All it does is flashes a led.

    This is still not quite as simple as it sounds. As we have found with the code to change the display color, such code is not ANSI C. So to get this to run on TinyC, I've had to add some code to comment out certain instructions (namely the HMI ones) if you are compiling for TinyC, but include those instructions if you are compiling for catalina.

    Setting pins will need different compiling for different platforms. Probably the easiest is to comment out certain lines for the TinyC compilation, as "HIGH 1" does not mean anything on a console program"

    I think this can all be possible.

    One thing that might be very handy is to know how much propeller memory is being used. So - is it possible to find out the file size of a program compiled by catalina? Or should I just compile it and then use a windows function to get the file size?
  • RossHRossH Posts: 5,548
    edited 2011-02-10 12:48
    Dr_Acula wrote: »
    One thing that might be very handy is to know how much propeller memory is being used. So - is it possible to find out the file size of a program compiled by catalina? Or should I just compile it and then use a windows function to get the file size?

    Catalina 2.9 prints the size of each segment at the end of each compile. I compiled your translated program using the command:
    catalina -lc bcx.c -lm -x2 -D DRACBLADE
    
    , and here is the result:
    code = 38264 bytes
    cnst = 1344 bytes
    init = 556 bytes
    data = 9596 bytes
    file = 82916 bytes
    

    This is quite promising - it means that a smaller program that (say) did not do floating point (and therefore could be compiled with -lci instead of -lc) might not even need XMM RAM!


    Ross.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-02-11 14:20
    That will be useful - I might see if I can put that into a bargraph or something. Does this output appear in a file or just on the screen?

    BCX is a treasure trove of goodies. Reading through the documentation you might get the impression that it only does integer, long, float and string variables, but in fact there are many other types - unsigned long, signed long, char, short etc. These are all in the Help under BCX "Other Procedures" in the DIM section. In fact, most of the C type variables seem to be there.

    I was looking into this because I want a variable that is 32 bit and unsigned, and the syntax for that is DIM a AS UINT
    I am not sure if BCX has 'binary' variable (not sure if C does either), eg Spins %%01010101010000111 and so maybe it might be possible to replicate this with a pre-processor that converts this to hex or decimal.
  • RossHRossH Posts: 5,548
    edited 2011-02-11 14:44
    Dr_Acula wrote: »
    That will be useful - I might see if I can put that into a bargraph or something. Does this output appear in a file or just on the screen?

    Do you mean the size statistics? They are printed on the screen (although of course they are also embedded in the binary file Catalina generated - that's actually where Catalina gets them from). You could simply redirect the output of the compilation command to a file if you wanted to process them.

    Ross.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-02-11 15:15
    Ah, so two options there. If I open the binary file, are they easy to find/decode?

    Or - (this is delving into the memory banks) - can you direct the screen output to a file with the > character?

    I'm thinking that as you move into XMM you might start with a 128k model because a 512k one takes longer to download, but if you can see it filling up, then just go into the settings and increase say to 256k.
  • RossHRossH Posts: 5,548
    edited 2011-02-11 15:45
    Hi Dr_A,

    Yss, use > to redirect output to a file. To extract the values from the binaries is much more complex, since the interpretation of the binary depends on the memory model in use. I wouldn't recommend this method, but if you're interested you can look at the code in source\catalina\catbind.c (search for all occurrence of the string "data = ").

    Ross.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-02-11 20:35
    Quick question - how do I get the latest 2.9 version? I tried downloading from sourceforge and extracting to c:\program files\catalina but it seems to have put all the files in c:\program files\catalina and not in all the sub directories (and didn't ask 'do you want to replace the old files').

    I'm still on version 2.6 which doesn't seem to display the files sizes, so time to upgrade!
  • RossHRossH Posts: 5,548
    edited 2011-02-11 21:07
    Dr_Acula wrote: »
    I tried downloading from sourceforge and extracting to c:\program files\catalina but it seems to have put all the files in c:\program files\catalina and not in all the sub directories (and didn't ask 'do you want to replace the old files').

    Not sure which "unzip" program you use, but I just downloaded and unzipped them again (twice actually - once with 7-zip and once with the built in windows zip file manager) and it's fine both ways.

    You must have selected an option to ignore the embedded directory names (I know there is one in WinZip, but I don't recall the details, and I don't have WinZip installed).

    There's probably no way to get all the files back into their correct places - you are better off deleting all the files you just added and unzipping them again.

    Ross.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-02-11 21:46
    Ok, I'll give that a try.

    Got binary numbers working. Run this through a little Basic pre-processor and it converts 0b numbers to 0x numbers. Prints "FF00FF55". Binary numbers come up a fair bit in Spin so this ought to make it easier to translate Spin to Basic.
    dim a as integer
    a=0b11111111_00000000_11111111_01010101 ' binary number
    print hex$(a) 
    
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-02-11 21:50
    Re the download, can you just check sourceforge. There is this line
    "Looking for the latest version? Download Catalina_2.9_C3_target_update_3.zip (237.3 KB) "
    and when you download that, it does not seem to have a directory structure, and does not seem to list very many files either (36 files). I am wondering if that is an update file rather than the complete file?? Or maybe I'm not in the right place in sourceforge?

    Addit: quick fix I'm reading the .binary file size. Getting values like 25k for a LMM version with just stdio, and when include most of the #includes and doing an xmm, getting 90k. Do these sound plausible?

    If so, when you have a value like 25k, what % of the propeller is that (I think some high memory is reserved, right?) Is it roughtly 25/32

    Addit - being able to see the size of the programs is very useful.

    How small can a program go? I'm thinking of a program that blinks a led, so no stdio etc. I tried this
    static int     a;
    
    int main(int argc, char *argv[])
    {
    a=5;
      return 0;   //  End of main program
    }
    

    and it is about 9k. Not sure if I have the command line options right though. I think vga is still there, and not 100% sure but I think the HMI and sd card is still there too. What command line option would you use to load no cogs and just blink a led?
  • RossHRossH Posts: 5,548
    edited 2011-02-12 03:50
    Dr_A,

    I have no control over the messages SourceForge puts up. The latest release of Catalina is Catalina_2.9_Win32.zip (or Catalina_2.9_linux.tgz). The file you are downloading (Catalina_2.9_C3_target_update.zip) is an update for the C3 to the target directory only - this file should be unzipped in the target directory AFTER installing one of the other files.

    As to your minimal program - I compiled it with the following command, which results in just about the smallest possible executable:
    catalina -lci program.c -D DRACBLADE -D NO_HMI -D NO_ARGS  -D ALTERNATE -D NO_FLOAT
    
    The result is:
    code = 88 bytes
    cnst = 0 bytes
    init = 4 bytes
    data = 8 bytes
    file = 2332 bytes
    
    This means the code is 88 bytes, but the resulting file is 2332 bytes. The reason for this is the size of the kernel itself, which must be included in the binary, but (once loaded) does not occupy any code space.

    Ross,
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-02-12 04:46
    Now that is a very small program!

    Very useful if you want to write simple code that, say, reads an input, waits a while, then flashes a led.

    I wonder if you can help with this. I'm sure I had this working but now it tells me Sin (and log etc) are not defined. Am I missing a .h file?
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <math.h>
    #include <ctype.h>
    #include <errno.h>
    #include <float.h>
    #include <inttypes.h>
    #include <limits.h>
    
    // *************************************************
    //            User Global Variables
    // *************************************************
    
    static double  number1;
    
    
    // *************************************************
    //                  Main Program
    // *************************************************
    
    int main(int argc, char *argv[])
    {
    number1=1.2345;
    printf("% .15G\n",(double)number1);
    printf("% .15G\n",(double)sin(number1));
      return 0;   //  End of main program
    }
    
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-02-13 04:31
    Hi Ross,

    I've got a lot of programs working in the last 24h. Prototypes for an ultra tiny version (5k), TinyC (for quick debugging), LMM and XMM.

    I'd like to be able to turn a led on and off with a minimalist program. Unfortunately in the process of deleting #include files I think I deleted too much. The following code compiles with Tiny C but with Catalina it gives two errors "pow not defined" and "log10 not defined".

    Your advice would be most appreciated.

    source Basic code
    #include <stdio.h>
    
    Print "Binary set and reset"               
    
    dim pins as uint
    pins = 0b00000000_00000000_00000000_00000001 ' start value
    pins =  HighBit(pins,31) ' set bit 31
    print bin$(pins) ' print binary value 1000000000000000000000000000001
    pins = HighBit(pins,30)' set bit 30
    print bin$(pins)' print binary value
    pins = LowBit(pins,30) 'reset bit 30
    print bin$(pins)' print binary value
    pins = LowBit(pins,0) ' reset pin 0
    print bin$(pins)' print binary value
    
    
    Do
    Loop Until 0=1                          ' infinite loop
    
    
    
    Function HighBit(pins as uint, pinnumber as integer) as uint
      pins = pins or (1 << pinnumber) ' shift and logical OR
      Function=pins ' return the value
    End Function
    
    Function LowBit(pins as uint, pinnumber as integer) as uint
      pins = pins and bnot((1 << pinnumber)) ' shift and logical And with inverse
      Function=pins ' return the value
    End Function
    


    c code
    #include <stdio.h>
    
    // *************************************************
    //                Typedef
    // *************************************************
    
    typedef unsigned char UCHAR;
    typedef unsigned long DWORD;
    typedef unsigned long UINT;
    
    // *************************************************
    //                System Variables
    // *************************************************
    
    
    // *************************************************
    //            User Global Variables
    // *************************************************
    
    static UINT    pins;
    
    
    
    // *************************************************
    //               Standard Macros
    // *************************************************
    
    #define BAND &
    #define BOR |
    #define BNOT ~(int)
    
    
    // *************************************************
    //               Standard Prototypes
    // *************************************************
    
    char*   BCX_TmpStr(size_t);
    char*   Bin (int);
    
    // *************************************************
    //               User Prototypes
    // *************************************************
    
    UINT    HighBit (UINT, int);
    UINT    LowBit (UINT, int);
    
    
    // *************************************************
    //            User Global Initialized Arrays
    // *************************************************
    
    
    // *************************************************
    //                  Main Program
    // *************************************************
    
    int main(int argc, char *argv[])
    {
    printf("%s\n","Binary set and reset");
    pins=0x00000001;
    pins=HighBit(pins,31);
    printf("%s\n",Bin(pins));
    pins=HighBit(pins,30);
    printf("%s\n",Bin(pins));
    pins=LowBit(pins,30);
    printf("%s\n",Bin(pins));
    pins=LowBit(pins,0);
    printf("%s\n",Bin(pins));
    for(;;)
      {
        if(0==1)
          {
            break;
          }
      }
      return 0;   //  End of main program
    }
    
    // *************************************************
    //                 Runtime Functions
    // *************************************************
    
    char *BCX_TmpStr (size_t Bites)
    {
      static int   StrCnt;
      static char *StrFunc[2048];
      StrCnt=(StrCnt + 1) & 2047;
      if(StrFunc[StrCnt]) free (StrFunc[StrCnt]);
      return StrFunc[StrCnt]=(char*)calloc(Bites+128,sizeof(char));
    }
    
    
    char* Bin(int number)
    {
      char *strtmp = BCX_TmpStr(2048);
       itoa(number,strtmp,2);
      return strtmp;
    }
    
    
    
    // ************************************
    //       User Subs and Functions
    // ************************************
    
    
    UINT HighBit (UINT pins, int pinnumber)
    {
      pins=pins BOR (1<<pinnumber);
      return pins;
    }
    
    
    UINT LowBit (UINT pins, int pinnumber)
    {
      pins=pins BAND  BNOT ((1<<pinnumber));
      return pins;
    }
    
  • Heater.Heater. Posts: 21,230
    edited 2011-02-13 05:03
    Dr_A,

    You will need to #include<math.h> to get definitions of pow() and log10().

    But I don't see those being used in your code snippets above.
  • RossHRossH Posts: 5,548
    edited 2011-02-13 14:07
    Hi Dr_A,

    There are a couple of problems here.

    The main one is that your code is using printf(), which also needs floating point support (since printf can be used to print floating point numbers). So while you don't need to include maths.h (because your code is not itself calling any floaitng point functions) you still need to link with the floating point library -lm (or -lma or -lmb).

    If you do not want floating point support, then normally you could link with the integer libraries -lci instead of -lc (and then you can omit the floating point libraries). However, you will run into problems here because you are using the non-ANSI function itoa(). Catalina has a version of itoa(), but it is in the floating point library!

    However, I have extracted the itoa function from the Catalina souce, and included it below - just include it in a file itoa.c and compile your program with a command such as:
    catalina -lci bcx.c itoa.c
    
    /*
     * itoa() - convert integer to string
     *
     * expects: an integer
     *
     * returns: pointer to a static buffer
     */
    
    #define ITOA_BUFSIZE 12 /* 10 digits + 1 sign + 1 trailing nul */
    
    static char itoa_buf[ITOA_BUFSIZE];
    
    char *itoa(int i) {
            char *pos = itoa_buf + ITOA_BUFSIZE - 1;
            unsigned int u;
            int negative = 0;
    
            if (i < 0) {
                    negative = 1;
                    u = ((unsigned)(-(1+i))) + 1;
            }
            else {
                    u = i;
            }
    
            *pos = 0;
    
            do
            {
                    *--pos = '0' + (u % 10);
            u /= 10;
            } while (u);
    
            if (negative) {
                    *--pos = '-';
            }
    
            return pos;
    }
    
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-02-13 14:10
    Cross posts, reading through your answer now...


    Ok, for debugging I need printf(). But what I am debugging is a minimalist piece of code that just flashes a led and has no display or keyboard or anything. So I guess I need to change my code so it doesn't have any printf.

    Re post 110, could that be a lm or lc or one of those command line errors too?

    Just on this point, one of the things I've thought about is all those command line switches and how they may need to change for different programs. So what I've done is added a $COMMAND section to the basic code, and within that section you can put the command line for catalina. If it does not find this it compiles with the defaults in the settings page. But if it does find this then it compiles using those commands. It might make it easier to debug too as you will be able to see what command line was used (I've now got three flavours just on the dracblade).
  • RossHRossH Posts: 5,548
    edited 2011-02-13 14:31
    Dr_Acula wrote: »
    Cross posts, reading through your answer now...

    Ok, for debugging I need printf(). But what I am debugging is a minimalist piece of code that just flashes a led and has no display or keyboard or anything. So I guess I need to change my code so it doesn't have any printf.
    Anything that includes printf() also includes a couple of thousand lines of C library code - hardly minimalist!

    As an alternative, you could use the much smaller t_printf() defined in catalina_hmi.h - see the Catalona reference manual for details.
    Dr_Acula wrote: »


    Re post 110, could that be a lm or lc or one of those command line errors too?
    Sorry - I missed that question. Yes, compile your program with -lm. For example:
    catalina bcx.c -lc -lm
    
    Dr_Acula wrote: »
    Just on this point, one of the things I've thought about is all those command line switches and how they may need to change for different programs. So what I've done is added a $COMMAND section to the basic code, and within that section you can put the command line for catalina. If it does not find this it compiles with the defaults in the settings page. But if it does find this then it compiles using those commands. It might make it easier to debug too as you will be able to see what command line was used (I've now got three flavours just on the dracblade).

    Yes, that's a good idea. I may add something similar to the next version of Catalina - e.g. a CATALINA_OPTION environment variable that works in much the same as the current CATALINA_DEFINE environment variable, but allows you to include other common command line options (libraries, memory model etc).

    Ross.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-02-13 15:20
    Ok, will check the -lm -lc and see if that works. It probably is the problem since I'm working with all these different command line versions.

    I've got the size of the program on the screen now and it is very handy to see how much extra space things like printf use. For the XMM program it is easy just to put everything in, but for a really small program it is useful to know how much space things take.

    At the moment the $COMMAND section is just a single line which is the compile line minus the name of the file (which gets added by a precompiler).

    But as I was writing this I was thinking about each of the options and how they relate to each other. For instance, if you are adding -lm in the command line, there is a pretty good chance that you will be using #include <math.h>.

    I was thinking of somehow associating these with each other. First thing was that I have added the #includes to the Basic program. I know that #include is not a strict basic command, but with vb.net I've been getting used to the idea of Basic and C merging together (eg the concept of file streams from C now appears in Basic, and the concept of strings from basic eg strings.left() now appears in C). So hopefully it is ok to add #include to Basic code!

    If you do that, then it could be possible to build up a command line based on what includes are present. eg, if you are using stdio, there is a pretty good chance you have a keyboard and a display present, so the command line could reflect this. Ditto if you have math.h present, then there are some other command line parameters one would always add. I'm not sure about sd access - which #includes those are and also which command line parameters those are.

    And then I was thinking of taking the $COMMAND section and splitting it up to individual -lm is on its own line, and then you could put a comment on that line to describe what this actually is.

    I've got some pro-forma "new" programs that come up when you click the new button, so that you don't have to think about this too much.

    One thing that is very nice about BCX is being able to see the C code being generated. So if you write a function, and you want to return a value, the Basic syntax is 'function = myvariable" which is translated to "return = myvariable;" in C. BCX lets you write either. Sometimes it is easier to write the C syntax than to go through the BCX manual looking for the Basic syntax!

    I'm working towards a Basic Stamp type of command where you type "HIGH 1" and pin 1 goes high. I don't think I can quite get there without a preprocessor, but I think I can get pretty close with a subroutine called HIGH and then the command is "HIGH(1)" which is pretty close to "HIGH 1". That function would read the current state of the pins (which you have already included in Catalina - thanks!), then change the bit with the code I have above, then output the new value. This shields a new user from slightly scary things like << and logical ands/ors with bitmasks.
  • RossHRossH Posts: 5,548
    edited 2011-02-13 15:35
    Dr_Acula wrote: »

    But as I was writing this I was thinking about each of the options and how they relate to each other. For instance, if you are adding -lm in the command line, there is a pretty good chance that you will be using #include <math.h>.

    I was thinking of somehow associating these with each other. First thing was that I have added the #includes to the Basic program. I know that #include is not a strict basic command, but with vb.net I've been getting used to the idea of Basic and C merging together (eg the concept of file streams from C now appears in Basic, and the concept of strings from basic eg strings.left() now appears in C). So hopefully it is ok to add #include to Basic code!

    If you do that, then it could be possible to build up a command line based on what includes are present. eg, if you are using stdio, there is a pretty good chance you have a keyboard and a display present, so the command line could reflect this. Ditto if you have math.h present, then there are some other command line parameters one would always add. I'm not sure about sd access - which #includes those are and also which command line parameters those are.

    Good thought - it is reasonable to use the #includes to determine a default set of command line options - just make sure it is configurable, because it will be different on each platform. Also, users will need to be able to override them. For example, some users might want the software floating point library and some might want the faster multi-cog one. Similarly, some users might want VGA output, while others will want TV etc etc.

    Ross.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-02-13 15:51
    Yes, I agree. The floating point for instance has three different options. Maybe you could have three lines in the $COMMAND section with all three of those options and a description of speed and cogs used, and two of them commented out, and a comment line "uncomment one of these three for floating point".

    Ditto the TV and VGA - maybe include both and one is commented? Then the new user does not need to know exactly what the syntax is.

    If these are simply lines in BASIC code, the user can then change them as they like.

    The precompiler uses this to build a command line which is stored in the IDE ready for compilation, and it still produces standard C89 code as well.

    Bean has some Basic code
    10 HIGH 23
    20 PAUSE 100
    30 LOW 23
    40 PAUSE 100
    50 GOTO 10
    

    I'd like something similar. No line numbers though, and replace the GOTO with a DO-LOOP. I think it is getting close to being able to write something like
    DO
      HIGH(23)
      PAUSE(100)
      LOW(23)
      PAUSE(100)
    LOOP
    

    Regarding the PAUSE function, is there somewhere internal to Catalina that has the clock frequency? Or do we just assume a 5Mhz xtal?
  • RossHRossH Posts: 5,548
    edited 2011-02-13 15:55
    Dr_Acula wrote: »
    Regarding the PAUSE function, is there somewhere internal to Catalina that has the clock frequency? Or do we just assume a 5Mhz xtal?

    Yes _clockfreq(), defined in catalina_cog.h. See the reference manual (pp 38) for more details.

    Ross.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-02-13 16:13
    Thanks. Catalina is like this giant Christmas stocking that is filled with goodies!
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2011-02-14 19:01
    Hi Ross,

    Can you explain the library options a little more? There is -lc, which I think is some essential libraries. -lm is maths. I added that to a program, but it doesn't change the compile size. Is there a memory cost with adding these libraries?

    In general terms, which libraries go with which #include files?

    Also, this program compiles and runs with TinyC and prints "11111111" but does not work with Catalina. Any idea what might be wrong?
    ' BCX help file http://www.bcxgurus.com/help/index.html
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <math.h>
    #include <ctype.h>
    #include <errno.h>
    #include <float.h>
    #include <inttypes.h>
    #include <limits.h>
    
    $COMMAND
    catalina -lcx -lm -x5 -M 128k -D DRACBLADE -D VGA_HIRES
    ' library cx, library maths (slow, doesn't use a cog), memory size, board, high res vga, mouse, keyboard
    $COMMAND
    ' ************ main **********
    
    print bin$(255) ' print binary value 255 is 11111111
    
    Do
    Loop Until 0=1                          ' infinite loop
    ' *********** end main *******
    

    c code
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <math.h>
    #include <ctype.h>
    #include <errno.h>
    #include <float.h>
    #include <inttypes.h>
    #include <limits.h>
    
    // *************************************************
    //                Typedef
    // *************************************************
    
    typedef unsigned char UCHAR;
    typedef unsigned long DWORD;
    typedef unsigned long UINT;
    
    // *************************************************
    //                System Variables
    // *************************************************
    
    
    
    
    // *************************************************
    //               Standard Prototypes
    // *************************************************
    
    char*   BCX_TmpStr(size_t);
    char*   Bin (int);
    
    
    // *************************************************
    //            User Global Initialized Arrays
    // *************************************************
    
    
    // *************************************************
    //                  Main Program
    // *************************************************
    
    int main(int argc, char *argv[])
    {
    printf("%s\n",Bin(255));
    for(;;)
      {
        if(0==1)
          {
            break;
          }
      }
      return 0;   //  End of main program
    }
    
    // *************************************************
    //                 Runtime Functions
    // *************************************************
    
    char *BCX_TmpStr (size_t Bites)
    {
      static int   StrCnt;
      static char *StrFunc[2048];
      StrCnt=(StrCnt + 1) & 2047;
      if(StrFunc[StrCnt]) free (StrFunc[StrCnt]);
      return StrFunc[StrCnt]=(char*)calloc(Bites+128,sizeof(char));
    }
    
    
    char* Bin(int number)
    {
      char *strtmp = BCX_TmpStr(2048);
       itoa(number,strtmp,2);
      return strtmp;
    }
    

    is the problem the third last line "itoa" which wikipedia says is "widespread but non standard" http://en.wikipedia.org/wiki/Itoa
Sign In or Register to comment.