mirror of
https://github.com/daveallie/crosspoint-reader.git
synced 2026-02-04 14:47:37 +03:00
Merge 5f1b0d5c84 into f67c544e16
This commit is contained in:
commit
6476b42943
@ -148,6 +148,9 @@ The Settings screen allows you to configure the device's behavior. There are a f
|
|||||||
- **Reader Paragraph Alignment**: Set the alignment of paragraphs; options are "Justified" (default), "Left", "Center", or "Right".
|
- **Reader Paragraph Alignment**: Set the alignment of paragraphs; options are "Justified" (default), "Left", "Center", or "Right".
|
||||||
- **Time to Sleep**: Set the duration of inactivity before the device automatically goes to sleep.
|
- **Time to Sleep**: Set the duration of inactivity before the device automatically goes to sleep.
|
||||||
- **Refresh Frequency**: Set how often the screen does a full refresh while reading to reduce ghosting.
|
- **Refresh Frequency**: Set how often the screen does a full refresh while reading to reduce ghosting.
|
||||||
|
- **Sunlight Fading Fix**: Configure whether to enable a software-fix for the issue where white X4 models may fade when used in direct sunlight
|
||||||
|
- "OFF" (default) - Disable the fix
|
||||||
|
- "ON" - Enable the fix
|
||||||
- **OPDS Browser**: Configure OPDS server settings for browsing and downloading books. Set the server URL (for Calibre Content Server, add `/opds` to the end), and optionally configure username and password for servers requiring authentication. Note: Only HTTP Basic authentication is supported. If using Calibre Content Server with authentication enabled, you must set it to use Basic authentication instead of the default Digest authentication.
|
- **OPDS Browser**: Configure OPDS server settings for browsing and downloading books. Set the server URL (for Calibre Content Server, add `/opds` to the end), and optionally configure username and password for servers requiring authentication. Note: Only HTTP Basic authentication is supported. If using Calibre Content Server with authentication enabled, you must set it to use Basic authentication instead of the default Digest authentication.
|
||||||
- **Check for updates**: Check for firmware updates over WiFi.
|
- **Check for updates**: Check for firmware updates over WiFi.
|
||||||
|
|
||||||
|
|||||||
@ -411,7 +411,9 @@ void GfxRenderer::invertScreen() const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GfxRenderer::displayBuffer(const HalDisplay::RefreshMode refreshMode) const { display.displayBuffer(refreshMode); }
|
void GfxRenderer::displayBuffer(const HalDisplay::RefreshMode refreshMode) const {
|
||||||
|
display.displayBuffer(refreshMode, fadingFix);
|
||||||
|
}
|
||||||
|
|
||||||
std::string GfxRenderer::truncatedText(const int fontId, const char* text, const int maxWidth,
|
std::string GfxRenderer::truncatedText(const int fontId, const char* text, const int maxWidth,
|
||||||
const EpdFontFamily::Style style) const {
|
const EpdFontFamily::Style style) const {
|
||||||
@ -669,7 +671,7 @@ void GfxRenderer::copyGrayscaleLsbBuffers() const { display.copyGrayscaleLsbBuff
|
|||||||
|
|
||||||
void GfxRenderer::copyGrayscaleMsbBuffers() const { display.copyGrayscaleMsbBuffers(display.getFrameBuffer()); }
|
void GfxRenderer::copyGrayscaleMsbBuffers() const { display.copyGrayscaleMsbBuffers(display.getFrameBuffer()); }
|
||||||
|
|
||||||
void GfxRenderer::displayGrayBuffer() const { display.displayGrayBuffer(); }
|
void GfxRenderer::displayGrayBuffer() const { display.displayGrayBuffer(fadingFix); }
|
||||||
|
|
||||||
void GfxRenderer::freeBwBufferChunks() {
|
void GfxRenderer::freeBwBufferChunks() {
|
||||||
for (auto& bwBufferChunk : bwBufferChunks) {
|
for (auto& bwBufferChunk : bwBufferChunks) {
|
||||||
|
|||||||
@ -28,6 +28,7 @@ class GfxRenderer {
|
|||||||
HalDisplay& display;
|
HalDisplay& display;
|
||||||
RenderMode renderMode;
|
RenderMode renderMode;
|
||||||
Orientation orientation;
|
Orientation orientation;
|
||||||
|
bool fadingFix;
|
||||||
uint8_t* bwBufferChunks[BW_BUFFER_NUM_CHUNKS] = {nullptr};
|
uint8_t* bwBufferChunks[BW_BUFFER_NUM_CHUNKS] = {nullptr};
|
||||||
std::map<int, EpdFontFamily> fontMap;
|
std::map<int, EpdFontFamily> fontMap;
|
||||||
void renderChar(const EpdFontFamily& fontFamily, uint32_t cp, int* x, const int* y, bool pixelState,
|
void renderChar(const EpdFontFamily& fontFamily, uint32_t cp, int* x, const int* y, bool pixelState,
|
||||||
@ -36,7 +37,8 @@ class GfxRenderer {
|
|||||||
void rotateCoordinates(int x, int y, int* rotatedX, int* rotatedY) const;
|
void rotateCoordinates(int x, int y, int* rotatedX, int* rotatedY) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit GfxRenderer(HalDisplay& halDisplay) : display(halDisplay), renderMode(BW), orientation(Portrait) {}
|
explicit GfxRenderer(HalDisplay& halDisplay)
|
||||||
|
: display(halDisplay), renderMode(BW), orientation(Portrait), fadingFix(false) {}
|
||||||
~GfxRenderer() { freeBwBufferChunks(); }
|
~GfxRenderer() { freeBwBufferChunks(); }
|
||||||
|
|
||||||
static constexpr int VIEWABLE_MARGIN_TOP = 9;
|
static constexpr int VIEWABLE_MARGIN_TOP = 9;
|
||||||
@ -51,6 +53,9 @@ class GfxRenderer {
|
|||||||
void setOrientation(const Orientation o) { orientation = o; }
|
void setOrientation(const Orientation o) { orientation = o; }
|
||||||
Orientation getOrientation() const { return orientation; }
|
Orientation getOrientation() const { return orientation; }
|
||||||
|
|
||||||
|
// Fading fix control
|
||||||
|
void setFadingFix(const bool enabled) { fadingFix = enabled; }
|
||||||
|
|
||||||
// Screen ops
|
// Screen ops
|
||||||
int getScreenWidth() const;
|
int getScreenWidth() const;
|
||||||
int getScreenHeight() const;
|
int getScreenHeight() const;
|
||||||
|
|||||||
@ -28,7 +28,9 @@ EInkDisplay::RefreshMode convertRefreshMode(HalDisplay::RefreshMode mode) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HalDisplay::displayBuffer(HalDisplay::RefreshMode mode) { einkDisplay.displayBuffer(convertRefreshMode(mode)); }
|
void HalDisplay::displayBuffer(HalDisplay::RefreshMode mode, bool turnOffScreen) {
|
||||||
|
einkDisplay.displayBuffer(convertRefreshMode(mode), turnOffScreen);
|
||||||
|
}
|
||||||
|
|
||||||
void HalDisplay::refreshDisplay(HalDisplay::RefreshMode mode, bool turnOffScreen) {
|
void HalDisplay::refreshDisplay(HalDisplay::RefreshMode mode, bool turnOffScreen) {
|
||||||
einkDisplay.refreshDisplay(convertRefreshMode(mode), turnOffScreen);
|
einkDisplay.refreshDisplay(convertRefreshMode(mode), turnOffScreen);
|
||||||
@ -48,4 +50,4 @@ void HalDisplay::copyGrayscaleMsbBuffers(const uint8_t* msbBuffer) { einkDisplay
|
|||||||
|
|
||||||
void HalDisplay::cleanupGrayscaleBuffers(const uint8_t* bwBuffer) { einkDisplay.cleanupGrayscaleBuffers(bwBuffer); }
|
void HalDisplay::cleanupGrayscaleBuffers(const uint8_t* bwBuffer) { einkDisplay.cleanupGrayscaleBuffers(bwBuffer); }
|
||||||
|
|
||||||
void HalDisplay::displayGrayBuffer() { einkDisplay.displayGrayBuffer(); }
|
void HalDisplay::displayGrayBuffer(bool turnOffScreen) { einkDisplay.displayGrayBuffer(turnOffScreen); }
|
||||||
|
|||||||
@ -31,7 +31,7 @@ class HalDisplay {
|
|||||||
void drawImage(const uint8_t* imageData, uint16_t x, uint16_t y, uint16_t w, uint16_t h,
|
void drawImage(const uint8_t* imageData, uint16_t x, uint16_t y, uint16_t w, uint16_t h,
|
||||||
bool fromProgmem = false) const;
|
bool fromProgmem = false) const;
|
||||||
|
|
||||||
void displayBuffer(RefreshMode mode = RefreshMode::FAST_REFRESH);
|
void displayBuffer(RefreshMode mode = RefreshMode::FAST_REFRESH, bool turnOffScreen = false);
|
||||||
void refreshDisplay(RefreshMode mode = RefreshMode::FAST_REFRESH, bool turnOffScreen = false);
|
void refreshDisplay(RefreshMode mode = RefreshMode::FAST_REFRESH, bool turnOffScreen = false);
|
||||||
|
|
||||||
// Power management
|
// Power management
|
||||||
@ -45,7 +45,7 @@ class HalDisplay {
|
|||||||
void copyGrayscaleMsbBuffers(const uint8_t* msbBuffer);
|
void copyGrayscaleMsbBuffers(const uint8_t* msbBuffer);
|
||||||
void cleanupGrayscaleBuffers(const uint8_t* bwBuffer);
|
void cleanupGrayscaleBuffers(const uint8_t* bwBuffer);
|
||||||
|
|
||||||
void displayGrayBuffer();
|
void displayGrayBuffer(bool turnOffScreen = false);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EInkDisplay einkDisplay;
|
EInkDisplay einkDisplay;
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
Subproject commit bd4e6707503ab9c97d13ee0d8f8c69e9ff03cd12
|
Subproject commit c8ce3949b3368329c290ca1858e65dc3416fc591
|
||||||
@ -22,7 +22,7 @@ void readAndValidate(FsFile& file, uint8_t& member, const uint8_t maxValue) {
|
|||||||
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 = 23;
|
constexpr uint8_t SETTINGS_COUNT = 24;
|
||||||
constexpr char SETTINGS_FILE[] = "/.crosspoint/settings.bin";
|
constexpr char SETTINGS_FILE[] = "/.crosspoint/settings.bin";
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
@ -61,6 +61,7 @@ bool CrossPointSettings::saveToFile() const {
|
|||||||
serialization::writeString(outputFile, std::string(opdsPassword));
|
serialization::writeString(outputFile, std::string(opdsPassword));
|
||||||
serialization::writePod(outputFile, sleepScreenCoverFilter);
|
serialization::writePod(outputFile, sleepScreenCoverFilter);
|
||||||
// New fields added at end for backward compatibility
|
// New fields added at end for backward compatibility
|
||||||
|
serialization::writePod(outputFile, fadingFix);
|
||||||
outputFile.close();
|
outputFile.close();
|
||||||
|
|
||||||
Serial.printf("[%lu] [CPS] Settings saved to file\n", millis());
|
Serial.printf("[%lu] [CPS] Settings saved to file\n", millis());
|
||||||
@ -148,6 +149,8 @@ bool CrossPointSettings::loadFromFile() {
|
|||||||
if (++settingsRead >= fileSettingsCount) break;
|
if (++settingsRead >= fileSettingsCount) break;
|
||||||
readAndValidate(inputFile, sleepScreenCoverFilter, SLEEP_SCREEN_COVER_FILTER_COUNT);
|
readAndValidate(inputFile, sleepScreenCoverFilter, SLEEP_SCREEN_COVER_FILTER_COUNT);
|
||||||
if (++settingsRead >= fileSettingsCount) break;
|
if (++settingsRead >= fileSettingsCount) break;
|
||||||
|
serialization::readPod(inputFile, fadingFix);
|
||||||
|
if (++settingsRead >= fileSettingsCount) break;
|
||||||
// New fields added at end for backward compatibility
|
// New fields added at end for backward compatibility
|
||||||
} while (false);
|
} while (false);
|
||||||
|
|
||||||
|
|||||||
@ -137,6 +137,8 @@ class CrossPointSettings {
|
|||||||
uint8_t hideBatteryPercentage = HIDE_NEVER;
|
uint8_t hideBatteryPercentage = HIDE_NEVER;
|
||||||
// Long-press chapter skip on side buttons
|
// Long-press chapter skip on side buttons
|
||||||
uint8_t longPressChapterSkip = 1;
|
uint8_t longPressChapterSkip = 1;
|
||||||
|
// Sunlight fading compensation
|
||||||
|
uint8_t fadingFix = 0;
|
||||||
|
|
||||||
~CrossPointSettings() = default;
|
~CrossPointSettings() = default;
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,7 @@
|
|||||||
const char* SettingsActivity::categoryNames[categoryCount] = {"Display", "Reader", "Controls", "System"};
|
const char* SettingsActivity::categoryNames[categoryCount] = {"Display", "Reader", "Controls", "System"};
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
constexpr int displaySettingsCount = 6;
|
constexpr int displaySettingsCount = 7;
|
||||||
const SettingInfo displaySettings[displaySettingsCount] = {
|
const SettingInfo displaySettings[displaySettingsCount] = {
|
||||||
// Should match with SLEEP_SCREEN_MODE
|
// Should match with SLEEP_SCREEN_MODE
|
||||||
SettingInfo::Enum("Sleep Screen", &CrossPointSettings::sleepScreen, {"Dark", "Light", "Custom", "Cover", "None"}),
|
SettingInfo::Enum("Sleep Screen", &CrossPointSettings::sleepScreen, {"Dark", "Light", "Custom", "Cover", "None"}),
|
||||||
@ -22,7 +22,9 @@ const SettingInfo displaySettings[displaySettingsCount] = {
|
|||||||
{"None", "No Progress", "Full w/ Percentage", "Full w/ Progress Bar", "Progress Bar"}),
|
{"None", "No Progress", "Full w/ Percentage", "Full w/ Progress Bar", "Progress Bar"}),
|
||||||
SettingInfo::Enum("Hide Battery %", &CrossPointSettings::hideBatteryPercentage, {"Never", "In Reader", "Always"}),
|
SettingInfo::Enum("Hide Battery %", &CrossPointSettings::hideBatteryPercentage, {"Never", "In Reader", "Always"}),
|
||||||
SettingInfo::Enum("Refresh Frequency", &CrossPointSettings::refreshFrequency,
|
SettingInfo::Enum("Refresh Frequency", &CrossPointSettings::refreshFrequency,
|
||||||
{"1 page", "5 pages", "10 pages", "15 pages", "30 pages"})};
|
{"1 page", "5 pages", "10 pages", "15 pages", "30 pages"}),
|
||||||
|
SettingInfo::Enum("Sunlight Fading Fix", &CrossPointSettings::fadingFix, {"OFF", "ON"}),
|
||||||
|
};
|
||||||
|
|
||||||
constexpr int readerSettingsCount = 9;
|
constexpr int readerSettingsCount = 9;
|
||||||
const SettingInfo readerSettings[readerSettingsCount] = {
|
const SettingInfo readerSettings[readerSettingsCount] = {
|
||||||
|
|||||||
@ -344,6 +344,8 @@ void loop() {
|
|||||||
|
|
||||||
gpio.update();
|
gpio.update();
|
||||||
|
|
||||||
|
renderer.setFadingFix(SETTINGS.fadingFix);
|
||||||
|
|
||||||
if (Serial && millis() - lastMemPrint >= 10000) {
|
if (Serial && millis() - lastMemPrint >= 10000) {
|
||||||
Serial.printf("[%lu] [MEM] Free: %d bytes, Total: %d bytes, Min Free: %d bytes\n", millis(), ESP.getFreeHeap(),
|
Serial.printf("[%lu] [MEM] Free: %d bytes, Total: %d bytes, Min Free: %d bytes\n", millis(), ESP.getFreeHeap(),
|
||||||
ESP.getHeapSize(), ESP.getMinFreeHeap());
|
ESP.getHeapSize(), ESP.getMinFreeHeap());
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user