diff --git a/esphttpdconfig.mk b/esphttpdconfig.mk index d8b6237..aa46aeb 100644 --- a/esphttpdconfig.mk +++ b/esphttpdconfig.mk @@ -39,15 +39,15 @@ OUTPUT_TYPE = combined ESP_SPI_FLASH_SIZE_K = 1024 GLOBAL_CFLAGS = \ - -DDEBUG_ROUTER=0 \ - -DDEBUG_CAPTDNS=0 \ - -DDEBUG_HTTP=0 \ - -DDEBUG_ESPFS=0 \ - -DDEBUG_PERSIST=0 \ - -DDEBUG_UTFCACHE=0 \ + -DDEBUG_ROUTER=1 \ + -DDEBUG_CAPTDNS=1 \ + -DDEBUG_HTTP=1 \ + -DDEBUG_ESPFS=1 \ + -DDEBUG_PERSIST=1 \ + -DDEBUG_UTFCACHE=1 \ -DDEBUG_CGI=0 \ -DDEBUG_WIFI=0 \ - -DDEBUG_WS=0 \ + -DDEBUG_WS=1 \ -DDEBUG_ANSI=1 \ -DDEBUG_ANSI_NOIMPL=1 \ -DDEBUG_INPUT=0 \ @@ -56,6 +56,6 @@ GLOBAL_CFLAGS = \ -DHTTPD_MAX_BACKLOG_SIZE=8192 \ -DHTTPD_MAX_HEAD_LEN=1024 \ -DHTTPD_MAX_POST_LEN=512 \ - -DDEBUG_LOGBUF_SIZE=1024 \ + -DDEBUG_LOGBUF_SIZE=2048 \ -mforce-l32 \ -DUSE_OPTIMIZE_PRINTF=1 diff --git a/user/cgi_sockets.c b/user/cgi_sockets.c index f3adcb8..9c7fac9 100644 --- a/user/cgi_sockets.c +++ b/user/cgi_sockets.c @@ -35,6 +35,8 @@ volatile int active_clients = 0; // this might glitch, very rarely. // it's recommended to put some delay between setting labels and updating the screen. +static void resetHeartbeatTimer(void); + /** * Cooldown delay is over * @param arg @@ -66,6 +68,8 @@ notifyContentTimCb(void *arg) } notify_available = false; + resetHeartbeatTimer(); + for (int i = 0; i < 20; i++) { httpd_cgi_state cont = screenSerializeToBuffer(sock_buff, SOCK_BUF_LEN, &data); int flg = 0; @@ -108,6 +112,7 @@ notifyLabelsTimCb(void *arg) screenSerializeLabelsToBuffer(sock_buff, SOCK_BUF_LEN); cgiWebsockBroadcast(URL_WS_UPDATE, sock_buff, (int) strlen(sock_buff), 0); + resetHeartbeatTimer(); notify_cooldown = true; notify_available = true; @@ -123,6 +128,7 @@ send_beep(void) // here's some potential for a race error with the other broadcast functions :C cgiWebsockBroadcast(URL_WS_UPDATE, "B", 1, 0); + resetHeartbeatTimer(); } @@ -135,6 +141,7 @@ notify_growl(char *msg) // TODO via timer... // here's some potential for a race error with the other broadcast functions :C cgiWebsockBroadcast(URL_WS_UPDATE, msg, (int) strlen(msg), 0); + resetHeartbeatTimer(); } @@ -170,7 +177,7 @@ void ICACHE_FLASH_ATTR screen_notifyChange(ScreenNotifyChangeTopic topic) * @param button - which button, 1-based. 0=none * @param mods - modifier keys bitmap: meta|alt|shift|ctrl */ -void ICACHE_FLASH_ATTR sendMouseAction(char evt, int y, int x, int button, u8 mods) +static void ICACHE_FLASH_ATTR sendMouseAction(char evt, int y, int x, int button, u8 mods) { // one-based x++; @@ -239,7 +246,7 @@ void ICACHE_FLASH_ATTR sendMouseAction(char evt, int y, int x, int button, u8 mo } /** Socket received a message */ -void ICACHE_FLASH_ATTR updateSockRx(Websock *ws, char *data, int len, int flags) +static void ICACHE_FLASH_ATTR updateSockRx(Websock *ws, char *data, int len, int flags) { // Add terminator if missing (seems to randomly happen) data[len] = 0; @@ -304,7 +311,7 @@ void ICACHE_FLASH_ATTR updateSockRx(Websock *ws, char *data, int len, int flags) } /** Send a heartbeat msg */ -void ICACHE_FLASH_ATTR heartbeatTimCb(void *unused) +static void ICACHE_FLASH_ATTR heartbeatTimCb(void *unused) { if (notify_available && active_clients > 0) { // Heartbeat packet - indicate we're still connected @@ -313,7 +320,13 @@ void ICACHE_FLASH_ATTR heartbeatTimCb(void *unused) } } -void ICACHE_FLASH_ATTR closeSockCb(Websock *ws) +static void ICACHE_FLASH_ATTR resetHeartbeatTimer(void) +{ + TIMER_START(&heartbeatTim, heartbeatTimCb, HB_TIME, 1); +} + + +static void ICACHE_FLASH_ATTR closeSockCb(Websock *ws) { active_clients--; if (active_clients <= 0) { @@ -340,7 +353,7 @@ void ICACHE_FLASH_ATTR updateSockConnect(Websock *ws) UART_SendAsync("\x1b[I", 3); } - TIMER_START(&heartbeatTim, heartbeatTimCb, HB_TIME, 1); + resetHeartbeatTimer(); } active_clients++; @@ -348,14 +361,14 @@ void ICACHE_FLASH_ATTR updateSockConnect(Websock *ws) ETSTimer xonTim; -void ICACHE_FLASH_ATTR notify_empty_txbuf_cb(void *unused) +static void ICACHE_FLASH_ATTR notify_empty_txbuf_cb(void *unused) { UART_WriteChar(UART1, '+', 100); cgiWebsockBroadcast(URL_WS_UPDATE, "+", 1, 0); + resetHeartbeatTimer(); browser_wants_xon = false; } - void notify_empty_txbuf(void) { if (browser_wants_xon) { diff --git a/user/screen.c b/user/screen.c index b753d59..057897b 100644 --- a/user/screen.c +++ b/user/screen.c @@ -545,6 +545,10 @@ screen_tab_reverse(int count) /** * Clear range, inclusive + * + * @param from - starting absolute position + * @param to - ending absolute position + * @param clear_utf - release any encountered utf8 */ static void ICACHE_FLASH_ATTR clear_range_do(unsigned int from, unsigned int to, bool clear_utf) @@ -566,7 +570,10 @@ clear_range_do(unsigned int from, unsigned int to, bool clear_utf) } /** - * Clear range, inclusive + * Clear range, inclusive, freeing any encountered UTF8 from the cache + * + * @param from - starting absolute position + * @param to - ending absolute position */ static inline void ICACHE_FLASH_ATTR clear_range_utf(unsigned int from, unsigned int to) @@ -576,6 +583,9 @@ clear_range_utf(unsigned int from, unsigned int to) /** * Clear range, inclusive. Do not release utf characters + * + * @param from - starting absolute position + * @param to - ending absolute position */ static inline void ICACHE_FLASH_ATTR clear_range_noutf(unsigned int from, unsigned int to) @@ -583,44 +593,105 @@ clear_range_noutf(unsigned int from, unsigned int to) clear_range_do(from, to, false); } +/** + * Free a utf8 reference character in a cell + * + * @param row + * @param col + */ static inline void ICACHE_FLASH_ATTR -utf_free_cell(int row, int i) +utf_free_cell(int row, int col) { - UnicodeCacheRef symbol = screen[row * W + i].symbol; + UnicodeCacheRef symbol = screen[row * W + col].symbol; if (IS_UNICODE_CACHE_REF(symbol)) unicode_cache_remove(symbol); } +/** + * Back-up utf8 reference in a cell (i.e. increment the counter, + * so 1 subsequent free has no effect) + * + * @param row + * @param col + */ +static inline void ICACHE_FLASH_ATTR +utf_backup_cell(int row, int col) +{ + UnicodeCacheRef symbol = screen[row * W + col].symbol; + if (IS_UNICODE_CACHE_REF(symbol)) + unicode_cache_inc(symbol); +} + +/** + * Free all utf8 on a row + * + * @param row + */ static inline void ICACHE_FLASH_ATTR -utf_free_row(int r) +utf_free_row(int row) { - for (int i = 0; i < W; i++) { - utf_free_cell(r, i); + for (int col = 0; col < W; col++) { + utf_free_cell(row, col); } } +/** + * Back-up all utf8 refs on a row + * + * @param row + */ +static inline void ICACHE_FLASH_ATTR +utf_backup_row(int row) +{ + for (int col = 0; col < W; col++) { + utf_backup_cell(row, col); + } +} + +/** + * Duplicate a row + * + * @param dest - destination row number (0-based) + * @param src - source row number (0-based) + */ static inline void ICACHE_FLASH_ATTR copy_row(int dest, int src) { memcpy(screen + dest * W, screen + src * W, sizeof(Cell) * W); } +/** + * Duplicate a cell within a row + * @param row - row to work on + * @param dest_col - destination column + * @param src_col - source column + */ static inline void ICACHE_FLASH_ATTR copy_cell(int row, int dest_col, int src_col) { memcpy(screen+row*W+dest_col, screen+row*W+src_col, sizeof(Cell)); } +/** + * Clear a row, do nothing with the utf8 cache + * + * @param row + */ static inline void ICACHE_FLASH_ATTR -clear_row_noutf(int r) +clear_row_noutf(int row) { - clear_range_noutf(r * W, (r + 1) * W - 1); + clear_range_noutf(row * W, (row + 1) * W - 1); } +/** + * Clear a row, freeing any utf8 refs + * + * @param row + */ static inline void ICACHE_FLASH_ATTR -clear_row_utf(int r) +clear_row_utf(int row) { - clear_range_utf(r * W, (r + 1) * W - 1); + clear_range_utf(row * W, (row + 1) * W - 1); } /** @@ -633,7 +704,8 @@ screen_clear(ClearMode mode) NOTIFY_LOCK(); switch (mode) { case CLEAR_ALL: - clear_range_utf(0, W * H - 1); + clear_range_noutf(0, W * H - 1); + unicode_cache_clear(); break; case CLEAR_FROM_CURSOR: @@ -691,20 +763,20 @@ screen_insert_lines(unsigned int lines) // shift the following lines int targetStart = cursor.y + lines; if (targetStart > BTM) { - targetStart = BTM - 1; + clear_range_utf(cursor.y*W, (BTM+1)*W-1); } else { // do the moving for (int i = BTM; i >= targetStart; i--) { utf_free_row(i); // release old characters copy_row(i, i - lines); } - } - // clear the first line - clear_row_noutf(CLEAR_ALL); - // copy it to the rest of the cleared region - for (int i = cursor.y+1; i < targetStart; i++) { - copy_row(i, cursor.y); + // clear the first line + clear_row_noutf(cursor.y); + // copy it to the rest of the cleared region + for (int i = cursor.y+1; i < targetStart; i++) { + copy_row(i, cursor.y); + } } NOTIFY_DONE(); } @@ -716,18 +788,18 @@ screen_delete_lines(unsigned int lines) NOTIFY_LOCK(); // shift lines up - int targetEnd = BTM - lines - 1; - if (targetEnd <= cursor.y) { + int movedBlockEnd = BTM - lines ; + if (movedBlockEnd <= cursor.y) { // clear the entire rest of the screen - targetEnd = cursor.y; - clear_range_utf(targetEnd * W, W * BTM); + movedBlockEnd = cursor.y; + clear_range_utf(movedBlockEnd*W, W * BTM); } else { // move some lines up, clear the rest - for (int i = cursor.y; i <= targetEnd; i++) { + for (int i = cursor.y; i <= movedBlockEnd; i++) { utf_free_row(i); copy_row(i, i+lines); } - clear_range_noutf(targetEnd*W, W*BTM); + clear_range_noutf((movedBlockEnd+1)*W, (BTM+1)*W-1); } NOTIFY_DONE(); @@ -743,8 +815,7 @@ screen_insert_characters(unsigned int count) int targetStart = cursor.x + count; if (targetStart >= W) { // all rest of line was cleared - targetStart = W-1; - clear_range_utf(cursor.y * W + cursor.x, cursor.y * W + targetStart - 1); + clear_range_utf(cursor.y * W + cursor.x, (cursor.y + 1) * W - 1); } else { // do the moving for (int i = W-1; i >= targetStart; i--) { diff --git a/user/utf8.c b/user/utf8.c index bc67de0..3d4c693 100644 --- a/user/utf8.c +++ b/user/utf8.c @@ -20,7 +20,8 @@ static UnicodeCacheSlot cache[UNICODE_CACHE_SIZE]; * @return */ void ICACHE_FLASH_ATTR -unicode_cache_clear(void) { +unicode_cache_clear(void) +{ utfc_dbg("utf8 cache clear!"); for (int slot = 0; slot < UNICODE_CACHE_SIZE; slot++) { cache[slot].count=0; @@ -35,7 +36,8 @@ unicode_cache_clear(void) { * @return the obtained look-up reference */ UnicodeCacheRef ICACHE_FLASH_ATTR -unicode_cache_add(const u8 *bytes) { +unicode_cache_add(const u8 *bytes) +{ if (bytes[0] < 32) { utfc_warn("utf8 cache bad char '%c'", bytes[0]); return '?'; @@ -69,6 +71,27 @@ unicode_cache_add(const u8 *bytes) { return ID_TO_REF(slot); } +/** + * Increment a reference + * + * @param ref - reference + * @return success + */ +bool ICACHE_FLASH_ATTR +unicode_cache_inc(UnicodeCacheRef ref) +{ + if (!IS_UNICODE_CACHE_REF(ref)) return true; // ASCII + + int slot = REF_TO_ID(ref); + if (cache[slot].count == 0) { + utfc_warn("utf8 cache inc-after-free ref @ %d", ref); + return false; + } + cache[slot].count++; + utfc_dbg("utf8 cache inc '%.4s' @ %d, %d uses", cache[slot].bytes, slot, cache[slot].count); + return true; +} + /** * Look up a code point in the cache by reference. Do not change the use counter. * @@ -77,7 +100,8 @@ unicode_cache_add(const u8 *bytes) { * @return true if the look-up succeeded */ bool ICACHE_FLASH_ATTR -unicode_cache_retrieve(UnicodeCacheRef ref, u8 *target) { +unicode_cache_retrieve(UnicodeCacheRef ref, u8 *target) +{ if (!IS_UNICODE_CACHE_REF(ref)) { // ASCII, bypass target[0] = ref; @@ -107,7 +131,8 @@ unicode_cache_retrieve(UnicodeCacheRef ref, u8 *target) { * @return true if the code point was found in the cache */ bool ICACHE_FLASH_ATTR -unicode_cache_remove(UnicodeCacheRef ref) { +unicode_cache_remove(UnicodeCacheRef ref) +{ if (!IS_UNICODE_CACHE_REF(ref)) return true; // ASCII, bypass u8 slot = REF_TO_ID(ref); diff --git a/user/utf8.h b/user/utf8.h index 81f9372..c24bf07 100644 --- a/user/utf8.h +++ b/user/utf8.h @@ -28,6 +28,14 @@ void unicode_cache_clear(void); */ UnicodeCacheRef unicode_cache_add(const u8 *bytes); +/** + * Increment a reference + * + * @param ref - reference + * @return success + */ +bool unicode_cache_inc(UnicodeCacheRef ref); + /** * Look up a code point in the cache by reference. Do not change the use counter. *