Skip to content

Commit

Permalink
unified file system
Browse files Browse the repository at this point in the history
  • Loading branch information
cgreening committed Dec 17, 2024
1 parent 52f4b37 commit 547b692
Show file tree
Hide file tree
Showing 15 changed files with 173 additions and 47 deletions.
123 changes: 119 additions & 4 deletions firmware/src/Files/Files.h
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ class IFiles
virtual void createDirectory(const char *folder) = 0;
virtual FileLetterCountVector getFileLetters(const char *folder, const std::vector<std::string> &extensions) = 0;
virtual FileInfoVector getFileStartingWithPrefix(const char *folder, const char *prefix, const std::vector<std::string> &extensions) = 0;
virtual std::string getPath(const char *path) = 0;
};

template <class FileSystemT>
Expand All @@ -252,13 +253,18 @@ class FilesImplementation: public IFiles

bool isAvailable()
{
return fileSystem->isMounted();
return fileSystem && fileSystem->isMounted();
}

std::string getPath(const char *path)
{
return std::string(fileSystem->mountPoint()) + path;
}

void createDirectory(const char *folder)
{
auto bl = BusyLight();
if (!fileSystem->isMounted())
if (!fileSystem || !fileSystem->isMounted())
{
return;
}
Expand All @@ -280,7 +286,7 @@ class FilesImplementation: public IFiles
{
auto bl = BusyLight();
FileLetterCountVector fileLetters;
if (!fileSystem->isMounted())
if (!fileSystem || !fileSystem->isMounted())
{
return fileLetters;
}
Expand Down Expand Up @@ -316,7 +322,7 @@ class FilesImplementation: public IFiles
{
auto bl = BusyLight();
FileInfoVector files;
if (!fileSystem->isMounted())
if (!fileSystem || !fileSystem->isMounted())
{
return files;
}
Expand All @@ -337,3 +343,112 @@ class FilesImplementation: public IFiles
return files;
}
};

class UnifiedStorage : public IFiles {
private:
IFiles *flashFiles;
IFiles *sdFiles;

public:
UnifiedStorage(IFiles* flash, IFiles* sd)
: flashFiles(flash), sdFiles(sd) {}

bool isAvailable() override {
return (flashFiles->isAvailable()) || (sdFiles->isAvailable());
}

std::string getPath(const char *path) override {
if (sdFiles->isAvailable()) {
return sdFiles->getPath(path);
}
return flashFiles->getPath(path);
}

void createDirectory(const char *folder) override {
if (sdFiles->isAvailable()) {
sdFiles->createDirectory(folder);
return;
}
// fallback to flash
if (flashFiles->isAvailable()) {
flashFiles->createDirectory(folder);
}
}

FileLetterCountVector getFileLetters(const char *folder, const std::vector<std::string> &extensions) override {
std::map<std::string, int> letterCountMap;

// Get files from both sources
if (flashFiles->isAvailable()) {
auto flashLetters = flashFiles->getFileLetters(folder, extensions);
for (const auto& letterCount : flashLetters) {
letterCountMap[letterCount->getLetter()] = letterCount->getTitle().find_first_of("0123456789");
}
}

if (sdFiles->isAvailable()) {
auto sdLetters = sdFiles->getFileLetters(folder, extensions);
for (const auto& letterCount : sdLetters) {
auto it = letterCountMap.find(letterCount->getLetter());
if (it != letterCountMap.end()) {
// Extract numbers from both counts and add them
int existingCount = it->second;
int newCount = letterCount->getTitle().find_first_of("0123456789");
letterCountMap[letterCount->getLetter()] = existingCount + newCount;
} else {
letterCountMap[letterCount->getLetter()] = letterCount->getTitle().find_first_of("0123456789");
}
}
}

// Convert map back to vector
FileLetterCountVector combined;
for (const auto& pair : letterCountMap) {
combined.push_back(std::make_shared<FileLetterCount>(pair.first, pair.second));
}

// Sort alphabetically
std::sort(combined.begin(), combined.end(),
[](const FileLetterCountPtr& a, const FileLetterCountPtr& b) {
return a->getLetter() < b->getLetter();
});

return combined;
}

FileInfoVector getFileStartingWithPrefix(const char *folder, const char *prefix, const std::vector<std::string> &extensions) override {
FileInfoVector combined;
std::map<std::string, FileInfoPtr> uniqueFiles;

// Get files from both sources
if (flashFiles->isAvailable()) {
auto flashFiles = this->flashFiles->getFileStartingWithPrefix(folder, prefix, extensions);
for (const auto& file : flashFiles) {
uniqueFiles[file->getTitle()] = file;
}
}

if (sdFiles->isAvailable()) {
auto sdFiles = this->sdFiles->getFileStartingWithPrefix(folder, prefix, extensions);
for (const auto& file : sdFiles) {
// Only add if not already present from flash
if (uniqueFiles.find(file->getTitle()) == uniqueFiles.end()) {
uniqueFiles[file->getTitle()] = file;
}
}
}

// Convert map back to vector
for (const auto& pair : uniqueFiles) {
combined.push_back(pair.second);
}

// Sort alphabetically
std::sort(combined.begin(), combined.end(),
[](const FileInfoPtr& a, const FileInfoPtr& b) {
return a->getTitle() < b->getTitle();
});

return combined;
}
};
1 change: 1 addition & 0 deletions firmware/src/Files/Flash.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ class Flash
bool _isMounted;
std::string m_mountPoint;
public:
static constexpr const char* DEFAULT_MOUNT_POINT = "/flash";
Flash(const char *mountPoint);
~Flash();
bool isMounted() {
Expand Down
1 change: 1 addition & 0 deletions firmware/src/Files/SDCard.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class SDCard
int m_sector_size = 0;
int m_sector_count = 0;
public:
static constexpr const char* DEFAULT_MOUNT_POINT = "/sdcard";
bool isMounted() { return _isMounted; }
const char *mountPoint() {
return m_mountPoint.c_str();
Expand Down
3 changes: 1 addition & 2 deletions firmware/src/Screens/AlphabetPicker.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,11 @@ template <class FilePickerScreen_T>
class AlphabetPicker : public PickerScreen<FileLetterCountPtr>
{
private:
IFiles *m_files;
std::string m_path;
std::vector<std::string> m_extensions;
public:
AlphabetPicker(std::string title, IFiles *files, Display &tft, HDMIDisplay *hdmiDisplay, AudioOutput *audioOutput, std::string path, std::vector<std::string> extensions)
: m_files(files), PickerScreen(title, tft, hdmiDisplay, audioOutput), m_path(path), m_extensions(extensions)
: PickerScreen(title, tft, hdmiDisplay, audioOutput, files), m_path(path), m_extensions(extensions)
{
}
void onItemSelect(FileLetterCountPtr item, int index) override
Expand Down
10 changes: 6 additions & 4 deletions firmware/src/Screens/EmulatorScreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ void EmulatorScreen::triggerLoadTape()
no_sd_card_error,
m_tft,
m_hdmiDisplay,
m_audioOutput);
m_audioOutput,
m_files);
m_navigationStack->push(errorScreen);
return;
}
Expand All @@ -43,7 +44,8 @@ void EmulatorScreen::triggerLoadTape()
no_files_error,
m_tft,
m_hdmiDisplay,
m_audioOutput);
m_audioOutput,
m_files);
m_navigationStack->push(errorScreen);
return;
}
Expand All @@ -53,7 +55,7 @@ void EmulatorScreen::triggerLoadTape()
}

