@@ -0,0 +1,4 @@ | |||
#include "Page.h" | |||
Page::Page() | |||
{} |
@@ -0,0 +1,16 @@ | |||
#ifndef _PAGE_H_ | |||
#define _PAGE_H_ | |||
#include <stdlib.h> | |||
class Page | |||
{ | |||
public: | |||
Page(); | |||
char* text; | |||
size_t len; | |||
private: | |||
}; | |||
#endif |
@@ -0,0 +1,27 @@ | |||
#include "display.h" | |||
#include "EPD.h" | |||
#include "PagePrinter.h" | |||
#include "esp_log.h" | |||
static const char *TAG = "PagePrinter"; | |||
int font = DEJAVU18_FONT;//DEFAULT_FONT; | |||
PagePrinter::PagePrinter() | |||
{} | |||
void PagePrinter::print(Page* page) | |||
{ | |||
if (page->text == NULL) { | |||
ESP_LOGE(TAG, "Page text is NULL"); | |||
return; | |||
} | |||
if (page->len == 0) { | |||
return; | |||
} | |||
EPD_setFont(font, NULL); | |||
text_wrap = 1; | |||
EPD_print(page->text, 0, 0); | |||
EPD_UpdateScreen(); | |||
} |
@@ -0,0 +1,11 @@ | |||
#include "Page.h" | |||
class PagePrinter | |||
{ | |||
public: | |||
PagePrinter(); | |||
void print(Page* page); | |||
private: | |||
}; |
@@ -0,0 +1,34 @@ | |||
#include "TextReader.h" | |||
#include "esp_log.h" | |||
static const char *TAG = "TextReader"; | |||
TextReader::TextReader(FILE* file) | |||
{ | |||
this->f = file; | |||
} | |||
void TextReader::close() | |||
{ | |||
fclose(this->f); | |||
} | |||
size_t TextReader::read(long pos, char* text, size_t len) | |||
{ | |||
if (this->f == NULL) { | |||
ESP_LOGE(TAG, "File not opened."); | |||
sprintf(text, "File could not be opened."); | |||
return 0; | |||
} 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; | |||
} | |||
} |
@@ -0,0 +1,16 @@ | |||
#include <stdlib.h> | |||
#include <stdio.h> | |||
class TextReader | |||
{ | |||
public: | |||
TextReader(FILE* file); | |||
size_t read(long pos, char* text, size_t len); | |||
void close(); | |||
private: | |||
FILE* f; | |||
}; |
@@ -0,0 +1,25 @@ | |||
#include "TextStorage.h" | |||
#include "esp_log.h" | |||
static const char *TAG = "TextStorage"; | |||
TextStorage::TextStorage() | |||
{} | |||
TextReader* TextStorage::open(char* filename) | |||
{ | |||
FILE* f = fopen("/sdcard/book.txt", "r"); | |||
if (f == NULL) { | |||
ESP_LOGE(TAG, "File could not be opened"); | |||
return NULL; | |||
} | |||
ESP_LOGI(TAG, "File opened for reading."); | |||
return new TextReader(f); | |||
} | |||
void TextStorage::close(TextReader* reader) | |||
{ | |||
reader->close(); | |||
delete reader; | |||
ESP_LOGI(TAG, "File closed."); | |||
} |
@@ -0,0 +1,10 @@ | |||
#include "TextReader.h" | |||
class TextStorage | |||
{ | |||
public: | |||
TextStorage(); | |||
TextReader* open(char* filename); | |||
void close(TextReader* reader); | |||
}; |
@@ -0,0 +1,10 @@ | |||
#include "Typesetter.h" | |||
Typesetter::Typesetter() | |||
{} | |||
void Typesetter::preparePage(Page* page, char* text, size_t len) | |||
{ | |||
page->text = text; | |||
page->len = len; | |||
} |
@@ -0,0 +1,13 @@ | |||
#include <stdlib.h> | |||
#include "Page.h" | |||
class Typesetter | |||
{ | |||
public: | |||
Typesetter(); | |||
void preparePage(Page* page, char* text, size_t len); | |||
//private: | |||
}; |
@@ -0,0 +1,27 @@ | |||
#include <stdlib.h> | |||
#include "driver/gpio.h" | |||
#include "buttons.h" | |||
#define BTN_PIN_PLUS ((gpio_num_t)39) | |||
#define BTN_PIN_OK ((gpio_num_t)37) | |||
#define BTN_PIN_MINUS ((gpio_num_t)38) | |||
void buttons_init() | |||
{ | |||
gpio_config_t buttons_config; | |||
buttons_config.intr_type = (gpio_int_type_t)GPIO_PIN_INTR_DISABLE; | |||
buttons_config.mode = GPIO_MODE_INPUT; | |||
buttons_config.pull_up_en = (gpio_pullup_t)1; | |||
buttons_config.pull_down_en = (gpio_pulldown_t)0; | |||
buttons_config.pin_bit_mask = (1LL << BTN_PIN_MINUS); | |||
gpio_config(&buttons_config); | |||
buttons_config.pin_bit_mask = (1LL << BTN_PIN_OK); | |||
gpio_config(&buttons_config); | |||
buttons_config.pin_bit_mask = (1LL << BTN_PIN_PLUS); | |||
gpio_config(&buttons_config); | |||
} | |||
bool buttons_pressed_ok() { return gpio_get_level(BTN_PIN_OK) == 0; } | |||
bool buttons_pressed_plus() { return gpio_get_level(BTN_PIN_PLUS) == 0; } | |||
bool buttons_pressed_minus() { return gpio_get_level(BTN_PIN_MINUS) == 0; } |
@@ -0,0 +1,4 @@ | |||
void buttons_init(); | |||
bool buttons_pressed_ok(); | |||
bool buttons_pressed_plus(); | |||
bool buttons_pressed_minus(); |
@@ -0,0 +1,2 @@ | |||
#define APP_VERSION "0.1" |
@@ -0,0 +1,102 @@ | |||
#include "spi_master_lobo.h" | |||
#include "EPD.h" | |||
#include <stdlib.h> | |||
#include "esp_system.h" | |||
#include "driver/gpio.h" | |||
#include "esp_system.h" | |||
#include "esp_heap_alloc_caps.h" | |||
#include "esp_log.h" | |||
#include "config.h" | |||
#include "display.h" | |||
void display_init() | |||
{ | |||
disp_buffer = (uint8_t*)pvPortMallocCaps(EPD_DISPLAY_WIDTH * (EPD_DISPLAY_HEIGHT/8), MALLOC_CAP_DMA); | |||
assert(disp_buffer); | |||
drawBuff = disp_buffer; | |||
gs_disp_buffer = (uint8_t*)pvPortMallocCaps(EPD_DISPLAY_WIDTH * EPD_DISPLAY_HEIGHT, MALLOC_CAP_DMA); | |||
assert(gs_disp_buffer); | |||
gs_drawBuff = gs_disp_buffer; | |||
} | |||
spi_lobo_device_interface_config_t devcfg; | |||
spi_lobo_bus_config_t buscfg; | |||
void spi_init() | |||
{ | |||
gpio_set_direction(DC_Pin, GPIO_MODE_OUTPUT); | |||
gpio_set_level(DC_Pin, 1); | |||
gpio_set_direction(RST_Pin, GPIO_MODE_OUTPUT); | |||
gpio_set_level(RST_Pin, 0); | |||
gpio_set_direction(BUSY_Pin, GPIO_MODE_INPUT); | |||
gpio_set_pull_mode(BUSY_Pin, GPIO_PULLUP_ONLY); | |||
#ifdef POWER_Pin | |||
gpio_set_direction(POWER_Pin, GPIO_MODE_OUTPUT); | |||
gpio_set_level(POWER_Pin, 1); | |||
#endif | |||
buscfg.miso_io_num = -1; // set SPI MISO pin | |||
buscfg.mosi_io_num = MOSI_Pin; // set SPI MOSI pin | |||
buscfg.sclk_io_num = SCK_Pin; // set SPI CLK pin | |||
buscfg.quadwp_io_num=-1; | |||
buscfg.quadhd_io_num=-1; | |||
buscfg.max_transfer_sz = 5*1024; // max transfer size is 4736 bytes | |||
devcfg.clock_speed_hz=40000000; // SPI clock is 40 MHz | |||
devcfg.mode=0; // SPI mode 0 | |||
devcfg.spics_io_num=-1; // we will use external CS pin | |||
devcfg.spics_ext_io_num = CS_Pin; // external CS pin | |||
devcfg.flags=SPI_DEVICE_HALFDUPLEX; // ALWAYS SET to HALF DUPLEX MODE for display spi !! | |||
} | |||
void display_connect() | |||
{ | |||
int ret; | |||
ret=spi_lobo_bus_add_device(SPI_BUS, &buscfg, &devcfg, &disp_spi); | |||
assert(ret==ESP_OK); | |||
printf("SPI: display device added to spi bus\r\n"); | |||
ret = spi_lobo_device_select(disp_spi, 1); | |||
assert(ret==ESP_OK); | |||
ret = spi_lobo_device_deselect(disp_spi); | |||
assert(ret==ESP_OK); | |||
printf("SPI: attached display device, speed=%u\r\n", spi_lobo_get_speed(disp_spi)); | |||
printf("SPI: bus uses native pins: %s\r\n", spi_lobo_uses_native_pins(disp_spi) ? "true" : "false"); | |||
//EPD_PowerOn(); | |||
} | |||
void display_splash_screen() | |||
{ | |||
EPD_DisplayClearPart(); | |||
EPD_fillScreen(0); | |||
EPD_UpdateScreen(); | |||
EPD_setFont(COMIC24_FONT, NULL); | |||
EPD_print("LilyBook", 30, 30); | |||
EPD_setFont(DEFAULT_FONT, NULL); | |||
EPD_print("Version:", 30, 70); | |||
EPD_print(APP_VERSION, 100, 70); | |||
EPD_UpdateScreen(); | |||
} | |||
void display_clear() | |||
{ | |||
EPD_fillScreen(_bg); | |||
} | |||
void display_refresh() | |||
{ | |||
EPD_DisplayClearPart(); | |||
EPD_fillScreen(_bg); | |||
} | |||
void display_update() | |||
{ | |||
EPD_UpdateScreen(); | |||
} |
@@ -0,0 +1,8 @@ | |||
void display_init(); | |||
void spi_init(); | |||
void display_connect(); | |||
void display_splash_screen(); | |||
void display_clear(); | |||
void display_refresh(); | |||
void display_update(); |
@@ -1,7 +1,6 @@ | |||
#include <time.h> | |||
#include <errno.h> | |||
#include <sys/fcntl.h> | |||
#include <stdio.h> | |||
#include <time.h> | |||
#include <stdlib.h> | |||
#include <string.h> | |||
@@ -11,20 +10,20 @@ | |||
#include "driver/gpio.h" | |||
#include "esp_system.h" | |||
#include "esp_heap_alloc_caps.h" | |||
#include "spiffs_vfs.h" | |||
#include "esp_log.h" | |||
#include "spi_master_lobo.h" | |||
#include "img_hacking.c" | |||
#include "EPD.h" | |||
#include "storage.h" | |||
#define APP_VERSION "0.1" | |||
#include "esp_log.h" | |||
static const char *TAG = "main"; | |||
#define BTN_PIN_PLUS ((gpio_num_t)39) | |||
#define BTN_PIN_OK ((gpio_num_t)37) | |||
#define BTN_PIN_MINUS ((gpio_num_t)38) | |||
extern "C" { | |||
#include "config.h" | |||
#include "buttons.h" | |||
#include "storage.h" | |||
#include "display.h" | |||
} | |||
static const char *TAG = "main"; | |||
#include "Typesetter.h" | |||
#include "TextStorage.h" | |||
#include "PagePrinter.h" | |||
static struct tm* tm_info; | |||
static char tmp_buff[128]; | |||
@@ -33,172 +32,64 @@ static const char *file_fonts[3] = {"/spiffs/fonts/DotMatrix_M.fon", "/spiffs/fo | |||
static const char tag[] = "[LilyBook]"; | |||
esp_err_t ret; | |||
void display_init() | |||
{ | |||
disp_buffer = (uint8_t*)pvPortMallocCaps(EPD_DISPLAY_WIDTH * (EPD_DISPLAY_HEIGHT/8), MALLOC_CAP_DMA); | |||
assert(disp_buffer); | |||
drawBuff = disp_buffer; | |||
gs_disp_buffer = (uint8_t*)pvPortMallocCaps(EPD_DISPLAY_WIDTH * EPD_DISPLAY_HEIGHT, MALLOC_CAP_DMA); | |||
assert(gs_disp_buffer); | |||
gs_drawBuff = gs_disp_buffer; | |||
} | |||
spi_lobo_device_interface_config_t devcfg; | |||
spi_lobo_bus_config_t buscfg; | |||
void spi_init() | |||
{ | |||
gpio_set_direction(DC_Pin, GPIO_MODE_OUTPUT); | |||
gpio_set_level(DC_Pin, 1); | |||
gpio_set_direction(RST_Pin, GPIO_MODE_OUTPUT); | |||
gpio_set_level(RST_Pin, 0); | |||
gpio_set_direction(BUSY_Pin, GPIO_MODE_INPUT); | |||
gpio_set_pull_mode(BUSY_Pin, GPIO_PULLUP_ONLY); | |||
#ifdef POWER_Pin | |||
gpio_set_direction(POWER_Pin, GPIO_MODE_OUTPUT); | |||
gpio_set_level(POWER_Pin, 1); | |||
#endif | |||
buscfg.miso_io_num = -1; // set SPI MISO pin | |||
buscfg.mosi_io_num = MOSI_Pin; // set SPI MOSI pin | |||
buscfg.sclk_io_num = SCK_Pin; // set SPI CLK pin | |||
buscfg.quadwp_io_num=-1; | |||
buscfg.quadhd_io_num=-1; | |||
buscfg.max_transfer_sz = 5*1024; // max transfer size is 4736 bytes | |||
devcfg.clock_speed_hz=40000000; // SPI clock is 40 MHz | |||
devcfg.mode=0; // SPI mode 0 | |||
devcfg.spics_io_num=-1; // we will use external CS pin | |||
devcfg.spics_ext_io_num = CS_Pin; // external CS pin | |||
devcfg.flags=SPI_DEVICE_HALFDUPLEX; // ALWAYS SET to HALF DUPLEX MODE for display spi !! | |||
} | |||
void display_connect() | |||
{ | |||
ret=spi_lobo_bus_add_device(SPI_BUS, &buscfg, &devcfg, &disp_spi); | |||
assert(ret==ESP_OK); | |||
printf("SPI: display device added to spi bus\r\n"); | |||
ret = spi_lobo_device_select(disp_spi, 1); | |||
assert(ret==ESP_OK); | |||
ret = spi_lobo_device_deselect(disp_spi); | |||
assert(ret==ESP_OK); | |||
printf("SPI: attached display device, speed=%u\r\n", spi_lobo_get_speed(disp_spi)); | |||
printf("SPI: bus uses native pins: %s\r\n", spi_lobo_uses_native_pins(disp_spi) ? "true" : "false"); | |||
//EPD_PowerOn(); | |||
} | |||
void fs_init() | |||
void sleep(unsigned int ms) | |||
{ | |||
vfs_spiffs_register(); | |||
if (spiffs_is_mounted) { | |||
ESP_LOGI(tag, "File system mounted."); | |||
} else { | |||
ESP_LOGE(tag, "Error mounting file system."); | |||
} | |||
if (storage_init() == 0) { | |||
ESP_LOGI(tag, "SD card mounted."); | |||
} else { | |||
ESP_LOGE(tag, "Error mounting SD card."); | |||
} | |||
vTaskDelay(ms / portTICK_RATE_MS); | |||
} | |||
extern "C" void app_main() | |||
{ | |||
gpio_config_t buttons_config; | |||
buttons_config.intr_type = (gpio_int_type_t)GPIO_PIN_INTR_DISABLE; | |||
buttons_config.mode = GPIO_MODE_INPUT; | |||
buttons_config.pull_up_en = (gpio_pullup_t)1; | |||
buttons_config.pull_down_en = (gpio_pulldown_t)0; | |||
buttons_config.pin_bit_mask = (1LL << BTN_PIN_MINUS); | |||
gpio_config(&buttons_config); | |||
buttons_config.pin_bit_mask = (1LL << BTN_PIN_OK); | |||
gpio_config(&buttons_config); | |||
buttons_config.pin_bit_mask = (1LL << BTN_PIN_PLUS); | |||
gpio_config(&buttons_config); | |||
printf("\n LilyBook v%s\n\n", APP_VERSION); | |||
storage_init(); | |||
buttons_init(); | |||
display_init(); | |||
spi_init(); | |||
vTaskDelay(500 / portTICK_RATE_MS); | |||
printf("\n LilyBook v%s\n\n", APP_VERSION); | |||
sleep(500); | |||
display_connect(); | |||
display_splash_screen(); | |||
EPD_DisplayClearPart(); | |||
EPD_fillScreen(0); | |||
EPD_UpdateScreen(); | |||
EPD_setFont(COMIC24_FONT, NULL); | |||
EPD_print("LilyBook", 30, 30); | |||
EPD_setFont(DEFAULT_FONT, NULL); | |||
EPD_print("Version:", 30, 70); | |||
EPD_print(APP_VERSION, 100, 70); | |||
EPD_UpdateScreen(); | |||
EPD_wait(500); | |||
fs_init(); | |||
sleep(500); | |||
printf("==== START ====\r\n\n"); | |||
_gs = 1; | |||
uint32_t tstart; | |||
int pass = 0; | |||
int font = DEJAVU18_FONT;//DEFAULT_FONT; | |||
EPD_setFont(font, NULL); | |||
Typesetter typesetter; | |||
PagePrinter pagePrinter; | |||
TextStorage textStorage; | |||
TextReader* textReader = textStorage.open("/sdcard/book.txt"); | |||
Page page; | |||
EPD_wait(100); | |||
FILE* f = fopen("/sdcard/book.txt", "r"); | |||
long bookmark = 0; | |||
while (1) { | |||
EPD_fillScreen(_bg); | |||
_fg = 15; | |||
_bg = 0; | |||
char text[1024]; | |||
if (f == NULL) { | |||
ESP_LOGE(TAG, "Failed to open file for reading"); | |||
sprintf(text, "Could not open SD card."); | |||
f = fopen("/sdcard/book.txt", "r"); | |||
char text[1024]; | |||
if (textReader != NULL) { | |||
size_t read = textReader->read(bookmark, text, sizeof(text)); | |||
} else { | |||
if (fread(text, 1, sizeof(text), f) > 0) { | |||
ESP_LOGI(TAG, "Read content: %s", text); | |||
} else { | |||
ESP_LOGI(TAG, "End of file. Closing."); | |||
fclose(f); | |||
f = NULL; | |||
} | |||
strcpy(text, "File could not be opened."); | |||
} | |||
text_wrap = 1; | |||
EPD_print(text, 0, 0); | |||
EPD_UpdateScreen(); | |||
typesetter.preparePage(&page, text, sizeof(text)); | |||
display_clear(); | |||
pagePrinter.print(&page); | |||
display_update(); | |||
while (1) { | |||
EPD_wait(100); | |||
if (gpio_get_level(BTN_PIN_OK) == 0) { | |||
sleep(10); | |||
if (buttons_pressed_ok()) { | |||
ESP_LOGI(TAG, "Clear page."); | |||
EPD_DisplayClearPart(); | |||
EPD_fillScreen(_bg); | |||
EPD_print(text, 10, 10); | |||
EPD_UpdateScreen(); | |||
display_refresh(); | |||
break; | |||
} | |||
if (gpio_get_level(BTN_PIN_PLUS) == 0) { | |||
if (buttons_pressed_plus()) { | |||
ESP_LOGI(TAG, "Turn page PLUS."); | |||
bookmark += sizeof(text); | |||
break; | |||
} | |||
if (gpio_get_level(BTN_PIN_MINUS) == 0) { | |||
if (buttons_pressed_minus()) { | |||
ESP_LOGI(TAG, "Turn page MINUS."); | |||
fseek(f, 2 * sizeof(text), SEEK_CUR); | |||
bookmark -= sizeof(text); | |||
break; | |||
} | |||
} | |||
@@ -9,9 +9,10 @@ | |||
#include "driver/sdmmc_host.h" | |||
#include "driver/sdspi_host.h" | |||
#include "sdmmc_cmd.h" | |||
#include "spiffs_vfs.h" | |||
#include "storage.h" | |||
static const char *TAG = "storage"; | |||
static const char *tag = "storage"; | |||
// This example can use SDMMC and SPI peripherals to communicate with SD card. | |||
// By default, SDMMC peripheral is used. | |||
@@ -33,10 +34,10 @@ static const char *TAG = "storage"; | |||
#define PIN_NUM_CS ((gpio_num_t)13) | |||
#endif //USE_SPI_MODE | |||
int storage_init() | |||
int sdcard_init() | |||
{ | |||
#ifndef USE_SPI_MODE | |||
ESP_LOGI(TAG, "Using SDMMC peripheral"); | |||
ESP_LOGI(tag, "Using SDMMC peripheral"); | |||
sdmmc_host_t host = SDMMC_HOST_DEFAULT(); | |||
// This initializes the slot without card detect (CD) and write protect (WP) signals. | |||
@@ -86,10 +87,10 @@ int storage_init() | |||
if (ret != ESP_OK) { | |||
if (ret == ESP_FAIL) { | |||
ESP_LOGE(TAG, "Failed to mount filesystem. " | |||
ESP_LOGE(tag, "Failed to mount filesystem. " | |||
"If you want the card to be formatted, set format_if_mount_failed = true."); | |||
} else { | |||
ESP_LOGE(TAG, "Failed to initialize the card (%s). " | |||
ESP_LOGE(tag, "Failed to initialize the card (%s). " | |||
"Make sure SD card lines have pull-up resistors in place.", esp_err_to_name(ret)); | |||
} | |||
return -1; | |||
@@ -100,3 +101,25 @@ int storage_init() | |||
return 0; | |||
} | |||
int storage_init() | |||
{ | |||
int ret = 0; | |||
vfs_spiffs_register(); | |||
if (spiffs_is_mounted) { | |||
ESP_LOGI(tag, "File system mounted."); | |||
} else { | |||
ESP_LOGE(tag, "Error mounting file system."); | |||
ret += 1 << 1; | |||
} | |||
if (sdcard_init() == 0) { | |||
ESP_LOGI(tag, "SD card mounted."); | |||
} else { | |||
ESP_LOGE(tag, "Error mounting SD card."); | |||
ret += 1 << 2; | |||
} | |||
return ret; | |||
} |
@@ -1,2 +1,2 @@ | |||
int storage_init(); | |||
int storage_init(); |