HEAVY speed improvement in SD/FAT write.
This commit is contained in:
@@ -50,5 +50,17 @@ typedef struct
|
|||||||
*/
|
*/
|
||||||
void (*rseek)(const int16_t offset);
|
void (*rseek)(const int16_t offset);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** Flush the data buffer if it's dirty.
|
||||||
|
*
|
||||||
|
* Should be called after each sequence of writes,
|
||||||
|
* to avoid data loss.
|
||||||
|
*
|
||||||
|
* Tmplementations that do not need this should provide
|
||||||
|
* a no-op function.
|
||||||
|
*/
|
||||||
|
void (*flush)(void);
|
||||||
|
|
||||||
} BLOCKDEV;
|
} BLOCKDEV;
|
||||||
|
|
||||||
|
|||||||
+99
-72
@@ -24,7 +24,7 @@ uint16_t next_clu(const FAT16* fat, uint16_t cluster);
|
|||||||
uint32_t clu_offs(const FAT16* fat, uint16_t cluster, uint32_t addr);
|
uint32_t clu_offs(const FAT16* fat, uint16_t cluster, uint32_t addr);
|
||||||
|
|
||||||
/** Read a file entry from directory (dir starting cluster, entry number) */
|
/** Read a file entry from directory (dir starting cluster, entry number) */
|
||||||
void open_file(const FAT16* fat, FAT16_FILE* file, const uint16_t dir_cluster, const uint16_t num);
|
void open_file(const FAT16* fat, FFILE* file, const uint16_t dir_cluster, const uint16_t num);
|
||||||
|
|
||||||
/** Allocate and chain new cluster to a chain starting at given cluster */
|
/** Allocate and chain new cluster to a chain starting at given cluster */
|
||||||
bool append_cluster(const FAT16* fat, const uint16_t clu);
|
bool append_cluster(const FAT16* fat, const uint16_t clu);
|
||||||
@@ -42,7 +42,7 @@ bool free_cluster_chain(const FAT16* fat, uint16_t clu);
|
|||||||
* Check if there is already a file of given RAW name
|
* Check if there is already a file of given RAW name
|
||||||
* Raw name - name as found on disk, not "display name".
|
* Raw name - name as found on disk, not "display name".
|
||||||
*/
|
*/
|
||||||
bool dir_find_file_raw(FAT16_FILE* dir, const char* fname);
|
bool dir_find_file_raw(FFILE* dir, const char* fname);
|
||||||
|
|
||||||
/** Write a value into FAT */
|
/** Write a value into FAT */
|
||||||
void write_fat(const FAT16* fat, const uint16_t cluster, const uint16_t value);
|
void write_fat(const FAT16* fat, const uint16_t cluster, const uint16_t value);
|
||||||
@@ -276,10 +276,10 @@ bool free_cluster_chain(const FAT16* fat, uint16_t clu)
|
|||||||
* Check if there is already a file of given RAW name
|
* Check if there is already a file of given RAW name
|
||||||
* Raw name - name as found on disk, not "display name".
|
* Raw name - name as found on disk, not "display name".
|
||||||
*/
|
*/
|
||||||
bool dir_find_file_raw(FAT16_FILE* dir, const char* fname)
|
bool dir_find_file_raw(FFILE* dir, const char* fname)
|
||||||
{
|
{
|
||||||
// rewind
|
// rewind
|
||||||
fat16_first(dir);
|
ff_first(dir);
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
@@ -299,7 +299,7 @@ bool dir_find_file_raw(FAT16_FILE* dir, const char* fname)
|
|||||||
return true; // file is already open.
|
return true; // file is already open.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (fat16_next(dir));
|
while (ff_next(dir));
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -311,7 +311,7 @@ bool dir_find_file_raw(FAT16_FILE* dir, const char* fname)
|
|||||||
* dir_cluster ... directory start cluster
|
* dir_cluster ... directory start cluster
|
||||||
* num ... entry number in the directory
|
* num ... entry number in the directory
|
||||||
*/
|
*/
|
||||||
void open_file(const FAT16* fat, FAT16_FILE* file, const uint16_t dir_cluster, const uint16_t num)
|
void open_file(const FAT16* fat, FFILE* file, const uint16_t dir_cluster, const uint16_t num)
|
||||||
{
|
{
|
||||||
// Resolve starting address
|
// Resolve starting address
|
||||||
uint32_t addr;
|
uint32_t addr;
|
||||||
@@ -397,7 +397,7 @@ void open_file(const FAT16* fat, FAT16_FILE* file, const uint16_t dir_cluster, c
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Init cursors
|
// Init cursors
|
||||||
fat16_seek(file, 0);
|
ff_seek(file, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -406,7 +406,7 @@ void open_file(const FAT16* fat, FAT16_FILE* file, const uint16_t dir_cluster, c
|
|||||||
* Write information into a file header.
|
* Write information into a file header.
|
||||||
* "file" is an open handle.
|
* "file" is an open handle.
|
||||||
*/
|
*/
|
||||||
void write_file_header(FAT16_FILE* file, const char* fname_raw, const uint8_t attribs, const uint16_t clu_start)
|
void write_file_header(FFILE* file, const char* fname_raw, const uint8_t attribs, const uint16_t clu_start)
|
||||||
{
|
{
|
||||||
const BLOCKDEV* dev = file->fat->dev;
|
const BLOCKDEV* dev = file->fat->dev;
|
||||||
|
|
||||||
@@ -442,7 +442,7 @@ void write_file_header(FAT16_FILE* file, const char* fname_raw, const uint8_t at
|
|||||||
// =============== PUBLIC FUNCTION IMPLEMENTATIONS =================
|
// =============== PUBLIC FUNCTION IMPLEMENTATIONS =================
|
||||||
|
|
||||||
/** Initialize a FAT16 handle */
|
/** Initialize a FAT16 handle */
|
||||||
bool fat16_init(const BLOCKDEV* dev, FAT16* fat)
|
bool ff_init(const BLOCKDEV* dev, FAT16* fat)
|
||||||
{
|
{
|
||||||
const uint32_t bs_a = find_bs(dev);
|
const uint32_t bs_a = find_bs(dev);
|
||||||
|
|
||||||
@@ -464,7 +464,7 @@ bool fat16_init(const BLOCKDEV* dev, FAT16* fat)
|
|||||||
* Move file cursor to a position relative to file start
|
* Move file cursor to a position relative to file start
|
||||||
* Allows seek past end of file, will allocate new cluster if needed.
|
* Allows seek past end of file, will allocate new cluster if needed.
|
||||||
*/
|
*/
|
||||||
bool fat16_seek(FAT16_FILE* file, uint32_t addr)
|
bool ff_seek(FFILE* file, uint32_t addr)
|
||||||
{
|
{
|
||||||
const FAT16* fat = file->fat;
|
const FAT16* fat = file->fat;
|
||||||
|
|
||||||
@@ -512,7 +512,7 @@ bool fat16_seek(FAT16_FILE* file, uint32_t addr)
|
|||||||
* Check if file is a regular file or directory entry.
|
* Check if file is a regular file or directory entry.
|
||||||
* Those files can be shown to user.
|
* Those files can be shown to user.
|
||||||
*/
|
*/
|
||||||
bool fat16_is_regular(const FAT16_FILE* file)
|
bool ff_is_regular(const FFILE* file)
|
||||||
{
|
{
|
||||||
switch (file->type)
|
switch (file->type)
|
||||||
{
|
{
|
||||||
@@ -530,7 +530,7 @@ bool fat16_is_regular(const FAT16_FILE* file)
|
|||||||
|
|
||||||
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||||
|
|
||||||
uint16_t fat16_read(FAT16_FILE* file, void* target, uint16_t len)
|
uint16_t ff_read(FFILE* file, void* target, uint16_t len)
|
||||||
{
|
{
|
||||||
if (file->cur_abs == 0xFFFF)
|
if (file->cur_abs == 0xFFFF)
|
||||||
return 0; // file at the end already
|
return 0; // file at the end already
|
||||||
@@ -580,14 +580,23 @@ uint16_t fat16_read(FAT16_FILE* file, void* target, uint16_t len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool fat16_write(FAT16_FILE* file, void* source, uint32_t len)
|
bool ff_write_str(FFILE* file, const char* source)
|
||||||
|
{
|
||||||
|
uint16_t len = 0;
|
||||||
|
for (; source[len] != 0; len++);
|
||||||
|
|
||||||
|
return ff_write(file, source, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool ff_write(FFILE* file, const void* source, uint32_t len)
|
||||||
{
|
{
|
||||||
const FAT16* fat = file->fat;
|
const FAT16* fat = file->fat;
|
||||||
const BLOCKDEV* dev = fat->dev;
|
const BLOCKDEV* dev = fat->dev;
|
||||||
|
|
||||||
|
|
||||||
if (file->cur_abs == 0xFFFF)
|
if (file->cur_abs == 0xFFFF)
|
||||||
return false; // file at the end already
|
return false; // file past it's end (rare)
|
||||||
|
|
||||||
// Attempt to write past end of file
|
// Attempt to write past end of file
|
||||||
if (file->cur_rel + len >= file->size)
|
if (file->cur_rel + len >= file->size)
|
||||||
@@ -596,14 +605,14 @@ bool fat16_write(FAT16_FILE* file, void* source, uint32_t len)
|
|||||||
|
|
||||||
// Seek to the last position
|
// Seek to the last position
|
||||||
// -> fseek will allocate clusters
|
// -> fseek will allocate clusters
|
||||||
if (!fat16_seek(file, pos_start + len))
|
if (!ff_seek(file, pos_start + len))
|
||||||
return false; // error in seek
|
return false; // error in seek
|
||||||
|
|
||||||
// Write starts beyond EOF - creating a zero-filled "hole"
|
// Write starts beyond EOF - creating a zero-filled "hole"
|
||||||
if (file->cur_rel > file->size)
|
if (pos_start > file->size + 1)
|
||||||
{
|
{
|
||||||
// Seek to the end of valid data
|
// Seek to the end of valid data
|
||||||
fat16_seek(file, file->size);
|
ff_seek(file, file->size);
|
||||||
|
|
||||||
// fill space between EOF and start-of-write with zeros
|
// fill space between EOF and start-of-write with zeros
|
||||||
uint32_t fill = pos_start - file->size;
|
uint32_t fill = pos_start - file->size;
|
||||||
@@ -631,22 +640,34 @@ bool fat16_write(FAT16_FILE* file, void* source, uint32_t len)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save new size
|
// Store new size
|
||||||
fat16_resize(file, pos_start + len);
|
file->size = pos_start + len;
|
||||||
|
|
||||||
// Seek back to where it was before
|
// Seek back to where it was before
|
||||||
fat16_seek(file, pos_start);
|
ff_seek(file, pos_start);
|
||||||
} // (end zerofill)
|
} // (end zerofill)
|
||||||
|
|
||||||
|
|
||||||
// write the data
|
// write the data
|
||||||
while (len > 0)
|
while (len > 0)
|
||||||
{
|
{
|
||||||
// How much can be stored in this cluster
|
|
||||||
const uint16_t chunk = MIN(fat->bs.bytes_per_cluster - file->cur_ofs, len);
|
|
||||||
|
|
||||||
// store the chunk
|
|
||||||
dev->seek(file->cur_abs);
|
dev->seek(file->cur_abs);
|
||||||
|
uint16_t chunk;
|
||||||
|
|
||||||
|
if (len == 1)
|
||||||
|
{
|
||||||
|
dev->write(*((uint8_t*)source));
|
||||||
|
file->cur_abs++;
|
||||||
|
file->cur_rel++;
|
||||||
|
file->cur_ofs++;
|
||||||
|
chunk = 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// How much can be stored in this cluster
|
||||||
|
chunk = MIN(fat->bs.bytes_per_cluster - file->cur_ofs, len);
|
||||||
|
|
||||||
dev->store(source, chunk);
|
dev->store(source, chunk);
|
||||||
|
|
||||||
// advance cursors
|
// advance cursors
|
||||||
@@ -656,6 +677,7 @@ bool fat16_write(FAT16_FILE* file, void* source, uint32_t len)
|
|||||||
|
|
||||||
// Pointer arith!
|
// Pointer arith!
|
||||||
source += chunk; // advance the source pointer
|
source += chunk; // advance the source pointer
|
||||||
|
}
|
||||||
|
|
||||||
// detect cluster overflow
|
// detect cluster overflow
|
||||||
if (file->cur_ofs >= fat->bs.bytes_per_cluster)
|
if (file->cur_ofs >= fat->bs.bytes_per_cluster)
|
||||||
@@ -676,7 +698,7 @@ bool fat16_write(FAT16_FILE* file, void* source, uint32_t len)
|
|||||||
|
|
||||||
|
|
||||||
/** Open next file in the directory */
|
/** Open next file in the directory */
|
||||||
bool fat16_next(FAT16_FILE* file)
|
bool ff_next(FFILE* file)
|
||||||
{
|
{
|
||||||
const FAT16* fat = file->fat;
|
const FAT16* fat = file->fat;
|
||||||
const BLOCKDEV* dev = fat->dev;
|
const BLOCKDEV* dev = fat->dev;
|
||||||
@@ -700,7 +722,7 @@ bool fat16_next(FAT16_FILE* file)
|
|||||||
|
|
||||||
|
|
||||||
/** Open previous file in the directory */
|
/** Open previous file in the directory */
|
||||||
bool fat16_prev(FAT16_FILE* file)
|
bool ff_prev(FFILE* file)
|
||||||
{
|
{
|
||||||
if (file->num == 0)
|
if (file->num == 0)
|
||||||
return false; // first file already
|
return false; // first file already
|
||||||
@@ -712,14 +734,14 @@ bool fat16_prev(FAT16_FILE* file)
|
|||||||
|
|
||||||
|
|
||||||
/** Rewind to first file in directory */
|
/** Rewind to first file in directory */
|
||||||
void fat16_first(FAT16_FILE* file)
|
void ff_first(FFILE* file)
|
||||||
{
|
{
|
||||||
open_file(file->fat, file, file->clu, 0);
|
open_file(file->fat, file, file->clu, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Open a directory denoted by the file. */
|
/** Open a directory denoted by the file. */
|
||||||
bool fat16_opendir(FAT16_FILE* dir)
|
bool ff_opendir(FFILE* dir)
|
||||||
{
|
{
|
||||||
// Don't open non-dirs and "." directory.
|
// Don't open non-dirs and "." directory.
|
||||||
if (!(dir->attribs & FA_DIR) || dir->type == FT_SELF)
|
if (!(dir->attribs & FA_DIR) || dir->type == FT_SELF)
|
||||||
@@ -730,7 +752,7 @@ bool fat16_opendir(FAT16_FILE* dir)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void fat16_root(const FAT16* fat, FAT16_FILE* file)
|
void ff_root(const FAT16* fat, FFILE* file)
|
||||||
{
|
{
|
||||||
open_file(fat, file, 0, 0);
|
open_file(fat, file, 0, 0);
|
||||||
}
|
}
|
||||||
@@ -741,16 +763,16 @@ void fat16_root(const FAT16* fat, FAT16_FILE* file)
|
|||||||
* If file is found, "dir" will contain it's handle.
|
* If file is found, "dir" will contain it's handle.
|
||||||
* Either way, "dir" gets modified and you may need to rewind it afterwards.
|
* Either way, "dir" gets modified and you may need to rewind it afterwards.
|
||||||
*/
|
*/
|
||||||
bool fat16_find(FAT16_FILE* dir, const char* name)
|
bool ff_open(FFILE* dir, const char* name)
|
||||||
{
|
{
|
||||||
char fname[11];
|
char fname[11];
|
||||||
fat16_rawname(name, fname);
|
ff_rawname(name, fname);
|
||||||
return dir_find_file_raw(dir, fname);
|
return dir_find_file_raw(dir, fname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Go through a directory, and "open" first FT_NONE or FT_DELETED file entry. */
|
/** Go through a directory, and "open" first FT_NONE or FT_DELETED file entry. */
|
||||||
bool find_empty_file_slot(FAT16_FILE* file)
|
bool find_empty_file_slot(FFILE* file)
|
||||||
{
|
{
|
||||||
const uint16_t clu = file->clu;
|
const uint16_t clu = file->clu;
|
||||||
const FAT16* fat = file->fat;
|
const FAT16* fat = file->fat;
|
||||||
@@ -795,15 +817,15 @@ bool find_empty_file_slot(FAT16_FILE* file)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool fat16_mkfile(FAT16_FILE* file, const char* name)
|
bool ff_newfile(FFILE* file, const char* name)
|
||||||
{
|
{
|
||||||
// Convert filename to zero padded raw string
|
// Convert filename to zero padded raw string
|
||||||
char fname[11];
|
char fname[11];
|
||||||
fat16_rawname(name, fname);
|
ff_rawname(name, fname);
|
||||||
|
|
||||||
// Abort if file already exists
|
// Abort if file already exists
|
||||||
bool exists = dir_find_file_raw(file, fname);
|
bool exists = dir_find_file_raw(file, fname);
|
||||||
fat16_first(file); // rewind dir
|
ff_first(file); // rewind dir
|
||||||
if (exists)
|
if (exists)
|
||||||
return false; // file already exists in the dir.
|
return false; // file already exists in the dir.
|
||||||
|
|
||||||
@@ -823,15 +845,15 @@ bool fat16_mkfile(FAT16_FILE* file, const char* name)
|
|||||||
* Create a sub-directory of given name.
|
* Create a sub-directory of given name.
|
||||||
* Directory is allocated and populated with entries "." and ".."
|
* Directory is allocated and populated with entries "." and ".."
|
||||||
*/
|
*/
|
||||||
bool fat16_mkdir(FAT16_FILE* file, const char* name)
|
bool ff_mkdir(FFILE* file, const char* name)
|
||||||
{
|
{
|
||||||
// Convert filename to zero padded raw string
|
// Convert filename to zero padded raw string
|
||||||
char fname[11];
|
char fname[11];
|
||||||
fat16_rawname(name, fname);
|
ff_rawname(name, fname);
|
||||||
|
|
||||||
// Abort if file already exists
|
// Abort if file already exists
|
||||||
bool exists = dir_find_file_raw(file, fname);
|
bool exists = dir_find_file_raw(file, fname);
|
||||||
fat16_first(file); // rewind dir
|
ff_first(file); // rewind dir
|
||||||
if (exists)
|
if (exists)
|
||||||
return false; // file already exusts in the dir.
|
return false; // file already exusts in the dir.
|
||||||
|
|
||||||
@@ -854,20 +876,20 @@ bool fat16_mkdir(FAT16_FILE* file, const char* name)
|
|||||||
write_file_header(file, ".. ", FA_DIR, parent_clu);
|
write_file_header(file, ".. ", FA_DIR, parent_clu);
|
||||||
|
|
||||||
// rewind.
|
// rewind.
|
||||||
fat16_first(file);
|
ff_first(file);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char* fat16_disk_label(const FAT16* fat, char* label_out)
|
char* ff_disk_label(const FAT16* fat, char* label_out)
|
||||||
{
|
{
|
||||||
FAT16_FILE first;
|
FFILE first;
|
||||||
fat16_root(fat, &first);
|
ff_root(fat, &first);
|
||||||
|
|
||||||
if (first.type == FT_LABEL)
|
if (first.type == FT_LABEL)
|
||||||
{
|
{
|
||||||
return fat16_dispname(&first, label_out);
|
return ff_dispname(&first, label_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
// find where spaces end
|
// find where spaces end
|
||||||
@@ -890,7 +912,7 @@ char* fat16_disk_label(const FAT16* fat, char* label_out)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char* fat16_dispname(const FAT16_FILE* file, char* disp_out)
|
char* ff_dispname(const FFILE* file, char* disp_out)
|
||||||
{
|
{
|
||||||
// Cannot get name for special files
|
// Cannot get name for special files
|
||||||
if (file->type == FT_NONE || // not-yet-used directory location
|
if (file->type == FT_NONE || // not-yet-used directory location
|
||||||
@@ -940,7 +962,7 @@ char* fat16_dispname(const FAT16_FILE* file, char* disp_out)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char* fat16_rawname(const char* disp_in, char* raw_out)
|
char* ff_rawname(const char* disp_in, char* raw_out)
|
||||||
{
|
{
|
||||||
uint8_t name_c = 0, wr_c = 0;
|
uint8_t name_c = 0, wr_c = 0;
|
||||||
bool filling = false;
|
bool filling = false;
|
||||||
@@ -1014,7 +1036,7 @@ char* fat16_rawname(const char* disp_in, char* raw_out)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
FSAVEPOS fat16_savepos(const FAT16_FILE* file)
|
FSAVEPOS ff_savepos(const FFILE* file)
|
||||||
{
|
{
|
||||||
FSAVEPOS fsp;
|
FSAVEPOS fsp;
|
||||||
fsp.clu = file->clu;
|
fsp.clu = file->clu;
|
||||||
@@ -1024,28 +1046,31 @@ FSAVEPOS fat16_savepos(const FAT16_FILE* file)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void fat16_reopen(FAT16_FILE* file, const FSAVEPOS* pos)
|
void ff_reopen(FFILE* file, const FSAVEPOS* pos)
|
||||||
{
|
{
|
||||||
open_file(file->fat, file, pos->clu, pos->num);
|
open_file(file->fat, file, pos->clu, pos->num);
|
||||||
fat16_seek(file, pos->cur_rel);
|
ff_seek(file, pos->cur_rel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Write new file size (also to the disk). Does not allocate clusters. */
|
void ff_flush_file(FFILE* file)
|
||||||
void fat16_resize(FAT16_FILE* file, uint32_t size)
|
|
||||||
{
|
{
|
||||||
const FAT16* fat = file->fat;
|
const FAT16* fat = file->fat;
|
||||||
const BLOCKDEV* dev = file->fat->dev;
|
const BLOCKDEV* dev = file->fat->dev;
|
||||||
|
|
||||||
|
// Store open page
|
||||||
|
dev->flush();
|
||||||
|
|
||||||
|
// Store file size
|
||||||
|
|
||||||
// Find address for storing the size
|
// Find address for storing the size
|
||||||
const uint32_t addr = clu_offs(fat, file->clu, file->num * 32 + 28);
|
const uint32_t addr = clu_offs(fat, file->clu, file->num * 32 + 28);
|
||||||
file->size = size;
|
|
||||||
|
|
||||||
dev->seek(addr);
|
dev->seek(addr);
|
||||||
dev->store(&size, 4);
|
dev->store(&(file->size), 4);
|
||||||
|
|
||||||
// Seek to the end of the file, to make sure clusters are allocated
|
// Seek to the end of the file, to make sure clusters are allocated
|
||||||
fat16_seek(file, size - 1);
|
ff_seek(file, file->size - 1);
|
||||||
|
|
||||||
const uint16_t next = next_clu(fat, file->cur_clu);
|
const uint16_t next = next_clu(fat, file->cur_clu);
|
||||||
if (next != 0xFFFF)
|
if (next != 0xFFFF)
|
||||||
@@ -1057,8 +1082,10 @@ void fat16_resize(FAT16_FILE* file, uint32_t size)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** Low level no-check file delete and free */
|
/** Low level no-check file delete and free */
|
||||||
void delete_file_do(FAT16_FILE* file)
|
void delete_file_do(FFILE* file)
|
||||||
{
|
{
|
||||||
const FAT16* fat = file->fat;
|
const FAT16* fat = file->fat;
|
||||||
|
|
||||||
@@ -1080,7 +1107,7 @@ void delete_file_do(FAT16_FILE* file)
|
|||||||
|
|
||||||
|
|
||||||
/** Delete a simple file */
|
/** Delete a simple file */
|
||||||
bool fat16_rmfile(FAT16_FILE* file)
|
bool ff_rmfile(FFILE* file)
|
||||||
{
|
{
|
||||||
switch (file->type)
|
switch (file->type)
|
||||||
{
|
{
|
||||||
@@ -1099,15 +1126,15 @@ bool fat16_rmfile(FAT16_FILE* file)
|
|||||||
|
|
||||||
|
|
||||||
/** Delete an empty directory */
|
/** Delete an empty directory */
|
||||||
bool fat16_rmdir(FAT16_FILE* file)
|
bool ff_rmdir(FFILE* file)
|
||||||
{
|
{
|
||||||
if (file->type != FT_SUBDIR)
|
if (file->type != FT_SUBDIR)
|
||||||
return false; // not a subdirectory entry
|
return false; // not a subdirectory entry
|
||||||
|
|
||||||
const FSAVEPOS orig = fat16_savepos(file);
|
const FSAVEPOS orig = ff_savepos(file);
|
||||||
|
|
||||||
// Open the subdir
|
// Open the subdir
|
||||||
if (!fat16_opendir(file))
|
if (!ff_opendir(file))
|
||||||
return false; // could not open
|
return false; // could not open
|
||||||
|
|
||||||
// Look for valid files and subdirs in the directory
|
// Look for valid files and subdirs in the directory
|
||||||
@@ -1124,16 +1151,16 @@ bool fat16_rmdir(FAT16_FILE* file)
|
|||||||
{
|
{
|
||||||
// Valid child file was found, aborting.
|
// Valid child file was found, aborting.
|
||||||
// reopen original file
|
// reopen original file
|
||||||
fat16_reopen(file, &orig);
|
ff_reopen(file, &orig);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cnt < 2) cnt++;
|
if (cnt < 2) cnt++;
|
||||||
}
|
}
|
||||||
while (fat16_next(file));
|
while (ff_next(file));
|
||||||
|
|
||||||
// reopen original file
|
// reopen original file
|
||||||
fat16_reopen(file, &orig);
|
ff_reopen(file, &orig);
|
||||||
|
|
||||||
// and delete as ordinary file
|
// and delete as ordinary file
|
||||||
delete_file_do(file);
|
delete_file_do(file);
|
||||||
@@ -1142,7 +1169,7 @@ bool fat16_rmdir(FAT16_FILE* file)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool fat16_delete(FAT16_FILE* file)
|
bool ff_delete(FFILE* file)
|
||||||
{
|
{
|
||||||
switch (file->type)
|
switch (file->type)
|
||||||
{
|
{
|
||||||
@@ -1153,7 +1180,7 @@ bool fat16_delete(FAT16_FILE* file)
|
|||||||
case FT_SUBDIR:; // semicolon needed to allow declaration after "case"
|
case FT_SUBDIR:; // semicolon needed to allow declaration after "case"
|
||||||
|
|
||||||
// store original file location
|
// store original file location
|
||||||
const FSAVEPOS orig = fat16_savepos(file);
|
const FSAVEPOS orig = ff_savepos(file);
|
||||||
|
|
||||||
// open the directory (skip "." and "..")
|
// open the directory (skip "." and "..")
|
||||||
open_file(file->fat, file, file->clu_start, 2);
|
open_file(file->fat, file, file->clu_start, 2);
|
||||||
@@ -1161,32 +1188,32 @@ bool fat16_delete(FAT16_FILE* file)
|
|||||||
// delete all children
|
// delete all children
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if (!fat16_delete(file))
|
if (!ff_delete(file))
|
||||||
{
|
{
|
||||||
// failure
|
// failure
|
||||||
// reopen original file
|
// reopen original file
|
||||||
fat16_reopen(file, &orig);
|
ff_reopen(file, &orig);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (fat16_next(file));
|
while (ff_next(file));
|
||||||
|
|
||||||
// go up and delete the dir
|
// go up and delete the dir
|
||||||
fat16_reopen(file, &orig);
|
ff_reopen(file, &orig);
|
||||||
return fat16_rmdir(file);
|
return ff_rmdir(file);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// try to delete as a regular file
|
// try to delete as a regular file
|
||||||
return fat16_rmfile(file);
|
return ff_rmfile(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool fat16_parent(FAT16_FILE* file)
|
bool ff_parent(FFILE* file)
|
||||||
{
|
{
|
||||||
// open second entry of the directory
|
// open second entry of the directory
|
||||||
open_file(file->fat, file, file->clu, 1);
|
open_file(file->fat, file, file->clu, 1);
|
||||||
const FSAVEPOS orig = fat16_savepos(file);
|
const FSAVEPOS orig = ff_savepos(file);
|
||||||
|
|
||||||
// if it's a valid PARENT link, follow it.
|
// if it's a valid PARENT link, follow it.
|
||||||
if (file->type == FT_PARENT)
|
if (file->type == FT_PARENT)
|
||||||
@@ -1198,7 +1225,7 @@ bool fat16_parent(FAT16_FILE* file)
|
|||||||
{
|
{
|
||||||
// in root already?
|
// in root already?
|
||||||
// reopen original file
|
// reopen original file
|
||||||
fat16_reopen(file, &orig);
|
ff_reopen(file, &orig);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+38
-26
@@ -99,24 +99,31 @@ typedef struct __attribute__((packed))
|
|||||||
// Pointer to the FAT16 handle. (internal)
|
// Pointer to the FAT16 handle. (internal)
|
||||||
const FAT16* fat;
|
const FAT16* fat;
|
||||||
}
|
}
|
||||||
FAT16_FILE;
|
FFILE;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store modified file metadata and flush it to disk.
|
||||||
|
*/
|
||||||
|
void ff_flush_file(FFILE* file);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save a file "position" into a struct, for later restoration.
|
* Save a file "position" into a struct, for later restoration.
|
||||||
* Cursor is also saved.
|
* Cursor is also saved.
|
||||||
*/
|
*/
|
||||||
FSAVEPOS fat16_savepos(const FAT16_FILE* file);
|
FSAVEPOS ff_savepos(const FFILE* file);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Restore a file from a saved position.
|
* Restore a file from a saved position.
|
||||||
*/
|
*/
|
||||||
void fat16_reopen(FAT16_FILE* file, const FSAVEPOS* pos);
|
void ff_reopen(FFILE* file, const FSAVEPOS* pos);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the file system - store into "fat"
|
* Initialize the file system - store into "fat"
|
||||||
*/
|
*/
|
||||||
bool fat16_init(const BLOCKDEV* dev, FAT16* fat);
|
bool ff_init(const BLOCKDEV* dev, FAT16* fat);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -124,7 +131,7 @@ bool fat16_init(const BLOCKDEV* dev, FAT16* fat);
|
|||||||
* The file may be invalid (eg. a volume label, deleted etc),
|
* The file may be invalid (eg. a volume label, deleted etc),
|
||||||
* or blank (type FT_NONE) if the filesystem is empty.
|
* or blank (type FT_NONE) if the filesystem is empty.
|
||||||
*/
|
*/
|
||||||
void fat16_root(const FAT16* fat, FAT16_FILE* file);
|
void ff_root(const FAT16* fat, FFILE* file);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -134,7 +141,7 @@ void fat16_root(const FAT16* fat, FAT16_FILE* file);
|
|||||||
* @param fat the FAT handle
|
* @param fat the FAT handle
|
||||||
* @param label_out string to store the label in. Should have at least 12 bytes.
|
* @param label_out string to store the label in. Should have at least 12 bytes.
|
||||||
*/
|
*/
|
||||||
char* fat16_disk_label(const FAT16* fat, char* label_out);
|
char* ff_disk_label(const FAT16* fat, char* label_out);
|
||||||
|
|
||||||
|
|
||||||
// ----------- FILE I/O -------------
|
// ----------- FILE I/O -------------
|
||||||
@@ -144,21 +151,26 @@ char* fat16_disk_label(const FAT16* fat, char* label_out);
|
|||||||
* Move file cursor to a position relative to file start
|
* Move file cursor to a position relative to file start
|
||||||
* Returns false on I/O error (bad file, out of range...)
|
* Returns false on I/O error (bad file, out of range...)
|
||||||
*/
|
*/
|
||||||
bool fat16_seek(FAT16_FILE* file, uint32_t addr);
|
bool ff_seek(FFILE* file, uint32_t addr);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read bytes from file into memory
|
* Read bytes from file into memory
|
||||||
* Returns number of bytes read, 0 on error.
|
* Returns number of bytes read, 0 on error.
|
||||||
*/
|
*/
|
||||||
uint16_t fat16_read(FAT16_FILE* file, void* target, uint16_t len);
|
uint16_t ff_read(FFILE* file, void* target, uint16_t len);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write into file at a "seek" position.
|
* Write into file at a "seek" position.
|
||||||
* "seek" cursor must be within (0..filesize)
|
|
||||||
*/
|
*/
|
||||||
bool fat16_write(FAT16_FILE* file, void* source, uint32_t len);
|
bool ff_write(FFILE* file, const void* source, uint32_t len);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store a 0-terminated string at cursor.
|
||||||
|
*/
|
||||||
|
bool ff_write_str(FFILE* file, const char* source);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -167,14 +179,14 @@ bool fat16_write(FAT16_FILE* file, void* source, uint32_t len);
|
|||||||
* file ... open directory; new file is opened into this handle.
|
* file ... open directory; new file is opened into this handle.
|
||||||
* name ... name of the new file, including extension
|
* name ... name of the new file, including extension
|
||||||
*/
|
*/
|
||||||
bool fat16_mkfile(FAT16_FILE* file, const char* name);
|
bool ff_newfile(FFILE* file, const char* name);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a sub-directory of given name.
|
* Create a sub-directory of given name.
|
||||||
* Directory is allocated and populated with entries "." and ".."
|
* Directory is allocated and populated with entries "." and ".."
|
||||||
*/
|
*/
|
||||||
bool fat16_mkdir(FAT16_FILE* file, const char* name);
|
bool ff_mkdir(FFILE* file, const char* name);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -183,26 +195,26 @@ bool fat16_mkdir(FAT16_FILE* file, const char* name);
|
|||||||
*
|
*
|
||||||
* Useful mainly for shrinking.
|
* Useful mainly for shrinking.
|
||||||
*/
|
*/
|
||||||
void fat16_resize(FAT16_FILE* file, uint32_t size);
|
void set_file_size(FFILE* file, uint32_t size);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete a *FILE* and free it's clusters.
|
* Delete a *FILE* and free it's clusters.
|
||||||
*/
|
*/
|
||||||
bool fat16_rmfile(FAT16_FILE* file);
|
bool ff_rmfile(FFILE* file);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete an empty *DIRECTORY* and free it's clusters.
|
* Delete an empty *DIRECTORY* and free it's clusters.
|
||||||
*/
|
*/
|
||||||
bool fat16_rmdir(FAT16_FILE* file);
|
bool ff_rmdir(FFILE* file);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete a file or directory, even FT_LFN and FT_INVALID.
|
* Delete a file or directory, even FT_LFN and FT_INVALID.
|
||||||
* Directories are deleted recursively (!)
|
* Directories are deleted recursively (!)
|
||||||
*/
|
*/
|
||||||
bool fat16_delete(FAT16_FILE* file);
|
bool ff_delete(FFILE* file);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -210,55 +222,55 @@ bool fat16_delete(FAT16_FILE* file);
|
|||||||
|
|
||||||
|
|
||||||
/** Go to previous file in the directory (false = no prev file) */
|
/** Go to previous file in the directory (false = no prev file) */
|
||||||
bool fat16_prev(FAT16_FILE* file);
|
bool ff_prev(FFILE* file);
|
||||||
|
|
||||||
|
|
||||||
/** Go to next file in directory (false = no next file) */
|
/** Go to next file in directory (false = no next file) */
|
||||||
bool fat16_next(FAT16_FILE* file);
|
bool ff_next(FFILE* file);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open a subdirectory denoted by the file.
|
* Open a subdirectory denoted by the file.
|
||||||
* Provided handle changes to the first entry of the directory.
|
* Provided handle changes to the first entry of the directory.
|
||||||
*/
|
*/
|
||||||
bool fat16_opendir(FAT16_FILE* dir);
|
bool ff_opendir(FFILE* dir);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open a parent directory. Fails in root.
|
* Open a parent directory. Fails in root.
|
||||||
* Provided handle changes to the first entry of the parent directory.
|
* Provided handle changes to the first entry of the parent directory.
|
||||||
*/
|
*/
|
||||||
bool fat16_parent(FAT16_FILE* file);
|
bool ff_parent(FFILE* file);
|
||||||
|
|
||||||
|
|
||||||
/** Jump to first file in this directory */
|
/** Jump to first file in this directory */
|
||||||
void fat16_first(FAT16_FILE* file);
|
void ff_first(FFILE* file);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find a file with given "display name" in this directory.
|
* Find a file with given "display name" in this directory, and open it.
|
||||||
* If file is found, "dir" will contain it's handle.
|
* If file is found, "dir" will contain it's handle.
|
||||||
* If file is NOT found, the handle points to the last entry of the directory.
|
* If file is NOT found, the handle points to the last entry of the directory.
|
||||||
*/
|
*/
|
||||||
bool fat16_find(FAT16_FILE* dir, const char* name);
|
bool ff_open(FFILE* dir, const char* name);
|
||||||
|
|
||||||
|
|
||||||
// -------- FILE INSPECTION -----------
|
// -------- FILE INSPECTION -----------
|
||||||
|
|
||||||
/** Check if file is a valid entry, or long-name/label/deleted */
|
/** Check if file is a valid entry, or long-name/label/deleted */
|
||||||
bool fat16_is_regular(const FAT16_FILE* file);
|
bool ff_is_regular(const FFILE* file);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve a file name, trim spaces and add null terminator.
|
* Resolve a file name, trim spaces and add null terminator.
|
||||||
* Returns the passed char*, or NULL on error.
|
* Returns the passed char*, or NULL on error.
|
||||||
*/
|
*/
|
||||||
char* fat16_dispname(const FAT16_FILE* file, char* disp_out);
|
char* ff_dispname(const FFILE* file, char* disp_out);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert filename to zero-padded fixed length one
|
* Convert filename to zero-padded fixed length one
|
||||||
* Returns the passed char*.
|
* Returns the passed char*.
|
||||||
*/
|
*/
|
||||||
char* fat16_rawname(const char* disp_in, char* raw_out);
|
char* ff_rawname(const char* disp_in, char* raw_out);
|
||||||
|
|
||||||
|
|||||||
@@ -15,8 +15,6 @@
|
|||||||
|
|
||||||
#include "iopins.h"
|
#include "iopins.h"
|
||||||
#include "spi.h"
|
#include "spi.h"
|
||||||
#include "uart.h"
|
|
||||||
#include "stream.h"
|
|
||||||
|
|
||||||
/** Init SD card on SPI */
|
/** Init SD card on SPI */
|
||||||
bool sd_init();
|
bool sd_init();
|
||||||
|
|||||||
+16
-4
@@ -16,6 +16,7 @@ uint8_t dev_read();
|
|||||||
void dev_write(const uint8_t b);
|
void dev_write(const uint8_t b);
|
||||||
void dev_seek(const uint32_t addr);
|
void dev_seek(const uint32_t addr);
|
||||||
void dev_rseek(const int16_t offset);
|
void dev_rseek(const int16_t offset);
|
||||||
|
void dev_flush();
|
||||||
|
|
||||||
|
|
||||||
/** Sector buffer */
|
/** Sector buffer */
|
||||||
@@ -36,7 +37,7 @@ uint16_t cursor_offs;
|
|||||||
|
|
||||||
|
|
||||||
/** Flush the buffer, if it's dirty */
|
/** Flush the buffer, if it's dirty */
|
||||||
void sdb_flush()
|
void dev_flush()
|
||||||
{
|
{
|
||||||
if (buff_dirty)
|
if (buff_dirty)
|
||||||
{
|
{
|
||||||
@@ -49,11 +50,12 @@ void sdb_flush()
|
|||||||
void load_sector(const uint32_t addr)
|
void load_sector(const uint32_t addr)
|
||||||
{
|
{
|
||||||
// do not load if already loaded
|
// do not load if already loaded
|
||||||
if (buff_valid && buff_addr == addr) {
|
if (buff_valid && buff_addr == addr)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sdb_flush();
|
dev_flush();
|
||||||
|
|
||||||
// read entire sector
|
// read entire sector
|
||||||
sd_read(addr, 0, buff, 0, 512);
|
sd_read(addr, 0, buff, 0, 512);
|
||||||
@@ -90,8 +92,17 @@ inline void handle_cursor_ov()
|
|||||||
void dev_write(const uint8_t b)
|
void dev_write(const uint8_t b)
|
||||||
{
|
{
|
||||||
load_sector(cursor_sec);
|
load_sector(cursor_sec);
|
||||||
|
|
||||||
|
// dirty only if changed
|
||||||
|
if (buff[cursor_offs] != b)
|
||||||
|
{
|
||||||
buff[cursor_offs++] = b;
|
buff[cursor_offs++] = b;
|
||||||
buff_dirty = true;
|
buff_dirty = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cursor_offs++;
|
||||||
|
}
|
||||||
|
|
||||||
handle_cursor_ov();
|
handle_cursor_ov();
|
||||||
}
|
}
|
||||||
@@ -158,7 +169,7 @@ void dev_rseek(const int16_t offset)
|
|||||||
/** Init SD card block device */
|
/** Init SD card block device */
|
||||||
bool sdb_init(BLOCKDEV* dev)
|
bool sdb_init(BLOCKDEV* dev)
|
||||||
{
|
{
|
||||||
if(!sd_init()) return false;
|
if (!sd_init()) return false;
|
||||||
|
|
||||||
dev->load = &dev_load;
|
dev->load = &dev_load;
|
||||||
dev->store = &dev_store;
|
dev->store = &dev_store;
|
||||||
@@ -166,6 +177,7 @@ bool sdb_init(BLOCKDEV* dev)
|
|||||||
dev->write = &dev_write;
|
dev->write = &dev_write;
|
||||||
dev->seek = &dev_seek;
|
dev->seek = &dev_seek;
|
||||||
dev->rseek = &dev_rseek;
|
dev->rseek = &dev_rseek;
|
||||||
|
dev->flush = &dev_flush;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,13 +2,5 @@
|
|||||||
|
|
||||||
#include "blockdev.h"
|
#include "blockdev.h"
|
||||||
|
|
||||||
/**
|
|
||||||
* Flush the sector buffer if it's dirty.
|
|
||||||
*
|
|
||||||
* Should be called after each sequence of writes,
|
|
||||||
* to avoid data loss.
|
|
||||||
*/
|
|
||||||
void sdb_flush();
|
|
||||||
|
|
||||||
/** Initialize the SD card block device */
|
/** Initialize the SD card block device */
|
||||||
bool sdb_init(BLOCKDEV* dev);
|
bool sdb_init(BLOCKDEV* dev);
|
||||||
|
|||||||
+39
-6
@@ -8,27 +8,60 @@
|
|||||||
FAT16 _fat;
|
FAT16 _fat;
|
||||||
BLOCKDEV _dev;
|
BLOCKDEV _dev;
|
||||||
|
|
||||||
|
|
||||||
|
static STREAM _s;
|
||||||
|
STREAM* sdf_stream = &_s;
|
||||||
|
|
||||||
|
FFILE* stream_file;
|
||||||
|
bool stream_active = false;
|
||||||
|
|
||||||
|
void stream_tx(uint8_t b)
|
||||||
|
{
|
||||||
|
if (!stream_active) return;
|
||||||
|
ff_write(stream_file, &b, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t stream_rx()
|
||||||
|
{
|
||||||
|
if (!stream_active) return 0;
|
||||||
|
|
||||||
|
uint8_t b;
|
||||||
|
ff_read(stream_file, &b, 1);
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sdf_open_stream(FFILE* file)
|
||||||
|
{
|
||||||
|
stream_active = true;
|
||||||
|
stream_file = file;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool sdfat_inited = false;
|
bool sdfat_inited = false;
|
||||||
|
|
||||||
bool sdfat_init()
|
bool sdf_init()
|
||||||
{
|
{
|
||||||
if (sdfat_inited) return true;
|
if (sdfat_inited) return true;
|
||||||
sdfat_inited = true;
|
sdfat_inited = true;
|
||||||
|
|
||||||
if (!sdb_init(&_dev)) return false;
|
if (!sdb_init(&_dev)) return false;
|
||||||
if (!fat16_init(&_dev, &_fat)) return false;
|
if (!ff_init(&_dev, &_fat)) return false;
|
||||||
|
|
||||||
|
sdf_stream->rx = &stream_rx;
|
||||||
|
sdf_stream->tx = &stream_tx;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void sdfat_root(FAT16_FILE* file)
|
void sdf_root(FFILE* file)
|
||||||
{
|
{
|
||||||
fat16_root(&_fat, file);
|
ff_root(&_fat, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void sdfat_disk_label(char* str)
|
void sdf_disk_label(char* str)
|
||||||
{
|
{
|
||||||
fat16_disk_label(&_fat, str);
|
ff_disk_label(&_fat, str);
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-6
@@ -1,19 +1,30 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
//
|
//
|
||||||
// FAT-on-SD helpers
|
// FAT-on-SD helpers.
|
||||||
|
//
|
||||||
|
// This can be used for convenience, as it does all the init for you
|
||||||
|
// and hides the implementation. All regular ff_* functions will work on the FFILE.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "fat16.h"
|
#include "fat16.h"
|
||||||
|
#include "stream.h"
|
||||||
|
|
||||||
/** Initialize FAT16 filesystem on a SPI-connected SD card */
|
/** Initialize FAT16 filesystem on a SPI-connected SD card */
|
||||||
bool sdfat_init();
|
bool sdf_init();
|
||||||
|
|
||||||
/** Get first file of the root folder. */
|
/** Get first file of the root folder. */
|
||||||
void sdfat_root(FAT16_FILE* file);
|
void sdf_root(FFILE* file);
|
||||||
|
|
||||||
/** Get a disk label. Str should have 12 chars. */
|
/** Get a disk label. Str should have 12 chars. */
|
||||||
void sdfat_disk_label(char* str);
|
void sdf_disk_label(char* str);
|
||||||
|
|
||||||
/** Flush the SD buffer (alis of sdb_flush()) */
|
extern STREAM* sdf_stream;
|
||||||
#define sdfat_flush() sdb_flush()
|
|
||||||
|
/**
|
||||||
|
* Open a stream for a file. There can be only one stream at a time.
|
||||||
|
*
|
||||||
|
* The stream will operate at the current file's cursor, just like
|
||||||
|
* ff_read and ff_write.
|
||||||
|
*/
|
||||||
|
void sdf_open_stream(FFILE* file);
|
||||||
|
|||||||
+6
-1
@@ -18,7 +18,7 @@ void put_bytes(const STREAM *p, const uint8_t* str, const uint16_t len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void put_str(const STREAM *p, char* str)
|
void put_str(const STREAM *p, const char *str)
|
||||||
{
|
{
|
||||||
char c;
|
char c;
|
||||||
while ((c = *str++))
|
while ((c = *str++))
|
||||||
@@ -41,6 +41,11 @@ void put_str_P(const STREAM *p, const char* str)
|
|||||||
static void _putnf(const STREAM *p, const uint8_t places);
|
static void _putnf(const STREAM *p, const uint8_t places);
|
||||||
|
|
||||||
|
|
||||||
|
void put_c(const STREAM *p, const uint8_t c)
|
||||||
|
{
|
||||||
|
p->tx(c);
|
||||||
|
}
|
||||||
|
|
||||||
/** Send signed int8 */
|
/** Send signed int8 */
|
||||||
void put_u8(const STREAM *p, const uint8_t num)
|
void put_u8(const STREAM *p, const uint8_t num)
|
||||||
{
|
{
|
||||||
|
|||||||
+18
-17
@@ -31,74 +31,75 @@ typedef struct
|
|||||||
|
|
||||||
|
|
||||||
/** Send bytes to stream */
|
/** Send bytes to stream */
|
||||||
void put_bytes(const STREAM *p, const uint8_t* str, const uint16_t len);
|
void put_bytes(const STREAM *p, const uint8_t* str, uint16_t len);
|
||||||
|
|
||||||
|
|
||||||
/** Print string into a stream */
|
/** Print string into a stream */
|
||||||
void put_str(const STREAM *p, char* str);
|
void put_str(const STREAM *p, const char *str);
|
||||||
|
|
||||||
|
|
||||||
/** Print a programspace string into a stream */
|
/** Print a programspace string into a stream */
|
||||||
void put_str_P(const STREAM *p, const char* str);
|
void put_str_P(const STREAM *p, const char* str);
|
||||||
|
|
||||||
|
/** Put a char/byte. Basically the same as p->tx() */
|
||||||
|
void put_c(const STREAM *p, uint8_t c);
|
||||||
|
|
||||||
/** Send signed int8 */
|
/** Send signed int8 */
|
||||||
#define put_char(p, c) (p)->tx((c))
|
void put_u8(const STREAM *p, uint8_t num);
|
||||||
void put_u8(const STREAM *p, const uint8_t num);
|
|
||||||
|
|
||||||
|
|
||||||
/** Send unsigned int8 */
|
/** Send unsigned int8 */
|
||||||
void put_i8(const STREAM *p, const int8_t num);
|
void put_i8(const STREAM *p, int8_t num);
|
||||||
|
|
||||||
|
|
||||||
/** Send unsigned int */
|
/** Send unsigned int */
|
||||||
void put_u16(const STREAM *p, const uint16_t num);
|
void put_u16(const STREAM *p, uint16_t num);
|
||||||
|
|
||||||
|
|
||||||
/** Send signed int */
|
/** Send signed int */
|
||||||
void put_i16(const STREAM *p, const int16_t num);
|
void put_i16(const STREAM *p, int16_t num);
|
||||||
|
|
||||||
|
|
||||||
/** Send unsigned long */
|
/** Send unsigned long */
|
||||||
void put_u32(const STREAM *p, const uint32_t num);
|
void put_u32(const STREAM *p, uint32_t num);
|
||||||
|
|
||||||
|
|
||||||
/** Send signed long */
|
/** Send signed long */
|
||||||
void put_i32(const STREAM *p, const int32_t num);
|
void put_i32(const STREAM *p, int32_t num);
|
||||||
|
|
||||||
|
|
||||||
/** Send unsigned int8 */
|
/** Send unsigned int8 */
|
||||||
void put_x8(const STREAM *p, const uint8_t num);
|
void put_x8(const STREAM *p, uint8_t num);
|
||||||
|
|
||||||
|
|
||||||
/** Send int as hex */
|
/** Send int as hex */
|
||||||
void put_x16(const STREAM *p, const uint16_t num);
|
void put_x16(const STREAM *p, uint16_t num);
|
||||||
|
|
||||||
|
|
||||||
/** Send long as hex */
|
/** Send long as hex */
|
||||||
void put_x32(const STREAM *p, const uint32_t num);
|
void put_x32(const STREAM *p, uint32_t num);
|
||||||
|
|
||||||
|
|
||||||
/** Send long long as hex */
|
/** Send long long as hex */
|
||||||
void put_x64(const STREAM *p, const uint64_t num);
|
void put_x64(const STREAM *p, uint64_t num);
|
||||||
|
|
||||||
|
|
||||||
// float variant doesn't make sense for 8-bit int
|
// float variant doesn't make sense for 8-bit int
|
||||||
|
|
||||||
/** Send unsigned int as float */
|
/** Send unsigned int as float */
|
||||||
void put_u16f(const STREAM *p, const uint16_t num, const uint8_t places);
|
void put_u16f(const STREAM *p, uint16_t num, uint8_t places);
|
||||||
|
|
||||||
|
|
||||||
/** Send signed int as float */
|
/** Send signed int as float */
|
||||||
void put_i16f(const STREAM *p, const int16_t num, const uint8_t places);
|
void put_i16f(const STREAM *p, int16_t num, uint8_t places);
|
||||||
|
|
||||||
|
|
||||||
/** Send unsigned long as float */
|
/** Send unsigned long as float */
|
||||||
void put_u32f(const STREAM *p, const uint32_t num, const uint8_t places);
|
void put_u32f(const STREAM *p, uint32_t num, uint8_t places);
|
||||||
|
|
||||||
|
|
||||||
/** Send signed long as float */
|
/** Send signed long as float */
|
||||||
void put_i32f(const STREAM *p, const int32_t num, const uint8_t places);
|
void put_i32f(const STREAM *p, int32_t num, uint8_t places);
|
||||||
|
|
||||||
|
|
||||||
/** Print CR LF */
|
/** Print CR LF */
|
||||||
|
|||||||
Reference in New Issue
Block a user