diff --git a/platformio.ini b/platformio.ini index 98d7076..2afe556 100644 --- a/platformio.ini +++ b/platformio.ini @@ -16,7 +16,6 @@ board_build.f_flash = 80000000L monitor_speed = 115200 build_flags = -DSPI_FREQUENCY=80000000L -; -DLV_ATTRIBUTE_FAST_MEM -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue src_filter = @@ -25,3 +24,5 @@ src_filter = +<../src/images> lib_deps = TTGO TWatch Library@>=1.2.0 + ESP Async WebServer@>=1.2.0 + AsyncTCP@>=1.1.1 diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 31e6a0b..e5d91f4 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -4,6 +4,7 @@ #include "gui.h" #include "statusbar.h" +#include "screenshot.h" #include "keyboard.h" #include "mainbar/mainbar.h" diff --git a/src/gui/screenshot.cpp b/src/gui/screenshot.cpp index 34bc5a4..1bcd743 100644 --- a/src/gui/screenshot.cpp +++ b/src/gui/screenshot.cpp @@ -1,5 +1,8 @@ #include "config.h" +#include #include "screenshot.h" +#include +#include lv_disp_drv_t screenshot_disp_drv; static lv_disp_buf_t screenshot_disp_buf; @@ -8,14 +11,20 @@ static lv_color_t screenshot_buf1[ LV_HOR_RES_MAX * 1 ]; lv_disp_t *system_disp; lv_disp_t *screenshot_disp; +uint16_t *png; + +volatile bool screenshot = false; + static void screenshot_disp_flush( lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p ); void screenshot_setup( void ) { + png = (uint16_t*)ps_malloc( LV_HOR_RES_MAX * LV_VER_RES_MAX * 2 ); + + system_disp = lv_disp_get_default(); - - lv_disp_buf_init(&screenshot_disp_buf, screenshot_buf1, NULL, LV_HOR_RES_MAX * 1 ); - + lv_disp_drv_init( &screenshot_disp_drv ); + lv_disp_buf_init( &screenshot_disp_buf, screenshot_buf1, NULL, LV_HOR_RES_MAX * 1 ); screenshot_disp_drv.hor_res = TFT_WIDTH; screenshot_disp_drv.ver_res = TFT_HEIGHT; screenshot_disp_drv.flush_cb = screenshot_disp_flush; @@ -26,30 +35,42 @@ void screenshot_setup( void ) { } void screenshot_take( void ) { -/* - unsigned char* image = (unsigned char*)ps_malloc(240 * 240 * 3); - Serial.printf("Total heap: %d\r\n", ESP.getHeapSize()); - Serial.printf("Free heap: %d\r\n", ESP.getFreeHeap()); - Serial.printf("Total PSRAM: %d\r\n", ESP.getPsramSize()); - Serial.printf("Free PSRAM: %d\r\n", ESP.getFreePsram()); -*/ - lv_obj_invalidate(lv_scr_act()); - lv_disp_set_default( screenshot_disp ); - lv_refr_now( screenshot_disp ); - lv_obj_invalidate(lv_scr_act()); - lv_disp_set_default( system_disp ); - lv_refr_now( system_disp ); + Serial.printf("take screenshot\r\n"); -// free(image); + screenshot_disp->driver.flush_cb = system_disp->driver.flush_cb; + system_disp->driver.flush_cb = screenshot_disp_flush; + lv_obj_invalidate( lv_scr_act() ); + lv_refr_now( system_disp ); + system_disp->driver.flush_cb = screenshot_disp->driver.flush_cb; +} + +void screenshot_save( void ) { + Serial.printf("save screenshot\r\n"); + + SPIFFS.remove("/screen.565"); + fs::File file = SPIFFS.open( "/screen.565", FILE_WRITE ); + + file.write( (uint8_t *)png, LV_HOR_RES_MAX * LV_VER_RES_MAX * 2 ); + file.close(); + + fs::File root = SPIFFS.open("/"); + file = root.openNextFile(); + while(file){ + Serial.printf("FILE: %s (%dbytes)\r\n", file.name(), file.size() ); + file = root.openNextFile(); + } } static void screenshot_disp_flush( lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p ) { - int32_t x, y; + uint32_t x, y; + uint16_t *data = (uint16_t *)color_p; + for(y = area->y1; y <= area->y2; y++) { -// Serial.printf("refresh Y=%d\r\n",y); -// for(x = area->x1; x <= area->x2; x++) { -// } - } + for(x = area->x1; x <= area->x2; x++) { + *(png + (y * LV_HOR_RES_MAX + x )) = *data; + data++; + } + } lv_disp_flush_ready(disp_drv); } diff --git a/src/gui/screenshot.h b/src/gui/screenshot.h index 16f83c0..333b1bd 100644 --- a/src/gui/screenshot.h +++ b/src/gui/screenshot.h @@ -3,34 +3,31 @@ #include "config.h" + #define SCREENSHOT_EVENT _BV(0) + void screenshot_setup( void ); void screenshot_take( void ); + void screenshot_save( void ); - struct _PNG_HEADER { - uint8_t png[8] = { 0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a }; - uint32_t len = 13; - uint8_t IHDR[4] = { 'I', 'H', 'D', 'R' }; - uint32_t width = LV_HOR_RES_MAX; - uint32_t height = LV_VER_RES_MAX; - uint8_t bitdepth = 8; - uint8_t colortype = 2; - uint8_t compression = 0; - uint8_t filter = 0; - uint8_t interlace_method = 0; - uint32_t crc = 0; - }; - - struct _PNG_RGB_PIXEL { - uint8_t r; - uint8_t g; - uint8_t b; - }; - - struct _PNG_IDAT_CHUNCK { - uint32_t len; - uint8_t IDAT[ 4 ] = { 'I', 'D', 'A', 'T' }; - uint8_t data[ LV_HOR_RES_MAX * LV_VER_RES_MAX * sizeof( _PNG_RGB_PIXEL ) ]; - uint32_t crc; - }; + struct PNG_IMAGE { + uint8_t png[ 8 ]; + uint32_t IHDR_len; + uint8_t IHDR[ 4 ]; + uint32_t width; + uint32_t height; + uint8_t bitdepth; + uint8_t colortype; + uint8_t compression; + uint8_t filter; + uint8_t interlace_method; + uint32_t IHDR_crc; + uint32_t IDAT_len = LV_HOR_RES_MAX * LV_VER_RES_MAX * 3; + uint8_t IDAT[ 4 ]; + uint8_t data[ LV_HOR_RES_MAX * LV_VER_RES_MAX * 3 ]; + uint32_t IDAT_crc; + uint32_t IEND_len; + uint8_t IEND[ 4 ]; + uint32_t IEND_crc; + } __attribute__((packed)); #endif // _SCREENSHOT_H \ No newline at end of file diff --git a/src/hardware/bma.cpp b/src/hardware/bma.cpp index 64f4663..efc7fdc 100644 --- a/src/hardware/bma.cpp +++ b/src/hardware/bma.cpp @@ -37,8 +37,7 @@ void bma_setup( TTGOClass *ttgo ) { pinMode( BMA423_INT1, INPUT ); attachInterrupt( BMA423_INT1, bma_irq, RISING ); - ttgo->bma->enableStepCountInterrupt( bma_config[ BMA_STEPCOUNTER ].enable ); - ttgo->bma->enableWakeupInterrupt( bma_config[ BMA_DOUBLECLICK ].enable ); + bma_reload_settings(); } /* diff --git a/src/hardware/wifictl.cpp b/src/hardware/wifictl.cpp index 122ce44..d5cdb62 100644 --- a/src/hardware/wifictl.cpp +++ b/src/hardware/wifictl.cpp @@ -6,6 +6,7 @@ #include "wifictl.h" #include "gui/statusbar.h" +#include "webserver/webserver.h" bool wifi_init = false; TaskHandle_t _WIFICTL_Task; @@ -76,6 +77,7 @@ void wifictl_setup( void ) { statusbar_style_icon( STATUSBAR_WIFI, STATUSBAR_STYLE_WHITE ); statusbar_show_icon( STATUSBAR_WIFI ); statusbar_wifi_set_state( true, wifiname ); + asyncwebserver_setup(); }, WiFiEvent_t::SYSTEM_EVENT_STA_GOT_IP ); WiFi.onEvent([](WiFiEvent_t event, WiFiEventInfo_t info) { diff --git a/src/my-ttgo-watch.ino b/src/my-ttgo-watch.ino index 3bef0be..dcdb103 100644 --- a/src/my-ttgo-watch.ino +++ b/src/my-ttgo-watch.ino @@ -23,6 +23,7 @@ void setup() { motor_setup(); Serial.begin(115200); + Serial.printf("starting t-watch V1\r\n"); ttgo->begin(); ttgo->lvgl_begin(); @@ -61,9 +62,4 @@ void loop() static int i = 0; gui_loop( ttgo ); powermgm_loop( ttgo ); - if ( i == 0 ) { - screenshot_take(); - i++; - } - } diff --git a/src/webserver/webserver.cpp b/src/webserver/webserver.cpp new file mode 100644 index 0000000..e825eb1 --- /dev/null +++ b/src/webserver/webserver.cpp @@ -0,0 +1,149 @@ + +#include +#include +#include +#include +#include +#include +#include + +#include "webserver.h" +#include "config.h" +#include "gui/screenshot.h" + +AsyncWebServer asyncserver( WEBSERVERPORT ); +TaskHandle_t _WEBSERVER_Task; + + +void handleUpdate( AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final) { + + if (!index){ + /* + * if filename includes spiffs, update the spiffs partition + */ + int cmd = (filename.indexOf("spiffs") > 0) ? U_SPIFFS : U_FLASH; + if (!Update.begin(UPDATE_SIZE_UNKNOWN, cmd)) { + Update.printError(Serial); + } + } + + /* + * Write Data an type message if fail + */ + if (Update.write(data, len) != len) { + Update.printError(Serial); + } + + /* + * After write Update restart + */ + if (final) { + AsyncWebServerResponse *response = request->beginResponse(302, "text/plain", "Please wait while the switch reboots"); + response->addHeader("Refresh", "20"); + response->addHeader("Location", "/"); + request->send(response); + if (!Update.end(true)){ + Update.printError(Serial); + } else { + Serial.println("Update complete"); + Serial.flush(); + ESP.restart(); + } + } +} + +/* + * + */ +void asyncwebserver_setup(void){ + + asyncserver.on("/info", HTTP_GET, [](AsyncWebServerRequest * request) { + request->send(200, "text/plain", "Firmwarestand: " __DATE__ " " __TIME__ "\r\nGCC-Version: " __VERSION__ "\r\n" ); + }); + + asyncserver.on("/shot", HTTP_GET, [](AsyncWebServerRequest * request) { + request->send(200, "text/plain", "Firmwarestand: " __DATE__ " " __TIME__ "\r\nGCC-Version: " __VERSION__ "\r\n" ); + screenshot_take(); + screenshot_save(); + }); + + asyncserver.addHandler(new SPIFFSEditor(SPIFFS)); + asyncserver.serveStatic("/", SPIFFS, "/").setDefaultFile("index.htm"); + + asyncserver.onNotFound([](AsyncWebServerRequest *request){ + Serial.printf( "NOT_FOUND: "); + if(request->method() == HTTP_GET) + Serial.printf( "GET"); + else if(request->method() == HTTP_POST) + Serial.printf( "POST"); + else if(request->method() == HTTP_DELETE) + Serial.printf( "DELETE"); + else if(request->method() == HTTP_PUT) + Serial.printf( "PUT"); + else if(request->method() == HTTP_PATCH) + Serial.printf( "PATCH"); + else if(request->method() == HTTP_HEAD) + Serial.printf( "HEAD"); + else if(request->method() == HTTP_OPTIONS) + Serial.printf( "OPTIONS"); + else + Serial.printf( "UNKNOWN"); + Serial.printf( " http://%s%s\n", request->host().c_str(), request->url().c_str()); + + if(request->contentLength()){ + Serial.printf( "_CONTENT_TYPE: %s\n", request->contentType().c_str()); + Serial.printf( "_CONTENT_LENGTH: %u\n", request->contentLength()); + } + + int headers = request->headers(); + int i; + for(i=0;igetHeader(i); + Serial.printf( "_HEADER[%s]: %s\n", h->name().c_str(), h->value().c_str()); + } + + int params = request->params(); + for(i=0;igetParam(i); + if(p->isFile()){ + Serial.printf( "_FILE[%s]: %s, size: %u\n", p->name().c_str(), p->value().c_str(), p->size()); + } else if(p->isPost()){ + Serial.printf( "_POST[%s]: %s\n", p->name().c_str(), p->value().c_str()); + } else { + Serial.printf( "_GET[%s]: %s\n", p->name().c_str(), p->value().c_str()); + } + } + request->send(404); + }); + + asyncserver.onFileUpload([](AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final){ + if(!index) + Serial.printf( "UploadStart: %s\n", filename.c_str()); + Serial.printf("%s", (const char*)data); + if(final) + Serial.printf( "UploadEnd: %s (%u)\n", filename.c_str(), index+len); + }); + + asyncserver.onRequestBody([](AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total){ + if(!index) { + Serial.printf( "BodyStart: %u\n", total); + } + Serial.printf( "%s", (const char*)data); + if(index + len == total) { + Serial.printf( "BodyEnd: %u\n", total); + } + }); + + asyncserver.on("/reset", HTTP_GET, []( AsyncWebServerRequest * request ) { + request->send(200, "text/plain", "Reset\r\n" ); + delay(3000); + ESP.restart(); + }); + + asyncserver.on("/update", HTTP_POST, + [](AsyncWebServerRequest *request) {}, + [](AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final) { handleUpdate(request, filename, index, data, len, final); } + ); + + asyncserver.begin(); +} \ No newline at end of file diff --git a/src/webserver/webserver.h b/src/webserver/webserver.h new file mode 100644 index 0000000..40e92ee --- /dev/null +++ b/src/webserver/webserver.h @@ -0,0 +1,9 @@ +#ifndef _ASYNCWEBSERVER_H + + #define _ASYNCWEBSERVER_H + + #define WEBSERVERPORT 80 + + void asyncwebserver_setup(void); + +#endif // _ASYNCWEBSERVER_H \ No newline at end of file