I've uploaded a new version (0.95) to code.google.com/p/spin2cpp. This one allows arrays of objects, fixes the bug with outa[pin] where pin is a variable, fixes a nasty problem with tabs in the source code, and has a bunch more compatibility improvements and fixes. It can compile some basic CSPIN code now (hello world works, dhrystone has some problems though) and it compiles and runs the graphics_demo object, albeit with single buffering only due to lack of HUB memory.
As always, bug reports and examples of objects that spin2cpp doesn't work right on are welcomed. Thanks to everyone for their feedback!
spin2cpp fails to compile on Rasperry Pi under Raspian. There is a variable "save" that is set but not used in outdat.c line 18. This is a warning in the compiler there which becomes an error due to the compiler flag settings.
Removing "save" gets it to build fine and it seems to work.
Finally had a chance to give this a try today...
This tool and CMM really takes away almost all my excuses for not converting to C...
I'm trying the PTP2_ScaleDemo for Rayslogic.com PTP2 on Quickstart.
Got off to a rocky start because it didn't like me using constants from objects..
Originally had things like this:
screensize = lcd#MaxHTiles*lcd#MaxVTiles
but had to change them to local constants.
After that, it did make come Cpp code, let's hope it works
Well, figured out how to get all the files into a SimpleIDE "project".
But, when I try to build, I get this:
Project Directory: D:/Propeller/GCC/PTP2/
propeller-elf-c++ -o a.out -Os -mlmm -I . -fno-exceptions -fno-rtti PTP2_LcdDriver.cpp PTP2_i2cDriver.cpp PTP2_ScaleDemo.cpp
c:/propgcc/bin/../lib/gcc/propeller-elf/4.6.1/_crtbegin.o: In function `argc_cnt':
(.init+0x3c): undefined reference to `_main'
collect2: ld returned 1 exit status
Done. Build Failed!
Check source for bad function call or global variable name `_main'
BTW: Can you have Spin2Cpp autmatically generate the .side project for SimpleIDE?
spin2cpp fails to compile on Rasperry Pi under Raspian. There is a variable "save" that is set but not used in outdat.c line 18. This is a warning in the compiler there which becomes an error due to the compiler flag settings.
Nice catch, Heater! I don't know why gcc -Wall didn't catch this on my Ubuntu box, but that is a real bug -- save was supposed to be used to save/restore the current parse state. For DAT output that doesn't matter at the present time, but in the future it might. I've checked in a fix.
Thanks for the bug report. That should be fixed in the next version of spin2cpp (the fix is checked into the source repository, so if you're building from source you can get it now).
Your other suggestion of automatic .side file generation is a good one. I'll look into it!
Eric, Ok I got the program to run finally...
Here's what I had to add to the main file to make it work:
/**
* Main program function.*/
int main(void)
{
PTP2_ScaleDemo test;
test.Main();
return 0;
}
I guess i don't understand... Why doesn't PropGCC use the original Main() as the entry point? Why do I need to add this main() function to make it work?
BTW: I really do appreciate the work you've done to make this app. This is going to make it very easy for me to port my assembly LCD drivers over to C...
Maybe I see from the bottom of the help file that I'm supposed to use the "--main" option to do this for C++.
But, then I don't see how this could work for the Catalina example above since it is regular C and not C++.
Also, how does the first example "spin2cpp --elf -O test.spin" work without the --main option?
I guess i don't understand... Why doesn't PropGCC use the original Main() as the entry point? Why do I need to add this main() function to make it work?
"Main" has no special meaning in Spin, so spin2cpp doesn't know whether a function named "Main" really should be the entry point or not.
Maybe I see from the bottom of the help file that I'm supposed to use the "--main" option to do this for C++.
But, then I don't see how this could work for the Catalina example above since it is regular C and not C++.
Also, how does the first example "spin2cpp --elf -O test.spin" work without the --main option?
The documentation is out of date, sorry. --main is for either C or C++. --elf automatically implies --main.
The reason --main is not the default is that often people use spin2cpp to convert Spin to drivers, which are then linked with their regular C files (which already have a main() function in them).
I think there might be something else wrong with Spin2Cpp, but I'm not sure exactly what it is...
I've found that the i2c driver write function (that I use in a lot of different applications) doesn't work when compiled with LMM,
but does when compiled with CMM...
I'm able to fix it by adding a delay function into it... So, perhaps the problem is that LMM is too fast, but that's not clear to me because
the same type of code is used in other places and works...
Anywhere, this is the function with the extra delay() call added. Do you see anything here that might be the problem?
It's in that do loop after a complicated expression for OUTA and before another OUTA expression.
But, I have back-back OUTAs in other places that work...
Could somehow this loop be faster that other places?
I2C devices, such as EEPROM have minimum requirements for clock high time, low time, data setup time and hold time. I2C drivers within in Spin are so slow that they easily meet the timing requirements. However, it is very likely that the LMM version runs too fast. It's been a while since I looked at this, but if you look at the pasm_i2c_driver object in the OBEX you'll see where I had to call a delay function to meet the timing requirements.
EDIT: After looking at the pasm_i2c_driver again, I would suggest that you add a call to the delay function after each OUTA/DIRA/INA access.
C is faster than spin, but not as fast assembly. I think it's just inside that loop that is too fast...
I looked at the dissassembly and there seems to be some kind of optimization in the loop that makes it too fast...
Eric, can you please answer a question about C versus C++ under PropGCC with Spin2CPP?
In the beginning, I remember people saying C++ would be much bigger (and presumably slower) than C...
Is this still true? Am I better off converting to C instead of C++?
C is faster than spin, but not as fast assembly. I think it's just inside that loop that is too fast...
I looked at the dissassembly and there seems to be some kind of optimization in the loop that makes it too fast...
I wouldn't be so sure of that :-). PropGCC's code can be pretty close to that of assembly, and even in LMM mode we use the FCACHE to hold loops in internal cog memory (so they run at full speed rather than the reduced speed of an LMM interpreter).
Eric, can you please answer a question about C versus C++ under PropGCC with Spin2CPP?
In the beginning, I remember people saying C++ would be much bigger (and presumably slower) than C...
Is this still true? Am I better off converting to C instead of C++?
It probably doesn't make very much difference, and depends on the objects and what you're doing with them. If you need more than one copy of any object, you'll have to use C++ mode. If you only ever have one copy of an object, then for most objects C will probably be slightly faster and smaller than C++, but it probably won't be a huge difference.
Ok, thanks for the tip: -mno-fcache did fix the problem... So, I think the issue is the compiler using cog cache to speed up my loop and making it too fast for the i2c bus...
But, I really don't want to turn this off for the whole program...
I guess there's no way to turn it off just for this one loop...
Is there anything I can put it there that will force the compiler not to use it there?
Right now, I have two: "waitcnt((CNT + 500));" lines in there to do it. I guess this isn't so bad though and I can live with it.
Perhaps better to worry about things being too fast than too slow...
I was trying to see if I could get an SD program working in C++. I downloaded the FSRW from OBEX, and tried to do a conversion on: test.spin, serial_terminal.spin, and fsrw.spin. They all came up with errors, and would not convert.
Comments
Thank you for the examples. I've fixed the object array problem, and I'll look into the non-constant pin issues.
Eric
As always, bug reports and examples of objects that spin2cpp doesn't work right on are welcomed. Thanks to everyone for their feedback!
Eric
Removing "save" gets it to build fine and it seems to work.
This tool and CMM really takes away almost all my excuses for not converting to C...
I'm trying the PTP2_ScaleDemo for Rayslogic.com PTP2 on Quickstart.
Got off to a rocky start because it didn't like me using constants from objects..
Originally had things like this:
but had to change them to local constants.
After that, it did make come Cpp code, let's hope it works
But, when I try to build, I get this:
BTW: Can you have Spin2Cpp autmatically generate the .side project for SimpleIDE?
Nice catch, Heater! I don't know why gcc -Wall didn't catch this on my Ubuntu box, but that is a real bug -- save was supposed to be used to save/restore the current parse state. For DAT output that doesn't matter at the present time, but in the future it might. I've checked in a fix.
Thanks,
Eric
Thanks for the bug report. That should be fixed in the next version of spin2cpp (the fix is checked into the source repository, so if you're building from source you can get it now).
Your other suggestion of automatic .side file generation is a good one. I'll look into it!
Eric
Here's what I had to add to the main file to make it work:
I guess i don't understand... Why doesn't PropGCC use the original Main() as the entry point? Why do I need to add this main() function to make it work?
BTW: I really do appreciate the work you've done to make this app. This is going to make it very easy for me to port my assembly LCD drivers over to C...
Maybe I see from the bottom of the help file that I'm supposed to use the "--main" option to do this for C++.
But, then I don't see how this could work for the Catalina example above since it is regular C and not C++.
Also, how does the first example "spin2cpp --elf -O test.spin" work without the --main option?
The documentation is out of date, sorry. --main is for either C or C++. --elf automatically implies --main.
The reason --main is not the default is that often people use spin2cpp to convert Spin to drivers, which are then linked with their regular C files (which already have a main() function in them).
Eric
So, I would want --main the default...
Actually, maybe this is a way around this... Just create a main.cpp file with something like this in it:
I've found that the i2c driver write function (that I use in a lot of different applications) doesn't work when compiled with LMM,
but does when compiled with CMM...
I'm able to fix it by adding a delay function into it... So, perhaps the problem is that LMM is too fast, but that's not clear to me because
the same type of code is used in other places and works...
Anywhere, this is the function with the extra delay() call added. Do you see anything here that might be the problem?
It's in that do loop after a complicated expression for OUTA and before another OUTA expression.
But, I have back-back OUTAs in other places that work...
Could somehow this loop be faster that other places?
EDIT: After looking at the pasm_i2c_driver again, I would suggest that you add a call to the delay function after each OUTA/DIRA/INA access.
I looked at the dissassembly and there seems to be some kind of optimization in the loop that makes it too fast...
In the beginning, I remember people saying C++ would be much bigger (and presumably slower) than C...
Is this still true? Am I better off converting to C instead of C++?
Turn off fcache and see what happens.
propeller-elf-gcc -Os -mlmm -mno-fcache foo.c
It probably doesn't make very much difference, and depends on the objects and what you're doing with them. If you need more than one copy of any object, you'll have to use C++ mode. If you only ever have one copy of an object, then for most objects C will probably be slightly faster and smaller than C++, but it probably won't be a huge difference.
But, I really don't want to turn this off for the whole program...
I guess there's no way to turn it off just for this one loop...
Is there anything I can put it there that will force the compiler not to use it there?
Right now, I have two: "waitcnt((CNT + 500));" lines in there to do it. I guess this isn't so bad though and I can live with it.
Perhaps better to worry about things being too fast than too slow...
Ray