EmulatorScreen::EmulatorScreen(Display &tft, HDMIDisplay *hdmiDisplay, AudioOutput *audioOutput, IFiles *files)
: Screen(tft, hdmiDisplay, audioOutput), m_files(files)
: Screen(tft, hdmiDisplay, audioOutput, files)
{
renderer = new Renderer(tft, hdmiDisplay);
machine = new Machine(renderer, audioOutput, [&]()
Expand Down Expand Up @@ -160,7 +162,7 @@ void EmulatorScreen::pressKey(SpecKeys key)
else if (key == SPECKEY_2) {
isShowingMenu = false;
// show the save snapshot UI
m_navigationStack->push(new SaveSnapshotScreen(m_tft, m_hdmiDisplay, m_audioOutput, machine->getMachine()));
m_navigationStack->push(new SaveSnapshotScreen(m_tft, m_hdmiDisplay, m_audioOutput, machine->getMachine(), m_files));
}
}
}
Expand Down
1 change: 0 additions & 1 deletion firmware/src/Screens/EmulatorScreen.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ class EmulatorScreen : public Screen
Machine *machine = nullptr;
GameLoader *gameLoader = nullptr;
FILE *audioFile = nullptr;
IFiles *m_files;
void triggerLoadTape();
bool isLoading = false;
bool isInTimeTravelMode = false;
Expand Down
3 changes: 2 additions & 1 deletion firmware/src/Screens/ErrorScreen.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ class ErrorScreen : public Screen
std::vector<std::string> messages,
Display &tft,
HDMIDisplay *hdmiDisplay,
AudioOutput *audioOutput) : m_messages(messages), Screen(tft, hdmiDisplay, audioOutput)
AudioOutput *audioOutput,
IFiles *files) : m_messages(messages), Screen(tft, hdmiDisplay, audioOutput, files)
{
}

