@@ -1749,6 +1749,13 @@ void EPD_clearStringRect(int x, int y, char *str) | |||||
EPD_fillRect(x+dispWin.x1, y+dispWin.y1, w, h, _bg); | 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 | * bit-encoded bar position of all digits' bcd segments | ||||
@@ -529,6 +529,10 @@ int EPD_getStringWidth(char* str); | |||||
*/ | */ | ||||
void EPD_clearStringRect(int x, int y, 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 | * Compile font c source file to .fnt file | ||||
@@ -1,5 +1,5 @@ | |||||
FILE(GLOB_RECURSE app_sources *.cpp *.c) | 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/") | set(COMPONENT_ADD_INCLUDEDIRS "." "../components/") | ||||
register_component() | register_component() |
@@ -111,3 +111,11 @@ void display_sleep() | |||||
{ | { | ||||
EPD_PowerOff(); | EPD_PowerOff(); | ||||
} | } | ||||
void display_alert(char* text) | |||||
{ | |||||
EPD_clearStringRect(CENTER, CENTER, text); | |||||
EPD_print(text, CENTER, CENTER); | |||||
EPD_frameStringRect(CENTER, CENTER, text); | |||||
EPD_UpdateScreen(); | |||||
} |
@@ -14,6 +14,8 @@ void display_update(); | |||||
void display_wake(); | void display_wake(); | ||||
void display_sleep(); | void display_sleep(); | ||||
void display_alert(char* text); | |||||
#ifdef __cplusplus | #ifdef __cplusplus | ||||
} | } | ||||
#endif | #endif |
@@ -6,8 +6,6 @@ | |||||
#include <string.h> | #include <string.h> | ||||
#include "esp_system.h" | #include "esp_system.h" | ||||
#include "driver/gpio.h" | #include "driver/gpio.h" | ||||
#include "esp_system.h" | |||||
#include "esp_heap_alloc_caps.h" | |||||
#include "esp_log.h" | #include "esp_log.h" | ||||
static const char *TAG = "main"; | static const char *TAG = "main"; | ||||
@@ -1,7 +1,9 @@ | |||||
#include <string.h> | |||||
#include "core/common.h" | #include "core/common.h" | ||||
#include "core/buttons.h" | #include "core/buttons.h" | ||||
#include "core/display.h" | #include "core/display.h" | ||||
#include <epaper/EPD.h> | #include <epaper/EPD.h> | ||||
#include "reader/reader_storage.h" | |||||
#include "InternalMemoryMenuMode.h" | #include "InternalMemoryMenuMode.h" | ||||
void InternalMemoryMenuMode::start() | void InternalMemoryMenuMode::start() | ||||
@@ -18,14 +20,25 @@ void InternalMemoryMenuMode::loop() | |||||
EPD_print("Internal Memory", CENTER, 00); | EPD_print("Internal Memory", CENTER, 00); | ||||
EPD_setFont(DEJAVU18_FONT, NULL); | 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(); | display_update(); | ||||
while (1) { | while (1) { | ||||
@@ -2,6 +2,7 @@ | |||||
#include "string.h" | #include "string.h" | ||||
#include "core/buttons.h" | #include "core/buttons.h" | ||||
#include "core/display.h" | #include "core/display.h" | ||||
#include "reader/reader_storage.h" | |||||
#include "ReaderMode.h" | #include "ReaderMode.h" | ||||
#include "esp_log.h" | #include "esp_log.h" | ||||
@@ -11,7 +12,20 @@ static const char *TAG = "ReaderMode"; | |||||
void ReaderMode::start() | 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() | void ReaderMode::loop() | ||||
@@ -42,7 +56,11 @@ void ReaderMode::loop() | |||||
} | } | ||||
display_clear(); | display_clear(); | ||||
pagePrinter.print(pageCurrent); | |||||
if (bookmark == bookmark_max) { | |||||
display_alert("THE END"); | |||||
} else { | |||||
pagePrinter.print(pageCurrent); | |||||
} | |||||
display_update(); | display_update(); | ||||
//time_t idleStart = clock(); | //time_t idleStart = clock(); | ||||
@@ -57,7 +75,10 @@ void ReaderMode::loop() | |||||
ESP_LOGI(TAG, "Turn page PLUS."); | ESP_LOGI(TAG, "Turn page PLUS."); | ||||
if (pageCurrent != NULL) { | if (pageCurrent != NULL) { | ||||
bookmark = pageCurrent->start + pageCurrent->len; | 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); | typesetter.destroyPage(pageLast); | ||||
pageLast = pageCurrent; | pageLast = pageCurrent; | ||||
pageCurrent = NULL; | pageCurrent = NULL; | ||||
@@ -70,6 +91,7 @@ void ReaderMode::loop() | |||||
ESP_LOGI(TAG, "Turn page MINUS."); | ESP_LOGI(TAG, "Turn page MINUS."); | ||||
if (pageLast != NULL) { | if (pageLast != NULL) { | ||||
bookmark = pageLast->start; | bookmark = pageLast->start; | ||||
reader_storage_set_position(bookmark); | |||||
typesetter.destroyPage(pageCurrent); | typesetter.destroyPage(pageCurrent); | ||||
pageCurrent = pageLast; | pageCurrent = pageLast; | ||||
pageLast = NULL; | pageLast = NULL; | ||||
@@ -12,6 +12,7 @@ public: | |||||
private: | private: | ||||
long bookmark = 0; | long bookmark = 0; | ||||
long bookmark_max = 0; | |||||
Typesetter typesetter; | Typesetter typesetter; | ||||
PagePrinter pagePrinter; | PagePrinter pagePrinter; | ||||
TextStorage textStorage; | TextStorage textStorage; | ||||
@@ -8,11 +8,14 @@ | |||||
#include <sys/stat.h> | #include <sys/stat.h> | ||||
#include <sys/types.h> | #include <sys/types.h> | ||||
#include <dirent.h> | #include <dirent.h> | ||||
#include "reader/reader_storage.h" | |||||
#include "SdCardMenuMode.h" | #include "SdCardMenuMode.h" | ||||
#include "esp_log.h" | #include "esp_log.h" | ||||
static char* TAG = "SdCardMenuMode"; | static char* TAG = "SdCardMenuMode"; | ||||
#define SDCARD_BASEDIR "/sdcard/" | |||||
// TODO: make use of bytes | // TODO: make use of bytes | ||||
void SdCardMenuMode::start() | void SdCardMenuMode::start() | ||||
@@ -104,7 +107,15 @@ void SdCardMenuMode::onOptionSelected(int option) | |||||
this->setFinished(); | this->setFinished(); | ||||
return; | 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() | int SdCardMenuMode::getOptionsX() | ||||
@@ -31,13 +31,6 @@ size_t TextReader::read(long pos, char* text, size_t len) | |||||
} else { | } else { | ||||
fseek(this->f, pos, SEEK_SET); | fseek(this->f, pos, SEEK_SET); | ||||
size_t read = fread(text, 1, len, this->f); | 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; | return read; | ||||
} | } | ||||
} | } |
@@ -8,7 +8,7 @@ TextStorage::TextStorage() | |||||
TextReader* TextStorage::open(char* filename) | TextReader* TextStorage::open(char* filename) | ||||
{ | { | ||||
FILE* f = fopen("/sdcard/book.txt", "r"); | |||||
FILE* f = fopen(filename, "r"); | |||||
if (f == NULL) { | if (f == NULL) { | ||||
ESP_LOGE(TAG, "File could not be opened"); | ESP_LOGE(TAG, "File could not be opened"); | ||||
return NULL; | return NULL; | ||||
@@ -0,0 +1,135 @@ | |||||
#include <stdlib.h> | |||||
#include <stdio.h> | |||||
#include <string.h> | |||||
#include <unistd.h> | |||||
#include <sys/stat.h> | |||||
#include <sys/types.h> | |||||
#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); | |||||
} |
@@ -0,0 +1,14 @@ | |||||
#include <stdlib.h> | |||||
#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 |