A real data logging project would use an external RTC, and actual external events. I just wanted to explore the possibilities of using pthreads, and see what sort of weakness that would arise from using them. Behind those weaknesses their may be some real hidden bugs, better to find them now, then have some future software guy make some major complaints about the Propeller as a whole. When the software and the PropBOE get in the hands of some really sharp students, what I am doing now, will seem like I was giving Parallax a pass on their attempt to enter into the C world.
If I were using Spin, then of course I would have a simulated RTC running in its own cog, the external event running in its own cog, and the uSD running in its own cog. But I am working with PropGCC, and trying to figure out how PropGCC should be used to the best advantage.
In my case, testing software with some real projects works best for me, I am not sure about everybody else, they may have different ideas about how to test things.
In conclusion, this should be lots of fun, and maybe a little excitement when a test project comes together, and it works.
Ray
Indeed!
I truly appreciate all you've done so far. It is lots of fun.
Attached is a COG-RTC Propeller demo. Hope you find it useful.
@denominator has a demo that actually uses an RTC chip.
Are you using SimpleIDE version 0-5-0 yet?
Thanks,
--Steve
Ted, yes the example is quite big at 22.7KB. Using simple_printf doesn't help much either :<
I just looked at proprtc.c, the first thing I noticed is the style change, prototypes up front, and the actual functions at the end of main(), interesting. Now I am getting to be like mindrobots, come to a fork in the road, of course I have to take the fork. Something new , and shiny, how can I play with this, now.
I tried this out with 0-5-0, looks good so far, I will be using it from this point on. The other thing that I noticed is, it really is starting to look like a professional package, who is really going to need Eclipse? Now if you add in a powerful new Spin package, bean's propbasic, ...
I just did a closer look at proprtc.c, and I noticed:
pause() - what library is that in? Do you have millisecond equivalent?
_rtc_start_timekeeping_cog() - Do you have to do settime() before you start the cog, or can settime() be done at anytime?
Since you you have settime(), printtime(), are their any other commands that are available?
I take it that their will be no problem with having settime() and ...timekeepping_cog() in a seperate function which will be activated from something like a gets()?
What else do you have like ...timekeeping_cog(), that starts in its own cog without any complicated code?
I just looked at proprtc.c, the first thing I noticed is the style change, prototypes up front, and the actual functions at the end of main(), interesting.
This is a style generally taught in C classes at college. There are advantages and disadvantages mostly good for the professor or other readers as an outline of the program without getting into too much detail.
I tried this out with 0-5-0, looks good so far, I will be using it from this point on. The other thing that I noticed is, it really is starting to look like a professional package, who is really going to need Eclipse?
Eclipse is important to the enterprise class of professional users. I'll probably add some new things to SimpleIDE later, but it will never provide the power-user experience available from Eclipse.
I just did a closer look at proprtc.c, and I noticed:
pause() - what library is that in? Do you have millisecond equivalent?
The pause() function is defined in the file and is very generic and relies on Propeller waitcnt, and should not be used with pthreads.
A millisecond version would take a similar form:
/**
* Sleep a number of milli-seconds based on Propeller system clock.
* This function is not pthread safe.
*/
void HUBTEXT mswait(int msecs)
{
waitcnt((CLKFREQ/1000)*msecs+CNT);
}
Maybe wait is a better name for such functions. The pause function will not be super precise and should have HUBTEXT when used with XMM/XMMC programs.
Since you you have settime(), printtime(), are their any other commands that are available?
Those functions are provided in the file. If you need more information on available Standard C Library functions, use man pages like this one: http://linux.die.net/man/3/mktime
I take it that their will be no problem with having settime() and ...timekeepping_cog() in a seperate function which will be activated from something like a gets()?
Right. Just don't use pthreads in the same program as waitcnt.
What else do you have like ...timekeeping_cog(), that starts in its own cog without any complicated code?
RTC, SD card driver, and the 2 current serial port drivers are all we have for standard C library support. TV, VGA, and Keyboard are plug-able drivers that can be used similar the serial port drivers.
- Unfortunately, feof(stdin) is the "standard" way of determining that there's a character ready for input. This doesn't work in PropGCC (this could be considered a bug in the library),
Can you open an issue on this?
Can you open an issue on this too?
That is my intention. I've got a bunch of stuff due for work early this week, but as soon as that settles out I'm going to post a proper bug reports with test programs.
The program below is using the built-in RTC function, but I am having a problem. In the settime() function, I am trying to get the values from the terminal screen. When I run the printtime(), I get 1970, no matter what I type in at the terminal. When I type in '2012', I am wondering what fgetc() is capturing, is it a '2', the last char in the stream, or it does not no how to handle the four chars? If I use fgets(), then it does not convert to an integer which the value of 'year' has to be. Do I have to do some sort of capture a string then convert it to an integer sort of thing, or is the explanation much simpler?
Ray
/**
* @file datalog2.c
* This is the main datalog2 program start point.
*/
#include <time.h>
#include <stdio.h>
#include <unistd.h>
#include <propeller.h>
#include <sys/rtc.h>
void printtime(void)
{
time_t now;
now = time(NULL);
printf("%s", asctime(localtime(&now)));
}
void starttime(void)
{
_rtc_start_timekeeping_cog();
}
settime()
{
struct timeval tv;
struct tm t;
int year /*,month,moday,dst,hr,min,sec*/;
printf("Year :");
year = fgetc(stdin);
t.tm_year = year-1900;
tv.tv_sec = mktime(&t);
settimeofday(&tv, 0);
printf("\n");
}
/**
* Main program function.
*/
int main(void)
{
putchar(0);
sleep(1);
settime();
sleep(1);
starttime();
sleep(1);
/* settime();
sleep(1); */
printtime();
while(1)
{
}
return 0;
}
This now works, displays the correct information. All variables have to be collected at one time, hopefully this would only have be done one time. Maybe the experts can clean this code up, if it can be cleaned up. What am I saying I am sure it can be cleaned up.
This is what I came up with, when I type in 2012, and 03, I get the correct year, but the month comes up as October. Something went wrong.
Ray,
The problem here is undoubtedly that you did not initialized all the members of the tv structure, so they are garbage. Unlike "global" variables, stack local variables are not initialized in C. Therefore, you need to zero-out tv with something like this:
Specifically regarding the above declarations, you are on very thin ice. The reason? If you type in garbage, you're going to trash the stack. For example, type "12345678" for any of the values and you're going to overwrite neighboring variables.
Much better to reuse a single copy of a much longer buffer, say something like "char inputBuffer[80]". Even that is vulnerable to hacking - that is why so many C programs have been subject to "buffer overrun" attacks. See http://stackoverflow.com/questions/4309746/safe-alternative-to-gets for more details.
You can use fgets instead of gets to ensure that you don't overflow the buffer. However, in this case it would probably be better to use scanf instead of gets/atoi. Setting the month would look like
I would like to test an xbee module with the QSboard, how close are the GCC drivers for this? A while back Parallax had mentioned that they had somebody doing the drivers, for things like xbee, and other things, but I have not seen anything else mentioned here, did I miss it? Has it been put on the back burner?
I was thinking about buying a propboe, to use with GCC, but if there are no C drivers for ALL of the things on the propboe, then I guess that idea goes on the back back back burner.
I would like to test an xbee module with the QSboard, how close are the GCC drivers for this? A while back Parallax had mentioned that they had somebody doing the drivers, for things like xbee, and other things, but I have not seen anything else mentioned here, did I miss it? Has it been put on the back burner?
I was thinking about buying a propboe, to use with GCC, but if there are no C drivers for ALL of the things on the propboe, then I guess that idea goes on the back back back burner.
Ray
Hi Ray,
We are working on PropBOE and other libraries. Much code is in our repository already.
We just need to finish some things. The xbee code is not done yet for example.
Please forgive my possible silly question -- as I have readily confessed, I'm not much with C (yet!). I was looking over the program you posted for Ray and wanted to look inside some of the libraries used. Is there an easy way to open one of those files (within SimpleIDE), or do I have to know where the compiler and standard library files are stored on my system?
Please forgive my possible silly question -- as I have readily confessed, I'm not much with C (yet!). I was looking over the program you posted for Ray and wanted to look inside some of the libraries used. Is there an easy way to open one of those files (within SimpleIDE), or do I have to know where the compiler and standard library files are stored on my system?
Hi Jon,
The simple answer is you do not have access to library code from SimpleIDE.
The "Standard C Library" source code lives in the Propeller-GCC repository. It is not distributed with the tool-chain. While this seems awkward to someone used to the openness of Spin, it carries 2 advantages: 1) user's can't break it very easily, and 2) user's don't have to be overwhelmed by it. The libraries are distributed as binary code, and there are several fundamental versions to support the memory models: COG, LMM, XMM, and XMMC.
That link helps. The difficulty for me as a new C programmer is peeling through all the layers that experienced users take for granted. I don't want to modify the library, I just want to see how it works so that I can use it and learn from it.
So, in that case, will you be adding a feature to SimpleIDE, that will provide a user with making a .lib file? I would like to make my misc.h file be used with an misc.lib file, if at all possible.
That link helps. The difficulty for me as a new C programmer is peeling through all the layers that experienced users take for granted. I don't want to modify the library, I just want to see how it works so that I can use it and learn from it.
Got it. I had planned to introduce a C library help feature, but I have to stop somewhere to make a release. I've reserved the F1 key for that later.
For the time being I recommend the following links.
The Library man pages are for BSD Unix and Linux. They contain a lot more than the Standard C Library function information.
Generally to find out about a function, just append the function name to a URL as: http://www.manpagez.com/man/3/printf http://linux.die.net/man/3/printf
So, in that case, will you be adding a feature to SimpleIDE, that will provide a user with making a .lib file? I would like to make my misc.h file be used with an misc.lib file, if at all possible.
Hi Ray. Sorry, there is no plan to support building user .lib files at the moment.
That's one of the problems I have with learning new languages such as C, Java, Python, etc. The languages themselves are syntactically (semantically?) simple with very few keywords and a simple structures where the underlying libraries supporting them are VAST and filled with many hidden goodies buried within. SPIN and BASIC are different in that they have bunches and bunches of powerful key words to learn and browse through.
Object oriented languages and/or their IDEs offer class and object browsers that make this exploration and discovery easier (while still and Easter egg hunt) but with C I always find myself looking in the library .h and .c files to see what is in there and what kind of fun things I can do without re-inventing wheels. I usually end up with a copy of the library sources with several editor windows opened up with library source and printed and highlighted .h file listings scattered around. I continue to stumble and struggle through the C libraries and spend lots of time trying to find stuff.
The Library man pages are for BSD Unix and Linux. They contain a lot more than the Standard C Library function information.
Generally to find out about a function, just append the function name to a URL as: http://www.manpagez.com/man/3/printf http://linux.die.net/man/3/printf
Below is my latest attempt at working with the QSboard. So far I have implemented Help(),LedON(), LedOFF(), and LedCheck(). The program is compiling OK, but the LedOFF() function is not working. The function is setup the same way as LedON(), which works, but LedOFF() does not, at least it is not turning off the LED. I cannot figure out what is causing this problem, any suggestions from the experts?
As I add on different components, like an uSD reader, xbee, ..., etc, I will have a command or two for working with the component. I guess this exercise is to see how far I can get before I starting running out of workable memory, this will include using the XMMC mode. I guess early suggestions for this would be appreciated.
I really like SimpleIDE, I think it covers just about everything that you would need from an IDE, except maybe creating some lib files, other than that it is a great little program, Thanks jazzed!
Ray
/*
* @file QScs.c
* This is the main QScs program start point.
*/
#include <stdio.h>
#include <propeller.h>
#include <unistd.h>
#include "misc.h"
FILE *stdinfile;
FILE *stdoutfile;
void Help()
{
printf("Commands are 'help, ledon xx, ledoff xx, ledcheck, '\n");
}
char *SkipChar(char *ptr, int val)
{
while (*ptr)
{
if (*ptr != val) break;
ptr++;
}
return ptr;
}
char *FindChar(char *ptr, int val)
{
while (*ptr)
{
if (*ptr == val) break;
ptr++;
}
return ptr;
}
int tokenize(char *ptr, char *tokens[])
{
int num = 0;
while (*ptr)
{
ptr = SkipChar(ptr, ' ');
if (*ptr == 0) break;
if (ptr[0] == '>')
{
ptr++;
if (ptr[0] == '>')
{
tokens[num++] = ">>";
ptr++;
}
else
tokens[num++] = ">";
continue;
}
if (ptr[0] == '<')
{
ptr++;
tokens[num++] = "<";
continue;
}
tokens[num++] = ptr;
ptr = FindChar(ptr, ' ');
if (*ptr) *ptr++ = 0;
}
return num;
}
int CheckRedirection(char **tokens, int num)
{
int i, j;
for (i = 0; i < num-1; i++)
{
if (!strcmp(tokens[i], ">"))
{
stdoutfile = fopen(tokens[i+1], "w");
if (!stdoutfile)
{
perror(tokens[i+1]);
stdoutfile = stdout;
return 0;
}
}
else if (!strcmp(tokens[i], ">>"))
{
stdoutfile = fopen(tokens[i+1], "a");
if (!stdoutfile)
{
perror(tokens[i+1]);
stdoutfile = stdout;
return 0;
}
}
else if (!strcmp(tokens[i], "<"))
{
stdinfile = fopen(tokens[i+1], "r");
if (!stdinfile)
{
perror(tokens[i+1]);
stdinfile = stdin;
return 0;
}
}
else
continue;
for (j = i + 2; j < num; j++) tokens[j-2] = tokens[j];
i--;
num -= 2;
}
return num;
}
void CloseRedirection()
{
if (stdinfile != stdin)
{
fclose(stdinfile);
stdinfile = stdin;
}
if (stdoutfile != stdout)
{
fclose(stdoutfile);
stdoutfile = stdout;
}
}
void LedON(int argc, char **argv)
{
if (argc < 1) return;
high(argv[1]);
}
void LedOFF(int argc, char **argv)
{
if (argc < 1) return;
low(argv[1]);
}
void LedCheck()
{
int y, x = 0;
while(x < 5)
{
for (y = 16; y <= 23; y++)
{
high(y);
waitMS(10);
low(y);
waitMS(10);
}
for (y = 23; y >= 16; y--)
{
high(y);
waitMS(10);
low(y);
waitMS(10);
}
x++;
}
}
/*
* Main program function.
*/
int main(void)
{
int num;
char *tokens[20];
uint8_t buffer[80];
sleep(1);
printf("This is the QScs Program!\n");
while(1)
{
printf(">");
fflush(stdout);
gets(buffer);
num = tokenize(buffer, tokens);
num = CheckRedirection(tokens, num);
if (num == 0) continue;
if (!strcmp(tokens[0], "help"))
Help();
else if (!strcmp(tokens[0], "ledon"))
LedON(num, tokens);
else if (!strcmp(tokens[0], "ledoff"))
LedOFF(num, tokens);
else if(!strcmp(tokens[0], "ledcheck"))
LedCheck();
else
{
printf("Invalid command!\n");
Help();
}
CloseRedirection();
}
return 0;
}
/* misc.h */
/* #include <propeller.h> */
/*
* 1000 = 1 second
* param WCtime - number of milliseconds to wait.
*/
int waitMS(int WCtime)
{
waitcnt(((CLKFREQ/1000)*WCtime) + CNT);
return WCtime;
}
/*
* param 1 = second
* param WCtime - number of seconds to wait.
*/
int wait(int WCtime)
{
waitcnt((CLKFREQ * WCtime) + CNT);
return WCtime;
}
/*
* Set a pin high without affecting other pins.
* param WCpin = pin number to set high.
*/
int high(int WCpin)
{
unsigned int bits = 1 << WCpin;
DIRA |= bits;
OUTA |= bits;
return WCpin;
}
/*
* Set a pin low without affecting other pins.
* param WCpin = pin number to set low.
*/
int low(int WCpin)
{
unsigned int mask = 1 << WCpin;
DIRA |= mask;
OUTA &= ~mask;
return WCpin;
}
C is a strongly typed language without automatic conversions. Therefore, your call:
high(argv[1]);
is suspect, because argv is typed char** and therefore argv[1] is typed char*. So, in both LedON() and LedOFF(), you're passing a pointer to a string (presumably the string representing the desired pin number) into the high() and low() routines. This most likely has unpredictable results.
Comments
Indeed!
I truly appreciate all you've done so far. It is lots of fun.
Attached is a COG-RTC Propeller demo. Hope you find it useful.
@denominator has a demo that actually uses an RTC chip.
Are you using SimpleIDE version 0-5-0 yet?
Thanks,
--Steve
Ted, yes the example is quite big at 22.7KB. Using simple_printf doesn't help much either :<
I tried this out with 0-5-0, looks good so far, I will be using it from this point on. The other thing that I noticed is, it really is starting to look like a professional package, who is really going to need Eclipse? Now if you add in a powerful new Spin package, bean's propbasic, ...
Ray
pause() - what library is that in? Do you have millisecond equivalent?
_rtc_start_timekeeping_cog() - Do you have to do settime() before you start the cog, or can settime() be done at anytime?
Since you you have settime(), printtime(), are their any other commands that are available?
I take it that their will be no problem with having settime() and ...timekeepping_cog() in a seperate function which will be activated from something like a gets()?
What else do you have like ...timekeeping_cog(), that starts in its own cog without any complicated code?
Ray
This is a style generally taught in C classes at college. There are advantages and disadvantages mostly good for the professor or other readers as an outline of the program without getting into too much detail.
Eclipse is important to the enterprise class of professional users. I'll probably add some new things to SimpleIDE later, but it will never provide the power-user experience available from Eclipse.
The pause() function is defined in the file and is very generic and relies on Propeller waitcnt, and should not be used with pthreads.
A millisecond version would take a similar form: Maybe wait is a better name for such functions. The pause function will not be super precise and should have HUBTEXT when used with XMM/XMMC programs.
Looks like settime can be called any time.
Those functions are provided in the file. If you need more information on available Standard C Library functions, use man pages like this one: http://linux.die.net/man/3/mktime
Right. Just don't use pthreads in the same program as waitcnt.
RTC, SD card driver, and the 2 current serial port drivers are all we have for standard C library support. TV, VGA, and Keyboard are plug-able drivers that can be used similar the serial port drivers.
Thanks,
--Steve
Can you open an issue on this?
Can you open an issue on this too?
That is my intention. I've got a bunch of stuff due for work early this week, but as soon as that settles out I'm going to post a proper bug reports with test programs.
Ray
Ray
Ray
Ray,
The problem here is undoubtedly that you did not initialized all the members of the tv structure, so they are garbage. Unlike "global" variables, stack local variables are not initialized in C. Therefore, you need to zero-out tv with something like this:
memset((void*)&tv, 0, sizeof(tv));
- Ted
Ray,
Specifically regarding the above declarations, you are on very thin ice. The reason? If you type in garbage, you're going to trash the stack. For example, type "12345678" for any of the values and you're going to overwrite neighboring variables.
Much better to reuse a single copy of a much longer buffer, say something like "char inputBuffer[80]". Even that is vulnerable to hacking - that is why so many C programs have been subject to "buffer overrun" attacks. See http://stackoverflow.com/questions/4309746/safe-alternative-to-gets for more details.
- Ted
I was thinking about buying a propboe, to use with GCC, but if there are no C drivers for ALL of the things on the propboe, then I guess that idea goes on the back back back burner.
Ray
Hi Ray,
We are working on PropBOE and other libraries. Much code is in our repository already.
We just need to finish some things. The xbee code is not done yet for example.
Someone will post a .zip here when it's ready.
Thanks,
--Steve
Please forgive my possible silly question -- as I have readily confessed, I'm not much with C (yet!). I was looking over the program you posted for Ray and wanted to look inside some of the libraries used. Is there an easy way to open one of those files (within SimpleIDE), or do I have to know where the compiler and standard library files are stored on my system?
Hi Jon,
The simple answer is you do not have access to library code from SimpleIDE.
The "Standard C Library" source code lives in the Propeller-GCC repository. It is not distributed with the tool-chain. While this seems awkward to someone used to the openness of Spin, it carries 2 advantages: 1) user's can't break it very easily, and 2) user's don't have to be overwhelmed by it. The libraries are distributed as binary code, and there are several fundamental versions to support the memory models: COG, LMM, XMM, and XMMC.
That being said, all the library code is available here for viewing: http://code.google.com/p/propgcc/source/browse/#hg%2Flib
Hope that helps.
Thanks,
--Steve
Ray
Got it. I had planned to introduce a C library help feature, but I have to stop somewhere to make a release. I've reserved the F1 key for that later.
For the time being I recommend the following links.
A list of Standard C Library Functions
BSD Library Manpagez Online Help (I prefer this one)
Linux Library Man Pages Online Help
The Library man pages are for BSD Unix and Linux. They contain a lot more than the Standard C Library function information.
Generally to find out about a function, just append the function name to a URL as:
http://www.manpagez.com/man/3/printf
http://linux.die.net/man/3/printf
Just replace printf with the function name. For example: http://www.manpagez.com/man/3/putchar
Hi Ray. Sorry, there is no plan to support building user .lib files at the moment.
Thanks,
--Steve
That's one of the problems I have with learning new languages such as C, Java, Python, etc. The languages themselves are syntactically (semantically?) simple with very few keywords and a simple structures where the underlying libraries supporting them are VAST and filled with many hidden goodies buried within. SPIN and BASIC are different in that they have bunches and bunches of powerful key words to learn and browse through.
Object oriented languages and/or their IDEs offer class and object browsers that make this exploration and discovery easier (while still and Easter egg hunt) but with C I always find myself looking in the library .h and .c files to see what is in there and what kind of fun things I can do without re-inventing wheels. I usually end up with a copy of the library sources with several editor windows opened up with library source and printed and highlighted .h file listings scattered around. I continue to stumble and struggle through the C libraries and spend lots of time trying to find stuff.
As I add on different components, like an uSD reader, xbee, ..., etc, I will have a command or two for working with the component. I guess this exercise is to see how far I can get before I starting running out of workable memory, this will include using the XMMC mode. I guess early suggestions for this would be appreciated.
I really like SimpleIDE, I think it covers just about everything that you would need from an IDE, except maybe creating some lib files, other than that it is a great little program, Thanks jazzed!
Ray
high(argv[1]);
is suspect, because argv is typed char** and therefore argv[1] is typed char*. So, in both LedON() and LedOFF(), you're passing a pointer to a string (presumably the string representing the desired pin number) into the high() and low() routines. This most likely has unpredictable results.
Instead, you need to use something like:
high(atoi(argv[1]));
Or
high(strtol(argv[1], 0, 10);