From a26a4275b2a27379809f512c5d572da7602afb51 Mon Sep 17 00:00:00 2001 From: Stephen White Date: Sun, 4 Nov 2018 17:14:28 +1100 Subject: [PATCH] Added USB drive support. --- src/FileBrowser.cpp | 214 +++++++++++++++++++++++++++++++------------- src/FileBrowser.h | 5 ++ src/diskio.cpp | 99 ++++++++------------ src/diskio.h | 1 + src/ff.cpp | 15 +++- src/ffconf.h | 9 +- src/main.cpp | 39 ++++++-- 7 files changed, 245 insertions(+), 137 deletions(-) diff --git a/src/FileBrowser.cpp b/src/FileBrowser.cpp index ffe2d5f..c83096a 100644 --- a/src/FileBrowser.cpp +++ b/src/FileBrowser.cpp @@ -42,6 +42,9 @@ extern Options options; extern void GlobalSetDeviceID(u8 id); 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]; static const u32 palette[] = @@ -498,6 +501,7 @@ FileBrowser::FileBrowser(InputMappings* inputMappings, DiskCaddy* diskCaddy, ROM , screenMain(screenMain) , screenLCD(screenLCD) , scrollHighlightRate(scrollHighlightRate) + , displayingDevices(false) { u32 columns = screenMain->ScaleX(80); u32 rows = (int)(38.0f * screenMain->GetScaleY()); @@ -557,58 +561,90 @@ void FileBrowser::RefreshFolderEntries() char* ext; folder.Clear(); - res = f_opendir(&dir, "."); - if (res == FR_OK) + if (displayingDevices) { - do - { - res = f_readdir(&dir, &entry.filImage); - 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); + char label[1024]; + DWORD vsn; + f_getlabel("SD:", label, &vsn); - // 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, "."); if (res == FR_OK) { do { - res = f_readdir(&dir, &entry.filIcon); - ext = strrchr(entry.filIcon.fname, '.'); - if (ext) + res = f_readdir(&dir, &entry.filImage); + 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 + res = f_opendir(&dir, "."); + if (res == FR_OK) + { + do { - int length = ext - entry.filIcon.fname; - if (res == FR_OK && entry.filIcon.fname[0] != 0 && strcasecmp(ext, ".png") == 0) + res = f_readdir(&dir, &entry.filIcon); + 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]; - if (strncasecmp(entry.filIcon.fname, entryAtIndex->filImage.fname, length) == 0) - entryAtIndex->filIcon = entry.filIcon; + for (unsigned index = 0; index < folder.entries.size(); ++index) + { + 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 @@ -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() { char buffer[1024]; if (f_getcwd(buffer, 1024) == FR_OK) { - // find the last '/' of the current dir - char *last_ptr = 0; - char *ptr = strtok(buffer, "/"); - while (ptr != NULL) + int deviceRoot = IsAtRootOfDevice(); + if (deviceRoot >= 0) { - last_ptr = ptr; - ptr = strtok(NULL, "/"); + displayingDevices = true; + RefreshFolderEntries(); + folder.currentIndex = deviceRoot; + folder.SetCurrent(); } - - f_chdir(".."); - RefreshFolderEntries(); - caddySelections.Clear(); - - unsigned found=0; - if (last_ptr) + else { - u32 numberOfEntriesMinus1 = folder.entries.size() - 1; - for (unsigned i=0; i <= numberOfEntriesMinus1 ; i++) + // find the last '/' of the current dir + char *last_ptr = 0; + char *ptr = strtok(buffer, "/"); + while (ptr != NULL) { - FileBrowser::BrowsableList::Entry* entry = &folder.entries[i]; - if (strcmp(last_ptr, entry->filImage.fname) == 0) + last_ptr = ptr; + 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; - break; + FileBrowser::BrowsableList::Entry* entry = &folder.entries[i]; + if (strcmp(last_ptr, entry->filImage.fname) == 0) + { + found = i; + break; + } } } - } - if (found) - { - folder.currentIndex=found; - folder.SetCurrent(); + if (found) + { + folder.currentIndex = found; + folder.SetCurrent(); + } } RefeshDisplay(); } @@ -989,7 +1052,32 @@ void FileBrowser::UpdateInputFolders() FileBrowser::BrowsableList::Entry* current = folder.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) { diff --git a/src/FileBrowser.h b/src/FileBrowser.h index e345b7a..5d28372 100644 --- a/src/FileBrowser.h +++ b/src/FileBrowser.h @@ -224,6 +224,9 @@ private: bool SelectROMOrDevice(u32 index); + // returns the volume index if at the root of a volume else -1 + int IsAtRootOfDevice(); + InputMappings* inputMappings; enum State @@ -248,6 +251,8 @@ private: float scrollHighlightRate; + bool displayingDevices; + char PNG[FILEBROWSER_MAX_PNG_SIZE]; }; #endif diff --git a/src/diskio.cpp b/src/diskio.cpp index 25dc6ef..a1480de 100644 --- a/src/diskio.cpp +++ b/src/diskio.cpp @@ -8,12 +8,20 @@ /*-----------------------------------------------------------------------*/ #include "diskio.h" /* FatFs lower layer API */ +#include "debug.h" +extern "C" +{ +#include +#include +} /* Definitions of physical drive number for each drive */ #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 CEMMCDevice* pEMMC; +static int USBDeviceIndex = -1; #define SD_BLOCK_SIZE 512 @@ -22,6 +30,11 @@ void disk_setEMM(CEMMCDevice* pEMMCDevice) pEMMC = pEMMCDevice; } +void disk_setUSB(unsigned deviceIndex) +{ + USBDeviceIndex = (int)deviceIndex; +} + int sd_card_init(struct block_device **dev) { 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) { // g_pLogger->Write("", LogNotice, "sd_read %d", block_no); - return pEMMC->DoRead(buf, buf_size, block_no); } @@ -130,46 +142,27 @@ DRESULT disk_read ( UINT count /* Number of sectors to read */ ) { - //DRESULT res; - //int result; - -// 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); - + //DEBUG_LOG("r pdrv = %d\r\n", pdrv); + if (pdrv == 0) + { 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; } buff += SD_BLOCK_SIZE; } return RES_OK; + } + else + { + unsigned bytes = (unsigned)USPiMassStorageDeviceRead(sector << UMSD_BLOCK_SHIFT, buff, count << UMSD_BLOCK_SHIFT, pdrv - 1); - //case DEV_USB : - // // translate the arguments here + if (bytes != (count << UMSD_BLOCK_SHIFT)) + return RES_ERROR; - // result = USB_disk_read(buff, sector, count); - - // // translate the reslut code here - - // return res; + return RES_OK; } return RES_PARERR; @@ -188,29 +181,9 @@ DRESULT disk_write ( UINT count /* Number of sectors to write */ ) { - //DRESULT res; - //int result; - - 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; - //} - + //DEBUG_LOG("w pdrv = %d\r\n", pdrv); + if (pdrv == 0) + { for (UINT s = 0; s < count; ++s) { 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; } + 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; - - //case DEV_USB : - // // translate the arguments here - - // result = USB_disk_write(buff, sector, count); - - // // translate the reslut code here - - // return res; } return RES_PARERR; diff --git a/src/diskio.h b/src/diskio.h index e09564c..2445d85 100644 --- a/src/diskio.h +++ b/src/diskio.h @@ -31,6 +31,7 @@ typedef enum { void disk_setEMM(CEMMCDevice* pEMMCDevice); +void disk_setUSB(unsigned deviceIndex); DSTATUS disk_initialize (BYTE pdrv); DSTATUS disk_status (BYTE pdrv); diff --git a/src/ff.cpp b/src/ff.cpp index 5a27728..40304d3 100644 --- a/src/ff.cpp +++ b/src/ff.cpp @@ -519,7 +519,7 @@ typedef struct { / at start-up. If not, either the linker or start-up routine being used is / not compliance with C standard. */ -#if _VOLUMES < 1 || _VOLUMES > 9 +#if _VOLUMES < 1 || _VOLUMES > 17 #error Wrong _VOLUMES setting #endif static FATFS *FatFs[_VOLUMES]; /* Pointer to the file system objects (logical drives) */ @@ -3863,7 +3863,9 @@ FRESULT f_getcwd ( TCHAR *tp; FILINFO fno; DEF_NAMBUF - +#if _STR_VOLUME_ID /* Find string drive id */ + static const char* const str[] = { _VOLUME_STRS }; +#endif *buff = 0; /* Get logical drive */ @@ -3902,7 +3904,16 @@ FRESULT f_getcwd ( tp = buff; if (res == FR_OK) { #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 */ +#endif *tp++ = ':'; #endif if (i == len) { /* Root-directory */ diff --git a/src/ffconf.h b/src/ffconf.h index 0ff0385..5e1a509 100644 --- a/src/ffconf.h +++ b/src/ffconf.h @@ -56,7 +56,7 @@ / (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(). / (0:Disable or 1:Enable) */ @@ -147,12 +147,13 @@ / Drive/Volume Configurations /---------------------------------------------------------------------------*/ -#define _VOLUMES 1 +#define _VOLUMES 17 /* Number of volumes (logical drives) to be used. */ -#define _STR_VOLUME_ID 0 -#define _VOLUME_STRS "RAM","NAND","CF","SD","SD2","USB","USB2","USB3" +#define _STR_VOLUME_ID 1 +//#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. / 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 diff --git a/src/main.cpp b/src/main.cpp index ab72a57..3afd264 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -47,7 +47,7 @@ extern "C" #include "ssd_logo.h" 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) // 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]; +int numberOfUSBMassStorageDevices = 0; DiskCaddy diskCaddy; Pi1541 pi1541; Pi1581 pi1581; @@ -109,6 +110,7 @@ u8 deviceID = 8; IEC_Commands m_IEC_Commands; InputMappings* inputMappings; Keyboard* keyboard; +bool USBKeyboardDetected = false; //bool resetWhileEmulating = false; bool selectedViaIECCommands = false; u16 pc; @@ -1456,15 +1458,26 @@ void Reboot_Pi() 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" { 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); - m_EMMC.Initialize(); - f_mount(&fileSystem, "", 1); + f_mount(&fileSystemSD, "SD:", 1); RPI_AuxMiniUartInit(115200, 8); @@ -1502,7 +1515,13 @@ extern "C" 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"); else DEBUG_LOG("Keyboard found\r\n"); @@ -1535,6 +1554,16 @@ extern "C" //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"); m_IEC_Commands.SetStarFileName(options.GetStarFileName());