diff --git a/README.md b/README.md index b0ccf3f..d72d0b2 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,17 @@ Configure the jumpers on the module depending on which communication protocol yo ![Alt text](extras/JumperSelect.png?raw=true "Setting") ## Versioning +v1.4.0 Sep 26, 2019 + - new functions + - getTotalSectors() - returns a unsigned long number, total sectors on the drive + - getFreeSectors() - returns a unsigned long number, free sectors on the drive + - getFileSystem() - returns a byte number, 0x01-FAT12, 0x02-FAT16, 0x03-FAT32 + - updated example files with a new functions + - new example file, seraching for the oldest/newest file on the flash drive + v1.3.1 Sep 20, 2019 - rearrange the folder structure to be 1.5 library format compatible - + v1.3 Sep 17, 2019 - bug fix for moveCursor issue #3 , minor changes diff --git a/examples/basicUsageHwSerial/basicUsageHwSerial.ino b/examples/basicUsageHwSerial/basicUsageHwSerial.ino index 4811660..cf20261 100644 --- a/examples/basicUsageHwSerial/basicUsageHwSerial.ino +++ b/examples/basicUsageHwSerial/basicUsageHwSerial.ino @@ -20,6 +20,9 @@ char adatBuffer[255];// max length 255 = 254 char + 1 NULL character char adat[]="Vivamus nec nisl molestie, blandit diam vel, varius mi. Fusce luctus cursus sapien in vulputate.\n"; char adat2[] = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis efficitur ac est eu pharetra. \n"; //.............................................................................................................................. +unsigned long totSect = 0; +unsigned long freeSect = 0; +byte percentg = 0; byte tmpCommand; //used to store data coming from serial port boolean readMore; @@ -27,7 +30,8 @@ boolean readMore; void setup() { Serial.begin(115200); flashDrive.init(); - printInfo("h:Print this help\n\n1:Create\n2:Append\n3:Read\n4:Read date/time\n5:Modify date/time\n6:Delete\n7:List dir"); + printInfo("h:Print this help\n\n1:Create\n2:Append\n3:Read\n4:Read date/time\n" + "5:Modify date/time\n6:Delete\n7:List dir\n8:Print free space"); } void loop() { @@ -35,36 +39,40 @@ void loop() { tmpCommand = Serial.read(); //read incoming bytes from the serial monitor if(((tmpCommand > 48)&&(tmpCommand < 58)) && !flashDrive.checkDrive()){ // if the data is ASCII 0 - 9 and no flash drive are attached printInfo("Attach flash drive first!"); - tmpCommand = 10; // change the command byte + tmpCommand = 10; // change the command byte } switch (tmpCommand) { - + case 49: //1 printInfo("COMMAND1: Create and write data to file : TEST1.TXT"); // Create a file called TEST1.TXT flashDrive.setFileName("TEST1.TXT"); //set the file name flashDrive.openFile(); //open the file - + for(int a = 0; a < 20; a++){ //write text from string(adat) to flash drive 20 times flashDrive.writeFile(adat, strlen(adat)); //string, string length } flashDrive.closeFile(); //at the end, close the file printInfo("Done!"); break; -//***************************************************************************************************************************************************** +//***************************************************************************************************************************************************** case 50: //2 printInfo("COMMAND2: Append data to file: TEST1.TXT"); // Append data to the end of the file. flashDrive.setFileName("TEST1.TXT"); //set the file name flashDrive.openFile(); //open the file flashDrive.moveCursor(CURSOREND); //move the "virtual" cursor at end of the file, with CURSORBEGIN we actually rewrite our old file //flashDrive.moveCursor(flashDrive.getFileSize()); // is almost the same as CURSOREND, because we put our cursor at end of the file - + for(int a = 0; a < 20; a++){ //write text from string(adat) to flash drive 20 times - flashDrive.writeFile(adat2, strlen(adat2)); //string, string length + if(flashDrive.getFreeSectors()){ //check the free space on the drive + flashDrive.writeFile(adat2, strlen(adat2)); //string, string length + } else { + Serial.println("Disk full"); + } } flashDrive.closeFile(); //at the end, close the file printInfo("Done!"); break; -//***************************************************************************************************************************************************** +//***************************************************************************************************************************************************** case 51: //3 printInfo("COMMAND3: Read File: TEST1.TXT"); // Read the contents of this file on the USB disk, and display contents in the Serial Monitor flashDrive.setFileName("TEST1.TXT"); //set the file name @@ -78,13 +86,13 @@ void loop() { flashDrive.closeFile(); //at the end, close the file printInfo("Done!"); break; -//***************************************************************************************************************************************************** +//***************************************************************************************************************************************************** case 52: //4 printInfo("COMMAND4: Read File date/time: TEST1.TXT"); // Read the date and time of file, default 2004.01.01 - 00:00:00 flashDrive.setFileName("TEST1.TXT"); //set the file name flashDrive.openFile(); //open the file //print informations about the file - Serial.println(flashDrive.getFileName()); + Serial.println(flashDrive.getFileName()); Serial.print(flashDrive.getYear()); Serial.print("y\t"); Serial.print(flashDrive.getMonth()); @@ -100,31 +108,31 @@ void loop() { flashDrive.closeFile(); //at the end, close the file printInfo("Done!"); break; -//***************************************************************************************************************************************************** +//***************************************************************************************************************************************************** case 53: //5 printInfo("COMMAND5: Modify File date/time: TEST1.TXT"); // Modify the file date/time and save flashDrive.setFileName("TEST1.TXT"); //set the file name flashDrive.openFile(); //open the file - + flashDrive.setYear(2019); flashDrive.setMonth(2); flashDrive.setDay(24); flashDrive.setHour(15); flashDrive.setMinute(47); flashDrive.setSecond(26); - + flashDrive.dirInfoSave(); //save the changed data flashDrive.closeFile(); //and yes again, close the file after when you don`t use it printInfo("Done!"); break; -//***************************************************************************************************************************************************** +//***************************************************************************************************************************************************** case 54: //6 printInfo("COMMAND6: Delete File: TEST1.TXT"); // Delete the file named TEST1.TXT flashDrive.setFileName("TEST1.TXT"); //set the file name flashDrive.deleteFile(); //delete file printInfo("Done!"); break; -//***************************************************************************************************************************************************** +//***************************************************************************************************************************************************** case 55: //7 printInfo("COMMAND7: List root directory"); //Print all file names in the current directory while(flashDrive.listDir()){ // reading next file @@ -136,9 +144,47 @@ void loop() { } printInfo("Done!"); break; -//***************************************************************************************************************************************************** +//***************************************************************************************************************************************************** + case 56: //8 + totSect = flashDrive.getTotalSectors(); // get the total sector number + freeSect = flashDrive.getFreeSectors(); // get the available sector number + percentg = map(freeSect,totSect,0,0,100); // convert it to percentage (0-100) + Serial.print("Disk size in bytes: "); + /*if the sector number is more than 8388607 (8388607 * 512 = 4294966784 byte = 4Gb (fits in a 32bit variable) ) + e.g. 8388608 * 512 = 4294967296 byte (32bit variable overflows) */ + if(totSect > 8388607){ + Serial.print(">4Gb"); + } else { + Serial.print(totSect * SECTORSIZE); + } + Serial.print("\tFree space in bytes: "); + if(freeSect > 8388607){ + Serial.print(">4Gb"); + } else { + Serial.print(freeSect * SECTORSIZE); + } + Serial.print("\tDisk usage :"); + Serial.print(percentg); + Serial.print("%"); + switch (flashDrive.getFileSystem()) { //1-FAT12, 2-FAT16, 3-FAT32 + case 1: + Serial.print("\tFAT12 partition"); + break; + case 2: + Serial.print("\tFAT16 partition"); + break; + case 3: + Serial.println("\tFAT32 partition"); + break; + default: + Serial.print("\tNo valid partition"); + break; + } + break; +//***************************************************************************************************************************************************** case 104: //h - printInfo("h:Print this help\n\n1:Create\n2:Append\n3:Read\n4:Read date/time\n5:Modify date/time\n6:Delete\n7:List dir"); + printInfo("h:Print this help\n\n1:Create\n2:Append\n3:Read\n4:Read date/time\n" + "5:Modify date/time\n6:Delete\n7:List dir\n8:Print free space"); break; default: break; @@ -149,9 +195,9 @@ void loop() { }//end loop //Print information -void printInfo(char* info){ +void printInfo(const char* info){ char * infoPtr = info; - int infoLength; + int infoLength = 0; while(*infoPtr){ infoPtr++; infoLength++; diff --git a/examples/basicUsageSPI/basicUsageSPI.ino b/examples/basicUsageSPI/basicUsageSPI.ino index 11e8fdd..4c40546 100644 --- a/examples/basicUsageSPI/basicUsageSPI.ino +++ b/examples/basicUsageSPI/basicUsageSPI.ino @@ -12,6 +12,8 @@ //.............................................................................................................................. // Connect to SPI port: MISO, MOSI, SCK Ch376msc flashDrive(10, 9); // chipSelect, busy pins (use this if no other device are attached to SPI port(MISO pin used as interrupt)) + +//If the SPI port shared with other devices e.g SD card, display, etc. remove from comment the code below and put the code above in a comment //Ch376msc flashDrive(10, 9, 8); // chipSelect, busy, interrupt pins //.............................................................................................................................. // buffer for reading @@ -21,6 +23,9 @@ char adatBuffer[255];// max length 255 = 254 char + 1 NULL character char adat[]="Vivamus nec nisl molestie, blandit diam vel, varius mi. Fusce luctus cursus sapien in vulputate.\n"; char adat2[] = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis efficitur ac est eu pharetra. \n"; //.............................................................................................................................. +unsigned long totSect = 0; +unsigned long freeSect = 0; +byte percentg = 0; byte tmpCommand; //used to store data coming from serial port boolean readMore; @@ -28,7 +33,8 @@ boolean readMore; void setup() { Serial.begin(115200); flashDrive.init(); - printInfo("h:Print this help\n\n1:Create\n2:Append\n3:Read\n4:Read date/time\n5:Modify date/time\n6:Delete\n7:List dir"); + printInfo("h:Print this help\n\n1:Create\n2:Append\n3:Read\n4:Read date/time\n" + "5:Modify date/time\n6:Delete\n7:List dir\n8:Print free space"); } void loop() { @@ -36,36 +42,40 @@ void loop() { tmpCommand = Serial.read(); //read incoming bytes from the serial monitor if(((tmpCommand > 48)&&(tmpCommand < 58)) && !flashDrive.checkDrive()){ // if the data is ASCII 0 - 9 and no flash drive are attached printInfo("Attach flash drive first!"); - tmpCommand = 10; // change the command byte + tmpCommand = 10; // change the command byte } switch (tmpCommand) { - + case 49: //1 printInfo("COMMAND1: Create and write data to file : TEST1.TXT"); // Create a file called TEST1.TXT flashDrive.setFileName("TEST1.TXT"); //set the file name flashDrive.openFile(); //open the file - + for(int a = 0; a < 20; a++){ //write text from string(adat) to flash drive 20 times flashDrive.writeFile(adat, strlen(adat)); //string, string length } flashDrive.closeFile(); //at the end, close the file printInfo("Done!"); break; -//***************************************************************************************************************************************************** +//***************************************************************************************************************************************************** case 50: //2 printInfo("COMMAND2: Append data to file: TEST1.TXT"); // Append data to the end of the file. flashDrive.setFileName("TEST1.TXT"); //set the file name flashDrive.openFile(); //open the file flashDrive.moveCursor(CURSOREND); //move the "virtual" cursor at end of the file, with CURSORBEGIN we actually rewrite our old file //flashDrive.moveCursor(flashDrive.getFileSize()); // is almost the same as CURSOREND, because we put our cursor at end of the file - + for(int a = 0; a < 20; a++){ //write text from string(adat) to flash drive 20 times - flashDrive.writeFile(adat2, strlen(adat2)); //string, string length + if(flashDrive.getFreeSectors()){ //check the free space on the drive + flashDrive.writeFile(adat2, strlen(adat2)); //string, string length + } else { + Serial.println("Disk full"); + } } flashDrive.closeFile(); //at the end, close the file printInfo("Done!"); break; -//***************************************************************************************************************************************************** +//***************************************************************************************************************************************************** case 51: //3 printInfo("COMMAND3: Read File: TEST1.TXT"); // Read the contents of this file on the USB disk, and display contents in the Serial Monitor flashDrive.setFileName("TEST1.TXT"); //set the file name @@ -79,13 +89,13 @@ void loop() { flashDrive.closeFile(); //at the end, close the file printInfo("Done!"); break; -//***************************************************************************************************************************************************** +//***************************************************************************************************************************************************** case 52: //4 printInfo("COMMAND4: Read File date/time: TEST1.TXT"); // Read the date and time of file, default 2004.01.01 - 00:00:00 flashDrive.setFileName("TEST1.TXT"); //set the file name flashDrive.openFile(); //open the file //print informations about the file - Serial.println(flashDrive.getFileName()); + Serial.println(flashDrive.getFileName()); Serial.print(flashDrive.getYear()); Serial.print("y\t"); Serial.print(flashDrive.getMonth()); @@ -101,31 +111,31 @@ void loop() { flashDrive.closeFile(); //at the end, close the file printInfo("Done!"); break; -//***************************************************************************************************************************************************** +//***************************************************************************************************************************************************** case 53: //5 printInfo("COMMAND5: Modify File date/time: TEST1.TXT"); // Modify the file date/time and save flashDrive.setFileName("TEST1.TXT"); //set the file name flashDrive.openFile(); //open the file - + flashDrive.setYear(2019); flashDrive.setMonth(2); flashDrive.setDay(24); flashDrive.setHour(15); flashDrive.setMinute(47); flashDrive.setSecond(26); - + flashDrive.dirInfoSave(); //save the changed data flashDrive.closeFile(); //and yes again, close the file after when you don`t use it printInfo("Done!"); break; -//***************************************************************************************************************************************************** +//***************************************************************************************************************************************************** case 54: //6 printInfo("COMMAND6: Delete File: TEST1.TXT"); // Delete the file named TEST1.TXT flashDrive.setFileName("TEST1.TXT"); //set the file name flashDrive.deleteFile(); //delete file printInfo("Done!"); break; -//***************************************************************************************************************************************************** +//***************************************************************************************************************************************************** case 55: //7 printInfo("COMMAND7: List root directory"); //Print all file names in the current directory while(flashDrive.listDir()){ // reading next file @@ -137,9 +147,47 @@ void loop() { } printInfo("Done!"); break; -//***************************************************************************************************************************************************** +//***************************************************************************************************************************************************** + case 56: //8 + totSect = flashDrive.getTotalSectors(); // get the total sector number + freeSect = flashDrive.getFreeSectors(); // get the available sector number + percentg = map(freeSect,totSect,0,0,100); // convert it to percentage (0-100) + Serial.print("Disk size in bytes: "); + /*if the sector number is more than 8388607 (8388607 * 512 = 4294966784 byte = 4Gb (fits in a 32bit variable) ) + e.g. 8388608 * 512 = 4294967296 byte (32bit variable overflows) */ + if(totSect > 8388607){ + Serial.print(">4Gb"); + } else { + Serial.print(totSect * SECTORSIZE); + } + Serial.print("\tFree space in bytes: "); + if(freeSect > 8388607){ + Serial.print(">4Gb"); + } else { + Serial.print(freeSect * SECTORSIZE); + } + Serial.print("\tDisk usage :"); + Serial.print(percentg); + Serial.print("%"); + switch (flashDrive.getFileSystem()) { //1-FAT12, 2-FAT16, 3-FAT32 + case 1: + Serial.print("\tFAT12 partition"); + break; + case 2: + Serial.print("\tFAT16 partition"); + break; + case 3: + Serial.println("\tFAT32 partition"); + break; + default: + Serial.print("\tNo valid partition"); + break; + } + break; +//***************************************************************************************************************************************************** case 104: //h - printInfo("h:Print this help\n\n1:Create\n2:Append\n3:Read\n4:Read date/time\n5:Modify date/time\n6:Delete\n7:List dir"); + printInfo("h:Print this help\n\n1:Create\n2:Append\n3:Read\n4:Read date/time\n" + "5:Modify date/time\n6:Delete\n7:List dir\n8:Print free space"); break; default: break; @@ -150,9 +198,9 @@ void loop() { }//end loop //Print information -void printInfo(char* info){ +void printInfo(const char* info){ char * infoPtr = info; - int infoLength; + int infoLength = 0; while(*infoPtr){ infoPtr++; infoLength++; diff --git a/examples/basicUsageSoftSerial/basicUsageSoftSerial.ino b/examples/basicUsageSoftSerial/basicUsageSoftSerial.ino index 630da26..d2f0b0c 100644 --- a/examples/basicUsageSoftSerial/basicUsageSoftSerial.ino +++ b/examples/basicUsageSoftSerial/basicUsageSoftSerial.ino @@ -22,6 +22,9 @@ char adatBuffer[255];// max length 255 = 254 char + 1 NULL character char adat[]="Vivamus nec nisl molestie, blandit diam vel, varius mi. Fusce luctus cursus sapien in vulputate.\n"; char adat2[] = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis efficitur ac est eu pharetra. \n"; //.............................................................................................................................. +unsigned long totSect = 0; +unsigned long freeSect = 0; +byte percentg = 0; byte tmpCommand; //used to store data coming from serial port boolean readMore; @@ -30,7 +33,8 @@ void setup() { Serial.begin(115200); mySerial.begin(9600);// Important! First initialize soft serial object and after Ch376 flashDrive.init(); - printInfo("h:Print this help\n\n1:Create\n2:Append\n3:Read\n4:Read date/time\n5:Modify date/time\n6:Delete\n7:List dir"); + printInfo("h:Print this help\n\n1:Create\n2:Append\n3:Read\n4:Read date/time\n" + "5:Modify date/time\n6:Delete\n7:List dir\n8:Print free space"); } void loop() { @@ -38,36 +42,40 @@ void loop() { tmpCommand = Serial.read(); //read incoming bytes from the serial monitor if(((tmpCommand > 48)&&(tmpCommand < 58)) && !flashDrive.checkDrive()){ // if the data is ASCII 0 - 9 and no flash drive are attached printInfo("Attach flash drive first!"); - tmpCommand = 10; // change the command byte + tmpCommand = 10; // change the command byte } switch (tmpCommand) { - + case 49: //1 printInfo("COMMAND1: Create and write data to file : TEST1.TXT"); // Create a file called TEST1.TXT flashDrive.setFileName("TEST1.TXT"); //set the file name flashDrive.openFile(); //open the file - + for(int a = 0; a < 20; a++){ //write text from string(adat) to flash drive 20 times flashDrive.writeFile(adat, strlen(adat)); //string, string length } flashDrive.closeFile(); //at the end, close the file printInfo("Done!"); break; -//***************************************************************************************************************************************************** +//***************************************************************************************************************************************************** case 50: //2 printInfo("COMMAND2: Append data to file: TEST1.TXT"); // Append data to the end of the file. flashDrive.setFileName("TEST1.TXT"); //set the file name flashDrive.openFile(); //open the file flashDrive.moveCursor(CURSOREND); //move the "virtual" cursor at end of the file, with CURSORBEGIN we actually rewrite our old file //flashDrive.moveCursor(flashDrive.getFileSize()); // is almost the same as CURSOREND, because we put our cursor at end of the file - + for(int a = 0; a < 20; a++){ //write text from string(adat) to flash drive 20 times - flashDrive.writeFile(adat2, strlen(adat2)); //string, string length + if(flashDrive.getFreeSectors()){ //check the free space on the drive + flashDrive.writeFile(adat2, strlen(adat2)); //string, string length + } else { + Serial.println("Disk full"); + } } flashDrive.closeFile(); //at the end, close the file printInfo("Done!"); break; -//***************************************************************************************************************************************************** +//***************************************************************************************************************************************************** case 51: //3 printInfo("COMMAND3: Read File: TEST1.TXT"); // Read the contents of this file on the USB disk, and display contents in the Serial Monitor flashDrive.setFileName("TEST1.TXT"); //set the file name @@ -81,13 +89,13 @@ void loop() { flashDrive.closeFile(); //at the end, close the file printInfo("Done!"); break; -//***************************************************************************************************************************************************** +//***************************************************************************************************************************************************** case 52: //4 printInfo("COMMAND4: Read File date/time: TEST1.TXT"); // Read the date and time of file, default 2004.01.01 - 00:00:00 flashDrive.setFileName("TEST1.TXT"); //set the file name flashDrive.openFile(); //open the file //print informations about the file - Serial.println(flashDrive.getFileName()); + Serial.println(flashDrive.getFileName()); Serial.print(flashDrive.getYear()); Serial.print("y\t"); Serial.print(flashDrive.getMonth()); @@ -103,31 +111,31 @@ void loop() { flashDrive.closeFile(); //at the end, close the file printInfo("Done!"); break; -//***************************************************************************************************************************************************** +//***************************************************************************************************************************************************** case 53: //5 printInfo("COMMAND5: Modify File date/time: TEST1.TXT"); // Modify the file date/time and save flashDrive.setFileName("TEST1.TXT"); //set the file name flashDrive.openFile(); //open the file - + flashDrive.setYear(2019); flashDrive.setMonth(2); flashDrive.setDay(24); flashDrive.setHour(15); flashDrive.setMinute(47); flashDrive.setSecond(26); - + flashDrive.dirInfoSave(); //save the changed data flashDrive.closeFile(); //and yes again, close the file after when you don`t use it printInfo("Done!"); break; -//***************************************************************************************************************************************************** +//***************************************************************************************************************************************************** case 54: //6 printInfo("COMMAND6: Delete File: TEST1.TXT"); // Delete the file named TEST1.TXT flashDrive.setFileName("TEST1.TXT"); //set the file name flashDrive.deleteFile(); //delete file printInfo("Done!"); break; -//***************************************************************************************************************************************************** +//***************************************************************************************************************************************************** case 55: //7 printInfo("COMMAND7: List root directory"); //Print all file names in the current directory while(flashDrive.listDir()){ // reading next file @@ -139,9 +147,47 @@ void loop() { } printInfo("Done!"); break; -//***************************************************************************************************************************************************** +//***************************************************************************************************************************************************** + case 56: //8 + totSect = flashDrive.getTotalSectors(); // get the total sector number + freeSect = flashDrive.getFreeSectors(); // get the available sector number + percentg = map(freeSect,totSect,0,0,100); // convert it to percentage (0-100) + Serial.print("Disk size in bytes: "); + /*if the sector number is more than 8388607 (8388607 * 512 = 4294966784 byte = 4Gb (fits in a 32bit variable) ) + e.g. 8388608 * 512 = 4294967296 byte (32bit variable overflows) */ + if(totSect > 8388607){ + Serial.print(">4Gb"); + } else { + Serial.print(totSect * SECTORSIZE); + } + Serial.print("\tFree space in bytes: "); + if(freeSect > 8388607){ + Serial.print(">4Gb"); + } else { + Serial.print(freeSect * SECTORSIZE); + } + Serial.print("\tDisk usage :"); + Serial.print(percentg); + Serial.print("%"); + switch (flashDrive.getFileSystem()) { //1-FAT12, 2-FAT16, 3-FAT32 + case 1: + Serial.print("\tFAT12 partition"); + break; + case 2: + Serial.print("\tFAT16 partition"); + break; + case 3: + Serial.println("\tFAT32 partition"); + break; + default: + Serial.print("\tNo valid partition"); + break; + } + break; +//***************************************************************************************************************************************************** case 104: //h - printInfo("h:Print this help\n\n1:Create\n2:Append\n3:Read\n4:Read date/time\n5:Modify date/time\n6:Delete\n7:List dir"); + printInfo("h:Print this help\n\n1:Create\n2:Append\n3:Read\n4:Read date/time\n" + "5:Modify date/time\n6:Delete\n7:List dir\n8:Print free space"); break; default: break; @@ -152,9 +198,9 @@ void loop() { }//end loop //Print information -void printInfo(char* info){ +void printInfo(const char* info){ char * infoPtr = info; - int infoLength; + int infoLength = 0; while(*infoPtr){ infoPtr++; infoLength++; diff --git a/examples/sortDate/sortDate.ino b/examples/sortDate/sortDate.ino new file mode 100644 index 0000000..910b052 --- /dev/null +++ b/examples/sortDate/sortDate.ino @@ -0,0 +1,120 @@ +/*------------------------------------------------------------------------------------------------------------------ + * Author: György Kovács | + * Created: 26 Sep 2019 | + * Description: Finding the oldest file, it can be useful e.g. writing log files to drive and | + * if the flash drive becomes full then we can delete the oldest. | + *------------------------------------------------------------------------------------------------------------------ + */ + + +#include + +//.............................................................................................................................. +// Connect to SPI port: MISO, MOSI, SCK +Ch376msc flashDrive(10, 9); // chipSelect, busy pins (use this if no other device are attached to SPI port(MISO pin used as interrupt)) + +//If the SPI port shared with other devices e.g SD card, display, etc. remove from comment the code below and put the code above in a comment +//Ch376msc flashDrive(10, 9, 8); // chipSelect, busy, interrupt pins +//.............................................................................................................................. + +//.............................................................................................................................. +char fname[12] = "TEST1.TXT"; +char adat[] = "Lorem ipsum dolor sit amet"; + +int fyear = 0; +int fmonth = 0; +int fday = 0; +int fhour = 0; +int fminute = 0; +int fsecond = 0; +unsigned long oldUnTime = 0; + + + +void setup() { + Serial.begin(115200); + //Read more about randomSeed at https://www.arduino.cc/reference/en/language/functions/random-numbers/randomseed/ + randomSeed(analogRead(0)); + flashDrive.init(); + makeFiles(); // create 10 files on the flash drive + + while(flashDrive.listDir()){ // read root directory + if((convUnixTime() < oldUnTime) || !oldUnTime){ //looking for the oldest file or change the '<' symbol to '>' + updateOldestFile(); // if you looking for the newest file + }//end if file is older + }//end while + printFileData(); // print the oldest file name in to serial terminal +}//end setup + +void loop() { + // do nothing +} //end loop + +unsigned long convUnixTime(){ // calculate "quasi" Unix time without taking into account leap years + // Unix time is the number of seconds that have elapsed since 1970.01.01 00:00:00 + // for the multipliers check the link https://www.epochconverter.com/ + unsigned long unxTime; + int yyr = flashDrive.getYear(); + yyr -= 1970; //elapsed years since 1970 + unxTime = (yyr * 31556926UL); + unxTime += (flashDrive.getMonth() * 2629743UL); + unxTime += (flashDrive.getDay() * 86400UL); + unxTime += (flashDrive.getHour() * 3600UL); + unxTime += (flashDrive.getMinute() * 60UL); + unxTime += flashDrive.getSecond(); + return unxTime; +} + +void updateOldestFile(){ + fyear = flashDrive.getYear(); + fmonth = flashDrive.getMonth(); + fday = flashDrive.getDay(); + fhour = flashDrive.getHour(); + fminute = flashDrive.getMinute(); + fsecond = flashDrive.getSecond(); + strcpy(fname,flashDrive.getFileName()); //copy file name to fname variable + oldUnTime = convUnixTime(); // update the oldest time variable +} + +void printFileData(){ // Print data to the serial terminal + Serial.print("The oldest file is:\t"); + Serial.print(fname); + Serial.print(' '); + Serial.print(fyear); + Serial.print('.'); + Serial.print(fmonth); + Serial.print('.'); + Serial.print(fday); + Serial.print(' '); + Serial.print(fhour); + Serial.print(':'); + Serial.print(fminute); + Serial.print(':'); + Serial.println(fsecond); +} + +void makeFiles(){ + for(byte a = 0; a < 10; a++){ + fname[4] = (char)(a+0x30);//change the number in the file name(a + ASCII hex number(0)) + Serial.println(fname); + flashDrive.setFileName(fname); + flashDrive.openFile(); + flashDrive.writeFile(adat, strlen(adat)); + flashDrive.closeFile(); + + flashDrive.setFileName(fname); + flashDrive.openFile(); + + flashDrive.setYear(random(1990, 2020)); // generate and set random year + flashDrive.setMonth(random(1, 12)); // generate and set random month + flashDrive.setDay(random(1, 30)); // generate and set random day + flashDrive.setHour(random(0, 23)); // generate and set random hour + flashDrive.setMinute(random(0, 59)); // generate and set random minute + flashDrive.setSecond(random(0, 59)); // generate and set random second + + flashDrive.dirInfoSave(); //save the changed data + flashDrive.closeFile(); + + } + +} diff --git a/keywords.txt b/keywords.txt index a236418..be9214f 100644 --- a/keywords.txt +++ b/keywords.txt @@ -23,6 +23,8 @@ readFile KEYWORD2 writeFile KEYWORD2 checkDrive KEYWORD2 +getFreeSectors KEYWORD2 +getTotalSectors KEYWORD2 getFileSize KEYWORD2 getYear KEYWORD2 getMonth KEYWORD2 @@ -31,6 +33,7 @@ getHour KEYWORD2 getMinute KEYWORD2 getSecond KEYWORD2 getStatus KEYWORD2 +getFileSystem KEYWORD2 getFileName KEYWORD2 getFileSizeStr KEYWORD2 getDeviceStatus KEYWORD2 @@ -47,3 +50,6 @@ setSecond KEYWORD2 ####################################### # Constants ####################################### +CURSORBEGIN LITERAL1 +CURSOREND LITERAL1 +SECTORSIZE LITERAL1 diff --git a/library.properties b/library.properties index 5791c8b..dec2997 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Ch376msc -version=1.3.1 +version=1.4.0 author=György Kovács maintainer=György Kovács sentence=A library for CH376 file manage control chip. diff --git a/src/Ch376msc.cpp b/src/Ch376msc.cpp index c57fea1..2c7aff2 100644 --- a/src/Ch376msc.cpp +++ b/src/Ch376msc.cpp @@ -4,7 +4,7 @@ * Created on: Feb 25, 2019 * Author: György Kovács * - * TODO: Handle if the drive becomes full 24.05.2019 + * * */ @@ -29,7 +29,7 @@ Ch376msc::Ch376msc(Stream &sUsb) { // @suppress("Class members should be properl //with SPI, MISO as INT pin(the SPI is only available for CH376) Ch376msc::Ch376msc(uint8_t spiSelect, uint8_t busy){ // @suppress("Class members should be properly initialized") _interface = SPII; - _intPin = MISO; // use the SPI MISO for interrupt, JUST if no other device is using the SPI!! + _intPin = MISO; // use the SPI MISO for interrupt JUST if no other device is using the SPI!! _spiChipSelect = spiSelect; _spiBusy = busy; _speed = 0; @@ -44,7 +44,7 @@ Ch376msc::Ch376msc(uint8_t spiSelect, uint8_t busy, uint8_t intPin){ // @suppres } Ch376msc::~Ch376msc() { - // TODO Auto-generated destructor stub + // Auto-generated destructor stub } ///////////////////////////////////////////////////////////////// @@ -190,9 +190,11 @@ bool Ch376msc::checkDrive(){ //always call this function to you know is it any m switch(_tmpReturn){ // 0x15 device attached, 0x16 device disconnect case ANSW_USB_INT_CONNECT: _deviceAttached = true; + rdDiskInfo(); break; case ANSW_USB_INT_DISCONNECT: _deviceAttached = false; + memset(&_diskData, 0, sizeof(_diskData));// fill up with NULL disk data container break; }//end switch return _deviceAttached; @@ -238,7 +240,7 @@ uint8_t Ch376msc::dirInfoRead(){ spiEndTransfer(); _tmpReturn = spiWaitInterrupt(); } - rdUsbData(); + rdFatInfo(); return _tmpReturn; } @@ -398,7 +400,7 @@ uint8_t Ch376msc::listDir(){ moreFiles = false;// no more files in the directory }//end if if(_answer == ANSW_USB_INT_DISK_READ){ - rdUsbData(); // read data to fatInfo buffer + rdFatInfo(); // read data to fatInfo buffer fileProcesSTM = NEXT; } break; @@ -437,12 +439,12 @@ uint8_t Ch376msc::readFile(char* buffer, uint8_t b_num){ //buffer for reading, b switch (fileProcesSTM) { case REQUEST: byteForRequest = b_num - _byteCounter; - if(_sectorCounter == 512){ //if one sector has read out + if(_sectorCounter == SECTORSIZE){ //if one sector has read out _sectorCounter = 0; fileProcesSTM = NEXT; break; - } else if((_sectorCounter + byteForRequest) > 512){ - byteForRequest = 512 - _sectorCounter; + } else if((_sectorCounter + byteForRequest) > SECTORSIZE){ + byteForRequest = SECTORSIZE - _sectorCounter; } //////////////// _answer = reqByteRead(byteForRequest); @@ -482,8 +484,12 @@ uint8_t Ch376msc::readFile(char* buffer, uint8_t b_num){ //buffer for reading, b uint8_t Ch376msc::writeFile(char* buffer, uint8_t b_num){ _fileWrite = true; // read mode, required for close procedure _byteCounter = 0; + bool diskFree = true; //free space on a disk bool bufferFull = true; //continue to write while there is data in the temporary buffer - //_tmpReturn = 0; //ready for next chunk of data + if(_diskData.freeSector == 0){ + diskFree = false; + return diskFree; + } if(_answer == ANSW_ERR_MISS_FILE){ // no file with given name _answer = fileCreate(); }//end if CREATED @@ -515,11 +521,17 @@ uint8_t Ch376msc::writeFile(char* buffer, uint8_t b_num){ } break; case NEXT: - _answer = byteWrGo(); - if(_answer == ANSW_USB_INT_SUCCESS){ - fileProcesSTM = REQUEST; - } else if(_byteCounter != b_num ){ - fileProcesSTM = READWRITE; + if(_diskData.freeSector > 0){ + _diskData.freeSector --; + _answer = byteWrGo(); + if(_answer == ANSW_USB_INT_SUCCESS){ + fileProcesSTM = REQUEST; + } else if(_byteCounter != b_num ){ + fileProcesSTM = READWRITE; + } + } else { // if disk is full + fileProcesSTM = DONE; + diskFree = false; } break; case DONE: @@ -532,11 +544,11 @@ uint8_t Ch376msc::writeFile(char* buffer, uint8_t b_num){ }//end while }// end file created - return true;//not finished + return diskFree; } ///////////////////////////////////////////////////////////////// -void Ch376msc::rdUsbData(){ +void Ch376msc::rdFatInfo(){ uint8_t fatInfBuffer[32]; //temporary buffer for raw file FAT info uint8_t dataLength; if(_interface == UART){ @@ -659,9 +671,9 @@ uint8_t Ch376msc::moveCursor(uint32_t position){ uint8_t tmpReturn = 0; fSizeContainer cPosition; //unsigned long union if(position > _fileData.size){ //fix for moveCursor issue #3 Sep 17, 2019 - _sectorCounter = _fileData.size % 512; + _sectorCounter = _fileData.size % SECTORSIZE; } else { - _sectorCounter = position % 512; + _sectorCounter = position % SECTORSIZE; } cPosition.value = position; if(_interface == SPII) spiBeginTransfer(); @@ -689,4 +701,35 @@ void Ch376msc::sendFilename(){ write((uint8_t)0x00); // ez a lezaro 0 jel if(_interface == SPII) spiEndTransfer(); } - +///////////////////////////////////////////////////////////////// +void Ch376msc::rdDiskInfo(){ + uint8_t dataLength; + uint8_t tmpReturn; + uint8_t tmpdata[9]; + if(_interface == UART){ + sendCommand(CMD_DISK_QUERY); + tmpReturn= readSerDataUSB(); + if(tmpReturn == ANSW_USB_INT_SUCCESS){ + sendCommand(CMD_RD_USB_DATA0); + dataLength = readSerDataUSB(); + for(uint8_t s =0;s < dataLength;s++){ + tmpdata[s] = readSerDataUSB();// fill up temporary buffer + }//end for + }//end if success + } else { + spiBeginTransfer(); + sendCommand(CMD_DISK_QUERY); + spiEndTransfer(); + tmpReturn= spiWaitInterrupt(); + if(tmpReturn == ANSW_USB_INT_SUCCESS){ + spiBeginTransfer(); + sendCommand(CMD_RD_USB_DATA0); + dataLength = spiReadData(); + for(uint8_t s =0;s < dataLength;s++){ + tmpdata[s] = spiReadData();// fill up temporary buffer + }//end for + spiEndTransfer(); + }//end if success + }//end if UART + memcpy ( &_diskData, &tmpdata, sizeof(tmpdata) ); //copy raw data to structured variable +} diff --git a/src/Ch376msc.h b/src/Ch376msc.h index a8e44a1..92684b9 100644 --- a/src/Ch376msc.h +++ b/src/Ch376msc.h @@ -27,6 +27,14 @@ ****************************************************** * Versions: * * **************************************************** + * v1.4.0 Sep 26, 2019 + * - new functions + * getTotalSectors() - returns a unsigned long number, total sectors on the drive + * getFreeSectors() - returns a unsigned long number, free sectors on the drive + * getFileSystem() - returns a byte number, 0x01-FAT12, 0x02-FAT16, 0x03-FAT32 + * - updated example files with a new functions + * - new example file, seraching the oldest/newest file on the flash drive + * **************************************************** * v1.3 Sep 17, 2019 * -bug fix for moveCursor issue #3 * https://github.com/djuseeq/Ch376msc/issues/3 @@ -55,7 +63,6 @@ #define TIMEOUT 2000 // waiting for data from CH #define SPICLKRATE 125000 //Clock rate 125kHz SystemClk DIV2 MAX // max 8000000 (8MHz)on UNO, Mega (16 000 000 / 2 = 8 000 000) -#define TEST // for dev class Ch376msc { @@ -86,6 +93,8 @@ class Ch376msc { //set/get //uint32_t getComSpeed(); + uint32_t getFreeSectors(); + uint32_t getTotalSectors(); uint32_t getFileSize(); uint16_t getYear(); uint16_t getMonth(); @@ -94,6 +103,7 @@ class Ch376msc { uint16_t getMinute(); uint16_t getSecond(); uint8_t getStatus(); + uint8_t getFileSystem(); char* getFileName(); char* getFileSizeStr(); bool getDeviceStatus(); // usb device mounted, unmounted @@ -131,13 +141,14 @@ class Ch376msc { uint8_t dirInfoRead(); uint8_t setMode(uint8_t mode); - void rdUsbData(); + void rdFatInfo(); void setSpeed(); void sendCommand(uint8_t b_parancs); void sendFilename(); void writeFatData(); void constructDate(uint16_t value, uint8_t ymd); void constructTime(uint16_t value, uint8_t hms); + void rdDiskInfo(); ///////Global Variables/////////////////////////////// bool _fileWrite = false; // read or write mode, needed for close operation @@ -161,6 +172,7 @@ class Ch376msc { fileProcessENUM fileProcesSTM = REQUEST; fatFileInfo _fileData; + diskInfo _diskData; };//end class diff --git a/src/CommDef.h b/src/CommDef.h index 6aa4399..78aa414 100644 --- a/src/CommDef.h +++ b/src/CommDef.h @@ -3,6 +3,7 @@ #define MODE_HOST_2 0x07 #define CURSORBEGIN 0x00000000 #define CURSOREND 0xFFFFFFFF +#define SECTORSIZE 512 ////////////Commands///////// #define CMD_GET_IC_VER 0x01 @@ -286,3 +287,10 @@ enum fileProcessENUM { // for file read/write state machine uint16_t startCl;//2 uint32_t size;//4 }; + /////////////// + struct diskInfo{ //disk information + uint32_t totalSector; //the number of total sectors (low byte first) + uint32_t freeSector; //the number of free sectors (low byte first) + uint8_t diskFat; //FAT type: 0x01-FAT12, 0x02-FAT16, 0x03-FAT32 + }; + diff --git a/src/SetGet.cpp b/src/SetGet.cpp index 10db491..945d6f5 100644 --- a/src/SetGet.cpp +++ b/src/SetGet.cpp @@ -200,5 +200,15 @@ void Ch376msc::constructTime(uint16_t value, uint8_t hms){ }//end switch _fileData.modTime = hour + minute + second; } - - +////////////////////////////////////////////////////// +uint32_t Ch376msc::getTotalSectors(){ // disk(partition?) size in bytes = totalSector * SECTORSIZE + return _diskData.totalSector; +} +////////////////////////////////////////////////////// +uint32_t Ch376msc::getFreeSectors(){ // total free bytes = freeSector * SECTORSIZE + return _diskData.freeSector; +} +////////////////////////////////////////////////////// +uint8_t Ch376msc::getFileSystem(){ //0x01-FAT12, 0x02-FAT16, 0x03-FAT32 + return _diskData.diskFat; +}