#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <SD.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#define UP_BUTTON_PIN 32 // Pin for up button
#define DOWN_BUTTON_PIN 33 // Pin for down button
#define SELECT_BUTTON_PIN 25 // Pin for select button
#define RETURN_BUTTON_PIN 26 // Pin for return button
#define MAX_FILE_COUNT 50 // Maximum number of files/folders to display
#define MAX_NAME_LENGTH 20 // Maximum length of file/folder names
// Define a struct to hold file/folder information
struct FileInfo {
char name[MAX_NAME_LENGTH];
bool isFolder;
};
FileInfo fileList[MAX_FILE_COUNT]; // Array to hold file/folder information
int fileCount = 0; // Number of files/folders in the array
int currentIndex = 0; // Index of the currently highlighted file/folder
int firstIndex = 0; // Index of the first file/folder to display on the screen
int lastIndex = 0; // Index of the last file/folder to display on the screen
void setup() {
// Initialize serial communication
Serial.begin(9600);
// Initialize the display
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(1);
// Initialize the SD card
if (!SD.begin(5)) {
Serial.println("SD card initialization failed!");
return;
}
// Load the file/folder information into the array
loadFiles();
// Display the file/folder list on the screen
displayList();
}
void loop() {
// Check if the up button is pressed
if (digitalRead(UP_BUTTON_PIN) == LOW) {
// Move the rectangle up one row
currentIndex--;
if (currentIndex < 0) {
currentIndex = fileCount - 1;
}
// Check if the first index needs to be updated
if (currentIndex < firstIndex) {
firstIndex--;
lastIndex--;
}
// Update the display
displayList();
}
// Check if the down button is pressed
if (digitalRead(DOWN_BUTTON_PIN) == LOW) {
// Move the rectangle down one row
currentIndex++;
if (currentIndex >= fileCount) {
currentIndex = 0;
}
// Check if the last index needs to be updated
if (currentIndex > lastIndex) {
lastIndex++;
firstIndex++;
}
// Update the display
displayList();
}
// Check if the select button is pressed
if (digitalRead(SELECT_BUTTON_PIN) == LOW) {
// Check if the current file/folder is a folder
if (fileList[currentIndex].isFolder) {
// Change to the selected folder
chdir(fileList[currentIndex].name);
// Load the file/folder information into the array
loadFiles();
// Reset the current, first, and last indices
currentIndex = 0;
firstIndex = 0;
lastIndex = min(fileCount - 1, SCREEN_HEIGHT / 8 - 1);
// Update the display
displayList();
}
else {
// Open the selected file
File file = SD.open(fileList[currentIndex].name);
// Read the contents of the file
String fileContents = "";
while (file.available()) {
fileContents += (char)file.read();
}
file.close();
// Display the contents of the file on the screen
display.clearDisplay();
display.setCursor(0, 0);
display.print(fileContents);
display.display();
// Wait for the user to press the return button
while (digitalRead(RETURN_BUTTON_PIN) == HIGH) {
delay(50);
}
// Display the file/folder list on the screen
displayList();
}
}
}
void loadFiles() {
// Clear the file list array and reset the file count
memset(fileList, 0, sizeof(fileList));
fileCount = 0;
// Open the current directory
File directory = SD.open(".");
// Iterate over the files/folders in the directory
while (File file = directory.openNextFile()) {
// Check if the file/folder name is too long
if (strlen(file.name()) > MAX_NAME_LENGTH) {
continue;
}
// Copy the file/folder name into the array
strcpy(fileList[fileCount].name, file.name());
// Check if the file is a folder
if (file.isDirectory()) {
fileList[fileCount].isFolder = true;
}
// Increment the file count
fileCount++;
// Check if the maximum file count has been reached
if (fileCount >= MAX_FILE_COUNT) {
break;
}
}
// Close the directory
directory.close();
// Sort the file list array
qsort(fileList, fileCount, sizeof(FileInfo), compareFileInfo);
}
void displayList() {
// Clear the display
display.clearDisplay();
// Draw the file/folder list
int y = 0;
for (int i = firstIndex; i <= lastIndex; i++) {
// Check if the current index is out of range
if (i >= fileCount) {
break;
}
// Draw the rectangle for the current row
if (i == currentIndex) {
display.drawRect(0, y, SCREEN_WIDTH, 8, WHITE);
}
// Print the file/folder name
display.setCursor(2, y + 1);
display.print(fileList[i].name);
// Move to the next row
y += 8;
}
// Display the contents of the display buffer
display.display();
}
int compareFileInfo(const void *a, const void *b) {
// Convert the void pointers to FileInfo pointers
FileInfo *infoA = (FileInfo *)a;
FileInfo *infoB = (FileInfo *)b;
// Compare the file/folder names
return strcasecmp(infoA->name, infoB->name);
}