Finally some progress again.
after fixing where I f'ed up in FatFs, the loading of the .sys files is happening and the thumbnails are being displayed.
Had two issues with FatFs. Default configuration is set for dos file names and "pic_system.sys" or "wave_system.sys" does not comply with that. Due to this f_open failed with "FR_INVALID_NAME". Since it did open "piclist.sys" it was quickly clear I needed LFN support enabled.
After fixing that it hung on f_read. This took a bit longer to find. It did work with a read of 511 bytes, but not with 512. Tested my low level sd_card_read with multiple blocks and that worked without problems. Then I realized I cleaned up the FatFs code and fixed the no no I mentioned in a previous post. So I went back to the original and started to compare what I changed.
Turns out that I missed a continue that was being used in a for loop. That behaves differently for a while loop, and that is what I changed the code to. So fixed by changing the continue into a goto.
The original FatFs f_read code, where there is no check on the *br pointer not being NULL
/*-----------------------------------------------------------------------*/
/* Read File */
/*-----------------------------------------------------------------------*/
FRESULT f_read (
FIL* fp, /* Open file to be read */
void* buff, /* Data buffer to store the read data */
UINT btr, /* Number of bytes to read */
UINT* br /* Number of bytes read */
)
{
FRESULT res;
FATFS *fs;
DWORD clst;
LBA_t sect;
FSIZE_t remain;
UINT rcnt, cc, csect;
BYTE *rbuff = (BYTE*)buff;
*br = 0; /* Clear read byte counter */
res = validate(&fp->obj, &fs); /* Check validity of the file object */
if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); /* Check validity */
if (!(fp->flag & FA_READ)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */
remain = fp->obj.objsize - fp->fptr;
if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */
for ( ; btr > 0; btr -= rcnt, *br += rcnt, rbuff += rcnt, fp->fptr += rcnt) { /* Repeat until btr bytes read */
if (fp->fptr % SS(fs) == 0) { /* On the sector boundary? */
csect = (UINT)(fp->fptr / SS(fs) & (fs->csize - 1)); /* Sector offset in the cluster */
if (csect == 0) { /* On the cluster boundary? */
if (fp->fptr == 0) { /* On the top of the file? */
clst = fp->obj.sclust; /* Follow cluster chain from the origin */
} else { /* Middle or end of the file */
#if FF_USE_FASTSEEK
if (fp->cltbl) {
clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */
} else
#endif
{
clst = get_fat(&fp->obj, fp->clust); /* Follow cluster chain on the FAT */
}
}
if (clst < 2) ABORT(fs, FR_INT_ERR);
if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR);
fp->clust = clst; /* Update current cluster */
}
sect = clst2sect(fs, fp->clust); /* Get current sector */
if (sect == 0) ABORT(fs, FR_INT_ERR);
sect += csect;
cc = btr / SS(fs); /* When remaining bytes >= sector size, */
if (cc > 0) { /* Read maximum contiguous sectors directly */
if (csect + cc > fs->csize) { /* Clip at cluster boundary */
cc = fs->csize - csect;
}
if (disk_read(fs->pdrv, rbuff, sect, cc) != RES_OK) ABORT(fs, FR_DISK_ERR);
#if !FF_FS_READONLY && FF_FS_MINIMIZE <= 2 /* Replace one of the read sectors with cached data if it contains a dirty sector */
#if FF_FS_TINY
if (fs->wflag && fs->winsect - sect < cc) {
memcpy(rbuff + ((fs->winsect - sect) * SS(fs)), fs->win, SS(fs));
}
#else
if ((fp->flag & FA_DIRTY) && fp->sect - sect < cc) {
memcpy(rbuff + ((fp->sect - sect) * SS(fs)), fp->buf, SS(fs));
}
#endif
#endif
rcnt = SS(fs) * cc; /* Number of bytes transferred */
continue;
}
#if !FF_FS_TINY
if (fp->sect != sect) { /* Load data sector if not in cache */
#if !FF_FS_READONLY
if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */
if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
fp->flag &= (BYTE)~FA_DIRTY;
}
#endif
if (disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Fill sector cache */
}
#endif
fp->sect = sect;
}
rcnt = SS(fs) - (UINT)fp->fptr % SS(fs); /* Number of bytes remains in the sector */
if (rcnt > btr) rcnt = btr; /* Clip it by btr if needed */
#if FF_FS_TINY
if (move_window(fs, fp->sect) != FR_OK) ABORT(fs, FR_DISK_ERR); /* Move sector window */
memcpy(rbuff, fs->win + fp->fptr % SS(fs), rcnt); /* Extract partial sector */
#else
memcpy(rbuff, fp->buf + fp->fptr % SS(fs), rcnt); /* Extract partial sector */
#endif
}
LEAVE_FF(fs, FR_OK);
}
My version of the code
//----------------------------------------------------------------------------------------------------------------------------------
//Read File
//
//Return:
// A FRESULT value
//
//Input:
// Pointer to the file structure
// Buffer to store the read data
// Number of bytes to read
// Pointer to a varialble to return the number of bytes read in
//
//----------------------------------------------------------------------------------------------------------------------------------
FRESULT f_read(FIL* fp, void* buff, UINT btr, UINT* br)
{
FRESULT res;
FATFS *fs;
DWORD clst;
LBA_t sect;
FSIZE_t remain;
UINT rcnt, cc, csect;
BYTE *rbuff = (BYTE*)buff;
//Check if the input parameters are valid
if(!fp || !buff)
return(FR_INVALID_OBJECT);
//Clear read byte counter when given
if(br)
*br = 0;
//Check validity of the file object
res = validate(&fp->obj, &fs);
//Check validity
if(res != FR_OK || (res = (FRESULT)fp->err) != FR_OK)
LEAVE_FF(fs, res);
//Check access mode
if(!(fp->flag & FA_READ))
LEAVE_FF(fs, FR_DENIED);
//Calculate how many bytes are left in the file
remain = fp->obj.objsize - fp->fptr;
//Truncate btr by remaining bytes
if(btr > remain)
btr = (UINT)remain;
//Repeat until btr bytes read
while(btr > 0)
{
//On the sector boundary?
if((fp->fptr % SS(fs)) == 0)
{
//Sector offset in the cluster
csect = (UINT)(fp->fptr / SS(fs) & (fs->csize - 1));
//On the cluster boundary?
if(csect == 0)
{
//On the top of the file?
if(fp->fptr == 0)
{
//Follow cluster chain from the origin
clst = fp->obj.sclust;
}
//Middle or end of the file
else
{
#if FF_USE_FASTSEEK
if(fp->cltbl)
{
//Get cluster# from the CLMT
clst = clmt_clust(fp, fp->fptr);
}
else
#endif
{
//Follow cluster chain on the FAT
clst = get_fat(&fp->obj, fp->clust);
}
}
//cluster in wrong place??
if(clst < 2)
ABORT(fs, FR_INT_ERR);
//Cluster out of range??
if(clst == 0xFFFFFFFF)
ABORT(fs, FR_DISK_ERR);
//Update current cluster
fp->clust = clst;
}
//Get current sector
sect = clst2sect(fs, fp->clust);
//Invalid sector??
if(sect == 0)
ABORT(fs, FR_INT_ERR);
sect += csect;
cc = btr / SS(fs);
//When remaining bytes >= sector size,
if(cc > 0)
{
//Read maximum contiguous sectors directly
//Clip at cluster boundary
if((csect + cc) > fs->csize)
{
cc = fs->csize - csect;
}
if(disk_read(fs->pdrv, rbuff, sect, cc) != RES_OK)
ABORT(fs, FR_DISK_ERR);
#if !FF_FS_READONLY && FF_FS_MINIMIZE <= 2
//Replace one of the read sectors with cached data if it contains a dirty sector
#if FF_FS_TINY
if(fs->wflag && ((fs->winsect - sect) < cc))
{
memcpy((rbuff + ((fs->winsect - sect) * SS(fs))), fs->win, SS(fs));
}
#else
if((fp->flag & FA_DIRTY) && ((fp->sect - sect) < cc))
{
memcpy((rbuff + ((fp->sect - sect) * SS(fs))), fp->buf, SS(fs));
}
#endif
#endif
//Number of bytes transferred
rcnt = SS(fs) * cc;
//Continue after update of counters and pointers. Original code uses for loop and continue
goto read_update;
}
#if !FF_FS_TINY
//Load data sector if not in cache
if(fp->sect != sect)
{
#if !FF_FS_READONLY
if(fp->flag & FA_DIRTY)
{
//Write-back dirty sector cache
if(disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK)
ABORT(fs, FR_DISK_ERR);
fp->flag &= (BYTE)~FA_DIRTY;
}
#endif
//Fill sector cache
if(disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK)
ABORT(fs, FR_DISK_ERR);
}
#endif
fp->sect = sect;
}
//Number of bytes remains in the sector
rcnt = SS(fs) - (UINT)fp->fptr % SS(fs);
//Clip it by btr if needed
if(rcnt > btr)
rcnt = btr;
#if FF_FS_TINY
//Move sector window
if(move_window(fs, fp->sect) != FR_OK)
ABORT(fs, FR_DISK_ERR);
//Extract partial sector
memcpy(rbuff, (fs->win + (fp->fptr % SS(fs))), rcnt);
#else
//Extract partial sector
memcpy(rbuff, (fp->buf + (fp->fptr % SS(fs))), rcnt);
#endif
//Update counters and pointers
read_update:
btr -= rcnt;
rbuff += rcnt;
fp->fptr += rcnt;
//Return bytes read, only when variable is given
if(br)
*br += rcnt;
}
LEAVE_FF(fs, FR_OK);
}
//----------------------------------------------------------------------------------------------------------------------------------
Attached are two pictures of what my version shows. This is test code the scope starts with directly. Still have to hook it into the main menu and write the code for handling all the file actions.
Made some changes.
- The original code uses a two pixel wide line. My code uses a single pixel wide line for now.
- Added a check to see if there is a thumbnail available. The original code suggest there can be a mismatch between the two files used for the list data.
My code differs quite a bit from the original since that is so inefficient with a lot of unnecessary copying of data. It took quite a bit of time to work through all of it to get a proper understanding of what was going on.
My binary version of the code, which is far from finished, but already has a fair bit of the functionality of the original is now 183KB in size. The original binary is 1.6MB. Sure part of this is from not using the bitmaps, but still.