djuseeq / Ch376msc

Arduino library for CH376 mass storage contoller
MIT License
75 stars 17 forks source link

Feature request: readStringUntil(delim) #21

Closed petervanderwalt closed 4 years ago

petervanderwalt commented 4 years ago

(: Missing a function I use all the time with SD libraries (: https://www.arduino.cc/reference/tr/language/functions/communication/serial/readstringuntil/

Would love if you could add something like this - my use of your library is to read a file line-by-line (:

djuseeq commented 4 years ago

Hi, if you can, please test this version. Here is a new function called 'readFileUntil(delim,buffer,buffSize);'. Not as simple like in SD library because i don't use Stream class. Here is the example code: flashDrive.setFileName("TEST1.TXT"); flashDrive.openFile(); while(flashDrive.getCursorPos() < flashDrive.getFileSize()){//until EOF readMore = true; while(readMore){//if the buffer is not enough big to hold one line readMore = flashDrive.readFileUntil('\n', adatBuffer, sizeof(adatBuffer));//till new line Serial.print(adatBuffer); } } flashDrive.closeFile();

djuseeq commented 4 years ago

You can make it faster if you read text to buffer with readFile() function and after write your own function where you lookup for terminator character. Because here i request one byte at the time and analyze it. So just to read 1940 byte of data and print to serial(example file (3, read TEST1.TXT)) takes 232 ms, the same data with 'readFileUntil()' function takes 1162 ms (these time intervals can differ, depending on the drive type)

petervanderwalt commented 4 years ago

Just getting the monday morning customer support out of the way then I'm on it! Awesome!

djuseeq commented 4 years ago

I have uploaded an example file also

petervanderwalt commented 4 years ago

Loaded it up and test works functionally beautiful! (as in perfect, gets my line-by-line out with no trouble)

You are right though, it is quite terribly slow (:

Same file copied to SD (Directly on SPI, not via the CH376) and USB drive (via CH376) SD Card Read test took 43ms USB Flash Read test took 3525ms (5kb +-300 line file)

Sketch I used:

// SD Card
#include <SPI.h>
//#include <SD.h>
#include "SdFat.h"
SdFat SD;
#define SD_CS   5 // SD card select pin
File myFile;

// USB Chip
#include <Ch376msc.h>
// use this if no other device are attached to SPI port(MISO pin used as interrupt)
Ch376msc flashDrive(4); // chipSelect
//If the SPI port shared with other devices e.g TFT display, etc. remove from comment the code below and put the code above in a comment
//Ch376msc flashDrive(10, 9); // chipSelect, interrupt pin
// buffer for reading
char adatBuffer[25];// max length 255 = 254 char + 1 NULL character
boolean readMore = true;
int trmCharCounter = 0;

void setup() {

  // Other Shared Bus Devices
  pinMode(27, OUTPUT);
  digitalWrite(27, HIGH);
  pinMode(2, OUTPUT);
  digitalWrite(2, HIGH);

  // Open serial communications and wait for port to open:
  Serial.begin(115200);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  // SD Read Test
  Serial.print("Initializing SD card...");
  if(!SD.begin(SD_CS, SD_SCK_MHZ(25))) { // ESP32 requires 25 MHz limit
    Serial.println(F("SD begin() failed"));
    for(;;); // Fatal error, do not continue
  }
  Serial.println("initialization done.");
  unsigned long StartTime = millis();
  myFile = SD.open("gcode.gcode", FILE_READ);
  String sline;
  if (myFile) {
    Serial.println("test.txt:");
    // read from the file until there's nothing else in it:
    while (myFile.available()) {
      sline = myFile.readStringUntil('\n');
//      Serial.println(sline);
    }
    // close the file:
    myFile.close();
    unsigned long CurrentTime = millis();
    unsigned long ElapsedTime = CurrentTime - StartTime;
    Serial.print("SD Card Read test took ");
    Serial.print(ElapsedTime);
    Serial.println("ms");
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening file");
  }

  // USB Read Test
  flashDrive.init();
  if(flashDrive.driveReady()){
    unsigned long StartTime = millis();
    flashDrive.setFileName("GCODE~1.GCO");  //set the file name
    flashDrive.openFile();                //open the file
    //read data from flash drive until we reach EOF
    while(flashDrive.getCursorPos() < flashDrive.getFileSize()){
      readMore = true;
      while(readMore){
        // terminator character, temporary buffer where we read data from flash drive and the size of that buffer
        // returns boolean true if the given buffer is full and didn't found the terminator character
        readMore = flashDrive.readFileUntil('\n', adatBuffer, sizeof(adatBuffer));//new line character
//        Serial.print(adatBuffer);          //print the contents of the temporary buffer
      }//end while readMore
    }//end while not EOF
    unsigned long CurrentTime = millis();
    unsigned long ElapsedTime = CurrentTime - StartTime;
    Serial.print("USB Flash Read test took ");
    Serial.print(ElapsedTime);
    Serial.println("ms");
  } else {
    Serial.println(F("Drive not initialized"));
  }//end if driveReady
}

void loop() {
  // nothing happens after setup
}
djuseeq commented 4 years ago

You can speed it up the SPI communication, default is slooow 125 kHz. Edit in src/Ch376msc.h file SPICLKRATE value, on Uno with 16MHz system clock the maximum speed is sysClk/2 = 8MHz but i don't tested on this speed.

petervanderwalt commented 4 years ago

Sweet, set it to 8Mhz:

SD Card Read test took 43ms USB Flash Read test took 542ms

Of course (; now you just know I'm going to ask that we can set SPI clock rate? SD library handles it at the SD.begin(): SD.begin(SD_CS, SD_SCK_MHZ(25))

I checked the CS376s datasheet, should be able to do 24Mhz, ESP32 should be able to do 40Mhz: Supply SPI device interface with 2MB/24MHz speed, support SPI serial bus connect to MCU.

I played with the rate a little: 10Mhz works too, all the way up to 19Mhz, at 20Mhz I cannot init the chip (probably PCB layout related, tracks a bit long for such high frequency). I'll use 10Mhz for now - reliability will be better than running at the edge. PS: Read time between 10Mhz and 19Mhz drops by 3ms so not missing out on much (:

djuseeq commented 4 years ago

I thought the library was ready, but now I see it is far from complete. I'm getting some very good ideas here. I like it

djuseeq commented 4 years ago

I had problem with 1MHz and above, because i used module with wires on breadboard, so that was the reason why i used 125kHz.

petervanderwalt commented 4 years ago

Sorry! But hey, if it makes it better it's all the more worth it right (:

Thank you for implementing requests at all (many developers just refuse) and even better in record time! Amazing!

On Wed, 29 Jan 2020, 16:46 György Kovács, notifications@github.com wrote:

I thought the library was ready, but now I see it is far from complete. I'm getting some very good ideas here. I like it

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/djuseeq/Ch376msc/issues/21?email_source=notifications&email_token=AHP6BN5HRP3OQUFIUENGL23RAGJGHA5CNFSM4KJWPYUKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEKHN5VY#issuecomment-579788503, or unsubscribe https://github.com/notifications/unsubscribe-auth/AHP6BN55K6U35F3X7CFU3GDRAGJGHANCNFSM4KJWPYUA .

djuseeq commented 4 years ago

It's implemented, but i need to reorganize the library and finish some new functions and after that i will upload the code again for testing.

djuseeq commented 4 years ago

I have done with 2 function-like macros: SPI_SCK_KHZ() and SPI_SCK_MHZ(). So constructors are Ch376msc flashDrive(4)//default 125 kHz, MISO as INT Ch376msc flashDrive(4, SPI_SCK_MHZ(8))//sck = 8 MHz, MISO as INT Ch376msc flashDrive(4, 5)//default 125 kHz Ch376msc flashDrive(4, 5, SPI_SCK_MHZ(8))//sck = 8 MHz

djuseeq commented 4 years ago

Hi, if you can, please download and test this version again, SPI_SCK_MHZ is implemented, and some new functions and example. But testing is required. Have a nice day.