mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2024-12-12 03:04:32 +00:00
Save
parent
36589a8491
commit
3e31a4a3fd
374
SD-Card-(DEV).md
374
SD-Card-(DEV).md
@ -120,69 +120,369 @@ if(check_sd_card()) { // Check to see if SD Card is mounted
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Delete Directory
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Create File
|
### Create File
|
||||||
|
|
||||||
|
To create a file we can use the `create()` function from [File](https://github.com/eried/portapack-mayhem/blob/next/firmware/application/file.cpp) class. The helper function below will return true if `create()` succeeds (Success from `create()` returns a 0, other values means failure) and takes two variable inputs for file path and directory name. Again the input for the file path is a `std::filesystem::path` which can be `UTF-16 string literal`. The root of the SD Card is `u""` and any directory beyond that is `u"DIRECTORY/SUB_DIRECTORY"`.
|
||||||
|
|
||||||
|
#### ui_newapp.cpp
|
||||||
|
```
|
||||||
|
bool NewAppView::create_file(const std::filesystem::path& path, std::string name) {
|
||||||
|
File file = { }; // Create File object
|
||||||
|
Optional<File::Error> sucess = file.create(path.string() + "/" + name); // Create File
|
||||||
|
return !(sucess.is_valid()); // 0 is success
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Below is an example on how the `create_file()` function can be used with basic error handling.
|
||||||
|
|
||||||
|
#### ui_newapp.cpp
|
||||||
|
```
|
||||||
|
// New file
|
||||||
|
if(check_sd_card()) { // Check to see if SD Card is mounted
|
||||||
|
if(create_file(u"", "NEW_FILE.txt")) { // New file in root of SD Card, returns true if successful
|
||||||
|
// Logic if new file succeeded
|
||||||
|
} else {
|
||||||
|
// Logic else new file failed
|
||||||
|
}
|
||||||
|
} else { // Else, check_sd_card() returned false
|
||||||
|
// Logic else SD Card is NOT mounted
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### Read File
|
### Read File
|
||||||
|
|
||||||
### Write File
|
### Write File
|
||||||
|
|
||||||
### Delete File
|
### Delete File or Directory
|
||||||
|
|
||||||
|
**NOTE: Code below reflects future update, current implementation of delete_file() dose not return a value.**
|
||||||
|
|
||||||
|
To delete a file or directory the `delete_file()` function from [File](https://github.com/eried/portapack-mayhem/blob/next/firmware/application/file.cpp) can be used. The helper function below will return true if `delete_file()` succeeds (Success from `make_new_directory()` returns a 0, other values means failure) and takes two variable inputs for file path and directory name. Again the input for the file path is a `std::filesystem::path` which can be `UTF-16 string literal`. The root of the SD Card is `u""` and any directory beyond that is `u"DIRECTORY/SUB_DIRECTORY"`
|
||||||
|
|
||||||
|
#### ui_newapp.cpp
|
||||||
|
```
|
||||||
|
bool NewAppView::delete_dir_or_file(const std::filesystem::path& path, std::string name) {
|
||||||
|
return !(delete_file(path.string() + "/" + name));
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Below is an example on how the `delete_dir_or_file()` function can be used with basic error handling.
|
||||||
|
|
||||||
|
#### ui_newapp.cpp
|
||||||
|
```
|
||||||
|
if(check_sd_card()) { // Check to see if SD Card is mounted
|
||||||
|
if(delete_dir_or_file(u"", "NEW_DIR")) { // New dir in root of SD Card
|
||||||
|
// Logic if file/dir delete was successful
|
||||||
|
} else {
|
||||||
|
// Logic if file/dir delete was NOT successful
|
||||||
|
}
|
||||||
|
} else { // Else, check_sd_card() returned false
|
||||||
|
// Logic else SD Card is NOT mounted
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Wrap Up
|
## Wrap Up
|
||||||
|
|
||||||
|
Below is example demo of all basic CRUD functions for files and directorys.
|
||||||
|
|
||||||
### ui_newapp.hpp
|
### ui_newapp.hpp
|
||||||
|
```
|
||||||
|
#include "ui.hpp"
|
||||||
|
#include "ui_widget.hpp"
|
||||||
|
#include "ui_navigation.hpp"
|
||||||
|
#include "string_format.hpp"
|
||||||
|
|
||||||
#include "ui.hpp"
|
// Add these to include File Class and SD Card helper functions.
|
||||||
#include "ui_widget.hpp"
|
#include "file.hpp"
|
||||||
#include "ui_navigation.hpp"
|
#include "sd_card.hpp"
|
||||||
#include "string_format.hpp"
|
|
||||||
|
|
||||||
// Add this to include the File Class.
|
namespace ui
|
||||||
#include "file.hpp"
|
{
|
||||||
|
// Struct that outlines file information
|
||||||
|
struct file_entry {
|
||||||
|
std::filesystem::path entry_path { };
|
||||||
|
uint32_t size { };
|
||||||
|
bool is_directory { };
|
||||||
|
};
|
||||||
|
|
||||||
namespace ui
|
class NewAppView : public View // App class declaration
|
||||||
{
|
{
|
||||||
class NewAppView : public View // App class declaration
|
public:
|
||||||
{
|
|
||||||
public:
|
|
||||||
NewAppView(NavigationView &nav); // App class init function declaration
|
|
||||||
std::string title() const override { return "New App"; }; // App title
|
|
||||||
|
|
||||||
private:
|
// Public declarations
|
||||||
void update(); // Function declaration
|
void focus() override; // ui::View function override
|
||||||
MessageHandlerRegistration message_handler_update{ // Example, not required: MessageHandlerRegistration class
|
|
||||||
Message::ID::DisplayFrameSync, // relays messages to your app code from baseband. Every time you
|
NewAppView(NavigationView &nav); // App class init function declaration
|
||||||
[this](const Message *const) { // get a DisplayFrameSync message the update() function will
|
std::string title() const override { return "New App"; }; // App title
|
||||||
this->update(); // be triggered.
|
|
||||||
}};
|
private:
|
||||||
|
|
||||||
|
// Function declarations
|
||||||
|
|
||||||
|
// Error check
|
||||||
|
bool check_sd_card();
|
||||||
|
|
||||||
|
// DIR CRUD
|
||||||
|
bool create_dir(const std::filesystem::path& path, std::string name);
|
||||||
|
std::vector<file_entry> list_dir(const std::filesystem::path& path);
|
||||||
|
|
||||||
|
// File CRUD
|
||||||
|
bool create_file(const std::filesystem::path& path, std::string name);
|
||||||
|
bool rename_dir_or_file(const std::filesystem::path& path, std::string old_name, std::string new_name);
|
||||||
|
std::string read_file(const std::filesystem::path& path, std::string name);
|
||||||
|
bool write_file(const std::filesystem::path& path, std::string name, std::string data);
|
||||||
|
bool delete_dir_or_file(const std::filesystem::path& path, std::string name);
|
||||||
|
|
||||||
|
|
||||||
|
// Widgets
|
||||||
|
Console my_console {
|
||||||
|
{ 1*8, 1*8, 224, 296 }, // Coordinates are: int:x (px), int:y (px), int:width (px), int:height (px)
|
||||||
};
|
};
|
||||||
}
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### ui_newapp.cpp
|
### ui_newapp.cpp
|
||||||
|
```
|
||||||
|
#include "ui_newapp.hpp"
|
||||||
|
#include "portapack.hpp"
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
#include "ui_newapp.hpp"
|
using namespace portapack;
|
||||||
#include "portapack.hpp"
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
using namespace portapack;
|
namespace ui
|
||||||
|
{
|
||||||
|
|
||||||
namespace ui
|
void NewAppView::focus() { // Default selection to my_console when app starts
|
||||||
{
|
my_console.focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks SD Card, returns true if Mounted, false if otherwise
|
||||||
|
bool NewAppView::check_sd_card() {
|
||||||
|
//return (sd_card::status() == sd_card::Status::Mounted) ? true : false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lists all files and directorys in path
|
||||||
|
std::vector<file_entry> NewAppView::list_dir(const std::filesystem::path& path) {
|
||||||
|
|
||||||
|
// Files and directories list
|
||||||
|
std::vector<file_entry> entry_list { };
|
||||||
|
|
||||||
|
// For each entry in the file system's directory
|
||||||
|
// Adds files in directorys into entry_list{}
|
||||||
|
// Directorys are inserted infront of files
|
||||||
|
for (const auto& entry : std::filesystem::directory_iterator(path, u"*")) {
|
||||||
|
|
||||||
|
// Dose not add directorys or files starting with '.' (hidden / tmp)
|
||||||
|
if (entry.path().string().length() && entry.path().filename().string()[0] != '.') {
|
||||||
|
|
||||||
|
// If file
|
||||||
|
if (std::filesystem::is_regular_file(entry.status())) {
|
||||||
|
entry_list.push_back({ entry.path(), (uint32_t)entry.size(), false });
|
||||||
|
|
||||||
|
// Else If directory
|
||||||
|
} else if (std::filesystem::is_directory(entry.status())) {
|
||||||
|
entry_list.insert(entry_list.begin(), { entry.path(), 0, true });
|
||||||
|
|
||||||
|
// Other
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NewAppView::NewAppView(NavigationView &nav) // Application Main
|
|
||||||
{
|
|
||||||
// App code
|
|
||||||
}
|
}
|
||||||
|
return entry_list;
|
||||||
|
}
|
||||||
|
|
||||||
void NewAppView::update() // Every time you get a DisplayFrameSync message this function will be ran
|
|
||||||
{
|
// Creates dir, returns true if sucessfull
|
||||||
// Message code
|
bool NewAppView::create_dir(const std::filesystem::path& path, std::string name) { // make_new_directory() returns 0 for sucess
|
||||||
|
return !(make_new_directory(path.string() + "/" + name)); // and other values means failure. Not operation
|
||||||
|
} // will return true only when 0 is returned.
|
||||||
|
|
||||||
|
|
||||||
|
bool NewAppView::delete_dir_or_file(const std::filesystem::path& path, std::string name) { // Deletes file or dir.
|
||||||
|
return !(delete_file(path.string() + "/" + name)); // 0 is sucess.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool NewAppView::create_file(const std::filesystem::path& path, std::string name) {
|
||||||
|
File file = { }; // Create File object
|
||||||
|
Optional<File::Error> sucess = file.create(path.string() + "/" + name); // Create File
|
||||||
|
return !(sucess.is_valid()); // 0 is sucess
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool NewAppView::rename_dir_or_file(const std::filesystem::path& path, std::string old_name, std::string new_name) {
|
||||||
|
return !(rename_file(path.string() + "/" + old_name, new_name)); // 0 is sucess
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string NewAppView::read_file(const std::filesystem::path& path, std::string name) { // Read file
|
||||||
|
std::string return_string = ""; // String to be returned
|
||||||
|
File file; // Create File object
|
||||||
|
auto sucess = file.open(path.string() + "/" + name); // Open file to write
|
||||||
|
|
||||||
|
if(!sucess.is_valid()) { // 0 is sucess
|
||||||
|
char one_char[1]; // Read file char by char
|
||||||
|
for(size_t pointer = 0; pointer < file.size() ; pointer++) { // Example won't work for large files
|
||||||
|
file.seek(pointer); // Sets file to next pointer
|
||||||
|
file.read(one_char, 1); // sets char to one_char[]
|
||||||
|
return_string += one_char[0]; // Add it to the return_string
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return "0"; // Basic error handling
|
||||||
|
}
|
||||||
|
return return_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool NewAppView::write_file(const std::filesystem::path& path, std::string name, std::string data) {
|
||||||
|
File file; // Create File object
|
||||||
|
auto sucess = file.append(path.string() + "/" + name); // Open file
|
||||||
|
if(!sucess.is_valid()) { // 0 is sucess
|
||||||
|
file.write_line(data);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NewAppView::NewAppView(NavigationView &nav) // Application Main
|
||||||
|
{
|
||||||
|
add_children({
|
||||||
|
&my_console, // Add pointers for widgets
|
||||||
|
});
|
||||||
|
|
||||||
|
// Enable scrolling
|
||||||
|
my_console.enable_scrolling(true);
|
||||||
|
|
||||||
|
// Check SD Card
|
||||||
|
if(check_sd_card()) { // Check to see if SD Card is mounted
|
||||||
|
my_console.writeln("+ SD Card is Mounted");
|
||||||
|
} else { // Else, check_sd_card() returned false
|
||||||
|
my_console.writeln("- SD Card is NOT Mounted");
|
||||||
|
}
|
||||||
|
|
||||||
|
// New directory
|
||||||
|
if(check_sd_card()) { // Check to see if SD Card is mounted
|
||||||
|
if(create_dir(u"", "NEW_DIR")) { // New dir in root of SD Card, returns true if sucessfull
|
||||||
|
my_console.writeln("+ New directory created"); // If new dir succeeded
|
||||||
|
} else {
|
||||||
|
my_console.writeln("- New directory FAILED"); // Else new dir failed
|
||||||
|
}
|
||||||
|
} else { // Else, check_sd_card() returned false
|
||||||
|
my_console.writeln("- New directory FAILED");
|
||||||
|
}
|
||||||
|
|
||||||
|
// List Directory
|
||||||
|
std::string dir_contents = ""; // String var that displays the dir contents
|
||||||
|
std::vector<file_entry> files = { }; // file_entry Vector
|
||||||
|
if(check_sd_card()) { // Check to see if SD Card is mounted
|
||||||
|
files = list_dir(u""); // dir of SD Card, u"" is root, u"DIRECTORY_NAME" for other directorys
|
||||||
|
// Vector has a capacity of 64 objects
|
||||||
|
if(files.size()) { // If files are not empty
|
||||||
|
dir_contents += "+ dir SD Card: ";
|
||||||
|
for (const auto& f : files) { // For each f of files
|
||||||
|
dir_contents += f.entry_path.string() + ", "; // Copy name to dir_contents
|
||||||
|
}
|
||||||
|
} else { // Else, files are empty
|
||||||
|
my_console.writeln("- dir SD Card FAILED");
|
||||||
|
}
|
||||||
|
} else { // Else, check_sd_card() returned false
|
||||||
|
my_console.writeln("- dir SD Card FAILED");
|
||||||
|
}
|
||||||
|
//my_console.writeln(dir_contents); // Write results to my_console
|
||||||
|
// Write total count to my_console
|
||||||
|
my_console.writeln("+ dir SD Card: " + std::to_string(files.size()) + " items");
|
||||||
|
|
||||||
|
// Rename directory
|
||||||
|
if(check_sd_card()) { // Check to see if SD Card is mounted
|
||||||
|
if(rename_dir_or_file(u"", "NEW_DIR", "NEWER_DIR")) { // Renames dir in root of SD Card, returns true if sucessfull
|
||||||
|
my_console.writeln("+ Directory renamed"); // If dir renamed succeeded
|
||||||
|
} else {
|
||||||
|
my_console.writeln("- Directory renamed FAILED"); // Else new dir renamed failed
|
||||||
|
}
|
||||||
|
} else { // Else, check_sd_card() returned false
|
||||||
|
my_console.writeln("- Directory renamed FAILED");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete file or directory
|
||||||
|
if(check_sd_card()) { // Check to see if SD Card is mounted
|
||||||
|
if(delete_dir_or_file(u"", "NEWER_DIR")) { // New dir in root of SD Card
|
||||||
|
my_console.writeln("+ New directory deleted");
|
||||||
|
} else {
|
||||||
|
my_console.writeln("- New directory deleted FAILED");
|
||||||
|
}
|
||||||
|
} else { // Else, check_sd_card() returned false
|
||||||
|
my_console.writeln("- New directory deleted FAILED");
|
||||||
|
}
|
||||||
|
|
||||||
|
// New file
|
||||||
|
if(check_sd_card()) { // Check to see if SD Card is mounted
|
||||||
|
if(create_file(u"", "NEW_FILE.txt")) { // New dir in root of SD Card, returns true if sucessfull
|
||||||
|
my_console.writeln("+ New file created"); // If new file succeeded
|
||||||
|
} else {
|
||||||
|
my_console.writeln("- New file FAILED"); // Else new file failed
|
||||||
|
}
|
||||||
|
} else { // Else, check_sd_card() returned false
|
||||||
|
my_console.writeln("- New file FAILED");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rename file
|
||||||
|
if(check_sd_card()) { // Check to see if SD Card is mounted
|
||||||
|
if(rename_dir_or_file(u"", "NEW_FILE.txt", "NEWER_FILE.TXT")) { // Renames file, returns true if sucessfull
|
||||||
|
my_console.writeln("+ File renamed"); // If file renamed succeeded
|
||||||
|
} else {
|
||||||
|
my_console.writeln("- File renamed FAILED"); // Else new file renamed failed
|
||||||
|
}
|
||||||
|
} else { // Else, check_sd_card() returned false
|
||||||
|
my_console.writeln("- File renamed FAILED");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write file
|
||||||
|
if(check_sd_card()) { // Check to see if SD Card is mounted
|
||||||
|
std::string data = "Your mother was a hamster!";
|
||||||
|
if(write_file(u"", "NEWER_FILE.TXT", data)) { // Sucess is anything but 0
|
||||||
|
my_console.writeln("+ Write File"); // Write data to my_console
|
||||||
|
} else {
|
||||||
|
my_console.writeln("- Write file FAILED");
|
||||||
|
}
|
||||||
|
} else { // Else, check_sd_card() returned false
|
||||||
|
my_console.writeln("- Write file FAILED");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read file
|
||||||
|
if(check_sd_card()) { // Check to see if SD Card is mounted
|
||||||
|
std::string data = ""; // Create output string
|
||||||
|
data = read_file(u"", "NEWER_FILE.TXT"); // read_file()
|
||||||
|
if(data != "0") { // Sucess is anything but 0
|
||||||
|
my_console.writeln("+ Read file: " + data); // Write data to my_console
|
||||||
|
} else {
|
||||||
|
my_console.writeln("- Read file FAILED");
|
||||||
|
}
|
||||||
|
} else { // Else, check_sd_card() returned false
|
||||||
|
my_console.writeln("- Read file FAILED");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete file or directory
|
||||||
|
if(check_sd_card()) { // Check to see if SD Card is mounted
|
||||||
|
if(delete_dir_or_file(u"", "NEWER_FILE.TXT")) { // New dir in root of SD Card
|
||||||
|
my_console.writeln("+ New file deleted");
|
||||||
|
} else {
|
||||||
|
my_console.writeln("- New file deleted FAILED");
|
||||||
|
}
|
||||||
|
} else { // Else, check_sd_card() returned false
|
||||||
|
my_console.writeln("- New file deleted FAILED");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Done
|
||||||
|
my_console.writeln("+ Demo Complete");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user