The main problem with using C on the P1 is that the standard C libraries tend to quickly fill up the limited amount of hub RAM. Any program that uses the standard I/O printf and file I/O has almost no memory left over to do anything useful. To get around this we've resorted to using smaller versions of the stdio functions that take less space. Other memory models were also developed to be more compact or to use external memory. A combination of using the Compact Memory Model (CMM) along with smaller libraries has proven to work quite well.
Another problem is integrating C with assembly code. It is possible to intersperse inline assembly in C code, and assembled assembly files can be linked with compiled C files. It is also possible to include blobs of pre-assembled assembly code as data, and run them in separate cogs from a C program. This is all a bit cumbersome, and I think SimpleIDE could be improved to make this task easier.
Yes, you have to be careful when porting large C programs from other platforms. In fact, this is true of any MCU. You can't just port a big desktop application to an MCU and expect it to work. You have to be aware of the limitations of your target platform and make intelligent decisions. If you do that and size your applications appropriately, you can use C/C++ successfully on the Propeller. Of course, Spin doesn't have this problem because the only Spin programs that exist were written for the Propeller so they, by definition, fit. Well, that's not entirely true. It's certainly possible to use a collection of "objects" from OBEX that together will not fit. So even in Spin you have to take into account your limited memory resources.
I know my own little experience with C on the Prop1 caused all the blood to drain from my face upon first use of printf(). I've since noted Mr Zemon recommending alternatives to printf(). Can't remember what they were now ...
The list continues to grow! I am aware of the following options, all of which are available in the "develop" branch of PropWare (here)
This time I'm breaking this out between high-level interaces and backend drivers. I think its important to recognize the difference because, with very minimal work, any driver can be used with (almost) any interface.
Interfaces:
printf - Part of the C standard library. Big, fat, most flexible option available
__simple_printf - Also packaged in the C standard library but it's special to PropGCC. Uses the same serial driver as printf but does not support as many formats (still supports more than most people need)
tinystream - Part of the C++ standard library, this is the std::cout interface on a severe diet.
print - Developed as part of the Simple libraries, this little guy uses a smaller driver and fewer supported formats relative to __simple_printf. Supports most everything you'd ever need.
printi - Exactly the same as print, but skips out on floating point support, saving significant code space. This is a great default for all of your applications compiled with SimpleIDE.
pwOut - Public, global instance of PropWare's Printer interface. It is both flexible (floating point support) and compact. My personal favorite, because I wrote it. Provides support for C++'s << operator as well as the familiar printf and println functions.
PrintStream - @SRLM's contribution to the Propeller commmunity, this is part of libpropeller.
Print - a port of Arduino's Print class, this comes with libPropelleruino. I have yet to test it out, but it is surely good for converting existing Arduino code.
Drivers:
Default driver shipped with C standard library. I don't know how this is coded or where it is documented. Seems to be reasonably compact.
Default driver used by print, printi, and other text functions in the Simple library. Not very fast for an unbuffered driver and only moderately compact.
tinyio - Used to be a reasonable backing to printf and std::cout, but Simple's drivers are better and the print and printi interfaces work great. tinyio is deprecated.
fdserial - A port of the Spin object, FullDuplexSerial. Buffered and full-duplex... but very large.
PropWare::UARTTX - Unbuffered, very fast, transmit-only UART driver. Capable of 4.4 Mbaud with an average throughput of 2.7 Mbps in 8N1 configuration with XTAL = 80 MHz. Slightly more compact that Simple's default driver if I remember correctly.
libpropeller::Serial - Port of Fast Full-Duplex. Max baudrate is documented as clkfreq / (86 * 2), or 465,116 @ 80 MHz.
I really hate to jump into language wars, particularly since I am not a Propeller expert or even a professional programmer.
I'm a retired metallurgical engineer with previous experience programming in a dialect of early MS Basic and have programmed at work using PDP11 Basic and Techtronics Basic. I had very limited exposure to 8080 ASM, forth, and Tiny C. My interest in the Prop was because of its multicore nature and the people on this forum.
I started to learn Spin (from the PEK), C from the Learn tutorials, and forth using Dave's pfth and PASM from the forum, C, and Spin objects. From my experience, I found pfth and the interactive nature of forth (particularly with the multicore nature of the prop) gave me great insight into the workings of the Prop. C was easy to learn (at least at a beginner level) from the tutorials, but Spin has been difficult for me. If I work at it for a few days straight, I can understand how it works, but if I am away a couple of days, I can't remember enough to write code or to read and understand someone else's code.
The main advantage of Spin for me is that it is so compact compared with C, and learning it is important to me primarily to take advantage of the Spin code already written so I can translate it into C and incorporate the PASM code into C programs.
Regarding the use of the C printf function (actually on the Prop I use print or printi), coming from a Basic background I really didn't like it, but now its a lot easier. Compare some code from a Spin program I wrote with C code that does the same thing.
print("\n PHSA = %d ", pinval); // yeah the ";" can be annoying
The C seems to be easier to write and read (for me).
Regarding speed, in the PEK section on using counters for RC measurements, Andy discusses the overhead delay in switching a pin from "out high" to "input" as is done in the RC examples. I wanted to see what the overhead would be in different languages (Spin, C, PASM and pfth. In this thread: forums.parallax.com/discussion/comment/1375740/#Comment_1375740
I show the time it took to make the switch.
PASM was obviously the fastest by an extreme amount (6 clocks) compared with everything else. Initially I saw that SPIN (595 clocks) was faster than C (compact memory model - 707 clocks), but that was using the Simple Libraries "input()" function to make the switch. By using the Propeller.h library "DIRA" to switch from output to input, the time for the CMM version was reduced to 163 clocks, significantly less than the Spin time. DIRA is a little more Spin like and complicated to use than "input()", so maybe not as easy to use in the educational program, but has a speed advantage.
I realize that there are many different ways to measure and compare language speeds, this was just a simple example, and the trend probably doesn't hold for other benchmarks.
Regarding incorporating PASM into C, Parallax has made it easier using a Simple Libraries call to link PASM in a Spin object than it was originally. I've used that method to both use PASM in a Spin object from the Prop Tool Library, as well as writing a short PASM function in a Spin wrapper that just had a PUB dummy and DAT section. I agree that inline PASM would be useful (maybe that already exists? and needs to be explained?)
I still have problems with C pointers and have to relearn the syntax and how they work, each time I need them.
I really like Spin, how compact it is and how it directly interacts with the Prop, but it does not seem intuitive (to me) so I have to work harder to understand it, particularly when experienced programmers use "tricks" to take maximum advantage of it.
I am looking forward to the P2 with its large memory and Hubex should significantly improve the capability of C (and other languages). I hope that Parallax is working on porting C to it.
Tom
In Tachyon Forth you can interactively type in this equivalent loop where you can exit by hitting any key.
pub MAIN BEGIN 0 PIN@ IF 1 HIGH 100 ms 1 LOW 100 ms ELSE 1 second THEN KEY UNTIL ;
Type MAIN to run which will flash the LED 5 times a second while P0 is high otherwise waits 1 second when low (which is redundant btw). Hit any key to exit back to Forth. This little routine consumes 27 bytes as measured by me Telneting to a Tachyon system since I am nowhere near my workshop. Of course you have to have Tachyon loaded to run this such as using the precompiled Explorer images but you are able to interact with the hardware and type simple one-liners for instance for immediate execution.
@forum
While I'm sure C will be a hit with P2 it certainly seems to be an awkward fit for P1 and I can probably understand David Betz's annoyance at the perceived C bashing, but the thing I've noticed over the years is that every language gets bashed for some reason or another. Spin is easy to learn and use and compact but relatively slow but still I found in the past that it still runs out of memory when I've tried to extend the capabilities which is why I wrote Tachyon, so I can have the speed, the compactness, the interactivity, and still fit everything in without resorting to memory expansion schemes. If whatever language you use works for you, good. If it doesn't then what's the point of using it since it is a means to an end after all, not the end itself (unless you are learning a language).
I started with the BASIC Stamp 2 (BS2) so at first Spin looked intimidating but I recognized many of the commands and structures as being the same.
Going section by section though the Propeller Education Kit (PEK) text and using the examples as a guide I became more comfortable with Spin and started to see how simple and yet powerful is was.
Unfortunately, the PEK text doesn't teach how to use Constants (CON) is programs, which is something that made BS2 programs easier to understand and quick to modify.
Even the Propeller C tutorial doesn't mention Constants (CONST) though they used to make I2C easier to use.
Seeing Button and LED makes a program a lot easier to understand that if you just use I/O pin numbers.
Peter,
That 1-liner may save keystrokes but it obfuscates, or makes it difficult to understand, what the code is doing.
If you were to come back to it later I am sure you would spend a lot more time decrypting it than you originally saved "keying" it in.
Seeing as it seems everytime I go on the internet some program is either written in C or has been rewritten into C, I find it ironic that you feel C is always being bashed on.
It gives the impression that something is wrong with people who don't program in C.
Seeing as it seems everytime I go on the internet some program is either written in C or has been rewritten into C, I find it ironic that you feel C is always being bashed on.
It gives the impression that something is wrong with people who don't program in C.
I assume you mean "everytime I come to these forums"? Certainly there is far more C/C++ code on the Internet as a whole than Spin code. My concern is that those who offer help here on these forums usually try to steer people away from C/C++ toward Spin or Forth. In fact, even that doesn't bother me. Sometimes those languages are the best choices. What I don't appreciate are all of the comments that C/C++ is not suited to the P1. That I consider bashing. You might prefer Spin or Forth or whatever but there is no need to bash C/C++ or any other language. As evidenced by the Parallax Learn tutorials, C is certainly a viable language on the P1.
Edit: And, no, I don't think there is anything wrong with people who don't program in C.
printf - Part of the C standard library. Big, fat, most flexible option available
__simple_printf - Also packaged in the C standard library but it's special to PropGCC. Uses the same serial driver as printf but does not support as many formats (still supports more than most people need)
tinystream - Part of the C++ standard library, this is the std::cout interface on a severe diet.
print - Developed as part of the Simple libraries, this little guy uses a smaller driver and fewer supported formats relative to __simple_printf. Supports most everything you'd ever need.
printi - Exactly the same as print, but skips out on floating point support, saving significant code space. This is a great default for all of your applications compiled with SimpleIDE.
pwOut - Public, global instance of PropWare's Printer interface. It is both flexible (floating point support) and compact. My personal favorite, because I wrote it. Provides support for C++'s << operator as well as the familiar printf and println functions.
PrintStream - @SRLM's contribution to the Propeller commmunity, this is part of libpropeller.
Print - a port of Arduino's Print class, this comes with libPropelleruino. I have yet to test it out, but it is surely good for converting existing Arduino code.
OT - language wars.
We really should try to keep on topic instead of digressing as it confuses the readers into believing there are problems where there are none.
Having said this, just to belay some fears, I have a commercial project that uses a very large Catalina C program (developed before GCC was available). It runs on a P1 with latchless (ie fast) 512KB SRAM and microSD card with a huge database of files (list of stars, nebulas, etc, etc). This P1 communicates with 2 other P1's to handle other I/O functions including driving a telescope.
Could it be done with other micros? Absolutely yes. But the P1 means all 3 processors are the same, easy to use Propeller. Each cog (core) can handle its' own dedicated I/O via a separate driver. There are no interrupts to handle, so everything can be done in real time where necessary. Basically we have 3*8 32-bit CPU cores, less inter-connecting cores. We have a mix of spin, pasm and C cores, with each able to perform its' own task(s) without worrying about the other tasks. And each of these languages is a pleasure to program thanks to the Propeller dynamics.
OT - language wars.
We really should try to keep on topic instead of digressing as it confuses the readers into believing there are problems where there are none.
Having said this, just to belay some fears, I have a commercial project that uses a very large Catalina C program (developed before GCC was available). It runs on a P1 with latchless (ie fast) 512KB SRAM and microSD card with a huge database of files (list of stars, nebulas, etc, etc). This P1 communicates with 2 other P1's to handle other I/O functions including driving a telescope.
Could it be done with other micros? Absolutely yes. But the P1 means all 3 processors are the same, easy to use Propeller. Each cog (core) can handle its' own dedicated I/O via a separate driver. There are no interrupts to handle, so everything can be done in real time where necessary. Basically we have 3*8 32-bit CPU cores, less inter-connecting cores. We have a mix of spin, pasm and C cores, with each able to perform its' own task(s) without worrying about the other tasks. And each of these languages is a pleasure to program thanks to the Propeller dynamics.
Sounds like a nice design. I wish RossH would come back. I know there were a number of Catalina users here who would probably appreciate that as well. Who knows, Catalina ported to the P2 could be the first C compiler for P2!
I'm getting really tired of people saying how bad C is on the Propeller. I think Parallax should just introduce P2 with only Spin and forget C. Their customer base just isn't interested in C and many are openly hostile to it.
David,
If you used the acronym IMO or IMHO or something in that order, I wouldn't be here replying. But you can't speak on behalf of everyone here. In my opinion, I'm a customer and I'm interested in C. Furthermore, I never used SPIN, and gave up on it once I realized that was "compiled" to bitcodes. C is fast and serves my purposes. The libraries are confusing and poorly documented, so I generally exclude them. No big deal.
Plus, as far as I'm concerned, it would be a bad move not supporting C, even worse given that the P2 will have a larger memory. The fact that C exists on the P1 does not harm SPIN in any way. Without C, I probably still wouldn't use it. I feel what you are saying is like the tactics that WMG or GM uses (or perhaps Linux vs Micro$oft). Because I'm not allowed to listen to their bands, I'm not forced to buy the CDs. I simply wont buy them. Same for SPIN.
I'm getting really tired of people saying how bad C is on the Propeller. I think Parallax should just introduce P2 with only Spin and forget C. Their customer base just isn't interested in C and many are openly hostile to it.
David,
If you used the acronym IMO or IMHO or something in that order, I wouldn't be here replying. But you can't speak on behalf of everyone here. In my opinion, I'm a customer and I'm interested in C. Furthermore, I never used SPIN, and gave up on it once I realized that was "compiled" to bitcodes. C is fast and serves my purposes. The libraries are confusing and poorly documented, so I generally exclude them. No big deal.
Plus, as far as I'm concerned, it would be a bad move not supporting C, even worse given that the P2 will have a larger memory. The fact that C exists on the P1 does not harm SPIN in any way. Without C, I probably still wouldn't use it. I feel what you are saying is like the tactics that WMG or GM uses (or perhaps Linux vs Micro$oft). Because I'm not allowed to listen to their bands, I'm not forced to buy the CDs. I simply wont buy them. Same for SPIN.
But that's my two cents.
Kind regards, Samuel Lourenço
Yes, you are probably correct. It's just that it is frustrating to have most references to C on P1 qualified with "is not really suited to the P1". I certainly agree that it will be better suited to the P2 but it is perfectly usable on the P1 as well for applications that will fit in the constrained memory. If you want to squeeze as much as possible out of the P1 then C is probably not the best choice but Spin isn't either. For that you need Tachyon. I'm pretty sure it holds the record for squeezing the most functionality out of the P1 without having to resort to adding external memory. In any case, I enjoy language discussions. I just don't like language bashing.
I'm getting really tired of people saying how bad C is on the Propeller. I think Parallax should just introduce P2 with only Spin and forget C. Their customer base just isn't interested in C and many are openly hostile to it.
David,
If you used the acronym IMO or IMHO or something in that order, I wouldn't be here replying. But you can't speak on behalf of everyone here. In my opinion, I'm a customer and I'm interested in C. Furthermore, I never used SPIN, and gave up on it once I realized that was "compiled" to bitcodes. C is fast and serves my purposes. The libraries are confusing and poorly documented, so I generally exclude them. No big deal.
Plus, as far as I'm concerned, it would be a bad move not supporting C, even worse given that the P2 will have a larger memory. The fact that C exists on the P1 does not harm SPIN in any way. Without C, I probably still wouldn't use it. I feel what you are saying is like the tactics that WMG or GM uses (or perhaps Linux vs Micro$oft). Because I'm not allowed to listen to their bands, I'm not forced to buy the CDs. I simply wont buy them. Same for SPIN.
But that's my two cents.
Kind regards, Samuel Lourenço
Yes, you are probably correct. It's just that it is frustrating to have most references to C on P1 qualified with "is not really suited to the P1". I certainly agree that it will be better suited to the P2 but it is perfectly usable on the P1 as well for applications that will fit in the constrained memory. If you want to squeeze as much as possible out of the P1 then C is probably not the best choice but Spin isn't either. For that you need Tachyon. I'm pretty sure it holds the record for squeezing the most functionality out of the P1 without having to resort to adding external memory. In any case, I enjoy language discussions. I just don't like language bashing.
Hi Dave. I agree with you in the sense that I dislike language bashing too. Each language has its own strong and weak points. Choosing one, might not always depend on the end application and might even be a matter of preference. In my case, I use C since I'm used to it. If it is faster or slower, it always depends on the compiler, on how good it is and how optimized the code it generates. It is fast enough for me.
Comments
Another problem is integrating C with assembly code. It is possible to intersperse inline assembly in C code, and assembled assembly files can be linked with compiled C files. It is also possible to include blobs of pre-assembled assembly code as data, and run them in separate cogs from a C program. This is all a bit cumbersome, and I think SimpleIDE could be improved to make this task easier.
The list continues to grow! I am aware of the following options, all of which are available in the "develop" branch of PropWare (here)
This time I'm breaking this out between high-level interaces and backend drivers. I think its important to recognize the difference because, with very minimal work, any driver can be used with (almost) any interface.
Interfaces:
Drivers:
I'm a retired metallurgical engineer with previous experience programming in a dialect of early MS Basic and have programmed at work using PDP11 Basic and Techtronics Basic. I had very limited exposure to 8080 ASM, forth, and Tiny C. My interest in the Prop was because of its multicore nature and the people on this forum.
I started to learn Spin (from the PEK), C from the Learn tutorials, and forth using Dave's pfth and PASM from the forum, C, and Spin objects. From my experience, I found pfth and the interactive nature of forth (particularly with the multicore nature of the prop) gave me great insight into the workings of the Prop. C was easy to learn (at least at a beginner level) from the tutorials, but Spin has been difficult for me. If I work at it for a few days straight, I can understand how it works, but if I am away a couple of days, I can't remember enough to write code or to read and understand someone else's code.
The main advantage of Spin for me is that it is so compact compared with C, and learning it is important to me primarily to take advantage of the Spin code already written so I can translate it into C and incorporate the PASM code into C programs.
Regarding the use of the C printf function (actually on the Prop I use print or printi), coming from a Basic background I really didn't like it, but now its a lot easier. Compare some code from a Spin program I wrote with C code that does the same thing.
Spin
C
The C seems to be easier to write and read (for me).
Regarding speed, in the PEK section on using counters for RC measurements, Andy discusses the overhead delay in switching a pin from "out high" to "input" as is done in the RC examples. I wanted to see what the overhead would be in different languages (Spin, C, PASM and pfth. In this thread:
forums.parallax.com/discussion/comment/1375740/#Comment_1375740
I show the time it took to make the switch.
PASM was obviously the fastest by an extreme amount (6 clocks) compared with everything else. Initially I saw that SPIN (595 clocks) was faster than C (compact memory model - 707 clocks), but that was using the Simple Libraries "input()" function to make the switch. By using the Propeller.h library "DIRA" to switch from output to input, the time for the CMM version was reduced to 163 clocks, significantly less than the Spin time. DIRA is a little more Spin like and complicated to use than "input()", so maybe not as easy to use in the educational program, but has a speed advantage.
I realize that there are many different ways to measure and compare language speeds, this was just a simple example, and the trend probably doesn't hold for other benchmarks.
Regarding incorporating PASM into C, Parallax has made it easier using a Simple Libraries call to link PASM in a Spin object than it was originally. I've used that method to both use PASM in a Spin object from the Prop Tool Library, as well as writing a short PASM function in a Spin wrapper that just had a PUB dummy and DAT section. I agree that inline PASM would be useful (maybe that already exists? and needs to be explained?)
I still have problems with C pointers and have to relearn the syntax and how they work, each time I need them.
I really like Spin, how compact it is and how it directly interacts with the Prop, but it does not seem intuitive (to me) so I have to work harder to understand it, particularly when experienced programmers use "tricks" to take maximum advantage of it.
I am looking forward to the P2 with its large memory and Hubex should significantly improve the capability of C (and other languages). I hope that Parallax is working on porting C to it.
Tom
pub MAIN BEGIN 0 PIN@ IF 1 HIGH 100 ms 1 LOW 100 ms ELSE 1 second THEN KEY UNTIL ;
Type MAIN to run which will flash the LED 5 times a second while P0 is high otherwise waits 1 second when low (which is redundant btw). Hit any key to exit back to Forth. This little routine consumes 27 bytes as measured by me Telneting to a Tachyon system since I am nowhere near my workshop. Of course you have to have Tachyon loaded to run this such as using the precompiled Explorer images but you are able to interact with the hardware and type simple one-liners for instance for immediate execution.
@forum
While I'm sure C will be a hit with P2 it certainly seems to be an awkward fit for P1 and I can probably understand David Betz's annoyance at the perceived C bashing, but the thing I've noticed over the years is that every language gets bashed for some reason or another. Spin is easy to learn and use and compact but relatively slow but still I found in the past that it still runs out of memory when I've tried to extend the capabilities which is why I wrote Tachyon, so I can have the speed, the compactness, the interactivity, and still fit everything in without resorting to memory expansion schemes. If whatever language you use works for you, good. If it doesn't then what's the point of using it since it is a means to an end after all, not the end itself (unless you are learning a language).
I started with the BASIC Stamp 2 (BS2) so at first Spin looked intimidating but I recognized many of the commands and structures as being the same.
Going section by section though the Propeller Education Kit (PEK) text and using the examples as a guide I became more comfortable with Spin and started to see how simple and yet powerful is was.
Unfortunately, the PEK text doesn't teach how to use Constants (CON) is programs, which is something that made BS2 programs easier to understand and quick to modify.
Even the Propeller C tutorial doesn't mention Constants (CONST) though they used to make I2C easier to use.
Seeing Button and LED makes a program a lot easier to understand that if you just use I/O pin numbers.
Peter,
That 1-liner may save keystrokes but it obfuscates, or makes it difficult to understand, what the code is doing.
If you were to come back to it later I am sure you would spend a lot more time decrypting it than you originally saved "keying" it in.
Seeing as it seems everytime I go on the internet some program is either written in C or has been rewritten into C, I find it ironic that you feel C is always being bashed on.
It gives the impression that something is wrong with people who don't program in C.
Edit: And, no, I don't think there is anything wrong with people who don't program in C.
We really should try to keep on topic instead of digressing as it confuses the readers into believing there are problems where there are none.
Having said this, just to belay some fears, I have a commercial project that uses a very large Catalina C program (developed before GCC was available). It runs on a P1 with latchless (ie fast) 512KB SRAM and microSD card with a huge database of files (list of stars, nebulas, etc, etc). This P1 communicates with 2 other P1's to handle other I/O functions including driving a telescope.
Could it be done with other micros? Absolutely yes. But the P1 means all 3 processors are the same, easy to use Propeller. Each cog (core) can handle its' own dedicated I/O via a separate driver. There are no interrupts to handle, so everything can be done in real time where necessary. Basically we have 3*8 32-bit CPU cores, less inter-connecting cores. We have a mix of spin, pasm and C cores, with each able to perform its' own task(s) without worrying about the other tasks. And each of these languages is a pleasure to program thanks to the Propeller dynamics.
If you used the acronym IMO or IMHO or something in that order, I wouldn't be here replying. But you can't speak on behalf of everyone here. In my opinion, I'm a customer and I'm interested in C. Furthermore, I never used SPIN, and gave up on it once I realized that was "compiled" to bitcodes. C is fast and serves my purposes. The libraries are confusing and poorly documented, so I generally exclude them. No big deal.
Plus, as far as I'm concerned, it would be a bad move not supporting C, even worse given that the P2 will have a larger memory. The fact that C exists on the P1 does not harm SPIN in any way. Without C, I probably still wouldn't use it. I feel what you are saying is like the tactics that WMG or GM uses (or perhaps Linux vs Micro$oft). Because I'm not allowed to listen to their bands, I'm not forced to buy the CDs. I simply wont buy them. Same for SPIN.
But that's my two cents.
Kind regards, Samuel Lourenço