Compare commits

..

No commits in common. "37d55a308c7e1ccef716c5349928c269b47a43f4" and "3de07b925c8af5c58297524daa9b5230deff7142" have entirely different histories.

9 changed files with 65 additions and 99 deletions

View File

@ -12,7 +12,7 @@ CrossPointSettings CrossPointSettings::instance;
namespace { namespace {
constexpr uint8_t SETTINGS_FILE_VERSION = 1; constexpr uint8_t SETTINGS_FILE_VERSION = 1;
// Increment this when adding new persisted settings fields // Increment this when adding new persisted settings fields
constexpr uint8_t SETTINGS_COUNT = 15; constexpr uint8_t SETTINGS_COUNT = 14;
constexpr char SETTINGS_FILE[] = "/.crosspoint/settings.bin"; constexpr char SETTINGS_FILE[] = "/.crosspoint/settings.bin";
} // namespace } // namespace
@ -40,7 +40,6 @@ bool CrossPointSettings::saveToFile() const {
serialization::writePod(outputFile, paragraphAlignment); serialization::writePod(outputFile, paragraphAlignment);
serialization::writePod(outputFile, sleepTimeout); serialization::writePod(outputFile, sleepTimeout);
serialization::writePod(outputFile, refreshFrequency); serialization::writePod(outputFile, refreshFrequency);
serialization::writePod(outputFile, screenMargin);
serialization::writePod(outputFile, sleepScreenCoverMode); serialization::writePod(outputFile, sleepScreenCoverMode);
outputFile.close(); outputFile.close();
@ -94,10 +93,7 @@ bool CrossPointSettings::loadFromFile() {
if (++settingsRead >= fileSettingsCount) break; if (++settingsRead >= fileSettingsCount) break;
serialization::readPod(inputFile, refreshFrequency); serialization::readPod(inputFile, refreshFrequency);
if (++settingsRead >= fileSettingsCount) break; if (++settingsRead >= fileSettingsCount) break;
serialization::readPod(inputFile, screenMargin);
if (++settingsRead >= fileSettingsCount) break;
serialization::readPod(inputFile, sleepScreenCoverMode); serialization::readPod(inputFile, sleepScreenCoverMode);
if (++settingsRead >= fileSettingsCount) break;
} while (false); } while (false);
inputFile.close(); inputFile.close();

View File

@ -16,7 +16,7 @@ class CrossPointSettings {
CrossPointSettings& operator=(const CrossPointSettings&) = delete; CrossPointSettings& operator=(const CrossPointSettings&) = delete;
// Should match with SettingsActivity text // Should match with SettingsActivity text
enum SLEEP_SCREEN_MODE { DARK = 0, LIGHT = 1, CUSTOM = 2, COVER = 3, BLANK = 4 }; enum SLEEP_SCREEN_MODE { DARK = 0, LIGHT = 1, CUSTOM = 2, COVER = 3 };
enum SLEEP_SCREEN_COVER_MODE { FIT = 0, CROP = 1 }; enum SLEEP_SCREEN_COVER_MODE { FIT = 0, CROP = 1 };
// Status bar display type enum // Status bar display type enum
@ -78,9 +78,6 @@ class CrossPointSettings {
// E-ink refresh frequency (default 15 pages) // E-ink refresh frequency (default 15 pages)
uint8_t refreshFrequency = REFRESH_15; uint8_t refreshFrequency = REFRESH_15;
// Reader screen margin settings
uint8_t screenMargin = 5;
~CrossPointSettings() = default; ~CrossPointSettings() = default;
// Get singleton instance // Get singleton instance
@ -95,7 +92,6 @@ class CrossPointSettings {
float getReaderLineCompression() const; float getReaderLineCompression() const;
unsigned long getSleepTimeoutMs() const; unsigned long getSleepTimeoutMs() const;
int getRefreshFrequency() const; int getRefreshFrequency() const;
int getReaderScreenMargin() const;
}; };
// Helper macro to access settings // Helper macro to access settings

View File

@ -15,21 +15,21 @@ void ScreenComponents::drawBattery(const GfxRenderer& renderer, const int left,
// 1 column on left, 2 columns on right, 5 columns of battery body // 1 column on left, 2 columns on right, 5 columns of battery body
constexpr int batteryWidth = 15; constexpr int batteryWidth = 15;
constexpr int batteryHeight = 12; constexpr int batteryHeight = 10;
const int x = left; const int x = left;
const int y = top + 6; const int y = top + 8;
// Top line // Top line
renderer.drawLine(x + 1, y, x + batteryWidth - 3, y); renderer.drawLine(x, y, x + batteryWidth - 4, y);
// Bottom line // Bottom line
renderer.drawLine(x + 1, y + batteryHeight - 1, x + batteryWidth - 3, y + batteryHeight - 1); renderer.drawLine(x, y + batteryHeight - 1, x + batteryWidth - 4, y + batteryHeight - 1);
// Left line // Left line
renderer.drawLine(x, y + 1, x, y + batteryHeight - 2); renderer.drawLine(x, y, x, y + batteryHeight - 1);
// Battery end // Battery end
renderer.drawLine(x + batteryWidth - 2, y + 1, x + batteryWidth - 2, y + batteryHeight - 2); renderer.drawLine(x + batteryWidth - 4, y, x + batteryWidth - 4, y + batteryHeight - 1);
renderer.drawPixel(x + batteryWidth - 1, y + 3); renderer.drawLine(x + batteryWidth - 3, y + 2, x + batteryWidth - 1, y + 2);
renderer.drawPixel(x + batteryWidth - 1, y + batteryHeight - 4); renderer.drawLine(x + batteryWidth - 3, y + batteryHeight - 3, x + batteryWidth - 1, y + batteryHeight - 3);
renderer.drawLine(x + batteryWidth - 0, y + 4, x + batteryWidth - 0, y + batteryHeight - 5); renderer.drawLine(x + batteryWidth - 1, y + 2, x + batteryWidth - 1, y + batteryHeight - 3);
// The +1 is to round up, so that we always fill at least one pixel // The +1 is to round up, so that we always fill at least one pixel
int filledWidth = percentage * (batteryWidth - 5) / 100 + 1; int filledWidth = percentage * (batteryWidth - 5) / 100 + 1;
@ -37,5 +37,5 @@ void ScreenComponents::drawBattery(const GfxRenderer& renderer, const int left,
filledWidth = batteryWidth - 5; // Ensure we don't overflow filledWidth = batteryWidth - 5; // Ensure we don't overflow
} }
renderer.fillRect(x + 2, y + 2, filledWidth, batteryHeight - 4); renderer.fillRect(x + 1, y + 1, filledWidth, batteryHeight - 2);
} }

