Pinguino Forum
Strings in C - help - Printable Version

+- Pinguino Forum (http://forum.pinguino.cc)
+-- Forum: Software (http://forum.pinguino.cc/forumdisplay.php?fid=7)
+--- Forum: Syntax & Programs (http://forum.pinguino.cc/forumdisplay.php?fid=19)
+--- Thread: Strings in C - help (/showthread.php?tid=3503)

Pages: 1 2 3 4


RE: Strings in C - help - mf01 - 11-05-2012

Hi Dale,

following on from Moreno's post above, it is possible to increase the length of the string that is handled by CDC.printf by changing the size of the appropriate buffer array in the associated library file. It does look like the buffer array size needs to be larger than the string to be printed but I could not quickly determine by how much other than by trial and error (increasing the buffer array size and seeing what happens).

I suspect that the size of the buffer array was a compromise between use of resources and functionality, bearing in mind that the some of the boards supported have quite small memory sizes compared with the PIC32MX440F256 in the PIC32 Pinguino OTG and PIC32 Pinguino Micro that you are using.

Regards


RE: Strings in C - help - KiloOne - 11-05-2012

Hi Guys,

Again I've spent too much time on this one.

To me there are more than one problems here.

I can solve the CDC buffer issue by just CDC printing 64 bytes at a time off my long string.

And, strcat() seems to be causing me issues so using sprintf to join strings as a kludge may have to be my solution for now (see // add timestamp below).

I do not like the inefficiency of the code I came up with but at PIC32 speeds it probably is OK.

Maybe someone could show me the elegant way to print 64 bytes at a time from a string (in the #ifdef section below), here is my working attempt in my SD card writing section:
Code:
// SD write process takes about 25-30 msec to write 200 char to file (tested up to 4mb file.)
// 8 ms of this is to mount, most of rest of time is the flush
// need global filename char variable with 8.3 filename in it
void storeit(char* intxt)  {
    if (strcmp(filename,"empty")==0) return;
    SPI_close();                                    // disables other SPI devices
    FIL     fil;                                    // File object
    FRESULT res, rc;
    UINT    btw, bw;
    char storetxt[400] = "";                        // set max write size to user needs!!!!!!                        
    sprintf(storetxt, "%4lu,%s", millis()/1000,intxt); // add timestamp
    #ifdef DEBUGMODE                                // adds CDC for debug (costs some overhead)
        char tmp[66] = "";
        char CDCline[400] = "";                        // set max write size to user needs!!!!!!
        strcpy(CDCline,storetxt);
        while (1==1){                                
            if (strlen(CDCline)<=64){
                CDC.println(CDCline);
                break;
            } else {
                strncpy(tmp,CDCline,64);
                CDC.print(tmp,strlen(tmp));
                strcpy(tmp,CDCline+64);
                strcpy(CDCline,tmp);
            }
        }
    #endif
    btw = strlen(storetxt);                            // number of Bytes To be Written
    SD.mount(40);                          
    res = SD.open(&fil, filename, FA_OPEN_ALWAYS | FA_READ | FA_WRITE);    // appends if file exists
    if (!res) {
        digitalWrite(YELLOWLED, HIGH);          
        SD.seek(&fil,fil.fsize);                    // Set R/W pointer to end of file
        rc = SD.write(&fil, storetxt, btw, &bw);    // write new data to file
        SD.flush(&fil);                             // flush cache to avoid data loss from loss of power etc
        SD.close(&fil);                             // Included for safety to ensure file properly closed
        SD.unmount();                                // in case user removes card instead of proceeding.
        digitalWrite(YELLOWLED, LOW);          
    }
    SPI_6803();                                     //reenables other SPI devices with user
}

void SPI_6803() {
    SPI_close();
    SPI_init();                         // left clock at 250khz, not much gain at 1mhz since reading all 18 volt regs takes 1ms while conversion takes 13ms
    SPI2CONCLR = 0x8000;                // turn off SPI mode before changing an SPI register!!!!!!!!!!!
    SPI2CONCLR = 0x100;                 // clock edge bit(8) to 0    for PHA POL needs                        
    SPI2CONSET = 0x40;                    // clock polarity bit(6) to 1     for PHA POL needs                        
    SPI2CONSET = 0x200;                 // SMP bit(9) to 1    hex of 2^9
    SPI2CONSET = 0x8000;                // turn SPI mode back ON after changing an SPI register!!!!!!!!!!!
    pinMode(39, OUTPUT);                // #SS CSBI or whatever is PIC pin RF0 at pin 39 in digitalw.c    
}

Thanks,
Dale


RE: Strings in C - help - pingotg - 11-05-2012

OK, some thoughts:

1. strcpy & strncpy have defined semantics which I sincerely hope are being honoured
2. I believe this is true for the definition of strncpy: "Warning: If there is no null byte among the first n bytes of src, the string placed in dest will not be null-terminated."

So, when you copy just 64 bytes, knowing the string is longer than 64, you get a result with no terminating null!!

John


RE: Strings in C - help - mf01 - 11-05-2012

Hi Dale,

a few minor points. As I noted in an earlier post Sprintf() is the Pinguino version of sprintf. The formatting capabilities are more limited but it does use less resources and may be faster. It is worth a try if you are concerned about time it takes to assemble the "string".

Secondly, you probably don't need to have SD.flush( ) if you are immediately going to close the file with SD.close(). If you look at the corresponding functions in ff.c (f_sync and f_close) you will see that for a file that is open as Read/Write f_close calls f_sync. If you are always going to close the file after writing dropping the SD.flush() may trim some time off the total process. The inclusion of both SD.flush and SD.close in the DataLogger.pde example was to allow for the expansion of the code to cover multiple writes at some separation without the file being "closed". Closing the file after each write should reduce the chances of data being lost due to it still being in a buffer in the event of loss of power supply or other problems.

Finally, I don't know what you are going to do with the data after you have captured it, but including a new line character (\n) or carraige return (\r) at the end of each data line means that the text file can easily be read into a spreadsheet with each string coming on a separate line. This can be done just by including "\n" (or \r or both \n\r) in the format string within sprintf/Sprintf, i.e.:-

Code:
sprintf(storetxt, "%4lu,%s\n", millis()/1000,intxt);

This might also make it easier to look at the data file with just a simple text editor to see if any particular sets of data are getting corrupted.

Regards


RE: Strings in C - help - KiloOne - 11-05-2012

(11-05-2012, 02:46 PM)pingotg Wrote: So, when you copy just 64 bytes, knowing the string is longer than 64, you get a result with no terminating null!!

John,

I think this is fine since the null character is being left in CDCline until CDCline finally gets smaller than 64. The 64 character strings that are printed with CDC.print and are simply added without \r\n to the terminal screen.

When CDCline gets to <64 long it is CDC printed with CDC.println which adds the \r\n so that the terminal program does not have to.

Is that what you were worried about?

Dale

(11-05-2012, 03:08 PM)mf01 Wrote: Hi Dale,

a few minor points. As I noted in an earlier post Sprintf() is the Pinguino version of sprintf. The formatting capabilities are more limited but it does use less resources and may be faster. It is worth a try if you are concerned about time it takes to assemble the "string".

Secondly, you probably don't need to have SD.flush( ) if you are immediately going to close the file with SD.close(). If you look at the corresponding functions in ff.c (f_sync and f_close) you will see that for a file that is open as Read/Write f_close calls f_sync. If you are always going to close the file after writing dropping the SD.flush() may trim some time off the total process. The inclusion of both SD.flush and SD.close in the DataLogger.pde example was to allow for the expansion of the code to cover multiple writes at some separation without the file being "closed". Closing the file after each write should reduce the chances of data being lost due to it still being in a buffer in the event of loss of power supply or other problems.

Finally, I don't know what you are going to do with the data after you have captured it, but including a new line character (\n) or carraige return (\r) at the end of each data line means that the text file can easily be read into a spreadsheet with each string coming on a separate line. This can be done just by including "\n" (or \r or both \n\r) in the format string within sprintf/Sprintf, i.e.:-

Code:
sprintf(storetxt, "%4lu,%s\n", millis()/1000,intxt);

This might also make it easier to look at the data file with just a simple text editor to see if any particular sets of data are getting corrupted.

Regards

Mark,

I will add looking at Sprintf vs sprintf to my 'todo' list.

I will also add removing flush item to my 'todo' list. Off the top of my head I don't think it will change much because the flush data would still have to get flushed by the close and I assume if there is no data to flush, it would flush very quickly.

Good catch, I had removed the \r\n a few iterations ago when I was working on CDC problem and hadn't looked at a file for a while, just noticed all went to one line LOL. The order doesn't matter does it? In my mind I am branded with 'Carriage return Line feed' for a lot of years.

I am a little concerned with having to set aside a second 400 character temporary string to use sprintf() for string concatenating vs strcat() and then yet another 400 character for the CDC printing but I don't see another way.

Thanks,
Dale


RE: Strings in C - help - pingotg - 11-05-2012

No.

You copy 64 bytes to tmp using strncpy. Then you use strlen(tmp) so you'll get a number more than 64 unless by chance the 65th byte happens to be a null, which occasionally it may be.

You need tmp[64] = 0; (or tmp[64] = '\0'; to be clearer).

John


RE: Strings in C - help - mf01 - 11-05-2012

Hi Dale,

About the unnecessary calling of SD.flush() - having had a quick look at the code in ff.c for f_sysnc, it seems that the function is more concerned about ensuring that various attributes, pointers etc are correctly set rather than the physical moving of any data, so it seems likely it will take a similar length of time irrespective of whether there is any data actually in the buffer.

Regards


RE: Strings in C - help - KiloOne - 11-05-2012

(11-05-2012, 03:27 PM)pingotg Wrote: You copy 64 bytes to tmp using strncpy. Then you use strlen(tmp) so you'll get a number more than 64 unless by chance the 65th byte happens to be a null, which occasionally it may be.

You need tmp[64] = 0; (or tmp[64] = '\0'; to be clearer).

John

Sorry, I am confused, I thought strlen() did not report the null as a character. So how would strlen(tmp) report more than 64 if I only put 64 in it?

Thanks,
Dale

(11-05-2012, 03:47 PM)mf01 Wrote: Hi Dale,

About the unnecessary calling of SD.flush() - having had a quick look at the code in ff.c for f_sysnc, it seems that the function is more concerned about ensuring that various attributes, pointers etc are correctly set rather than the physical moving of any data, so it seems likely it will take a similar length of time irrespective of whether there is any data actually in the buffer.

Regards

Great, I will take it out and check the timing later Big Grin

Thanks,
Dale


RE: Strings in C - help - mf01 - 11-05-2012

Hi again,

re your concerned with having to set aside a second 400 character temporary string to use sprintf(), in that you already have the data assembled in a string, you don't need the formatting capabilities of CDC.printf. It might be worth delving into __cdc.c and see what CDC.printf does with the data after it has done the fomatting. I suspect that it then uses another routine to output the formatted string. You might be able to call this directly, skipping the "middle man" and may be the buffer length problem associated with CDC.printf.

Regards


RE: Strings in C - help - KiloOne - 11-05-2012

Great, I will check it out.

I did decide that I could just whittle intxt down in the CDC print section and dispense with defining and using CDCline.

Dale