Added USB drive support.

This commit is contained in:
Stephen White 2018-11-04 17:14:28 +11:00
parent 2a8dad9f16
commit a26a4275b2
7 changed files with 245 additions and 137 deletions

View File

@ -42,6 +42,9 @@ extern Options options;
extern void GlobalSetDeviceID(u8 id); extern void GlobalSetDeviceID(u8 id);
extern void CheckAutoMountImage(EXIT_TYPE reset_reason , FileBrowser* fileBrowser); extern void CheckAutoMountImage(EXIT_TYPE reset_reason , FileBrowser* fileBrowser);
extern void SwitchDrive(const char* drive);
extern int numberOfUSBMassStorageDevices;
unsigned char FileBrowser::LSTBuffer[FileBrowser::LSTBuffer_size]; unsigned char FileBrowser::LSTBuffer[FileBrowser::LSTBuffer_size];
static const u32 palette[] = static const u32 palette[] =
@ -498,6 +501,7 @@ FileBrowser::FileBrowser(InputMappings* inputMappings, DiskCaddy* diskCaddy, ROM
, screenMain(screenMain) , screenMain(screenMain)
, screenLCD(screenLCD) , screenLCD(screenLCD)
, scrollHighlightRate(scrollHighlightRate) , scrollHighlightRate(scrollHighlightRate)
, displayingDevices(false)
{ {
u32 columns = screenMain->ScaleX(80); u32 columns = screenMain->ScaleX(80);
u32 rows = (int)(38.0f * screenMain->GetScaleY()); u32 rows = (int)(38.0f * screenMain->GetScaleY());
@ -557,58 +561,90 @@ void FileBrowser::RefreshFolderEntries()
char* ext; char* ext;
folder.Clear(); folder.Clear();
res = f_opendir(&dir, "."); if (displayingDevices)
if (res == FR_OK)
{ {
do char label[1024];
{ DWORD vsn;
res = f_readdir(&dir, &entry.filImage); f_getlabel("SD:", label, &vsn);
ext = strrchr(entry.filImage.fname, '.');
if (res == FR_OK && entry.filImage.fname[0] != 0 && !(ext && strcasecmp(ext, ".png") == 0))
folder.entries.push_back(entry);
}
while (res == FR_OK && entry.filImage.fname[0] != 0);
f_closedir(&dir);
// Now check for icons if (strlen(label) > 0)
sprintf(entry.filImage.fname, "SD: %s", label);
else
sprintf(entry.filImage.fname, "SD:");
entry.filImage.fattrib |= AM_DIR;
entry.filIcon.fname[0] = 0;
folder.entries.push_back(entry);
for (int USBDriveIndex = 0; USBDriveIndex < numberOfUSBMassStorageDevices; ++USBDriveIndex)
{
char USBDriveId[16];
sprintf(USBDriveId, "USB%02d:", USBDriveIndex + 1);
f_getlabel(USBDriveId, label, &vsn);
if (strlen(label) > 0)
sprintf(entry.filImage.fname, "%s %s", USBDriveId, label);
else
strcpy(entry.filImage.fname, USBDriveId);
entry.filImage.fattrib |= AM_DIR;
entry.filIcon.fname[0] = 0;
folder.entries.push_back(entry);
}
}
else
{
res = f_opendir(&dir, "."); res = f_opendir(&dir, ".");
if (res == FR_OK) if (res == FR_OK)
{ {
do do
{ {
res = f_readdir(&dir, &entry.filIcon); res = f_readdir(&dir, &entry.filImage);
ext = strrchr(entry.filIcon.fname, '.'); ext = strrchr(entry.filImage.fname, '.');
if (ext) if (res == FR_OK && entry.filImage.fname[0] != 0 && !(ext && strcasecmp(ext, ".png") == 0))
folder.entries.push_back(entry);
} while (res == FR_OK && entry.filImage.fname[0] != 0);
f_closedir(&dir);
// Now check for icons
res = f_opendir(&dir, ".");
if (res == FR_OK)
{
do
{ {
int length = ext - entry.filIcon.fname; res = f_readdir(&dir, &entry.filIcon);
if (res == FR_OK && entry.filIcon.fname[0] != 0 && strcasecmp(ext, ".png") == 0) ext = strrchr(entry.filIcon.fname, '.');
if (ext)
{ {
for (unsigned index = 0; index < folder.entries.size(); ++index) int length = ext - entry.filIcon.fname;
if (res == FR_OK && entry.filIcon.fname[0] != 0 && strcasecmp(ext, ".png") == 0)
{ {
FileBrowser::BrowsableList::Entry* entryAtIndex = &folder.entries[index]; for (unsigned index = 0; index < folder.entries.size(); ++index)
if (strncasecmp(entry.filIcon.fname, entryAtIndex->filImage.fname, length) == 0) {
entryAtIndex->filIcon = entry.filIcon; FileBrowser::BrowsableList::Entry* entryAtIndex = &folder.entries[index];
if (strncasecmp(entry.filIcon.fname, entryAtIndex->filImage.fname, length) == 0)
entryAtIndex->filIcon = entry.filIcon;
}
} }
} }
} } while (res == FR_OK && entry.filIcon.fname[0] != 0);
} }
while (res == FR_OK && entry.filIcon.fname[0] != 0); f_closedir(&dir);
strcpy(entry.filImage.fname, "..");
entry.filImage.fattrib |= AM_DIR;
entry.filIcon.fname[0] = 0;
folder.entries.push_back(entry);
std::sort(folder.entries.begin(), folder.entries.end(), greater());
folder.currentIndex = 0;
folder.SetCurrent();
}
else
{
//DEBUG_LOG("Cannot open dir");
} }
f_closedir(&dir);
strcpy(entry.filImage.fname, "..");
entry.filImage.fattrib |= AM_DIR;
entry.filIcon.fname[0] = 0;
folder.entries.push_back(entry);
std::sort(folder.entries.begin(), folder.entries.end(), greater());
folder.currentIndex = 0;
folder.SetCurrent();
}
else
{
//DEBUG_LOG("Cannot open dir");
} }
// incase they deleted something selected in the caddy // incase they deleted something selected in the caddy
@ -807,42 +843,69 @@ void FileBrowser::DisplayPNG()
} }
} }
int FileBrowser::IsAtRootOfDevice()
{
char buffer[1024];
if (f_getcwd(buffer, 1024) == FR_OK)
{
if (strcmp("SD:/", buffer) == 0)
return 0;
for (int USBDriveIndex = 0; USBDriveIndex < numberOfUSBMassStorageDevices; ++USBDriveIndex)
{
char USBDriveId[16];
sprintf(USBDriveId, "USB%02d:/", USBDriveIndex + 1);
if (strcmp(USBDriveId, buffer) == 0)
return USBDriveIndex + 1;
}
}
return -1;
}
void FileBrowser::PopFolder() void FileBrowser::PopFolder()
{ {
char buffer[1024]; char buffer[1024];
if (f_getcwd(buffer, 1024) == FR_OK) if (f_getcwd(buffer, 1024) == FR_OK)
{ {
// find the last '/' of the current dir int deviceRoot = IsAtRootOfDevice();
char *last_ptr = 0; if (deviceRoot >= 0)
char *ptr = strtok(buffer, "/");
while (ptr != NULL)
{ {
last_ptr = ptr; displayingDevices = true;
ptr = strtok(NULL, "/"); RefreshFolderEntries();
folder.currentIndex = deviceRoot;
folder.SetCurrent();
} }
else
f_chdir("..");
RefreshFolderEntries();
caddySelections.Clear();
unsigned found=0;
if (last_ptr)
{ {
u32 numberOfEntriesMinus1 = folder.entries.size() - 1; // find the last '/' of the current dir
for (unsigned i=0; i <= numberOfEntriesMinus1 ; i++) char *last_ptr = 0;
char *ptr = strtok(buffer, "/");
while (ptr != NULL)
{ {
FileBrowser::BrowsableList::Entry* entry = &folder.entries[i]; last_ptr = ptr;
if (strcmp(last_ptr, entry->filImage.fname) == 0) ptr = strtok(NULL, "/");
}
f_chdir("..");
RefreshFolderEntries();
unsigned found = 0;
if (last_ptr)
{
u32 numberOfEntriesMinus1 = folder.entries.size() - 1;
for (unsigned i = 0; i <= numberOfEntriesMinus1; i++)
{ {
found=i; FileBrowser::BrowsableList::Entry* entry = &folder.entries[i];
break; if (strcmp(last_ptr, entry->filImage.fname) == 0)
{
found = i;
break;
}
} }
} }
} if (found)
if (found) {
{ folder.currentIndex = found;
folder.currentIndex=found; folder.SetCurrent();
folder.SetCurrent(); }
} }
RefeshDisplay(); RefeshDisplay();
} }
@ -989,7 +1052,32 @@ void FileBrowser::UpdateInputFolders()
FileBrowser::BrowsableList::Entry* current = folder.current; FileBrowser::BrowsableList::Entry* current = folder.current;
if (current) if (current)
{ {
if (current->filImage.fattrib & AM_DIR) if (displayingDevices)
{
if (strncmp(current->filImage.fname, "SD", 2) == 0)
{
SwitchDrive("SD:");
displayingDevices = false;
RefreshFolderEntries();
}
else
{
for (int USBDriveIndex = 0; USBDriveIndex < numberOfUSBMassStorageDevices; ++USBDriveIndex)
{
char USBDriveId[16];
sprintf(USBDriveId, "USB%02d:", USBDriveIndex + 1);
if (strncmp(current->filImage.fname, USBDriveId, 5) == 0)
{
SwitchDrive(USBDriveId);
displayingDevices = false;
RefreshFolderEntries();
}
}
}
dirty = true;
}
else if (current->filImage.fattrib & AM_DIR)
{ {
if (strcmp(current->filImage.fname, "..") == 0) if (strcmp(current->filImage.fname, "..") == 0)
{ {

View File

@ -224,6 +224,9 @@ private:
bool SelectROMOrDevice(u32 index); bool SelectROMOrDevice(u32 index);
// returns the volume index if at the root of a volume else -1
int IsAtRootOfDevice();
InputMappings* inputMappings; InputMappings* inputMappings;
enum State enum State
@ -248,6 +251,8 @@ private:
float scrollHighlightRate; float scrollHighlightRate;
bool displayingDevices;
char PNG[FILEBROWSER_MAX_PNG_SIZE]; char PNG[FILEBROWSER_MAX_PNG_SIZE];
}; };
#endif #endif

View File

@ -8,12 +8,20 @@
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
#include "diskio.h" /* FatFs lower layer API */ #include "diskio.h" /* FatFs lower layer API */
#include "debug.h"
extern "C"
{
#include <uspi.h>
#include <uspi/usbmassdevice.h>
}
/* Definitions of physical drive number for each drive */ /* Definitions of physical drive number for each drive */
#define DEV_MMC 0 /* Example: Map MMC/SD card to physical drive 0 */ #define DEV_MMC 0 /* Example: Map MMC/SD card to physical drive 0 */
#define DEV_USB 1
//static struct emmc_block_dev *emmc_dev; //static struct emmc_block_dev *emmc_dev;
static CEMMCDevice* pEMMC; static CEMMCDevice* pEMMC;
static int USBDeviceIndex = -1;
#define SD_BLOCK_SIZE 512 #define SD_BLOCK_SIZE 512
@ -22,6 +30,11 @@ void disk_setEMM(CEMMCDevice* pEMMCDevice)
pEMMC = pEMMCDevice; pEMMC = pEMMCDevice;
} }
void disk_setUSB(unsigned deviceIndex)
{
USBDeviceIndex = (int)deviceIndex;
}
int sd_card_init(struct block_device **dev) int sd_card_init(struct block_device **dev)
{ {
return 0; return 0;
@ -30,7 +43,6 @@ int sd_card_init(struct block_device **dev)
size_t sd_read(uint8_t *buf, size_t buf_size, uint32_t block_no) size_t sd_read(uint8_t *buf, size_t buf_size, uint32_t block_no)
{ {
// g_pLogger->Write("", LogNotice, "sd_read %d", block_no); // g_pLogger->Write("", LogNotice, "sd_read %d", block_no);
return pEMMC->DoRead(buf, buf_size, block_no); return pEMMC->DoRead(buf, buf_size, block_no);
} }
@ -130,46 +142,27 @@ DRESULT disk_read (
UINT count /* Number of sectors to read */ UINT count /* Number of sectors to read */
) )
{ {
//DRESULT res; //DEBUG_LOG("r pdrv = %d\r\n", pdrv);
//int result; if (pdrv == 0)
{
// g_pLogger->Write("", LogNotice, "disk_read pdrv = %d", pdrv);
switch (pdrv) {
//case DEV_RAM :
// // translate the arguments here
// result = RAM_disk_read(buff, sector, count);
// // translate the reslut code here
// return res;
case DEV_MMC :
// translate the arguments here
//result = MMC_disk_read(buff, sector, count);
// g_pLogger->Write("", LogNotice, "!!!!!!!!!!!!!!!!!!!!!!!!!!!!disk_read %d %d buf_size = 0x%x", sector, count, buf_size);
for (UINT s = 0; s < count; ++s) for (UINT s = 0; s < count; ++s)
{ {
if (sd_read(buff, SD_BLOCK_SIZE, sector+s) < SD_BLOCK_SIZE) if (sd_read(buff, SD_BLOCK_SIZE, sector + s) < SD_BLOCK_SIZE)
{ {
return RES_ERROR; return RES_ERROR;
} }
buff += SD_BLOCK_SIZE; buff += SD_BLOCK_SIZE;
} }
return RES_OK; return RES_OK;
}
else
{
unsigned bytes = (unsigned)USPiMassStorageDeviceRead(sector << UMSD_BLOCK_SHIFT, buff, count << UMSD_BLOCK_SHIFT, pdrv - 1);
//case DEV_USB : if (bytes != (count << UMSD_BLOCK_SHIFT))
// // translate the arguments here return RES_ERROR;
// result = USB_disk_read(buff, sector, count); return RES_OK;
// // translate the reslut code here
// return res;
} }
return RES_PARERR; return RES_PARERR;
@ -188,29 +181,9 @@ DRESULT disk_write (
UINT count /* Number of sectors to write */ UINT count /* Number of sectors to write */
) )
{ {
//DRESULT res; //DEBUG_LOG("w pdrv = %d\r\n", pdrv);
//int result; if (pdrv == 0)
{
switch (pdrv) {
//case DEV_RAM :
// // translate the arguments here
// result = RAM_disk_write(buff, sector, count);
// // translate the reslut code here
// return res;
case DEV_MMC :
// translate the arguments here
//result = MMC_disk_write(buff, sector, count);
//size_t buf_size = count * SD_BLOCK_SIZE;
//if (sd_write((uint8_t *)buff, buf_size, sector) < buf_size)
//{
// return RES_ERROR;
//}
for (UINT s = 0; s < count; ++s) for (UINT s = 0; s < count; ++s)
{ {
if (sd_write((uint8_t *)buff, SD_BLOCK_SIZE, sector+s) < SD_BLOCK_SIZE) if (sd_write((uint8_t *)buff, SD_BLOCK_SIZE, sector+s) < SD_BLOCK_SIZE)
@ -219,17 +192,17 @@ DRESULT disk_write (
} }
buff += SD_BLOCK_SIZE; buff += SD_BLOCK_SIZE;
} }
return RES_OK;
}
else
{
unsigned bytes = (unsigned)USPiMassStorageDeviceWrite(sector << UMSD_BLOCK_SHIFT, buff, count << UMSD_BLOCK_SHIFT, pdrv - 1);
//DEBUG_LOG("USB disk_write %d %d\r\n", (int)sector, (int)count);
if (bytes != (count << UMSD_BLOCK_SHIFT))
return RES_ERROR;
return RES_OK; return RES_OK;
//case DEV_USB :
// // translate the arguments here
// result = USB_disk_write(buff, sector, count);
// // translate the reslut code here
// return res;
} }
return RES_PARERR; return RES_PARERR;

View File

@ -31,6 +31,7 @@ typedef enum {
void disk_setEMM(CEMMCDevice* pEMMCDevice); void disk_setEMM(CEMMCDevice* pEMMCDevice);
void disk_setUSB(unsigned deviceIndex);
DSTATUS disk_initialize (BYTE pdrv); DSTATUS disk_initialize (BYTE pdrv);
DSTATUS disk_status (BYTE pdrv); DSTATUS disk_status (BYTE pdrv);

View File

@ -519,7 +519,7 @@ typedef struct {
/ at start-up. If not, either the linker or start-up routine being used is / at start-up. If not, either the linker or start-up routine being used is
/ not compliance with C standard. */ / not compliance with C standard. */
#if _VOLUMES < 1 || _VOLUMES > 9 #if _VOLUMES < 1 || _VOLUMES > 17
#error Wrong _VOLUMES setting #error Wrong _VOLUMES setting
#endif #endif
static FATFS *FatFs[_VOLUMES]; /* Pointer to the file system objects (logical drives) */ static FATFS *FatFs[_VOLUMES]; /* Pointer to the file system objects (logical drives) */
@ -3863,7 +3863,9 @@ FRESULT f_getcwd (
TCHAR *tp; TCHAR *tp;
FILINFO fno; FILINFO fno;
DEF_NAMBUF DEF_NAMBUF
#if _STR_VOLUME_ID /* Find string drive id */
static const char* const str[] = { _VOLUME_STRS };
#endif
*buff = 0; *buff = 0;
/* Get logical drive */ /* Get logical drive */
@ -3902,7 +3904,16 @@ FRESULT f_getcwd (
tp = buff; tp = buff;
if (res == FR_OK) { if (res == FR_OK) {
#if _VOLUMES >= 2 #if _VOLUMES >= 2
#if _STR_VOLUME_ID /* Find string drive id */
const char* strptr = str[CurrVol];
while (*strptr != 0)
{
*tp++ = *strptr++;
}
#else
*tp++ = '0' + CurrVol; /* Put drive number */ *tp++ = '0' + CurrVol; /* Put drive number */
#endif
*tp++ = ':'; *tp++ = ':';
#endif #endif
if (i == len) { /* Root-directory */ if (i == len) { /* Root-directory */

View File

@ -56,7 +56,7 @@
/ (0:Disable or 1:Enable) Also _FS_READONLY needs to be 0 to enable this option. */ / (0:Disable or 1:Enable) Also _FS_READONLY needs to be 0 to enable this option. */
#define _USE_LABEL 0 #define _USE_LABEL 1
/* This option switches volume label functions, f_getlabel() and f_setlabel(). /* This option switches volume label functions, f_getlabel() and f_setlabel().
/ (0:Disable or 1:Enable) */ / (0:Disable or 1:Enable) */
@ -147,12 +147,13 @@
/ Drive/Volume Configurations / Drive/Volume Configurations
/---------------------------------------------------------------------------*/ /---------------------------------------------------------------------------*/
#define _VOLUMES 1 #define _VOLUMES 17
/* Number of volumes (logical drives) to be used. */ /* Number of volumes (logical drives) to be used. */
#define _STR_VOLUME_ID 0 #define _STR_VOLUME_ID 1
#define _VOLUME_STRS "RAM","NAND","CF","SD","SD2","USB","USB2","USB3" //#define _VOLUME_STRS "RAM","NAND","CF","SD","SD2","USB","USB2","USB3"
#define _VOLUME_STRS "SD","USB01","USB02","USB03","USB04","USB05","USB06","USB07","USB08","USB09","USB10","USB11","USB12","USB13","USB14","USB15","USB16"
/* _STR_VOLUME_ID switches string support of volume ID. /* _STR_VOLUME_ID switches string support of volume ID.
/ When _STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive / When _STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive
/ number in the path name. _VOLUME_STRS defines the drive ID strings for each / number in the path name. _VOLUME_STRS defines the drive ID strings for each

View File

@ -47,7 +47,7 @@ extern "C"
#include "ssd_logo.h" #include "ssd_logo.h"
unsigned versionMajor = 1; unsigned versionMajor = 1;
unsigned versionMinor = 15; unsigned versionMinor = 16;
// When the emulated CPU starts we execute the first million odd cycles in non-real-time (ie as fast as possible so the emulated 1541 becomes responsive to CBM-Browser asap) // When the emulated CPU starts we execute the first million odd cycles in non-real-time (ie as fast as possible so the emulated 1541 becomes responsive to CBM-Browser asap)
// During these cycles the CPU is executing the ROM self test routines (these do not need to be cycle accurate) // During these cycles the CPU is executing the ROM self test routines (these do not need to be cycle accurate)
@ -97,6 +97,7 @@ u8 LcdLogoFile[LCD_LOGO_MAX_SIZE];
u8 s_u8Memory[0xc000]; u8 s_u8Memory[0xc000];
int numberOfUSBMassStorageDevices = 0;
DiskCaddy diskCaddy; DiskCaddy diskCaddy;
Pi1541 pi1541; Pi1541 pi1541;
Pi1581 pi1581; Pi1581 pi1581;
@ -109,6 +110,7 @@ u8 deviceID = 8;
IEC_Commands m_IEC_Commands; IEC_Commands m_IEC_Commands;
InputMappings* inputMappings; InputMappings* inputMappings;
Keyboard* keyboard; Keyboard* keyboard;
bool USBKeyboardDetected = false;
//bool resetWhileEmulating = false; //bool resetWhileEmulating = false;
bool selectedViaIECCommands = false; bool selectedViaIECCommands = false;
u16 pc; u16 pc;
@ -1456,15 +1458,26 @@ void Reboot_Pi()
reboot_now(); reboot_now();
} }
void SwitchDrive(const char* drive)
{
FRESULT res;
res = f_chdrive(drive);
DEBUG_LOG("chdrive %s res %d\r\n", drive, res);
}
extern "C" extern "C"
{ {
void kernel_main(unsigned int r0, unsigned int r1, unsigned int atags) void kernel_main(unsigned int r0, unsigned int r1, unsigned int atags)
{ {
FATFS fileSystem; FRESULT res;
FATFS fileSystemSD;
FATFS fileSystemUSB[16];
m_EMMC.Initialize();
disk_setEMM(&m_EMMC); disk_setEMM(&m_EMMC);
m_EMMC.Initialize(); f_mount(&fileSystemSD, "SD:", 1);
f_mount(&fileSystem, "", 1);
RPI_AuxMiniUartInit(115200, 8); RPI_AuxMiniUartInit(115200, 8);
@ -1502,7 +1515,13 @@ extern "C"
USPiInitialize(); USPiInitialize();
if (!USPiKeyboardAvailable()) DEBUG_LOG("\r\n");
numberOfUSBMassStorageDevices = USPiMassStorageDeviceAvailable();
DEBUG_LOG("%d USB Mass Storage Devices found\r\n", numberOfUSBMassStorageDevices);
USBKeyboardDetected = USPiKeyboardAvailable();
if (!USBKeyboardDetected)
DEBUG_LOG("Keyboard not found\r\n"); DEBUG_LOG("Keyboard not found\r\n");
else else
DEBUG_LOG("Keyboard found\r\n"); DEBUG_LOG("Keyboard found\r\n");
@ -1535,6 +1554,16 @@ extern "C"
//PlaySoundDMA(); //PlaySoundDMA();
} }
for (int USBDriveIndex = 0; USBDriveIndex < numberOfUSBMassStorageDevices; ++USBDriveIndex)
{
char USBDriveId[16];
disk_setUSB(USBDriveIndex);
sprintf(USBDriveId, "USB%02d:", USBDriveIndex + 1);
res = f_mount(&fileSystemUSB[USBDriveIndex], USBDriveId, 1);
}
if (numberOfUSBMassStorageDevices > 0)
SwitchDrive("USB01:");
f_chdir("/1541"); f_chdir("/1541");
m_IEC_Commands.SetStarFileName(options.GetStarFileName()); m_IEC_Commands.SetStarFileName(options.GetStarFileName());