View File

@ -28,10 +28,6 @@ void SleepActivity::onEnter() {
Activity::onEnter(); Activity::onEnter();
renderPopup("Entering Sleep..."); renderPopup("Entering Sleep...");
if (SETTINGS.sleepScreen == CrossPointSettings::SLEEP_SCREEN_MODE::BLANK) {
return renderBlankSleepScreen();
}
if (SETTINGS.sleepScreen == CrossPointSettings::SLEEP_SCREEN_MODE::CUSTOM) { if (SETTINGS.sleepScreen == CrossPointSettings::SLEEP_SCREEN_MODE::CUSTOM) {
return renderCustomSleepScreen(); return renderCustomSleepScreen();
} }
@ -255,8 +251,3 @@ void SleepActivity::renderCoverSleepScreen() const {
renderDefaultSleepScreen(); renderDefaultSleepScreen();
} }
void SleepActivity::renderBlankSleepScreen() const {
renderer.clearScreen();
renderer.displayBuffer(EInkDisplay::HALF_REFRESH);
}

View File

@ -15,5 +15,4 @@ class SleepActivity final : public Activity {
void renderCustomSleepScreen() const; void renderCustomSleepScreen() const;
void renderCoverSleepScreen() const; void renderCoverSleepScreen() const;
void renderBitmapSleepScreen(const Bitmap& bitmap) const; void renderBitmapSleepScreen(const Bitmap& bitmap) const;
void renderBlankSleepScreen() const;
}; };

View File

@ -381,7 +381,7 @@ void CrossPointWebServerActivity::renderServerRunning() const {
renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 3, renderer.drawCenteredText(SMALL_FONT_ID, startY + LINE_SPACING * 3,
"or scan QR code with your phone to connect to Wifi."); "or scan QR code with your phone to connect to Wifi.");
// Show QR code for URL // Show QR code for URL
const std::string wifiConfig = std::string("WIFI:S:") + connectedSSID + ";;"; std::string wifiConfig = std::string("WIFI:T:WPA;S:") + connectedSSID + ";P:" + "" + ";;";
drawQRCode(renderer, (480 - 6 * 33) / 2, startY + LINE_SPACING * 4, wifiConfig); drawQRCode(renderer, (480 - 6 * 33) / 2, startY + LINE_SPACING * 4, wifiConfig);
startY += 6 * 29 + 3 * LINE_SPACING; startY += 6 * 29 + 3 * LINE_SPACING;

