If you are going to be using stdint.h types you really should be consistent and use them exclusively instead of the built in integer types. In addition to uintX_t/intX_t there are unit_fastX_t/int_fastX_t (the unsigned/signed types with at least X bits that offer the best performance), uint_leastX_t/int_leastX_t (the smallest unsigned/signed types that have at least X bits), uintmax_t/intmax_t (the maximum width integer types), and uintptr_t/intptr_t (the integer types capable of holding pointers). These types are guaranteed to exists unlike the truly fixed width types. The only times you should really use the truly fixed width types are when you are directly interacting with hardware, or you need exact wrap/overflow behavior.
@cgracey : I've started implementing the new functions, and ran into a small snag: "PIN" is a really common variable name, it would be nice if it didn't conflict with a built in function name. Could we rename this to "GETPIN" or something else that makes it obvious that we're fetching a pin's value (I guess "PINVAL" would work too)? To a lesser degree it would be nice to use "GETRND" and "GETCNT" in place of "RND" and "CNT", too.
I've re-read parts of this thread and read through the Spin2 interpreter thread (aka: the editor war thread) as well. I want to address something directly that I may have been saying (thinking?) too subtly.
I do not think propeller2.h should take Spin into consideration. This header should not be about providing Spin compatibility in C. It should be about providing access to all of the P2's hardware from C. IF that happens to be the same feature set as Spin, so be it, but if Spin offers extra features that are not hardware-specific - maybe some string manipulation extra trig functions outside the scope of what the hardware does - I think it should be left out of propeller2.h. It can go elsewhere.
But it's this idea of bringing Spin to C that I want to address. It should not be the goal of propeller2.h. It's a valiant goal, but this is the wrong place for it.
I agree, but there are a lot of Spin instructions which relate to PASM instructions which will be needed in C. They are going to need names and Spin has names for them. Might as well harmonize those names. I'm thinking about the obvious RDPIN/WRPIN and pin-related instructions. Most CORDIC operations don't conform to any industry standard, so maybe QLOG/QEXP are appropriate.
Agreed.
Type conformity is another matter when writing those prototypes though.
Basically, in the decision tree of "should we do A or B," the node that reads "do whichever one Spin does" should be at the very bottom of the three.
I've re-read parts of this thread and read through the Spin2 interpreter thread (aka: the editor war thread) as well. I want to address something directly that I may have been saying (thinking?) too subtly.
I do not think propeller2.h should take Spin into consideration. This header should not be about providing Spin compatibility in C. It should be about providing access to all of the P2's hardware from C. IF that happens to be the same feature set as Spin, so be it, but if Spin offers extra features that are not hardware-specific - maybe some string manipulation extra trig functions outside the scope of what the hardware does - I think it should be left out of propeller2.h. It can go elsewhere.
But it's this idea of bringing Spin to C that I want to address. It should not be the goal of propeller2.h. It's a valiant goal, but this is the wrong place for it.
I agree, but there are a lot of Spin instructions which relate to PASM instructions which will be needed in C. They are going to need names and Spin has names for them. Might as well harmonize those names. I'm thinking about the obvious RDPIN/WRPIN and pin-related instructions. Most CORDIC operations don't conform to any industry standard, so maybe QLOG/QEXP are appropriate.
Agreed.
Type conformity is another matter when writing those prototypes though.
Basically, in the decision tree of "should we do A or B," the node that reads "do whichever one Spin does" should be at the very bottom of the three.
Not really right, since Spin is currently fluid, it does make sense to harmonize the both languages. No need to bend C/C++ but possible to bend Spin a bit, like with strsize and strlen.
That all sounds good to me, except that I'd like to distinguish the types in some way. If we're not going to use "_t" then perhaps we should make POLAR and CARTESIAN all upper case as well, or captialize at least the first letter, and/or put an underscore in front of them to avoid conflicts with user variables.
The convention I was suggesting we adopt would be to use an underscore in front of the structure tag, but not the type name - i.e.
// type for cartesian coordinates
typedef struct _cartesian {
long x, y;
} cartesian;
// type for polar coordinates
typedef struct _polar {
long r, t;
} polar;
You can, of course, do it the other way around, but this way around seems to be more in keeping with the convention that the leading underscore implies the implementation-defined entity, whereas the typedef is more of a naming convenience.
If you are going to be using stdint.h types you really should be consistent and use them exclusively instead of the built in integer types. In addition to uintX_t/intX_t there are unit_fastX_t/int_fastX_t (the unsigned/signed types with at least X bits that offer the best performance), uint_leastX_t/int_leastX_t (the smallest unsigned/signed types that have at least X bits), uintmax_t/intmax_t (the maximum width integer types), and uintptr_t/intptr_t (the integer types capable of holding pointers). These types are guaranteed to exists unlike the truly fixed width types. The only times you should really use the truly fixed width types are when you are directly interacting with hardware, or you need exact wrap/overflow behavior.
Basically, in the decision tree of "should we do A or B," the node that reads "do whichever one Spin does" should be at the very bottom of the three.
We are by no means just "doing whatever Spin does", we are just proposing to do a few simple things that are easy and sensible to do to assist Propeller users transition between languages (or even just read a program written in another language).
That all sounds good to me, except that I'd like to distinguish the types in some way. If we're not going to use "_t" then perhaps we should make POLAR and CARTESIAN all upper case as well, or captialize at least the first letter, and/or put an underscore in front of them to avoid conflicts with user variables.
The convention I was suggesting we adopt would be to use an underscore in front of the structure tag, but not the type name - i.e.
// type for cartesian coordinates
typedef struct _cartesian {
long x, y;
} cartesian;
// type for polar coordinates
typedef struct _polar {
long r, t;
} polar;
You can, of course, do it the other way around, but this way around seems to be more in keeping with the convention that the leading underscore implies the implementation-defined entity, whereas the typedef is more of a naming convenience.
I've never understood why the structure tag and the typedef name have to be different. I don't think that's required by the C standard is it? If so, it doesn't seem to be enforced by any of the compilers I use. However, in this case I think using cartesian_t and polar_t for the typedef names would be more consistent with the stdint.h typedef names. In that case, I don't think the structure tag should have the _t suffix. It doesn't need an _ prefix either though.
Strsize and strcmp are unnecessary aren't they? Other than that, looks good.
Strictly, yes. But if you are porting Spin code to C, they might make life a little easier.
I think we should have a separate header file / library for Spin utilities like bytemove, strsize, etc., and keep propeller2.h for just the hardware specific features.
That all sounds good to me, except that I'd like to distinguish the types in some way. If we're not going to use "_t" then perhaps we should make POLAR and CARTESIAN all upper case as well, or captialize at least the first letter, and/or put an underscore in front of them to avoid conflicts with user variables.
The convention I was suggesting we adopt would be to use an underscore in front of the structure tag, but not the type name - i.e.
// type for cartesian coordinates
typedef struct _cartesian {
long x, y;
} cartesian;
// type for polar coordinates
typedef struct _polar {
long r, t;
} polar;
You can, of course, do it the other way around, but this way around seems to be more in keeping with the convention that the leading underscore implies the implementation-defined entity, whereas the typedef is more of a naming convenience.
I've never understood why the structure tag and the typedef name have to be different. I don't think that's required by the C standard is it? If so, it doesn't seem to be enforced by any of the compilers I use. However, in this case I think using cartesian_t and polar_t for the typedef names would be more consistent with the stdint.h typedef names. In that case, I don't think the structure tag should have the _t suffix. It doesn't need an _ prefix either though.
I'm pretty sure the C standard specifies that struct names (the "foo" in "struct foo") are in a different namespace from variable and type names, so they won't conflict with those. I think we can use whatever we'd like there, and most modern compilers even let you leave them off entirely to create anonymous structs (great for typedefs).
I'm more concerned that the actual typedef name not conflict with user variables. So I'd like:
It's probably easier to comment if we can all see an example in front of us, so here is the current proposal ...
Thanks Ross! I think it's coming together quite nicely. A few comments (nothing major, just trying to polish things):
#define MAX_COG 0x07
I think this should be 0x0f -- the architecture allows for up to 16 COGs, although the current implementation just has 8. Or we could leave this define out entirely; it may be misleading for some programmers, especially if Chip creates 2 or 4 COG versions of the P2.
As I mentioned above, I think these should be signed and I'd personally prefer "cartesian_t", "Cartesian", or "CARTESIAN" for the type name, to avoid conflict with user variables and types.
int _coginit(int cog, uint32_t pgm, uint32_t ptr);
I'd probably use "void *" for pgm and ptr, since that's what the type of a pointer is in C (yes, it happens to be 32 bits, but we might was well use the type system to distinguish pointers and integers).
int _pin(int pin);
@cgracey , any thought on renaming this? The function signature alone indicates why "PIN" might not be a good reserved function name. It's not such a big deal in C, where we've put an underscore in front, but in Spin I think "PINGET" or "PINVAL" might be a better name.
Eric, I really like PIN, CNT, and RND. Putting GET in front of each of those will certainly make user code more verbose, even though it would inhibit the user from naming variables PIN, CNT, and RND.
Eric, I really like PIN, CNT, and RND. Putting GET in front of each of those will certainly make user code more verbose, even though it would inhibit the user from naming variables PIN, CNT, and RND.
The thing that bothers me about it is that it kind of conflates the input value of the pin with the pin itself. Writing "pin(56)" makes it seem you're referring to pin 56 in general, rather than specifically the current input value of the pin. Someone might think they could write "pin(56) = 1" instead of "pinh(56)".
Even a tiny bit longer name like "pini(56)" (pin input) or "pinv(56)" (pin value) seems less likely to cause confusion to the reader.
I don't think we should try to make the code too concise. Code is much harder to read than to write, so helping the reader is probably more important than saving a few keystrokes. "pininp(56)" is only a little more typing than "pin(56)", and makes it pretty obvious that you're getting the input value. (I like "pinlo" and "pinhi" better than "pinl" and "pinh" for the same reason). There is a happy medium, of course: "pin_input_value(56)" is more informative, but even I think that one's too verbose .
Also, of course, "pin" is a super common variable / constant name in existing code, so using it will make porting code from Spin1 and from other languages harder.
Eric, I really like PIN, CNT, and RND. Putting GET in front of each of those will certainly make user code more verbose, even though it would inhibit the user from naming variables PIN, CNT, and RND.
The thing that bothers me about it is that it kind of conflates the input value of the pin with the pin itself. Writing "pin(56)" makes it seem you're referring to pin 56 in general, rather than specifically the current input value of the pin. Someone might think they could write "pin(56) = 1" instead of "pinh(56)".
Even a tiny bit longer name like "pini(56)" (pin input) or "pinv(56)" (pin value) seems less likely to cause confusion to the reader.
I don't think we should try to make the code too concise. Code is much harder to read than to write, so helping the reader is probably more important than saving a few keystrokes. "pininp(56)" is only a little more typing than "pin(56)", and makes it pretty obvious that you're getting the input value. (I like "pinlo" and "pinhi" better than "pinl" and "pinh" for the same reason). There is a happy medium, of course: "pin_input_value(56)" is more informative, but even I think that one's too verbose .
Also, of course, "pin" is a super common variable / constant name in existing code, so using it will make porting code from Spin1 and from other languages harder.
I understand what you are saying. I just wish there was a really good simple name for pin input.
I'm pretty sure the C standard specifies that struct names (the "foo" in "struct foo") are in a different namespace from variable and type names, so they won't conflict with those. I think we can use whatever we'd like there, and most modern compilers even let you leave them off entirely to create anonymous structs (great for typedefs).
I'm more concerned that the actual typedef name not conflict with user variables. So I'd like:
You can indeed use the same name for both the tag and the type name in C. But not in C++ I believe. In any case, most C coding standard documents seem to think its a bad idea - and it is certainly confusing. I think the consensus is that using different names prompts you to remember that one requires the "struct" keyword and one doesn't.
Note that the coordinates should be signed, at least for cartesian ones (for polar we could go either way).
int _coginit(int cog, uint32_t pgm, uint32_t ptr);
I'd probably use "void *" for pgm and ptr, since that's what the type of a pointer is in C (yes, it happens to be 32 bits, but we might was well use the type system to distinguish pointers and integers).
Yes, good point. I will amend it. And also remove MAX_COG.
I have not yet used the P2 smart pins. Perhaps someone who has could come up with a meaningful set of names (and possibly macros) for the various smart pin configurations?
These register names are known to the compiler, which will ensure that when the propeller header file is included, these names are reserved and will map to the correct cog registers (if the propeller header file is not included, the names can be used as normal variable names). I do it this way because always reserving them would lead to potential name collisions, but including the propeller header file is a fair indication that the program has been specifically written for the propeller.
If you are going to be using stdint.h types you really should be consistent and use them exclusively instead of the built in integer types. In addition to uintX_t/intX_t there are unit_fastX_t/int_fastX_t (the unsigned/signed types with at least X bits that offer the best performance), uint_leastX_t/int_leastX_t (the smallest unsigned/signed types that have at least X bits), uintmax_t/intmax_t (the maximum width integer types), and uintptr_t/intptr_t (the integer types capable of holding pointers). These types are guaranteed to exists unlike the truly fixed width types. The only times you should really use the truly fixed width types are when you are directly interacting with hardware, or you need exact wrap/overflow behavior.
It would be nice to see Propeller C supporting the C99 standard fully, with the "bool" type defined, as well as exact length uintx_t types and also fast/least types.
Regarding your last point, I can imagine many situations where you need to use exact length types, for example, interfacing with a DAC via I2C or SPI. Many DACs use shift registers, and the data length needs to be "cut exact" so that no more data is sent there, causing unwanted shifts and erroneous values.
Eric, I really like PIN, CNT, and RND. Putting GET in front of each of those will certainly make user code more verbose, even though it would inhibit the user from naming variables PIN, CNT, and RND.
The thing that bothers me about it is that it kind of conflates the input value of the pin with the pin itself. Writing "pin(56)" makes it seem you're referring to pin 56 in general, rather than specifically the current input value of the pin. Someone might think they could write "pin(56) = 1" instead of "pinh(56)".
Even a tiny bit longer name like "pini(56)" (pin input) or "pinv(56)" (pin value) seems less likely to cause confusion to the reader.
I don't think we should try to make the code too concise. Code is much harder to read than to write, so helping the reader is probably more important than saving a few keystrokes. "pininp(56)" is only a little more typing than "pin(56)", and makes it pretty obvious that you're getting the input value. (I like "pinlo" and "pinhi" better than "pinl" and "pinh" for the same reason). There is a happy medium, of course: "pin_input_value(56)" is more informative, but even I think that one's too verbose .
Also, of course, "pin" is a super common variable / constant name in existing code, so using it will make porting code from Spin1 and from other languages harder.
I understand what you are saying. I just wish there was a really good simple name for pin input.
I hope there will be a function for reading the latched value as well as the value present in the pin (valid for output pins, at least). This was possible to do in the P1 by reading OUTA in the case of latches and INA in the case of pins.
It would be nice to see Propeller C supporting the C99 standard fully
I doubt any propeller C compiler will ever fully implement the C99 standard. For a start, the Propeller has no native 64 bit types, and why would you want to simulate them?
That is what I was referring to. Seeing that there was some hangup in this thread on the fact that an implementation isn't required to support the truly fixed width types and performance considerations, which to me at least indicates some lack of familiarity with stdint.h, I decided to explicitly point out some of what is there. I should have provided a link to the documentation for the header as well.
It would be nice to see Propeller C supporting the C99 standard fully, with the "bool" type defined, as well as exact length uintx_t types and also fast/least types.
Indeed it would. Even better would be C11 support (the multi-threading additions in particular would be quite relevant) and beyond. I can see many people being put off if there is no support for anything beyond C89/90.
Regarding your last point, I can imagine many situations where you need to use exact length types, for example, interfacing with a DAC via I2C or SPI. Many DACs use shift registers, and the data length needs to be "cut exact" so that no more data is sent there, causing unwanted shifts and erroneous values.
Those are cases of directly interacting with hardware and thus you do want to use fixed width types as you pointed out and I had stated.
Seeing that there was some hangup in this thread on the fact that an implementation isn't required to support the truly fixed width types and performance considerations, which to me at least indicates some lack of familiarity with stdint.h
Not lack of familiarity so much as active dislike of stdint.h in my case
However, I think we have found the appropriate compromise - i.e. use uintN_t where a specific number of bits is appropriate, and use the fundamental C types elsewhere. This way, we maximize compatibility but minimize the loss of readability.
These register names are known to the compiler, which will ensure that when the propeller header file is included, these names are reserved and will map to the correct cog registers (if the propeller header file is not included, the names can be used as normal variable names). I do it this way because always reserving them would lead to potential name collisions, but including the propeller header file is a fair indication that the program has been specifically written for the propeller.
I'm not sure how Catalina works, but for some compilers once a global name is used (for example in a library) then any other use of it could conflict. That is, for some compilers if we use OUTA or INA in a library function, e.g. to bit-bang serial, then any user variable named OUTA or INA will conflict with it. So it would be safer to put an underscore in front of those names. We could then provide a #define for an alias -- that's OK, since the preprocessor only affects things in the single file being compiled. That is:
would accomplish pretty much the same thing as your original proposal, without conflicting with user variables.
(I'm pretty sure the C99 standard, at least, imposes restrictions on what global identifiers can be defined in the standard library, and it would be nice to be able to write libc mostly in C.)
At least one set of compilers (the P2 RISCV emulation ones) won't be able to directly access the P2 registers as variables, but will be able to access them via functions. So we might want to consider get/set macros for some of these registers.
It would be nice to see Propeller C supporting the C99 standard fully
I doubt any propeller C compiler will ever fully implement the C99 standard. For a start, the Propeller has no native 64 bit types, and why would you want to simulate them?
Ross.
Because I've already hit a brick wall when using 32-bit types. My prime number calculation program clearly proves it. They might not be as efficient as 32-bit types on a P2, and I understand that. But there is a reason why 64-bit types were supported even on 32-bit machines, about 20 years ago. So, why not?
Seeing that there was some hangup in this thread on the fact that an implementation isn't required to support the truly fixed width types and performance considerations, which to me at least indicates some lack of familiarity with stdint.h
Not lack of familiarity so much as active dislike of stdint.h in my case
However, I think we have found the appropriate compromise - i.e. use uintN_t where a specific number of bits is appropriate, and use the fundamental C types elsewhere. This way, we maximize compatibility but minimize the loss of readability.
Mind that "stdint.h" was an afterthought, and many typical programs don't need them. But I've already have shown you cases where it is essential to have fixed types, and therefore, "stdint.h" is useful. On another post, I even uploaded a code example, which you considered a good one, if I recall correctly.
If you don't wish to include "stdint.h", don't include it. Speaking of which, "propeller.h" on SimpleIDE seems to include almost every dependency, which I don't think it is a good idea. People should learn to code in C correctly and make the decision by themselves on what to include and not to include. "stdint.h", "stddef.h", "math.h", "stdio.h" and any others should be included only when needed, by the code, explicitly. When not, the compiler should emit a warning, at least. Lets not facilitate (or jump into the Arduino bandwagon, that pretty much screwed its C implementation for the sake of simplicity).
That means "propeller2.h" should include only what is needed for it to perform, and should only handle P2 related stuff (I/O pin direction and latches/inputs/outputs, smartpins, DACs, ADCs, CORDIC stuff, registers and the works). And that is plenty to handle (don't need to make system.d out of it).
It would be nice to see Propeller C supporting the C99 standard fully
I doubt any propeller C compiler will ever fully implement the C99 standard. For a start, the Propeller has no native 64 bit types, and why would you want to simulate them?
PropGCC came very close to fully implementing C99, including int64_t (useful for holding cycle counters longer than a minute or so, or for intermediate results of multiplcation). The only compiler exception was some missing #pragmas for floating point rounding. There were a few minor library issues as well (mostly floating point related).
But as David said, this isn't really the place for a language discussion, except insofar as it impacts propeller2.h. Catalina does a great job of implementing the things that users need in practice, as does GCC, and I hope someday fastspin's C support will be of similar quality.
Comments
Agreed.
Type conformity is another matter when writing those prototypes though.
Basically, in the decision tree of "should we do A or B," the node that reads "do whichever one Spin does" should be at the very bottom of the three.
Not really right, since Spin is currently fluid, it does make sense to harmonize the both languages. No need to bend C/C++ but possible to bend Spin a bit, like with strsize and strlen.
Enjoy!
Mike
The convention I was suggesting we adopt would be to use an underscore in front of the structure tag, but not the type name - i.e.
You can, of course, do it the other way around, but this way around seems to be more in keeping with the convention that the leading underscore implies the implementation-defined entity, whereas the typedef is more of a naming convenience.
Do you really hate C programmers that much?
We are by no means just "doing whatever Spin does", we are just proposing to do a few simple things that are easy and sensible to do to assist Propeller users transition between languages (or even just read a program written in another language).
More comments welcome!
EDIT: _bytefill and _wordfill should accept uint8_t and uint16_t as the value to use.
EDIT: X & Y are signed in cartesian coordinates.
EDIT: addresses should use "void *"
EDIT: remove MAX_COG
Mike
Strictly, yes. But if you are porting Spin code to C, they might make life a little easier.
I think we should have a separate header file / library for Spin utilities like bytemove, strsize, etc., and keep propeller2.h for just the hardware specific features.
I'm pretty sure the C standard specifies that struct names (the "foo" in "struct foo") are in a different namespace from variable and type names, so they won't conflict with those. I think we can use whatever we'd like there, and most modern compilers even let you leave them off entirely to create anonymous structs (great for typedefs).
I'm more concerned that the actual typedef name not conflict with user variables. So I'd like: Note that the coordinates should be signed, at least for cartesian ones (for polar we could go either way).
I think this should be 0x0f -- the architecture allows for up to 16 COGs, although the current implementation just has 8. Or we could leave this define out entirely; it may be misleading for some programmers, especially if Chip creates 2 or 4 COG versions of the P2.
As I mentioned above, I think these should be signed and I'd personally prefer "cartesian_t", "Cartesian", or "CARTESIAN" for the type name, to avoid conflict with user variables and types.
I'd probably use "void *" for pgm and ptr, since that's what the type of a pointer is in C (yes, it happens to be 32 bits, but we might was well use the type system to distinguish pointers and integers).
@cgracey , any thought on renaming this? The function signature alone indicates why "PIN" might not be a good reserved function name. It's not such a big deal in C, where we've put an underscore in front, but in Spin I think "PINGET" or "PINVAL" might be a better name.
I'd probably put all of these into a "spin2.h" header file (or something similar) and use appropriate pointer types for the src and dst arguments.
Thanks for putting the draft together, Ross, it does make discussion easier.
Eric
The thing that bothers me about it is that it kind of conflates the input value of the pin with the pin itself. Writing "pin(56)" makes it seem you're referring to pin 56 in general, rather than specifically the current input value of the pin. Someone might think they could write "pin(56) = 1" instead of "pinh(56)".
Even a tiny bit longer name like "pini(56)" (pin input) or "pinv(56)" (pin value) seems less likely to cause confusion to the reader.
I don't think we should try to make the code too concise. Code is much harder to read than to write, so helping the reader is probably more important than saving a few keystrokes. "pininp(56)" is only a little more typing than "pin(56)", and makes it pretty obvious that you're getting the input value. (I like "pinlo" and "pinhi" better than "pinl" and "pinh" for the same reason). There is a happy medium, of course: "pin_input_value(56)" is more informative, but even I think that one's too verbose .
Also, of course, "pin" is a super common variable / constant name in existing code, so using it will make porting code from Spin1 and from other languages harder.
I understand what you are saying. I just wish there was a really good simple name for pin input.
You can indeed use the same name for both the tag and the type name in C. But not in C++ I believe. In any case, most C coding standard documents seem to think its a bad idea - and it is certainly confusing. I think the consensus is that using different names prompts you to remember that one requires the "struct" keyword and one doesn't.
Yes, I wondered about that.
Yes, good point. I will amend it. And also remove MAX_COG.
These register names are known to the compiler, which will ensure that when the propeller header file is included, these names are reserved and will map to the correct cog registers (if the propeller header file is not included, the names can be used as normal variable names). I do it this way because always reserving them would lead to potential name collisions, but including the propeller header file is a fair indication that the program has been specifically written for the propeller.
https://en.cppreference.com/w/c/types/integer
It would be nice to see Propeller C supporting the C99 standard fully, with the "bool" type defined, as well as exact length uintx_t types and also fast/least types.
Regarding your last point, I can imagine many situations where you need to use exact length types, for example, interfacing with a DAC via I2C or SPI. Many DACs use shift registers, and the data length needs to be "cut exact" so that no more data is sent there, causing unwanted shifts and erroneous values.
I hope there will be a function for reading the latched value as well as the value present in the pin (valid for output pins, at least). This was possible to do in the P1 by reading OUTA in the case of latches and INA in the case of pins.
Kind regards, Samuel Lourenço
I doubt any propeller C compiler will ever fully implement the C99 standard. For a start, the Propeller has no native 64 bit types, and why would you want to simulate them?
Ross.
That is what I was referring to. Seeing that there was some hangup in this thread on the fact that an implementation isn't required to support the truly fixed width types and performance considerations, which to me at least indicates some lack of familiarity with stdint.h, I decided to explicitly point out some of what is there. I should have provided a link to the documentation for the header as well.
Indeed it would. Even better would be C11 support (the multi-threading additions in particular would be quite relevant) and beyond. I can see many people being put off if there is no support for anything beyond C89/90.
Those are cases of directly interacting with hardware and thus you do want to use fixed width types as you pointed out and I had stated.
Not lack of familiarity so much as active dislike of stdint.h in my case
However, I think we have found the appropriate compromise - i.e. use uintN_t where a specific number of bits is appropriate, and use the fundamental C types elsewhere. This way, we maximize compatibility but minimize the loss of readability.
I'm not sure how Catalina works, but for some compilers once a global name is used (for example in a library) then any other use of it could conflict. That is, for some compilers if we use OUTA or INA in a library function, e.g. to bit-bang serial, then any user variable named OUTA or INA will conflict with it. So it would be safer to put an underscore in front of those names. We could then provide a #define for an alias -- that's OK, since the preprocessor only affects things in the single file being compiled. That is: would accomplish pretty much the same thing as your original proposal, without conflicting with user variables.
(I'm pretty sure the C99 standard, at least, imposes restrictions on what global identifiers can be defined in the standard library, and it would be nice to be able to write libc mostly in C.)
At least one set of compilers (the P2 RISCV emulation ones) won't be able to directly access the P2 registers as variables, but will be able to access them via functions. So we might want to consider get/set macros for some of these registers.
Mind that "stdint.h" was an afterthought, and many typical programs don't need them. But I've already have shown you cases where it is essential to have fixed types, and therefore, "stdint.h" is useful. On another post, I even uploaded a code example, which you considered a good one, if I recall correctly.
If you don't wish to include "stdint.h", don't include it. Speaking of which, "propeller.h" on SimpleIDE seems to include almost every dependency, which I don't think it is a good idea. People should learn to code in C correctly and make the decision by themselves on what to include and not to include. "stdint.h", "stddef.h", "math.h", "stdio.h" and any others should be included only when needed, by the code, explicitly. When not, the compiler should emit a warning, at least. Lets not facilitate (or jump into the Arduino bandwagon, that pretty much screwed its C implementation for the sake of simplicity).
That means "propeller2.h" should include only what is needed for it to perform, and should only handle P2 related stuff (I/O pin direction and latches/inputs/outputs, smartpins, DACs, ADCs, CORDIC stuff, registers and the works). And that is plenty to handle (don't need to make system.d out of it).
Kind regards, Samuel Lourenço
PropGCC came very close to fully implementing C99, including int64_t (useful for holding cycle counters longer than a minute or so, or for intermediate results of multiplcation). The only compiler exception was some missing #pragmas for floating point rounding. There were a few minor library issues as well (mostly floating point related).
But as David said, this isn't really the place for a language discussion, except insofar as it impacts propeller2.h. Catalina does a great job of implementing the things that users need in practice, as does GCC, and I hope someday fastspin's C support will be of similar quality.
Eric