Files
Flipdot-display/src/esp32/display/bitmap_store.cpp
T

154 lines
3.7 KiB
C++
Raw Normal View History

2026-10-13 01:52:34 +02:00
#include "display/bitmap_store.h"
#include <LittleFS.h>
#include <strings.h>
#include "display/bitmaps.h"
static const char *DIR = "/bitmaps";
struct BuiltinBitmap
{
const char *name;
const uint8_t *data; // PROGMEM, BITMAP_BYTES
};
static const BuiltinBitmap BUILTIN[] = {
{"Nintendo", nintendo_bitmap_Nintendo_new},
{"Pikachu", pikachu_clock_bitmap},
{"Pikachu yawning", pikachu_yawning_clock_bitmap},
2026-10-13 01:52:34 +02:00
};
static bool mounted = false;
static uint32_t revision = 0;
2026-10-13 01:52:34 +02:00
static const BuiltinBitmap *builtin(const char *name)
{
for (const BuiltinBitmap &b : BUILTIN)
if (strcasecmp(b.name, name) == 0)
return &b;
return nullptr;
}
static String path(const char *name)
{
return String(DIR) + "/" + name + ".bin";
}
bool bitmapStoreBegin()
{
mounted = LittleFS.begin(true);
for (const char *dir : {DIR, "/pages", "/fonts"})
if (mounted && !LittleFS.exists(dir))
LittleFS.mkdir(dir);
2026-10-13 01:52:34 +02:00
Serial.printf("Bitmap storage %s\n", mounted ? "ready" : "not available (old flash layout?)");
return mounted;
}
bool bitmapStorageAvailable()
{
return mounted;
}
void bitmapStorageUsage(size_t &used, size_t &total)
{
used = mounted ? LittleFS.usedBytes() : 0;
total = mounted ? LittleFS.totalBytes() : 0;
}
std::vector<String> storedNames(const char *dir_path, const char *extension)
2026-10-13 01:52:34 +02:00
{
std::vector<String> names;
2026-10-13 01:52:34 +02:00
if (!mounted)
return names;
File dir = LittleFS.open(dir_path);
if (!dir)
return names;
2026-10-13 01:52:34 +02:00
for (File file = dir.openNextFile(); file; file = dir.openNextFile())
{
String name = file.name();
int slash = name.lastIndexOf('/');
if (slash >= 0)
name = name.substring(slash + 1);
if (!name.endsWith(extension))
2026-10-13 01:52:34 +02:00
continue;
name.remove(name.length() - strlen(extension));
if (validBitmapName(name.c_str()))
names.push_back(name);
2026-10-13 01:52:34 +02:00
}
return names;
}
std::vector<BitmapInfo> listBitmaps()
{
std::vector<BitmapInfo> list;
for (const BuiltinBitmap &b : BUILTIN)
list.push_back({b.name, true});
for (const String &name : storedNames(DIR, ".bin"))
if (!builtin(name.c_str()))
list.push_back({name, false});
2026-10-13 01:52:34 +02:00
return list;
}
uint32_t bitmapListRevision()
{
return revision;
}
2026-10-13 01:52:34 +02:00
bool bitmapExists(const char *name)
{
if (builtin(name))
return true;
return mounted && validBitmapName(name) && LittleFS.exists(path(name));
}
bool loadBitmap(const char *name, uint8_t *bitmap)
{
const BuiltinBitmap *b = builtin(name);
if (b)
{
memcpy_P(bitmap, b->data, BITMAP_BYTES);
return true;
}
// Checked first: open() logs an error for a missing file (images try names by state)
if (!mounted || !validBitmapName(name) || !LittleFS.exists(path(name)))
2026-10-13 01:52:34 +02:00
return false;
File file = LittleFS.open(path(name), "r");
if (!file)
return false;
bool ok = file.read(bitmap, BITMAP_BYTES) == (size_t)BITMAP_BYTES;
file.close();
return ok;
}
const char *saveBitmap(const char *name, const uint8_t *bitmap)
{
if (!validBitmapName(name))
return "Invalid name: use 1-24 letters, digits, spaces, - or _";
if (builtin(name))
return "A built-in bitmap has this name";
if (!mounted)
return "No bitmap storage (install the new flash layout over USB, see README)";
if (!LittleFS.exists(path(name)) && listBitmaps().size() >= (size_t)MAX_BITMAPS + (sizeof(BUILTIN) / sizeof(BUILTIN[0])))
return "Too many bitmaps, delete some first";
File file = LittleFS.open(path(name), "w");
if (!file)
return "Could not write the file";
bool ok = file.write(bitmap, BITMAP_BYTES) == (size_t)BITMAP_BYTES;
file.close();
revision++;
2026-10-13 01:52:34 +02:00
return ok ? nullptr : "Storage full";
}
const char *deleteBitmap(const char *name)
{
if (builtin(name))
return "Built-in bitmaps can't be deleted";
if (!mounted || !validBitmapName(name) || !LittleFS.exists(path(name)))
return "Bitmap not found";
if (!LittleFS.remove(path(name)))
return "Could not delete the file";
revision++;
return nullptr;
2026-10-13 01:52:34 +02:00
}