Expand Down
4 changes: 1 addition & 3 deletions firmware/src/Screens/GameFilePickerScreen.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,9 @@

class GameFilePickerScreen : public PickerScreen<FileInfoPtr>
{
private:
IFiles *m_files;
public:
GameFilePickerScreen(Display &tft, HDMIDisplay *hdmiDisplay, AudioOutput *audioOutput, IFiles *files)
: PickerScreen("Games", tft, hdmiDisplay, audioOutput), m_files(files) {}
: PickerScreen("Games", tft, hdmiDisplay, audioOutput, files) {}
void onItemSelect(FileInfoPtr item, int index) {
Serial.printf("Selected %s\n", item->getPath().c_str());
// locate the emaulator screen if it's on the stack already
Expand Down
12 changes: 6 additions & 6 deletions firmware/src/Screens/MainMenuScreen.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,9 @@ using MenuItemVector = std::vector<MenuItemPtr>;

class MainMenuScreen : public PickerScreen<MenuItemPtr>
{
private:
IFiles *m_files;

public:
MainMenuScreen(Display &tft, HDMIDisplay *hdmiDisplay, AudioOutput *audioOutput, IFiles *files) : m_files(files), PickerScreen("Main Menu", tft, hdmiDisplay, audioOutput)
MainMenuScreen(Display &tft, HDMIDisplay *hdmiDisplay, AudioOutput *audioOutput, IFiles *files)
: PickerScreen("Main Menu", tft, hdmiDisplay, audioOutput, files)
{
// Main menu
MenuItemVector menuItems = {
Expand Down Expand Up @@ -89,7 +87,8 @@ class MainMenuScreen : public PickerScreen<MenuItemPtr>
no_sd_card_error,
m_tft,
m_hdmiDisplay,
m_audioOutput);
m_audioOutput,
m_files);
m_navigationStack->push(errorScreen);
return;
}
Expand All @@ -101,7 +100,8 @@ class MainMenuScreen : public PickerScreen<MenuItemPtr>
no_files_error,
m_tft,
m_hdmiDisplay,
m_audioOutput);
m_audioOutput,
m_files);
m_navigationStack->push(errorScreen);
return;
}
Expand Down
5 changes: 3 additions & 2 deletions firmware/src/Screens/PickerScreen.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ class PickerScreen : public Screen
std::string title,
Display &tft,
HDMIDisplay *hdmiDisplay,
AudioOutput *audioOutput
) : title(title), Screen(tft, hdmiDisplay, audioOutput)
AudioOutput *audioOutput,
IFiles *files
) : title(title), Screen(tft, hdmiDisplay, audioOutput, files)
{
}

Expand Down
8 changes: 6 additions & 2 deletions firmware/src/Screens/SaveSnapshotScreen.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
#include "../Emulator/spectrum.h"
#include "../Emulator/snaps.h"

