From 37a48bf3b53140c9de9ccda87e7cc9c34583eaf5 Mon Sep 17 00:00:00 2001 From: dejvino Date: Mon, 3 Feb 2020 07:32:47 +0100 Subject: [PATCH] Added reading storage for text and current position, ability to copy from SD Card. --- components/epaper/EPD.c | 7 ++ components/epaper/EPD.h | 4 + main/CMakeLists.txt | 2 +- main/core/display.c | 8 ++ main/core/display.h | 2 + main/main.cpp | 2 - main/modes/InternalMemoryMenuMode.cpp | 27 ++++-- main/modes/ReaderMode.cpp | 28 +++++- main/modes/ReaderMode.h | 1 + main/modes/SdCardMenuMode.cpp | 13 ++- main/modes/reader/TextReader.cpp | 7 -- main/modes/reader/TextStorage.cpp | 2 +- main/modes/reader/reader_storage.c | 135 ++++++++++++++++++++++++++ main/modes/reader/reader_storage.h | 14 +++ 14 files changed, 230 insertions(+), 22 deletions(-) create mode 100644 main/modes/reader/reader_storage.c create mode 100644 main/modes/reader/reader_storage.h diff --git a/components/epaper/EPD.c b/components/epaper/EPD.c index 2872e4c..1d724c0 100644 --- a/components/epaper/EPD.c +++ b/components/epaper/EPD.c @@ -1749,6 +1749,13 @@ void EPD_clearStringRect(int x, int y, char *str) EPD_fillRect(x+dispWin.x1, y+dispWin.y1, w, h, _bg); } +void EPD_frameStringRect(int x, int y, char *str) +{ + int w = EPD_getStringWidth(str); + int h = EPD_getfontheight(); + EPD_drawRect(x+dispWin.x1, y+dispWin.y1, w, h, _fg); +} + //============================================================================== /** * bit-encoded bar position of all digits' bcd segments diff --git a/components/epaper/EPD.h b/components/epaper/EPD.h index ba82252..0654d81 100644 --- a/components/epaper/EPD.h +++ b/components/epaper/EPD.h @@ -529,6 +529,10 @@ int EPD_getStringWidth(char* str); */ void EPD_clearStringRect(int x, int y, char *str); +/* + * Frames the rectangle occupied by string with current foreground color + */ +void EPD_frameStringRect(int x, int y, char *str); /* * Compile font c source file to .fnt file diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index f78d9dd..da76928 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -1,5 +1,5 @@ FILE(GLOB_RECURSE app_sources *.cpp *.c) -set(COMPONENT_SRCS "${app_sources} main.cpp") +set(COMPONENT_SRCS "${app_sources}" "main.cpp") set(COMPONENT_ADD_INCLUDEDIRS "." "../components/") register_component() diff --git a/main/core/display.c b/main/core/display.c index f6271fd..ba40d30 100644 --- a/main/core/display.c +++ b/main/core/display.c @@ -111,3 +111,11 @@ void display_sleep() { EPD_PowerOff(); } + +void display_alert(char* text) +{ + EPD_clearStringRect(CENTER, CENTER, text); + EPD_print(text, CENTER, CENTER); + EPD_frameStringRect(CENTER, CENTER, text); + EPD_UpdateScreen(); +} diff --git a/main/core/display.h b/main/core/display.h index 4a59a06..b5b825e 100644 --- a/main/core/display.h +++ b/main/core/display.h @@ -14,6 +14,8 @@ void display_update(); void display_wake(); void display_sleep(); +void display_alert(char* text); + #ifdef __cplusplus } #endif diff --git a/main/main.cpp b/main/main.cpp index 4a0b098..e49916f 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -6,8 +6,6 @@ #include #include "esp_system.h" #include "driver/gpio.h" -#include "esp_system.h" -#include "esp_heap_alloc_caps.h" #include "esp_log.h" static const char *TAG = "main"; diff --git a/main/modes/InternalMemoryMenuMode.cpp b/main/modes/InternalMemoryMenuMode.cpp index e53bbc2..1eb05ba 100644 --- a/main/modes/InternalMemoryMenuMode.cpp +++ b/main/modes/InternalMemoryMenuMode.cpp @@ -1,7 +1,9 @@ +#include #include "core/common.h" #include "core/buttons.h" #include "core/display.h" #include +#include "reader/reader_storage.h" #include "InternalMemoryMenuMode.h" void InternalMemoryMenuMode::start() @@ -18,14 +20,25 @@ void InternalMemoryMenuMode::loop() EPD_print("Internal Memory", CENTER, 00); EPD_setFont(DEJAVU18_FONT, NULL); - EPD_print("Current File:", 5, 30); - EPD_print("/spiffs/book.txt", 20, 50); - - EPD_print("Size:", 5, 80); - EPD_print("1234 kB", 100, 80); + // TODO: free memory? + + EPD_print("Size:", 5, 40); + long length = reader_storage_get_length(); + if (length < 0) { + strcpy(text, "unknown"); + } else { + sprintf(text, "%ld kB", length / 1024); + } + EPD_print(text, 100, 40); - EPD_print("Position:", 5, 100); - EPD_print("45%", 100, 100); + EPD_print("Position:", 5, 70); + long position = reader_storage_get_position(); + if (position < 0) { + strcpy(text, "unknown"); + } else { + sprintf(text, "%d%%", (int)(position * 100 / length)); + } + EPD_print(text, 100, 70); display_update(); while (1) { diff --git a/main/modes/ReaderMode.cpp b/main/modes/ReaderMode.cpp index bcfe642..0a137b9 100644 --- a/main/modes/ReaderMode.cpp +++ b/main/modes/ReaderMode.cpp @@ -2,6 +2,7 @@ #include "string.h" #include "core/buttons.h" #include "core/display.h" +#include "reader/reader_storage.h" #include "ReaderMode.h" #include "esp_log.h" @@ -11,7 +12,20 @@ static const char *TAG = "ReaderMode"; void ReaderMode::start() { - this->textReader = textStorage.open("/sdcard/book.txt"); + char filename[64]; + reader_storage_get_filename(filename, sizeof(filename)); + this->textReader = textStorage.open(filename); + + this->bookmark_max = reader_storage_get_length(); + this->bookmark = reader_storage_get_position(); + if (this->bookmark_max < 0) { + this->bookmark_max = 0; + } + if (this->bookmark < 0 || this->bookmark > this->bookmark_max) { + this->bookmark = 0; + } + ESP_LOGI(TAG, "Opening %s for reading at %ld / %ld.", + filename, bookmark, bookmark_max); } void ReaderMode::loop() @@ -42,7 +56,11 @@ void ReaderMode::loop() } display_clear(); - pagePrinter.print(pageCurrent); + if (bookmark == bookmark_max) { + display_alert("THE END"); + } else { + pagePrinter.print(pageCurrent); + } display_update(); //time_t idleStart = clock(); @@ -57,7 +75,10 @@ void ReaderMode::loop() ESP_LOGI(TAG, "Turn page PLUS."); if (pageCurrent != NULL) { bookmark = pageCurrent->start + pageCurrent->len; - // TODO: limit bookmark to file size + if (bookmark > bookmark_max) { + bookmark = bookmark_max; + } + reader_storage_set_position(bookmark); typesetter.destroyPage(pageLast); pageLast = pageCurrent; pageCurrent = NULL; @@ -70,6 +91,7 @@ void ReaderMode::loop() ESP_LOGI(TAG, "Turn page MINUS."); if (pageLast != NULL) { bookmark = pageLast->start; + reader_storage_set_position(bookmark); typesetter.destroyPage(pageCurrent); pageCurrent = pageLast; pageLast = NULL; diff --git a/main/modes/ReaderMode.h b/main/modes/ReaderMode.h index 1278ee9..97beff1 100644 --- a/main/modes/ReaderMode.h +++ b/main/modes/ReaderMode.h @@ -12,6 +12,7 @@ public: private: long bookmark = 0; + long bookmark_max = 0; Typesetter typesetter; PagePrinter pagePrinter; TextStorage textStorage; diff --git a/main/modes/SdCardMenuMode.cpp b/main/modes/SdCardMenuMode.cpp index a78fab5..c278bee 100644 --- a/main/modes/SdCardMenuMode.cpp +++ b/main/modes/SdCardMenuMode.cpp @@ -8,11 +8,14 @@ #include #include #include +#include "reader/reader_storage.h" #include "SdCardMenuMode.h" #include "esp_log.h" static char* TAG = "SdCardMenuMode"; +#define SDCARD_BASEDIR "/sdcard/" + // TODO: make use of bytes void SdCardMenuMode::start() @@ -104,7 +107,15 @@ void SdCardMenuMode::onOptionSelected(int option) this->setFinished(); return; } - // TODO files + + // TODO: spawn a copy AppMode + display_alert("Copying into internal memory..."); + char source[64]; + strcpy(source, SDCARD_BASEDIR); + strcat(source, this->options[option]); + reader_storage_store_file(source); + reader_storage_set_position(0); + this->setFinished(); } int SdCardMenuMode::getOptionsX() diff --git a/main/modes/reader/TextReader.cpp b/main/modes/reader/TextReader.cpp index 38a4bdc..9f57c14 100644 --- a/main/modes/reader/TextReader.cpp +++ b/main/modes/reader/TextReader.cpp @@ -31,13 +31,6 @@ size_t TextReader::read(long pos, char* text, size_t len) } else { fseek(this->f, pos, SEEK_SET); size_t read = fread(text, 1, len, this->f); - if (read > 0) { - //ESP_LOGI(TAG, "Read content: %s", text); - } else { - ESP_LOGI(TAG, "End of file. Closing."); - fclose(this->f); - this->f = NULL; - } return read; } } diff --git a/main/modes/reader/TextStorage.cpp b/main/modes/reader/TextStorage.cpp index 4c78dd2..2123eda 100644 --- a/main/modes/reader/TextStorage.cpp +++ b/main/modes/reader/TextStorage.cpp @@ -8,7 +8,7 @@ TextStorage::TextStorage() TextReader* TextStorage::open(char* filename) { - FILE* f = fopen("/sdcard/book.txt", "r"); + FILE* f = fopen(filename, "r"); if (f == NULL) { ESP_LOGE(TAG, "File could not be opened"); return NULL; diff --git a/main/modes/reader/reader_storage.c b/main/modes/reader/reader_storage.c new file mode 100644 index 0000000..3ba99df --- /dev/null +++ b/main/modes/reader/reader_storage.c @@ -0,0 +1,135 @@ +#include +#include +#include +#include +#include +#include +#include "esp_system.h" +#include "spiffs/spiffs_vfs.h" + +#include "esp_log.h" +static const char *TAG = "reader_storage"; + +static const char* filename_stored = "stored.dat"; +static const char* filename_position = "position.dat"; + +static int check_storage_ready() +{ + if (spiffs_is_mounted == 0) { + ESP_LOGE(TAG, "Reader storage is not mounted."); + } + return spiffs_is_mounted; +} + +void reader_storage_get_filename(char* buf, int len) +{ + if (check_storage_ready() == 0) { + return; + } + + strcpy(buf, SPIFFS_BASE_PATH); + strcat(buf, "/"); + strcat(buf, filename_stored); +} + +long reader_storage_get_length() +{ + if (check_storage_ready() == 0) { + return -1; + } + + char path[64]; + reader_storage_get_filename(path, sizeof(path)); + + long length = -1; + struct stat stats; + if (stat(path, &stats) == 0) { + length = stats.st_size; + } + + ESP_LOGI(TAG, "Getting length: %ld", length); + return length; +} + +void reader_storage_store_file(char* source_path) +{ + if (check_storage_ready() == 0) { + return; + } + + char dest_path[64]; + reader_storage_get_filename(dest_path, sizeof(dest_path)); + + ESP_LOGI(TAG, "Storing file %s into %s", source_path, dest_path); + + FILE* src = fopen(source_path, "r"); + if (src == NULL) { + ESP_LOGE(TAG, "Failed opening source file."); + return; + } + FILE* dst = fopen(dest_path, "w"); + if (dst == NULL) { + ESP_LOGE(TAG, "Failed opening destination file."); + return; + } + + char buf[32]; + int len = 0; + do { + len = fread(buf, 1, sizeof(buf), src); + if (len > 0) { + len = fwrite(buf, 1, sizeof(buf), dst); + } + } while (len > 0); + fclose(dst); + fclose(src); + ESP_LOGI(TAG, "File stored."); +} + +long reader_storage_get_position() +{ + if (check_storage_ready() == 0) { + return -1; + } + + long position = 0; + char* path[64]; + strcpy(path, SPIFFS_BASE_PATH); + strcat(path, "/"); + strcat(path, filename_position); + FILE* f = fopen(path, "r"); + if (f == NULL) { + ESP_LOGE(TAG, "Failed opening position file for reading."); + return; + } + if (fread(&position, sizeof(position), 1, f) != 1) { + ESP_LOGE(TAG, "Failed reading position."); + position = -1; + } + fclose(f); + ESP_LOGI(TAG, "Getting position: %ld", position); + return position; +} + +void reader_storage_set_position(long position) +{ + if (check_storage_ready() == 0) { + return; + } + + ESP_LOGI(TAG, "Setting position: %ld", position); + + char* path[64]; + strcpy(path, SPIFFS_BASE_PATH); + strcat(path, "/"); + strcat(path, filename_position); + FILE* f = fopen(path, "w"); + if (f == NULL) { + ESP_LOGE(TAG, "Failed opening position file for writing."); + return; + } + if (fwrite(&position, sizeof(position), 1, f) != 1) { + ESP_LOGE(TAG, "Failed writing position."); + } + fclose(f); +} diff --git a/main/modes/reader/reader_storage.h b/main/modes/reader/reader_storage.h new file mode 100644 index 0000000..265b02c --- /dev/null +++ b/main/modes/reader/reader_storage.h @@ -0,0 +1,14 @@ +#include +#ifdef __cplusplus +extern "C" { +#endif + +void reader_storage_get_filename(char* buf, int len); +long reader_storage_get_length(); +void reader_storage_store_file(char* source_path); +long reader_storage_get_position(); +void reader_storage_set_position(long position); + +#ifdef __cplusplus +} +#endif