View File

@ -16,6 +16,8 @@ namespace {
// pagesPerRefresh now comes from SETTINGS.getRefreshFrequency() // pagesPerRefresh now comes from SETTINGS.getRefreshFrequency()
constexpr unsigned long skipChapterMs = 700; constexpr unsigned long skipChapterMs = 700;
constexpr unsigned long goHomeMs = 1000; constexpr unsigned long goHomeMs = 1000;
constexpr int topPadding = 5;
constexpr int horizontalPadding = 5;
constexpr int statusBarMargin = 19; constexpr int statusBarMargin = 19;
} // namespace } // namespace
@ -251,9 +253,9 @@ void EpubReaderActivity::renderScreen() {
int orientedMarginTop, orientedMarginRight, orientedMarginBottom, orientedMarginLeft; int orientedMarginTop, orientedMarginRight, orientedMarginBottom, orientedMarginLeft;
renderer.getOrientedViewableTRBL(&orientedMarginTop, &orientedMarginRight, &orientedMarginBottom, renderer.getOrientedViewableTRBL(&orientedMarginTop, &orientedMarginRight, &orientedMarginBottom,
&orientedMarginLeft); &orientedMarginLeft);
orientedMarginTop += SETTINGS.screenMargin; orientedMarginTop += topPadding;
orientedMarginLeft += SETTINGS.screenMargin; orientedMarginLeft += horizontalPadding;
orientedMarginRight += SETTINGS.screenMargin; orientedMarginRight += horizontalPadding;
orientedMarginBottom += statusBarMargin; orientedMarginBottom += statusBarMargin;
if (!section) { if (!section) {

View File

@ -1,7 +1,6 @@
#include "SettingsActivity.h" #include "SettingsActivity.h"
#include <GfxRenderer.h> #include <GfxRenderer.h>
#include <HardwareSerial.h>
#include "CrossPointSettings.h" #include "CrossPointSettings.h"
#include "MappedInputManager.h" #include "MappedInputManager.h"
@ -10,32 +9,46 @@
// Define the static settings list // Define the static settings list
namespace { namespace {
constexpr int settingsCount = 16; constexpr int settingsCount = 15;
const SettingInfo settingsList[settingsCount] = { const SettingInfo settingsList[settingsCount] = {
// Should match with SLEEP_SCREEN_MODE // Should match with SLEEP_SCREEN_MODE
SettingInfo::Enum("Sleep Screen", &CrossPointSettings::sleepScreen, {"Dark", "Light", "Custom", "Cover", "None"}), {"Sleep Screen", SettingType::ENUM, &CrossPointSettings::sleepScreen, {"Dark", "Light", "Custom", "Cover"}},
SettingInfo::Enum("Sleep Screen Cover Mode", &CrossPointSettings::sleepScreenCoverMode, {"Fit", "Crop"}), {"Sleep Screen Cover Mode", SettingType::ENUM, &CrossPointSettings::sleepScreenCoverMode, {"Fit", "Crop"}},
SettingInfo::Enum("Status Bar", &CrossPointSettings::statusBar, {"None", "No Progress", "Full"}), {"Status Bar", SettingType::ENUM, &CrossPointSettings::statusBar, {"None", "No Progress", "Full"}},
SettingInfo::Toggle("Extra Paragraph Spacing", &CrossPointSettings::extraParagraphSpacing), {"Extra Paragraph Spacing", SettingType::TOGGLE, &CrossPointSettings::extraParagraphSpacing, {}},
SettingInfo::Toggle("Short Power Button Click", &CrossPointSettings::shortPwrBtn), {"Short Power Button Click", SettingType::TOGGLE, &CrossPointSettings::shortPwrBtn, {}},
SettingInfo::Enum("Reading Orientation", &CrossPointSettings::orientation, {"Reading Orientation",
{"Portrait", "Landscape CW", "Inverted", "Landscape CCW"}), SettingType::ENUM,
SettingInfo::Enum("Front Button Layout", &CrossPointSettings::frontButtonLayout, &CrossPointSettings::orientation,
{"Bck, Cnfrm, Lft, Rght", "Lft, Rght, Bck, Cnfrm", "Lft, Bck, Cnfrm, Rght"}), {"Portrait", "Landscape CW", "Inverted", "Landscape CCW"}},
SettingInfo::Enum("Side Button Layout (reader)", &CrossPointSettings::sideButtonLayout, {"Front Button Layout",
{"Prev, Next", "Next, Prev"}), SettingType::ENUM,
SettingInfo::Enum("Reader Font Family", &CrossPointSettings::fontFamily, &CrossPointSettings::frontButtonLayout,
{"Bookerly", "Noto Sans", "Open Dyslexic"}), {"Bck, Cnfrm, Lft, Rght", "Lft, Rght, Bck, Cnfrm", "Lft, Bck, Cnfrm, Rght"}},
SettingInfo::Enum("Reader Font Size", &CrossPointSettings::fontSize, {"Small", "Medium", "Large", "X Large"}), {"Side Button Layout (reader)",
SettingInfo::Enum("Reader Line Spacing", &CrossPointSettings::lineSpacing, {"Tight", "Normal", "Wide"}), SettingType::ENUM,
SettingInfo::Value("Reader Screen Margin", &CrossPointSettings::screenMargin, {5, 40, 5}), &CrossPointSettings::sideButtonLayout,
SettingInfo::Enum("Reader Paragraph Alignment", &CrossPointSettings::paragraphAlignment, {"Prev, Next", "Next, Prev"}},
{"Justify", "Left", "Center", "Right"}), {"Reader Font Family",
SettingInfo::Enum("Time to Sleep", &CrossPointSettings::sleepTimeout, SettingType::ENUM,
{"1 min", "5 min", "10 min", "15 min", "30 min"}), &CrossPointSettings::fontFamily,
SettingInfo::Enum("Refresh Frequency", &CrossPointSettings::refreshFrequency, {"Bookerly", "Noto Sans", "Open Dyslexic"}},
{"1 page", "5 pages", "10 pages", "15 pages", "30 pages"}), {"Reader Font Size", SettingType::ENUM, &CrossPointSettings::fontSize, {"Small", "Medium", "Large", "X Large"}},
SettingInfo::Action("Check for updates")}; {"Reader Line Spacing", SettingType::ENUM, &CrossPointSettings::lineSpacing, {"Tight", "Normal", "Wide"}},
{"Reader Paragraph Alignment",
SettingType::ENUM,
&CrossPointSettings::paragraphAlignment,
{"Justify", "Left", "Center", "Right"}},
{"Time to Sleep",
SettingType::ENUM,
&CrossPointSettings::sleepTimeout,
{"1 min", "5 min", "10 min", "15 min", "30 min"}},
{"Refresh Frequency",
SettingType::ENUM,
&CrossPointSettings::refreshFrequency,
{"1 page", "5 pages", "10 pages", "15 pages", "30 pages"}},
{"Check for updates", SettingType::ACTION, nullptr, {}},
};
} // namespace } // namespace
void SettingsActivity::taskTrampoline(void* param) { void SettingsActivity::taskTrampoline(void* param) {
@ -45,6 +58,7 @@ void SettingsActivity::taskTrampoline(void* param) {
void SettingsActivity::onEnter() { void SettingsActivity::onEnter() {
Activity::onEnter(); Activity::onEnter();
renderingMutex = xSemaphoreCreateMutex(); renderingMutex = xSemaphoreCreateMutex();
// Reset selection to first item // Reset selection to first item
@ -54,7 +68,7 @@ void SettingsActivity::onEnter() {
updateRequired = true; updateRequired = true;
xTaskCreate(&SettingsActivity::taskTrampoline, "SettingsActivityTask", xTaskCreate(&SettingsActivity::taskTrampoline, "SettingsActivityTask",
4096, // Stack size 2048, // Stack size
this, // Parameters this, // Parameters
1, // Priority 1, // Priority
&displayTaskHandle // Task handle &displayTaskHandle // Task handle
@ -101,10 +115,12 @@ void SettingsActivity::loop() {
updateRequired = true; updateRequired = true;
} else if (mappedInput.wasPressed(MappedInputManager::Button::Down) || } else if (mappedInput.wasPressed(MappedInputManager::Button::Down) ||
mappedInput.wasPressed(MappedInputManager::Button::Right)) { mappedInput.wasPressed(MappedInputManager::Button::Right)) {
// Move selection down (with wrap around) // Move selection down
selectedSettingIndex = (selectedSettingIndex < settingsCount - 1) ? (selectedSettingIndex + 1) : 0; if (selectedSettingIndex < settingsCount - 1) {
selectedSettingIndex++;
updateRequired = true; updateRequired = true;
} }
}
} }
void SettingsActivity::toggleCurrentSetting() { void SettingsActivity::toggleCurrentSetting() {
@ -122,15 +138,6 @@ void SettingsActivity::toggleCurrentSetting() {
} else if (setting.type == SettingType::ENUM && setting.valuePtr != nullptr) { } else if (setting.type == SettingType::ENUM && setting.valuePtr != nullptr) {
const uint8_t currentValue = SETTINGS.*(setting.valuePtr); const uint8_t currentValue = SETTINGS.*(setting.valuePtr);
SETTINGS.*(setting.valuePtr) = (currentValue + 1) % static_cast<uint8_t>(setting.enumValues.size()); SETTINGS.*(setting.valuePtr) = (currentValue + 1) % static_cast<uint8_t>(setting.enumValues.size());
} else if (setting.type == SettingType::VALUE && setting.valuePtr != nullptr) {
// Decreasing would also be nice for large ranges I think but oh well can't have everything
const int8_t currentValue = SETTINGS.*(setting.valuePtr);
// Wrap to minValue if exceeding setting value boundary
if (currentValue + setting.valueRange.step > setting.valueRange.max) {
SETTINGS.*(setting.valuePtr) = setting.valueRange.min;
} else {
SETTINGS.*(setting.valuePtr) = currentValue + setting.valueRange.step;
}
} else if (setting.type == SettingType::ACTION) { } else if (setting.type == SettingType::ACTION) {
if (std::string(setting.name) == "Check for updates") { if (std::string(setting.name) == "Check for updates") {
xSemaphoreTake(renderingMutex, portMAX_DELAY); xSemaphoreTake(renderingMutex, portMAX_DELAY);
@ -189,8 +196,6 @@ void SettingsActivity::render() const {
} else if (settingsList[i].type == SettingType::ENUM && settingsList[i].valuePtr != nullptr) { } else if (settingsList[i].type == SettingType::ENUM && settingsList[i].valuePtr != nullptr) {
const uint8_t value = SETTINGS.*(settingsList[i].valuePtr); const uint8_t value = SETTINGS.*(settingsList[i].valuePtr);
valueText = settingsList[i].enumValues[value]; valueText = settingsList[i].enumValues[value];
} else if (settingsList[i].type == SettingType::VALUE && settingsList[i].valuePtr != nullptr) {
valueText = std::to_string(SETTINGS.*(settingsList[i].valuePtr));
} }
const auto width = renderer.getTextWidth(UI_10_FONT_ID, valueText.c_str()); const auto width = renderer.getTextWidth(UI_10_FONT_ID, valueText.c_str());
renderer.drawText(UI_10_FONT_ID, pageWidth - 20 - width, settingY, valueText.c_str(), i != selectedSettingIndex); renderer.drawText(UI_10_FONT_ID, pageWidth - 20 - width, settingY, valueText.c_str(), i != selectedSettingIndex);

View File

@ -11,37 +11,14 @@
class CrossPointSettings; class CrossPointSettings;
enum class SettingType { TOGGLE, ENUM, ACTION, VALUE }; enum class SettingType { TOGGLE, ENUM, ACTION };
// Structure to hold setting information // Structure to hold setting information
struct SettingInfo { struct SettingInfo {
const char* name; // Display name of the setting const char* name; // Display name of the setting
SettingType type; // Type of setting SettingType type; // Type of setting
uint8_t CrossPointSettings::* valuePtr; // Pointer to member in CrossPointSettings (for TOGGLE/ENUM/VALUE) uint8_t CrossPointSettings::* valuePtr; // Pointer to member in CrossPointSettings (for TOGGLE/ENUM)
std::vector<std::string> enumValues; std::vector<std::string> enumValues;
struct ValueRange {
uint8_t min;
uint8_t max;
uint8_t step;
};
// Bounds/step for VALUE type settings
ValueRange valueRange;
// Static constructors
static SettingInfo Toggle(const char* name, uint8_t CrossPointSettings::* ptr) {
return {name, SettingType::TOGGLE, ptr};
}
static SettingInfo Enum(const char* name, uint8_t CrossPointSettings::* ptr, std::vector<std::string> values) {
return {name, SettingType::ENUM, ptr, std::move(values)};
}
static SettingInfo Action(const char* name) { return {name, SettingType::ACTION, nullptr}; }
static SettingInfo Value(const char* name, uint8_t CrossPointSettings::* ptr, const ValueRange valueRange) {
return {name, SettingType::VALUE, ptr, {}, valueRange};
}
}; };
class SettingsActivity final : public ActivityWithSubactivity { class SettingsActivity final : public ActivityWithSubactivity {