class IFiles;

class SaveSnapshotScreen : public Screen
{
private:
Expand All @@ -17,7 +19,8 @@ class SaveSnapshotScreen : public Screen
Display &tft,
HDMIDisplay *hdmiDisplay,
AudioOutput *audioOutput,
ZXSpectrum *machine) : machine(machine), Screen(tft, hdmiDisplay, audioOutput)
ZXSpectrum *machine,
IFiles *files) : machine(machine), Screen(tft, hdmiDisplay, audioOutput, files)
{
}

Expand All @@ -35,7 +38,8 @@ class SaveSnapshotScreen : public Screen
if (filename.length() > 0) {
auto bl = BusyLight();
drawBusy();
saveZ80(machine, ("/fs/snapshots/" + filename + ".Z80").c_str());
std::string fname = m_files->getPath("/snapshots") + "/" + filename + ".Z80";
saveZ80(machine, fname.c_str());
playSuccessBeep();
vTaskDelay(500 / portTICK_PERIOD_MS);
m_navigationStack->pop();
Expand Down
7 changes: 6 additions & 1 deletion firmware/src/Screens/Screen.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,22 @@
class Display;
class AudioOutput;
class NavigationStack;
class IFiles;

const uint8_t click[] = { 50, 50, 50, 0 };

class IFiles;

class Screen {
protected:
NavigationStack *m_navigationStack = nullptr;
Display &m_tft;
HDMIDisplay *m_hdmiDisplay = nullptr;
AudioOutput *m_audioOutput;
IFiles *m_files;
public:
Screen(Display &tft, HDMIDisplay *hdmiDisplay, AudioOutput *audioOutput) : m_tft(tft), m_hdmiDisplay(hdmiDisplay), m_audioOutput(audioOutput) {}
Screen(Display &tft, HDMIDisplay *hdmiDisplay, AudioOutput *audioOutput, IFiles *files)
: m_tft(tft), m_hdmiDisplay(hdmiDisplay), m_audioOutput(audioOutput), m_files(files) {}
// input
virtual void updateKey(SpecKeys key, uint8_t state) {};
virtual void pressKey(SpecKeys key) {};
Expand Down
6 changes: 2 additions & 4 deletions firmware/src/Screens/VideoFilePickerScreen.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,11 @@

class VideoFilePickerScreen : public PickerScreen<FileInfoPtr>
{
private:
IFiles *m_files;
public:
VideoFilePickerScreen(Display &tft, HDMIDisplay *hdmiDisplay, AudioOutput *audioOutput, IFiles *files)
: PickerScreen("Videos", tft, hdmiDisplay, audioOutput), m_files(files) {}
: PickerScreen("Videos", tft, hdmiDisplay, audioOutput, files) {}
void onItemSelect(FileInfoPtr item, int index) {
VideoPlayerScreen *playerScreen = new VideoPlayerScreen(m_tft, m_hdmiDisplay, m_audioOutput);
VideoPlayerScreen *playerScreen = new VideoPlayerScreen(m_tft, m_hdmiDisplay, m_audioOutput, m_files);
playerScreen->play(item->getPath().c_str());
m_navigationStack->push(playerScreen);
}
Expand Down
4 changes: 3 additions & 1 deletion firmware/src/Screens/VideoPlayerScreen.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ using fs::File;
#include "VideoPlayer/VideoPlayerState.h"

class VideoSource;
class IFiles;

class VideoPlayerScreen : public Screen
{
Expand Down Expand Up @@ -44,7 +45,8 @@ class VideoPlayerScreen : public Screen
VideoPlayerScreen(
Display &tft,
HDMIDisplay *hdmiDisplay,
AudioOutput *audioOutput) : Screen(tft, hdmiDisplay, audioOutput)
AudioOutput *audioOutput,
IFiles *files) : Screen(tft, hdmiDisplay, audioOutput, files)
{
}
void play(const char *aviFilename);
Expand Down
Loading

0 comments on commit 547b692

Please sign in to comment.