This commit is contained in:
Stanislav Khromov 2026-01-19 21:50:44 +10:00 committed by GitHub
commit d293185ab2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 185 additions and 3 deletions

@ -1 +1 @@
Subproject commit bd4e6707503ab9c97d13ee0d8f8c69e9ff03cd12
Subproject commit 82e6f846bc427c130a3ca9ecf0b4d27214699d4e

View File

@ -0,0 +1,134 @@
#include "FormatSDCardActivity.h"
#include <GfxRenderer.h>
#include <SDCardManager.h>
#include <esp_system.h>
#include "MappedInputManager.h"
#include "fontIds.h"
void FormatSDCardActivity::taskTrampoline(void* param) {
auto* self = static_cast<FormatSDCardActivity*>(param);
self->displayTaskLoop();
}
void FormatSDCardActivity::onEnter() {
ActivityWithSubactivity::onEnter();
renderingMutex = xSemaphoreCreateMutex();
updateRequired = true;
xTaskCreate(&FormatSDCardActivity::taskTrampoline, "FormatSDCardTask",
4096, // Stack size
this, // Parameters
1, // Priority
&displayTaskHandle // Task handle
);
}
void FormatSDCardActivity::onExit() {
ActivityWithSubactivity::onExit();
xSemaphoreTake(renderingMutex, portMAX_DELAY);
if (displayTaskHandle) {
vTaskDelete(displayTaskHandle);
displayTaskHandle = nullptr;
}
vSemaphoreDelete(renderingMutex);
renderingMutex = nullptr;
}
void FormatSDCardActivity::displayTaskLoop() {
while (true) {
if (updateRequired) {
updateRequired = false;
xSemaphoreTake(renderingMutex, portMAX_DELAY);
render();
xSemaphoreGive(renderingMutex);
}
vTaskDelay(10 / portTICK_PERIOD_MS);
}
}
void FormatSDCardActivity::render() {
if (subActivity) return;
renderer.clearScreen();
renderer.drawCenteredText(UI_12_FONT_ID, 15, "Format SD Card", true, EpdFontFamily::BOLD);
if (state == WAITING_CONFIRMATION) {
renderer.drawCenteredText(UI_10_FONT_ID, 150, "WARNING!", true, EpdFontFamily::BOLD);
renderer.drawCenteredText(UI_10_FONT_ID, 200, "This will ERASE ALL DATA");
renderer.drawCenteredText(UI_10_FONT_ID, 230, "on the SD card including:");
renderer.drawCenteredText(UI_10_FONT_ID, 270, "- All books and documents");
renderer.drawCenteredText(UI_10_FONT_ID, 300, "- Reading progress");
renderer.drawCenteredText(UI_10_FONT_ID, 330, "- Cached data");
renderer.drawCenteredText(UI_10_FONT_ID, 380, "This action CANNOT be undone.");
const auto labels = mappedInput.mapLabels("Cancel", "FORMAT", "", "");
renderer.drawButtonHints(UI_10_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
} else if (state == FORMATTING) {
renderer.drawCenteredText(UI_10_FONT_ID, 300, "Formatting...", true, EpdFontFamily::BOLD);
renderer.drawCenteredText(UI_10_FONT_ID, 350, "Please wait, do not power off");
} else if (state == SUCCESS) {
renderer.drawCenteredText(UI_10_FONT_ID, 280, "Format Complete!", true, EpdFontFamily::BOLD);
renderer.drawCenteredText(UI_10_FONT_ID, 330, "SD card has been formatted.");
renderer.drawCenteredText(UI_10_FONT_ID, 380, "Device will restart...");
} else if (state == FAILED) {
renderer.drawCenteredText(UI_10_FONT_ID, 300, "Format Failed", true, EpdFontFamily::BOLD);
renderer.drawCenteredText(UI_10_FONT_ID, 350, "Please try again or check SD card.");
const auto labels = mappedInput.mapLabels("« Back", "", "", "");
renderer.drawButtonHints(UI_10_FONT_ID, labels.btn1, labels.btn2, labels.btn3, labels.btn4);
}
renderer.displayBuffer();
}
void FormatSDCardActivity::loop() {
if (subActivity) {
subActivity->loop();
return;
}
if (state == WAITING_CONFIRMATION) {
if (mappedInput.wasPressed(MappedInputManager::Button::Confirm)) {
xSemaphoreTake(renderingMutex, portMAX_DELAY);
state = FORMATTING;
render(); // Render synchronously to show "Formatting..." before we start
xSemaphoreGive(renderingMutex);
performFormat();
}
if (mappedInput.wasPressed(MappedInputManager::Button::Back)) {
goBack();
}
return;
}
if (state == FAILED) {
if (mappedInput.wasPressed(MappedInputManager::Button::Back)) {
goBack();
}
return;
}
if (state == SUCCESS) {
// Auto-restart after brief delay
vTaskDelay(2000 / portTICK_PERIOD_MS);
esp_restart();
}
}
void FormatSDCardActivity::performFormat() {
Serial.printf("[%lu] [FORMAT] Starting SD card format...\n", millis());
// Call the format method on SDCardManager
bool success = SdMan.format(&Serial);
xSemaphoreTake(renderingMutex, portMAX_DELAY);
state = success ? SUCCESS : FAILED;
xSemaphoreGive(renderingMutex);
updateRequired = true;
Serial.printf("[%lu] [FORMAT] Format %s\n", millis(), success ? "succeeded" : "failed");
}

View File

@ -0,0 +1,32 @@
#pragma once
#include <freertos/FreeRTOS.h>
#include <freertos/semphr.h>
#include <freertos/task.h>
#include <functional>
#include "activities/ActivityWithSubactivity.h"
class FormatSDCardActivity final : public ActivityWithSubactivity {
enum State { WAITING_CONFIRMATION, FORMATTING, SUCCESS, FAILED };
TaskHandle_t displayTaskHandle = nullptr;
SemaphoreHandle_t renderingMutex = nullptr;
bool updateRequired = false;
const std::function<void()> goBack;
State state = WAITING_CONFIRMATION;
static void taskTrampoline(void* param);
[[noreturn]] void displayTaskLoop();
void render();
void performFormat();
public:
explicit FormatSDCardActivity(GfxRenderer& renderer, MappedInputManager& mappedInput,
const std::function<void()>& goBack)
: ActivityWithSubactivity("FormatSDCard", renderer, mappedInput), goBack(goBack) {}
void onEnter() override;
void onExit() override;
void loop() override;
bool preventAutoSleep() override { return state == FORMATTING; }
};

View File

@ -7,13 +7,14 @@
#include "CalibreSettingsActivity.h"
#include "CrossPointSettings.h"
#include "FormatSDCardActivity.h"
#include "MappedInputManager.h"
#include "OtaUpdateActivity.h"
#include "fontIds.h"
// Define the static settings list
namespace {
constexpr int settingsCount = 20;
constexpr int settingsCount = 21;
const SettingInfo settingsList[settingsCount] = {
// Should match with SLEEP_SCREEN_MODE
SettingInfo::Enum("Sleep Screen", &CrossPointSettings::sleepScreen, {"Dark", "Light", "Custom", "Cover", "None"}),
@ -42,7 +43,8 @@ const SettingInfo settingsList[settingsCount] = {
SettingInfo::Enum("Refresh Frequency", &CrossPointSettings::refreshFrequency,
{"1 page", "5 pages", "10 pages", "15 pages", "30 pages"}),
SettingInfo::Action("Calibre Settings"),
SettingInfo::Action("Check for updates")};
SettingInfo::Action("Check for updates"),
SettingInfo::Action("Format SD Card")};
} // namespace
void SettingsActivity::taskTrampoline(void* param) {
@ -155,6 +157,14 @@ void SettingsActivity::toggleCurrentSetting() {
updateRequired = true;
}));
xSemaphoreGive(renderingMutex);
} else if (strcmp(setting.name, "Format SD Card") == 0) {
xSemaphoreTake(renderingMutex, portMAX_DELAY);
exitActivity();
enterNewActivity(new FormatSDCardActivity(renderer, mappedInput, [this] {
exitActivity();
updateRequired = true;
}));
xSemaphoreGive(renderingMutex);
}
} else {
// Only toggle if it's a toggle type and has a value pointer

View File

@ -6,6 +6,7 @@
#include <SDCardManager.h>
#include <SPI.h>
#include <builtinFonts/all.h>
#include <esp_system.h>
#include <cstring>
@ -150,6 +151,11 @@ void enterNewActivity(Activity* activity) {
// Verify long press on wake-up from deep sleep
void verifyWakeupLongPress() {
// Skip verification for software resets (for example when calling esp_restart after sd card format)
if (esp_reset_reason() == ESP_RST_SW) {
return;
}
// Give the user up to 1000ms to start holding the power button, and must hold for SETTINGS.getPowerButtonDuration()
const auto start = millis();
bool abort = false;