uCUS.c for the QS+HIB
Rsadeika
Posts: 3,837
This is a program that I am running in XMMC mode on the QuickStart with HIB. I used filetest.c by Dave Hein as a base, I added a softRTC to see if it in fact it runs on the QS+HIB, so far it is running as expected. I was thinking about changing the command names to resemble DOS commands, but I think I will leave it as xNIX commands, for now.
If you want to create a file, on your blank uSD card - 'echo >> test.txt'. You can also add something to the file - 'echo This is the one. >> test.txt'. And of course if you want to check the file contents - 'cat test.txt'. Yep, this is primitive stuff, if somebody would like to add an editor, that would be a nice addition. Now if only you had COGs in XMMC mode, then ...
I noticed in SimpleIDE, there is no QUICKSTART-SDXMMC selection, but I am not sure would you would gain with that. I do not know what the usage for that would be, is it necessary for the QS+HIB?
Ray
If you want to create a file, on your blank uSD card - 'echo >> test.txt'. You can also add something to the file - 'echo This is the one. >> test.txt'. And of course if you want to check the file contents - 'cat test.txt'. Yep, this is primitive stuff, if somebody would like to add an editor, that would be a nice addition. Now if only you had COGs in XMMC mode, then ...
I noticed in SimpleIDE, there is no QUICKSTART-SDXMMC selection, but I am not sure would you would gain with that. I do not know what the usage for that would be, is it necessary for the QS+HIB?
Ray
/* uCUS.c Based on filetest.c developed by Dave Hein. */ #include "simpletools.h" #include "simpletext.h" #include "fdserial.h" #include <sys/rtc.h> #define BUFFERLEN 10 /* SD card */ int DO = 0, CLK = 1, DI = 2, CS = 3; char *FindChar(char *ptr, int val); FILE *stdinfile; FILE *stdoutfile; /* Print help information */ void Help() { printf("Commands are help, cat, rm, ls, ll, echo \n"); printf(" cd, pwd, mkdir, rmdir, quit, time, date \n"); printf(" setclock, \n"); } void Cd(int argc, char **argv) { if (argc < 2) return; if (chdir(argv[1])) perror(argv[1]); } void Pwd(int argc, char **argv) { uint8_t buffer[64]; char *ptr = getcwd(buffer, 64); if (!ptr) perror(0); else fprintf(stdoutfile, "%s\n", ptr); } void Mkdir(int argc, char **argv) { #ifndef __PROPELLER_LMM__ int i; for (i = 1; i < argc; i++) { if (mkdir(argv[i], 0)) perror(argv[i]); } #else printf("Not enough memory for mkdir in LMM mode\n"); #endif } void Rmdir(int argc, char **argv) { #ifndef __PROPELLER_LMM__ int i; for (i = 1; i < argc; i++) { if (rmdir(argv[i])) perror(argv[i]); } #else printf("Not enough memory for rmdir in LMM mode\n"); #endif } /* This routine implements the file cat function */ void Cat(int argc, char **argv) { int i; int num; void *infile; uint8_t buffer[40]; for (i = 0; i < argc; i++) { if (i == 0) { if (argc == 1 || stdinfile != stdin) infile = stdinfile; else continue; } else { infile = fopen(argv[i], "r"); if (infile == 0) { perror(argv[i]); continue; } } if (infile == stdin) { while (gets(buffer)) { if (buffer[0] == 4) break; fprintf(stdoutfile, "%s\n", buffer); } } else { while ((num = fread(buffer, 1, 40, infile))) fwrite(buffer, 1, num, stdoutfile); } if (i) fclose(infile); } fflush(stdout); } /* This routine deletes the files specified by the command line arguments */ void Remove(int argc, char **argv) { int i; for (i = 1; i < argc; i++) { if (remove(argv[i])) perror(argv[i]); } } /* This routine echos the command line arguments */ void Echo(int argc, char **argv) { int i; for (i = 1; i < argc; i++) { if (i != argc - 1) fprintf(stdoutfile, "%s ", argv[i]); else fprintf(stdoutfile, "%s\n", argv[i]); } } /* This routine lists the root directory or any subdirectories specified in the command line arguments. If the "-l" option is specified, it will print the file attributes and size. Otherwise, it will just print the file names. */ void List(int argc, char **argv) { int i, j; char *ptr; char fname[13]; int32_t count = 0; uint32_t filesize; uint32_t longflag = 0; char *path; char drwx[5]; int column; int prevlen; DIR *dirp; struct dirent *entry; // Check flags for (j = 1; j < argc; j++) { if (argv[j][0] == '-') { if (!strcmp(argv[j], "-l")) longflag = 1; else printf("Unknown option \"%s\"\n", argv[j]); } else count++; } // List directories for (j = 1; j < argc || count == 0; j++) { if (count == 0) { count--; path = "./"; } else if (argv[j][0] == '-') continue; else path = argv[j]; if (count >= 2) fprintf(stdoutfile, "\n%s:\n", path); dirp = opendir(path); if (!dirp) { perror(path); continue; } column = 0; prevlen = 14; while (entry = readdir(dirp)) { if (entry->name[0] == '.') continue; ptr = fname; for (i = 0; i < 8; i++) { if (entry->name[i] == ' ') break; *ptr++ = tolower(entry->name[i]); } if (entry->name[8] != ' ') { *ptr++ = '.'; for (i = 8; i < 11; i++) { if (entry->name[i] == ' ') break; *ptr++ = tolower(entry->name[i]); } } *ptr = 0; filesize = entry->filesize_3; filesize = (filesize << 8) | entry->filesize_2; filesize = (filesize << 8) | entry->filesize_1; filesize = (filesize << 8) | entry->filesize_0; strcpy(drwx, "-rw-"); if (entry->attr & ATTR_READ_ONLY) drwx[2] = '-'; if (entry->attr & ATTR_ARCHIVE) drwx[3] = 'x'; if (entry->attr & ATTR_DIRECTORY) { drwx[0] = 'd'; drwx[3] = 'x'; } if (longflag) fprintf(stdoutfile, "%s %8d %s\n", drwx, filesize, fname); else if (++column == 5) { for (i = prevlen; i < 14; i++) fprintf(stdoutfile, " "); fprintf(stdoutfile, "%s\n", fname); column = 0; prevlen = 14; } else { for (i = prevlen; i < 14; i++) fprintf(stdoutfile, " "); prevlen = strlen(fname); fprintf(stdoutfile, "%s", fname); } } closedir(dirp); if (!longflag && column) fprintf(stdoutfile, "\n"); } } /* This routine returns a pointer to the first character that doesn't match val. */ char *SkipChar(char *ptr, int val) { while (*ptr) { if (*ptr != val) break; ptr++; } return ptr; } /* This routine returns a pointer to the first character that matches val. */ char *FindChar(char *ptr, int val) { while (*ptr) { if (*ptr == val) break; ptr++; } return ptr; } /* This routine extracts tokens from a string that are separated by one or more spaces. It returns the number of tokens found. */ 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; } /* This routine searches the list of tokens for the redirection operators and opens the files for input, output or append depending on the operator. */ 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; } /* This routine closes files that were open for redirection */ void CloseRedirection() { if (stdinfile != stdin) { fclose(stdinfile); stdinfile = stdin; } if (stdoutfile != stdout) { fclose(stdoutfile); stdoutfile = stdout; } } void Get_Date(int argc, char **argv) { char timebuff[16]; time_t now = 0; now = time(&now); strftime(timebuff,16,"%b %d, %Y", localtime(&now)); fprintf(stdoutfile,"%s\n",timebuff); } void Get_Time(int argc, char **argv) { char timebuff[16]; time_t now = 0; now = time(&now); strftime(timebuff,16,"%T", localtime(&now)); fprintf(stdoutfile,"%s\n",timebuff); } void Set_Clock(int argc, char **argv) { struct timeval tv; struct tm t; t.tm_isdst = getdst(); t.tm_year = prompttime("Year")-1900; t.tm_mon = prompttime("Month")-1; t.tm_mday = prompttime("Day of the month"); t.tm_hour = prompttime("Hour"); t.tm_min = prompttime("Minute"); t.tm_sec = prompttime("Second"); tv.tv_sec = mktime(&t); settimeofday(&tv, 0); } int getdst() { int rc = 0; printf("Use daylight savings time [y/n] ? "); //fflush(stdout); rc = (getchar() == 'y') ? 1 : 0; getchar(); return rc; } int prompttime(char *prompt) { int rc = 0; char *endp; char buffer[BUFFERLEN]; do { printf("Enter %s: ",prompt); //fflush(stdout); fgets(buffer, BUFFERLEN,stdin); //fflush(stdin); rc = strtol(buffer, &endp, 10); if(endp == buffer) { if('\n' == *endp) { rc = 0; break; } printf("Invalid entry \"%c....\" Please enter a number.\n", *endp); } } while(endp == buffer); return rc; } /* The program starts the file system. It then loops reading commands and calling the appropriate routine to process it. */ int main() { int num; char *tokens[20]; uint8_t buffer[80]; stdinfile = stdin; stdoutfile = stdout; // Wait for the serial terminal to start waitcnt(CNT + CLKFREQ); _rtc_start_timekeeping_cog(); pause(100); sd_mount(DO, CLK, DI, CS); Help(); while (1) { // printf("\n> "); 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], "quit")) break; else if (!strcmp(tokens[0], "cat")) Cat(num, tokens); else if (!strcmp(tokens[0], "ls")) List(num, tokens); else if (!strcmp(tokens[0], "ll")) { tokens[num++] = "-l"; List(num, tokens); } else if (!strcmp(tokens[0], "rm")) Remove(num, tokens); else if (!strcmp(tokens[0], "echo")) Echo(num, tokens); else if (!strcmp(tokens[0], "cd")) Cd(num, tokens); else if (!strcmp(tokens[0], "pwd")) Pwd(num, tokens); else if (!strcmp(tokens[0], "mkdir")) Mkdir(num, tokens); else if (!strcmp(tokens[0], "rmdir")) Rmdir(num, tokens); else if (!strcmp(tokens[0], "date")) Get_Date(num, tokens); else if (!strcmp(tokens[0], "time")) Get_Time(num, tokens); else if (!strcmp(tokens[0], "setclock")) Set_Clock(num, tokens); else { printf("Invalid command\n"); Help(); } CloseRedirection(); } printf("System Stop\n"); return 0; }
Comments
Now, what do I do next with my QS+HIB contraption? I was thinking about making a stand alone with a VGA and keyboard, but I noticed in the Learn section examples, there is no C example for using a keyboard with the VGA, and I also did not notice if the C VGA version is 80x25 output. This will give me something to think about.
Ray
It would be real PIA, if I have to re-write the whole program just so it can run with an XBee attached, and then if I wanted too hook back up to the USB I would have to revert back to this existing program. Their has to be a more efficient way of doing these sort of things, yes?
Ray
Ray
Ray
Ray
Ray
The standard libraries seem to be more or less written for boards like the C3 that are designed for extended memory model (XMM) operation, where programs are stored in and fetched from peripheral memory. In contrast, the simple libraries were written for the compact memory model (CMM), where programs are stored only in the Propeller chip's main RAM.
This is all part of an in-progress open source project. The next step is to start testing the Simple Libraries with XMM and update any functions that are not currently compatible. Things like waitcnt might or might not need some adjustments to work with XMM. When that's up and running, the step after that might be to modify the functions and types so that they work with the standard libraries.
Community involvement could help accelerate this process. I'll check with the development group and find out what needs to be made available so that an open project thread can be started.
Andy