Paul and others, while waiting for 1.57 to be released and hopefully time to merge in more stuff, I am playing around with a few ideas:
For example with SD library:
There is a comment in the SDClass that says:
Code:
public: // allow access, so users can mix SD & SdFat APIs
SDFAT_BASE sdfs;
Which gives us a little bit of ability to mix and match.... Mainly for things like how to use SPI1 instead of SPI.
But this does not allow us to do much with mix and match of the stuff associated with the underlying files. For example suppose I want to pre-allocate 40K or 400K. when I open the file.
I can do it, but then I can not use it as a File object...
That is we can do:
Code:
FsFile fsfile = SD.sdfs.open("/prealloc.txt", O_RDWR | O_CREAT);
if (fsfile) {
fsfile.preAllocate(40*1024);
...
But currently there is no way then to convert this to a File object.
I have experimented with 4 different ways:
a) Punt (what we do now)
b) Duplicate the SDFile class to allow me to wrap it... This is more or less what the USBFilesystem class is doing today.. Just another wrapper of FsFile objects.
c) add a method to the SDClass that does this for us. For example I have this in experiment
Code:
inline static File FileFromSDFile(SDFAT_FILE &file) {
if (file) return File(new SDFile(file));
return File();
}
I changed the open method to use it:
Code:
File open(const char *filepath, uint8_t mode = FILE_READ) {
oflag_t flags = O_READ;
if (mode == FILE_WRITE) flags = O_RDWR | O_CREAT | O_AT_END;
else if (mode == FILE_WRITE_BEGIN) flags = O_RDWR | O_CREAT;
SDFAT_FILE file = sdfs.open(filepath, flags);
return FileFromSDFile(file);
}
Then in my sketch I had:
Code:
File our_file;
FsFile fsfile = SD.sdfs.open("/prealloc.txt", O_RDWR | O_CREAT);
if (fsfile) {
fsfile.preAllocate(40*1024);
our_file = SD.FileFromSDFile(fsfile);
}
if (our_file) {
our_file.write("Our preallocated file");
our_file.close();
}
And it worked.
d) Like c) except don't touch SDClass instead change SDFile to make it's constructor public instead of private.
Then example code would look like:
Code:
File our_file;
FsFile fsfile = SD.sdfs.open("/prealloc.txt", O_RDWR | O_CREAT);
if (fsfile) {
fsfile.preAllocate(40*1024);
our_file = new SDFile(fsfile);
}
if (our_file) {
our_file.write("Our preallocated file");
our_file.close();
}
Given c) or d) we could potentially eliminate the MSCFILE stuff within USBHost.
Second experiment:
Keep a linked list of SDClass objects:
Code:
SDClass() {
_nextSD = s_firstSD;
s_firstSD = this;
}
~SDClass() {
// unlink us... I expect rairly called.
if (s_firstSD == this) s_firstSD = _nextSD;
else {
SDClass *psd = s_firstSD;
while (psd && (psd->_nextSD != this)) psd = psd->_nextSD;
if (psd) psd->_nextSD = _nextSD;
}
}
Why? Good question, just starting to play
But one goal with the MTP stuff is to hopefully be able to process SD insertion and removals, without user code needing to do anything special.
I have a hacked up version of MTP_Teensy, that tries to do it by: knowing we have SD.h included in our sketch and then add method override to object:
Code:
#if defined(__SD_H__)
uint32_t addFilesystem(SDClass &disk, const char *diskname) {
printStream_->println("Add **SDClass** file system");
return addFilesystem(disk, diskname, MTP_FSTYPE_SD);
}
#endif
That we then know that you are adding an SD object and then I have other code that uses this doing the mtp loop code... But it is error prone as SD.h has to be included before MTP_Teensy is included as
__has_include() has issues...
But another approach is for me to have a way to know if the FS you are adding is an SD object...
Another way would be then to walk this chain of SD objects and see if it is one of them...
For this experiment, I added method to SDClass:
Code:
static bool isSDFS(FS *pfs) {
SDClass *psd = s_firstSD;
while (psd && (psd != pfs)) psd = psd->_nextSD;
return (psd != nullptr);
}
Overhead of this, I don't think will be much as most sketches maybe have one or two, maybe up to 4-5 SD objects. I doubt the destructor code will be called...
Again just trying a few experiments.
Thoughts?