From 6666a131ab36b1d96a854da80524d860f9a3884b Mon Sep 17 00:00:00 2001
From: Uros Majstorovic <majstor@majstor.org>
Date: Wed, 19 Feb 2020 06:47:43 +0100
Subject: eve long press/double tap/inertial scroll spi flush bugfix resolved
 dependecies: spi -> net; event -> net renamed various handlers

---
 code/fe310/eos/Makefile     |   2 +-
 code/fe310/eos/cell.c       |  22 +-
 code/fe310/eos/cell.h       |   2 +-
 code/fe310/eos/eos.c        |   8 +-
 code/fe310/eos/eos.h        |   1 +
 code/fe310/eos/eve.c        | 662 ++++++++++++++++++++++++++------------------
 code/fe310/eos/eve.h        | 149 ++++++----
 code/fe310/eos/eve_config.h |  40 ---
 code/fe310/eos/eve_kbd.c    |  85 +++---
 code/fe310/eos/eve_kbd.h    |  14 +-
 code/fe310/eos/eve_text.c   | 209 +++++++-------
 code/fe310/eos/eve_text.h   |  35 +--
 code/fe310/eos/event.c      |  73 ++---
 code/fe310/eos/event.h      |   6 +-
 code/fe310/eos/evt_def.h    |   2 +-
 code/fe310/eos/i2s.c        |  17 +-
 code/fe310/eos/i2s.h        |   6 +-
 code/fe310/eos/interrupt.c  |   6 +-
 code/fe310/eos/interrupt.h  |   8 +-
 code/fe310/eos/net.c        | 220 +++++++--------
 code/fe310/eos/net.h        |  10 +-
 code/fe310/eos/net_def.h    |   2 +
 code/fe310/eos/sock.c       |  42 +--
 code/fe310/eos/sock.h       |   6 +-
 code/fe310/eos/spi.c        | 231 ++++++----------
 code/fe310/eos/spi.h        |  21 +-
 code/fe310/eos/spi_def.h    |  14 +-
 code/fe310/eos/spi_dev.c    |  50 ++++
 code/fe310/eos/spi_dev.h    |   9 +
 code/fe310/eos/timer.c      |  56 +---
 code/fe310/eos/timer.h      |   5 +-
 code/fe310/eos/trap_entry.S |  36 +--
 code/fe310/eos/uart.c       |  21 +-
 code/fe310/eos/uart.h       |   4 +-
 code/fe310/eos/wifi.c       |  22 +-
 code/fe310/eos/wifi.h       |   2 +-
 36 files changed, 1080 insertions(+), 1018 deletions(-)
 create mode 100644 code/fe310/eos/spi_dev.c
 create mode 100644 code/fe310/eos/spi_dev.h

(limited to 'code')

diff --git a/code/fe310/eos/Makefile b/code/fe310/eos/Makefile
index 95e0da5..02196d8 100644
--- a/code/fe310/eos/Makefile
+++ b/code/fe310/eos/Makefile
@@ -2,7 +2,7 @@ include ../common.mk
 
 CFLAGS += -I../include -I../drivers
 
-obj = trap_entry.o eos.o msgq.o event.o interrupt.o timer.o i2s.o uart.o spi.o net.o wifi.o cell.o sock.o eve.o eve_kbd.o eve_text.o
+obj = trap_entry.o eos.o msgq.o event.o interrupt.o timer.o i2s.o uart.o spi.o spi_dev.o net.o wifi.o cell.o sock.o eve.o eve_kbd.o eve_text.o
 
 
 %.o: %.c %.h
diff --git a/code/fe310/eos/cell.c b/code/fe310/eos/cell.c
index b2d62f8..d75e1b9 100644
--- a/code/fe310/eos/cell.c
+++ b/code/fe310/eos/cell.c
@@ -8,25 +8,25 @@
 
 #include "cell.h"
 
-static eos_evt_fptr_t evt_handler[EOS_CELL_MAX_MTYPE];
+static eos_evt_handler_t evt_handler[EOS_CELL_MAX_MTYPE];
 static uint16_t evt_handler_flags_buf_free = 0;
 static uint16_t evt_handler_flags_buf_acq = 0;
 
-static void cell_handler_evt(unsigned char type, unsigned char *buffer, uint16_t len) {
+static void cell_handle_evt(unsigned char type, unsigned char *buffer, uint16_t len) {
     if ((buffer == NULL) || (len < 1)) {
         eos_evtq_bad_handler(type, buffer, len);
         eos_net_free(buffer, 0);
         return;
     }
 
-    uint8_t mtype = buffer[0];
-    if (mtype >= EOS_CELL_MAX_MTYPE) {
+    unsigned char mtype = buffer[0];
+    if (mtype < EOS_CELL_MAX_MTYPE) {
+        evt_handler[mtype](type, buffer, len);
+    } else {
         eos_evtq_bad_handler(type, buffer, len);
         eos_net_free(buffer, 0);
         return;
     }
-
-    _eos_net_handle(type, buffer, len, mtype, evt_handler, &evt_handler_flags_buf_free, &evt_handler_flags_buf_acq);
 }
 
 void eos_cell_init(void) {
@@ -35,12 +35,10 @@ void eos_cell_init(void) {
     for (i=0; i<EOS_CELL_MAX_MTYPE; i++) {
         evt_handler[i] = eos_evtq_bad_handler;
     }
-    eos_net_set_handler(EOS_NET_MTYPE_CELL, cell_handler_evt, 0);
+    eos_net_set_handler(EOS_NET_MTYPE_CELL, cell_handle_evt);
 }
 
-void eos_cell_set_handler(int mtype, eos_evt_fptr_t handler, uint8_t flags) {
-    if (mtype >= EOS_CELL_MAX_MTYPE) {
-        return;
-    }
-    _eos_net_set_handler(mtype, handler, evt_handler, flags, &evt_handler_flags_buf_free, &evt_handler_flags_buf_acq);
+void eos_cell_set_handler(unsigned char mtype, eos_evt_handler_t handler) {
+    if (handler == NULL) handler = eos_evtq_bad_handler;
+    if (mtype < EOS_CELL_MAX_MTYPE) evt_handler[mtype] = handler;
 }
diff --git a/code/fe310/eos/cell.h b/code/fe310/eos/cell.h
index d6f6c35..2103c72 100644
--- a/code/fe310/eos/cell.h
+++ b/code/fe310/eos/cell.h
@@ -13,4 +13,4 @@
 #define EOS_CELL_MAX_MTYPE          2
 
 void eos_cell_init(void);
-void eos_cell_set_handler(int mtype, eos_evt_fptr_t handler, uint8_t flags);
\ No newline at end of file
+void eos_cell_set_handler(unsigned char mtype, eos_evt_handler_t handler);
\ No newline at end of file
diff --git a/code/fe310/eos/eos.c b/code/fe310/eos/eos.c
index bb231d1..715549f 100644
--- a/code/fe310/eos/eos.c
+++ b/code/fe310/eos/eos.c
@@ -12,6 +12,8 @@
 
 #include "eos.h"
 
+uint32_t touch_transform[6] = {0xfa46,0xfffffcf6,0x422fe,0xffffff38,0x10002,0xf3cb0};
+
 void eos_init(void) {
     eos_evtq_init();
     eos_intr_init();
@@ -23,7 +25,9 @@ void eos_init(void) {
     eos_wifi_init();
     eos_cell_init();
     eos_sock_init();
-    eos_spi_dev_start(EOS_SPI_DEV_DISP);
-    eos_eve_init();
+    eos_spi_dev_init();
+
+    eos_spi_dev_start(EOS_DEV_DISP);
+    eve_init(touch_transform);
     eos_spi_dev_stop();
 }
diff --git a/code/fe310/eos/eos.h b/code/fe310/eos/eos.h
index 08bd10b..b48b7c0 100644
--- a/code/fe310/eos/eos.h
+++ b/code/fe310/eos/eos.h
@@ -3,5 +3,6 @@
 #define EOS_ERR_FULL            -10
 #define EOS_ERR_EMPTY           -11
 #define EOS_ERR_NET             -20
+#define EOS_ERR_TEXT            -30
 
 void eos_init(void);
diff --git a/code/fe310/eos/eve.c b/code/fe310/eos/eve.c
index 22af7d7..ccc52e2 100644
--- a/code/fe310/eos/eve.c
+++ b/code/fe310/eos/eve.c
@@ -1,6 +1,7 @@
 #include <stdlib.h>
 #include <stdarg.h>
 #include <stdio.h>
+#include <math.h>
 
 #include "encoding.h"
 #include "platform.h"
@@ -13,28 +14,38 @@
 #include "eve.h"
 #include "irq_def.h"
 
-#define MEM_WRITE               0x800000
 
-#define EVE_PIN_INT             0
+#define EVE_PIN_INTR            0
 #define EVE_MAX_TOUCH           5
+#define EVE_ETYPE_INTR          1
 
-#define EVE_ETYPE_INT           1
+#define EVE_THRESHOLD_X         5
+#define EVE_THRESHOLD_Y         5
+#define EVE_TIMEOUT_TAP         1000
+#define EVE_TIMEOUT_TRACK       20
+#define EVE_TRAVG               3
+#define EVE_FRICTION            500
 
-#define EVE_MOVE_THRESHOLD      10
-#define EVE_LPRESS_TIMEOUT      1000
+#define EVE_NOTOUCH             0x80000000
+#define EVE_MEM_WRITE           0x800000
 
-static char eve_cmd_burst;
-static uint16_t eve_cmd_offset;
-static uint32_t eve_dl_addr;
+// #define EOS_SPI_FLAG_TX         0
 
-static int eve_int_mask = EVE_INT_TAG | EVE_INT_TOUCH;
-static int eve_multitouch = 0;
-static uint8_t eve_tag0;
-static EOSTouch eve_touch[5];
-static uint64_t eve_touch_timer_t0;
-static uint8_t eve_touch_timer_tag;
-static uint8_t eve_tag_evt[256];
-static eos_eve_fptr_t eve_renderer;
+static char _cmd_burst;
+static uint16_t _cmd_offset;
+static uint32_t _dl_addr;
+
+static int _intr_mask = EVE_INT_TAG | EVE_INT_TOUCH;
+static int _multitouch;
+static uint8_t _tag0;
+
+static EVETouch _touch[EVE_MAX_TOUCH];
+static EVETouchTimer _touch_timer;
+
+static eve_touch_handler_t _touch_handler;
+static void *_touch_handler_param;
+
+static uint8_t _tag_opt[255];
 
 static const uint32_t _reg_touch[] = {
     REG_CTOUCH_TOUCH0_XY,
@@ -59,13 +70,13 @@ static const uint32_t _reg_track[] = {
     REG_TRACKER_4
 };
 
-void eos_eve_command(uint8_t command, uint8_t parameter) {
+void eve_command(uint8_t command, uint8_t parameter) {
     eos_spi_cs_set();
     eos_spi_xchg24(((uint32_t)command << 16) | ((uint32_t)parameter << 8), 0);
     eos_spi_cs_clear();
 }
 
-uint8_t eos_eve_read8(uint32_t addr) {
+uint8_t eve_read8(uint32_t addr) {
     uint8_t r;
     eos_spi_cs_set();
     eos_spi_xchg32(addr << 8, 0);
@@ -75,7 +86,7 @@ uint8_t eos_eve_read8(uint32_t addr) {
     return r;
 }
 
-uint16_t eos_eve_read16(uint32_t addr) {
+uint16_t eve_read16(uint32_t addr) {
     uint16_t r;
     eos_spi_cs_set();
     eos_spi_xchg32(addr << 8, 0);
@@ -85,7 +96,7 @@ uint16_t eos_eve_read16(uint32_t addr) {
     return r;
 }
 
-uint32_t eos_eve_read32(uint32_t addr) {
+uint32_t eve_read32(uint32_t addr) {
     uint32_t r;
     eos_spi_cs_set();
     eos_spi_xchg32(addr << 8, 0);
@@ -95,77 +106,77 @@ uint32_t eos_eve_read32(uint32_t addr) {
     return r;
 }
 
-void eos_eve_write8(uint32_t addr, uint8_t data) {
+void eve_write8(uint32_t addr, uint8_t data) {
     eos_spi_cs_set();
-    eos_spi_xchg24(addr | MEM_WRITE, 0);
+    eos_spi_xchg24(addr | EVE_MEM_WRITE, 0);
     eos_spi_xchg8(data, EOS_SPI_FLAG_BSWAP);
     eos_spi_cs_clear();
 }
 
-void eos_eve_write16(uint32_t addr, uint16_t data) {
+void eve_write16(uint32_t addr, uint16_t data) {
     eos_spi_cs_set();
-    eos_spi_xchg24(addr | MEM_WRITE, 0);
+    eos_spi_xchg24(addr | EVE_MEM_WRITE, 0);
     eos_spi_xchg16(data, EOS_SPI_FLAG_BSWAP);
     eos_spi_cs_clear();
 }
 
-void eos_eve_write32(uint32_t addr, uint32_t data) {
+void eve_write32(uint32_t addr, uint32_t data) {
     eos_spi_cs_set();
-    eos_spi_xchg24(addr | MEM_WRITE, 0);
+    eos_spi_xchg24(addr | EVE_MEM_WRITE, 0);
     eos_spi_xchg32(data, EOS_SPI_FLAG_BSWAP);
     eos_spi_cs_clear();
 }
 
-void eos_eve_active(void) {
-    eos_eve_command(EVE_ACTIVE, 0);
+void eve_active(void) {
+    eve_command(EVE_ACTIVE, 0);
 }
 
-void eos_eve_brightness(uint8_t b) {
-	eos_eve_write8(REG_PWM_DUTY, b);
+void eve_brightness(uint8_t b) {
+	eve_write8(REG_PWM_DUTY, b);
 }
 
 static void _dl_inc(uint32_t i) {
-	eve_dl_addr += i;
+	_dl_addr += i;
 }
 
-void eos_eve_dl_start(uint32_t addr) {
-    eve_dl_addr = addr;
+void eve_dl_start(uint32_t addr) {
+    _dl_addr = addr;
 }
 
-void eos_eve_dl_write(uint32_t dl) {
-    eos_eve_write32(eve_dl_addr, dl);
+void eve_dl_write(uint32_t dl) {
+    eve_write32(_dl_addr, dl);
     _dl_inc(4);
 }
 
-void eos_eve_dl_swap(void) {
-    eos_eve_write8(REG_DLSWAP, EVE_DLSWAP_FRAME);
+void eve_dl_swap(void) {
+    eve_write8(REG_DLSWAP, EVE_DLSWAP_FRAME);
 }
 
-uint32_t eos_eve_dl_addr(void) {
-    return eve_dl_addr;
+uint32_t eve_dl_get_addr(void) {
+    return _dl_addr;
 }
 
 static void _cmd_inc(uint16_t i) {
-	eve_cmd_offset += i;
-	eve_cmd_offset &= 0x0fff;
+	_cmd_offset += i;
+	_cmd_offset &= 0x0fff;
 }
 
 static void _cmd_begin(uint32_t command) {
     uint8_t flags = 0;
 
-    if (eve_cmd_burst) {
+    if (_cmd_burst) {
         flags = EOS_SPI_FLAG_TX;
     } else {
-    	uint32_t addr = EVE_RAM_CMD + eve_cmd_offset;
+    	uint32_t addr = EVE_RAM_CMD + _cmd_offset;
         eos_spi_cs_set();
-        eos_spi_xchg24(addr | MEM_WRITE, 0);
+        eos_spi_xchg24(addr | EVE_MEM_WRITE, 0);
     }
     eos_spi_xchg32(command, EOS_SPI_FLAG_BSWAP | flags);
     _cmd_inc(4);
 }
 
 static void _cmd_end(void) {
-    if (!eve_cmd_burst) eos_spi_cs_clear();
+    if (!_cmd_burst) eos_spi_cs_clear();
 }
 
 static void _cmd_string(const char *s, uint8_t flags) {
@@ -189,8 +200,8 @@ static void _cmd_buffer(const char *b, int size, uint8_t flags) {
     _cmd_inc(size);
 }
 
-void eos_eve_cmd(uint32_t cmd, const char *fmt, ...) {
-    uint8_t flags = eve_cmd_burst ? EOS_SPI_FLAG_TX : 0;
+void eve_cmd(uint32_t cmd, const char *fmt, ...) {
+    uint8_t flags = _cmd_burst ? EOS_SPI_FLAG_TX : 0;
     va_list argv;
     uint16_t *p;
     int i = 0;
@@ -213,7 +224,7 @@ void eos_eve_cmd(uint32_t cmd, const char *fmt, ...) {
                 break;
             case '&':
                 p = va_arg(argv, uint16_t *);
-                *p = eve_cmd_offset;
+                *p = _cmd_offset;
                 eos_spi_xchg32(0, EOS_SPI_FLAG_BSWAP | flags);
                 _cmd_inc(4);
                 break;
@@ -227,7 +238,7 @@ void eos_eve_cmd(uint32_t cmd, const char *fmt, ...) {
         i++;
     }
     /* padding */
-	i = eve_cmd_offset & 3;  /* equivalent to eve_cmd_offset % 4 */
+	i = _cmd_offset & 3;  /* equivalent to _cmd_offset % 4 */
     if (i) {
     	i = 4 - i;  /* 3, 2 or 1 */
         _cmd_inc(i);
@@ -241,363 +252,482 @@ void eos_eve_cmd(uint32_t cmd, const char *fmt, ...) {
 	va_end(argv);
 }
 
-uint32_t eos_eve_cmd_result(uint16_t offset) {
-    return eos_eve_read32(EVE_RAM_CMD + offset);
+uint32_t eve_cmd_result(uint16_t offset) {
+    return eve_read32(EVE_RAM_CMD + offset);
 }
 
-void eos_eve_cmd_dl(uint32_t dl) {
+void eve_cmd_dl(uint32_t dl) {
     _cmd_begin(dl);
     _cmd_end();
 }
 
-int eos_eve_cmd_done(void) {
-	uint16_t r = eos_eve_read16(REG_CMD_READ);
+int eve_cmd_done(void) {
+	uint16_t r = eve_read16(REG_CMD_READ);
     if (r == 0xfff) {
-		eve_cmd_offset = 0;
-		eos_eve_write8(REG_CPURESET, 1);
-		eos_eve_write16(REG_CMD_READ, 0);
-		eos_eve_write16(REG_CMD_WRITE, 0);
-		eos_eve_write16(REG_CMD_DL, 0);
-		eos_eve_write8(REG_CPURESET, 0);
+		_cmd_offset = 0;
+		eve_write8(REG_CPURESET, 1);
+		eve_write16(REG_CMD_READ, 0);
+		eve_write16(REG_CMD_WRITE, 0);
+		eve_write16(REG_CMD_DL, 0);
+		eve_write8(REG_CPURESET, 0);
         return -1;
     }
-    return (r == eve_cmd_offset);
+    return (r == _cmd_offset);
 }
 
-int eos_eve_cmd_exec(int w) {
-    eos_eve_write16(REG_CMD_WRITE, eve_cmd_offset);
+int eve_cmd_exec(int w) {
+    eve_write16(REG_CMD_WRITE, _cmd_offset);
     if (w) {
         int r;
         do {
-            r = eos_eve_cmd_done();
+            r = eve_cmd_done();
         } while (!r);
         if (r < 0) return EOS_ERR;
     }
     return EOS_OK;
 }
 
-void eos_eve_cmd_burst_start(void) {
-	uint32_t addr = EVE_RAM_CMD + eve_cmd_offset;
+void eve_cmd_burst_start(void) {
+	uint32_t addr = EVE_RAM_CMD + _cmd_offset;
     eos_spi_cs_set();
-    eos_spi_xchg24(addr | MEM_WRITE, EOS_SPI_FLAG_TX);
-    eve_cmd_burst = 1;
+    eos_spi_xchg24(addr | EVE_MEM_WRITE, EOS_SPI_FLAG_TX);
+    _cmd_burst = 1;
 }
 
-void eos_eve_cmd_burst_end(void) {
+void eve_cmd_burst_end(void) {
+    eos_spi_flush();
     eos_spi_cs_clear();
-    eve_cmd_burst = 0;
+    _cmd_burst = 0;
 }
 
-static void eve_handle_touch(uint8_t flags) {
+static void _touch_timer_clear(void) {
+    _touch_timer.tag = 0;
+    _touch_timer.fc = 0;
+}
+
+static void handle_touch(uint8_t flags) {
     int i;
-    uint8_t tag0 = eve_tag0;
-    uint8_t touch_last = 0;
     char touch_ex = 0;
     char int_ccomplete = 0;
-    if (!eve_multitouch && (flags & EVE_INT_TOUCH)) eve_multitouch = 1;
+    uint8_t tag0 = _tag0;
+    uint8_t touch_last = 0;
 
+    if (!_multitouch && (flags & EVE_INT_TOUCH)) _multitouch = 1;
     for (i=0; i<EVE_MAX_TOUCH; i++) {
         uint8_t touch_tag;
         uint32_t touch_xy;
-        EOSTouch *touch = &eve_touch[i];
-
-        touch->evt &= (EOS_TOUCH_ETYPE_LPRESS | EOS_TOUCH_ETYPE_TRACK_MASK);
+        volatile uint64_t *mtime = (uint64_t *) (CLINT_CTRL_ADDR + CLINT_MTIME);
+        uint64_t now = 0;
+        EVETouch *touch = &_touch[i];
 
-        touch_xy = i < 4 ? eos_eve_read32(_reg_touch[i]) : (((uint32_t)eos_eve_read16(REG_CTOUCH_TOUCH4_X) << 16) | eos_eve_read16(REG_CTOUCH_TOUCH4_Y));
+        touch->evt &= 0xff00;
+        touch_xy = i < 4 ? eve_read32(_reg_touch[i]) : (((uint32_t)eve_read16(REG_CTOUCH_TOUCH4_X) << 16) | eve_read16(REG_CTOUCH_TOUCH4_Y));
 
         if (touch_xy != 0x80008000) {
-            uint16_t touch_x = touch_xy >> 16;
-            uint16_t touch_y = touch_xy & 0xffff;
-            if (touch->x == 0x8000) {
-                touch->evt |= EOS_TOUCH_ETYPE_POINT_DOWN;
+            int16_t touch_x = touch_xy >> 16;
+            int16_t touch_y = touch_xy & 0xffff;
+            now = *mtime;
+            if (touch->x == EVE_NOTOUCH) {
+                if (!_tag0 && _touch_timer.tag) {
+                    if (_touch_timer.evt & EVE_TOUCH_ETYPE_TAP1) {
+                        int dx = touch_x - touch->x0;
+                        int dy = touch_y - touch->y0;
+                        dx = dx < 0 ? -dx : dx;
+                        dy = dy < 0 ? -dy : dy;
+                        if ((dx > EVE_THRESHOLD_X) || (dy > EVE_THRESHOLD_Y)) {
+                            touch->evt = EVE_TOUCH_ETYPE_TAP1;
+                        } else {
+                            touch->evt = EVE_TOUCH_ETYPE_TAP2;
+                        }
+                        _touch_handler(_touch_handler_param, _touch_timer.tag, i);
+                    }
+                    eos_timer_clear(EOS_TIMER_ETYPE_UI);
+                    _touch_timer_clear();
+                }
+                touch->evt = EVE_TOUCH_ETYPE_POINT;
+                touch->tag0 = 0;
+                touch->tag = 0;
+                touch->tag_up = 0;
+                touch->tracker.tag = 0;
+                touch->tracker.track = 0;
+                touch->tracker.val = 0;
+                touch->t = 0;
+                touch->vx = 0;
+                touch->vy = 0;
                 touch->x0 = touch_x;
                 touch->y0 = touch_y;
+            } else if (touch->t) {
+                int dt = now - touch->t;
+                int vx = ((int)touch_x - touch->x) * (int)(RTC_FREQ) / dt;
+                int vy = ((int)touch_y - touch->y) * (int)(RTC_FREQ) / dt;
+                touch->vx = touch->vx ? (vx + touch->vx * EVE_TRAVG) / (EVE_TRAVG + 1) : vx;
+                touch->vy = touch->vy ? (vy + touch->vy * EVE_TRAVG) / (EVE_TRAVG + 1) : vy;
+                touch->t = now;
             }
             touch->x = touch_x;
             touch->y = touch_y;
-            if (eve_multitouch || (flags & EVE_INT_TAG)) {
-                touch_tag = eos_eve_read8(_reg_tag[i]);
+            if (_multitouch || (flags & EVE_INT_TAG)) {
+                touch_tag = eve_read8(_reg_tag[i]);
             } else {
-                touch_tag = touch->tag_down;
+                touch_tag = touch->tag;
             }
             touch_ex = 1;
         } else {
             touch_tag = 0;
-            if (touch->x != 0x8000) touch->evt |= EOS_TOUCH_ETYPE_POINT_UP;
+            if (touch->x != EVE_NOTOUCH) {
+                touch->evt |= EVE_TOUCH_ETYPE_POINT_UP;
+                if (_touch_timer.tag && (i == 0)) {
+                    _touch_timer.evt &= ~EVE_TOUCH_ETYPE_LPRESS;
+                    if (!_touch_timer.evt) {
+                        eos_timer_clear(EOS_TIMER_ETYPE_UI);
+                        _touch_timer_clear();
+                    }
+                }
+                if (!_touch_timer.tag && touch->tracker.tag && touch->tracker.track && (_tag_opt[touch->tracker.tag] & EVE_TOUCH_OPT_INERT)) {
+                    _touch_timer.x0 = touch->x;
+                    _touch_timer.y0 = touch->y;
+                    _touch_timer.tag = touch->tracker.tag;
+                    _touch_timer.idx = i;
+                    _touch_timer.evt = EVE_TOUCH_ETYPE_TRACK;
+                    eos_timer_set(EVE_TIMEOUT_TRACK, EOS_TIMER_ETYPE_UI, 0);
+                }
+                touch->x = EVE_NOTOUCH;
+                touch->y = EVE_NOTOUCH;
+            }
         }
-        if (touch_tag != touch->tag_down) {
+        if (touch_tag != touch->tag) {
             if (touch_tag) {
-                if (!eve_tag0) tag0 = eve_tag0 = touch_tag;
                 if (!touch->tag0) {
                     touch->tag0 = touch_tag;
-                    touch->evt |= eve_tag_evt[touch_tag] & EOS_TOUCH_ETYPE_TRACK_MASK;
-                    if (touch->evt & EOS_TOUCH_ETYPE_TRACK_MASK) {
-                        if (touch->evt & EOS_TOUCH_ETYPE_TRACK) touch->tracker.tag = touch_tag;
-                    } else {
-                        touch->evt |= eve_tag_evt[0xff] & EOS_TOUCH_ETYPE_TRACK_MASK;
-                        if (touch->evt & EOS_TOUCH_ETYPE_TRACK) touch->tracker.tag = 0xff;
+                    if (_tag_opt[touch_tag] & EVE_TOUCH_OPT_TRACK_MASK) {
+                        touch->tracker.tag = touch_tag;
+                    } else if (_tag_opt[0xff] & EVE_TOUCH_OPT_TRACK_MASK) {
+                        touch->tracker.tag = 0xff;
                     }
-                    if (((eve_tag_evt[touch_tag] | eve_tag_evt[0xff]) & EOS_TOUCH_ETYPE_LPRESS) && (i == 0)) {
-                        volatile uint64_t *mtime = (uint64_t *) (CLINT_CTRL_ADDR + CLINT_MTIME);
-
-                        eve_touch_timer_t0 = *mtime;
-                        eve_touch_timer_tag = eve_tag_evt[touch_tag] & EOS_TOUCH_ETYPE_LPRESS ? touch_tag : 0xff;
-                        eos_timer_set(EVE_LPRESS_TIMEOUT, EOS_TIMER_ETYPE_UI, 0);
+                    if (touch->tracker.tag && !(_tag_opt[touch->tracker.tag] & EVE_TOUCH_OPT_TRACK_XY)) {
+                        touch->tracker.track = 1;
+                        if (!touch->t && (_tag_opt[touch->tracker.tag] & EVE_TOUCH_OPT_INERT)) touch->t = now;
+                    }
+                    if (!_tag0 && ((_tag_opt[touch_tag] | _tag_opt[0xff]) & EVE_TOUCH_OPT_TIMER_MASK)) {
+                        _touch_timer.tag = _tag_opt[touch_tag] & EVE_TOUCH_OPT_TIMER_MASK ? touch_tag : 0xff;
+                        _touch_timer.idx = 0;
+                        _touch_timer.evt = 0;
+                        if (_tag_opt[_touch_timer.tag] & EVE_TOUCH_OPT_LPRESS) _touch_timer.evt |= EVE_TOUCH_ETYPE_LPRESS;
+                        if (_tag_opt[_touch_timer.tag] & EVE_TOUCH_OPT_DTAP) _touch_timer.evt |= EVE_TOUCH_ETYPE_TAP1;
+                        eos_timer_set(EVE_TIMEOUT_TAP, EOS_TIMER_ETYPE_UI, 0);
                     }
                 }
+                if (!_tag0) tag0 = _tag0 = touch_tag;
             }
-            touch->tag_up = touch->tag_down;
-            touch->tag_down = touch_tag;
-            if (touch->tag_up) touch->evt |= EOS_TOUCH_ETYPE_TAG_UP;
-            if (touch->tag_down) touch->evt |= EOS_TOUCH_ETYPE_TAG_DOWN;
+            touch->tag_up = touch->tag;
+            if (touch->tag_up) touch->evt |= EVE_TOUCH_ETYPE_TAG_UP;
+            touch->tag = touch_tag;
+            if (touch->tag) touch->evt |= EVE_TOUCH_ETYPE_TAG;
         }
-        if (touch->evt & EOS_TOUCH_ETYPE_TRACK_REG) {
-            uint32_t touch_track = eos_eve_read32(_reg_track[i]);
-            touch->tracker.tag = touch_track & 0xffff;
-            touch->tracker.val = touch_track >> 16;
-        }
-        if (eve_touch_timer_tag && (i == 0)) {
-            uint16_t dx = touch->x > touch->x0 ? touch->x - touch->x0 : touch->x0 - touch->x;
-            uint16_t dy = touch->y > touch->y0 ? touch->y - touch->y0 : touch->y0 - touch->y;
-            if ((dx > EVE_MOVE_THRESHOLD) || (dy > EVE_MOVE_THRESHOLD)) {
-                eos_timer_clear(EOS_TIMER_ETYPE_UI);
-                eve_touch_timer_t0 = 0;
-                eve_touch_timer_tag = 0;
+        if (touch_xy != 0x80008000) {
+            char _track = touch->tracker.tag && !touch->tracker.track;
+            if (_track || _touch_timer.tag) {
+                int dx = touch->x - touch->x0;
+                int dy = touch->y - touch->y0;
+                dx = dx < 0 ? -dx : dx;
+                dy = dy < 0 ? -dy : dy;
+                if (_track) {
+                    if ((dx > EVE_THRESHOLD_X) && !(_tag_opt[touch->tracker.tag] & EVE_TOUCH_OPT_TRACK_X)) {
+                        touch->tracker.tag = 0;
+                    }
+                    if ((dy > EVE_THRESHOLD_Y) && !(_tag_opt[touch->tracker.tag] & EVE_TOUCH_OPT_TRACK_Y)) {
+                        touch->tracker.tag = 0;
+                    }
+                    if (touch->tracker.tag && ((dx > EVE_THRESHOLD_X) || (dy > EVE_THRESHOLD_Y))) {
+                        if (dx > EVE_THRESHOLD_X) {
+                            touch->evt |= touch->x > touch->x0 ? EVE_TOUCH_ETYPE_TRACK_RIGHT : EVE_TOUCH_ETYPE_TRACK_LEFT;
+                        }
+                        if (dy > EVE_THRESHOLD_Y) {
+                            touch->evt |= touch->y > touch->y0 ? EVE_TOUCH_ETYPE_TRACK_DOWN : EVE_TOUCH_ETYPE_TRACK_UP;
+                        }
+                        touch->tracker.track = 1;
+                        if (!touch->t && (_tag_opt[touch->tracker.tag] & EVE_TOUCH_OPT_INERT)) touch->t = now;
+                    }
+                }
+                if (_touch_timer.tag && ((dx > EVE_THRESHOLD_X) || (dy > EVE_THRESHOLD_Y))) {
+                    eos_timer_clear(EOS_TIMER_ETYPE_UI);
+                    _touch_timer_clear();
+                }
             }
+            if (touch->tracker.tag && touch->tracker.track) {
+                touch->evt |= _tag_opt[touch->tracker.tag] & EVE_TOUCH_ETYPE_TRACK_MASK;
+            }
+            if (touch->evt & EVE_TOUCH_ETYPE_TRACK_REG) {
+                uint32_t touch_track = eve_read32(_reg_track[i]);
+                if (touch->tracker.tag == (touch_track & 0xff)) {
+                    touch->tracker.val = touch_track >> 16;
+                } else {
+                    touch->evt &= ~EVE_TOUCH_ETYPE_TRACK_REG;
+                }
+            }
+            if (touch->tracker.tag || _touch_timer.tag) int_ccomplete = 1;
         }
-        if (touch->evt) {
-            touch_last = i + 1;
-            if (touch->evt & EOS_TOUCH_ETYPE_TRACK_MASK) int_ccomplete = 1;
+        if (touch->evt & 0xff) touch_last = i + 1;
+        if (!_multitouch) break;
+        if (_touch_timer.tag) {
+            eos_timer_clear(EOS_TIMER_ETYPE_UI);
+            _touch_timer_clear();
         }
-        if (!eve_multitouch) break;
     }
 
     if (!touch_ex) {
-        eve_tag0 = 0;
-        eve_multitouch = 0;
+        _tag0 = 0;
+        _multitouch = 0;
     }
 
-    if (eve_multitouch) int_ccomplete = 1;
+    if (_multitouch) int_ccomplete = 1;
 
-    if (int_ccomplete && !(eve_int_mask & EVE_INT_CONVCOMPLETE)) {
-        eve_int_mask |= EVE_INT_CONVCOMPLETE;
-        eos_eve_write8(REG_INT_MASK, eve_int_mask);
+    if (int_ccomplete && !(_intr_mask & EVE_INT_CONVCOMPLETE)) {
+        _intr_mask |= EVE_INT_CONVCOMPLETE;
+        eve_write8(REG_INT_MASK, _intr_mask);
     }
-    if (!int_ccomplete && (eve_int_mask & EVE_INT_CONVCOMPLETE)) {
-        eve_int_mask &= ~EVE_INT_CONVCOMPLETE;
-        eos_eve_write8(REG_INT_MASK, eve_int_mask);
+    if (!int_ccomplete && (_intr_mask & EVE_INT_CONVCOMPLETE)) {
+        _intr_mask &= ~EVE_INT_CONVCOMPLETE;
+        eve_write8(REG_INT_MASK, _intr_mask);
     }
 
     for (i=0; i<touch_last; i++) {
-        EOSTouch *touch = &eve_touch[i];
-        if (touch->evt) {
-            eve_renderer(tag0, i);
-            if (touch->evt & EOS_TOUCH_ETYPE_POINT_UP) {
-                touch->x = 0x8000;
-                touch->y = 0x8000;
-                touch->evt = 0;
-                touch->tag0 = 0;
-                touch->tag_up = 0;
-                touch->tag_down = 0;
-                touch->tracker.tag = 0;
-                touch->tracker.val = 0;
-                if (eve_touch_timer_tag && (i == 0)) {
-                    eos_timer_clear(EOS_TIMER_ETYPE_UI);
-                    eve_touch_timer_t0 = 0;
-                    eve_touch_timer_tag = 0;
-                }
-            }
+        EVETouch *touch = &_touch[i];
+        if (touch->evt & 0xff) {
+            _touch_handler(_touch_handler_param, tag0, i);
         }
     }
 }
 
-static void eve_handler_time(unsigned char type) {
-    eve_touch[0].evt |= EOS_TOUCH_ETYPE_LPRESS;
+static void handle_time(unsigned char type) {
+    if (_touch_timer.tag) {
+        EVETouch *touch = &_touch[_touch_timer.idx];
 
-    eos_spi_dev_start(EOS_SPI_DEV_DISP);
-    eve_handle_touch(0);
-    eos_spi_dev_stop();
+        if ((_touch_timer.evt & EVE_TOUCH_ETYPE_TAP1) && (touch->x != EVE_NOTOUCH)) _touch_timer.evt &= ~EVE_TOUCH_ETYPE_TAP1;
+
+        if (_touch_timer.evt) {
+            char more = 0;
+            int _x = touch->x;
+            int _y = touch->y;
+            uint16_t _evt = touch->evt;
+
+            touch->evt = _touch_timer.evt;
+            if (touch->evt & EVE_TOUCH_ETYPE_TRACK) {
+                volatile uint64_t *mtime = (uint64_t *) (CLINT_CTRL_ADDR + CLINT_MTIME);
+                int dt = *mtime - touch->t;
+
+                if (_touch_timer.fc == 0) {
+                    double d = sqrt(touch->vx * touch->vx + touch->vy * touch->vy);
+                    _touch_timer.fc = (double)(RTC_FREQ) * d / EVE_FRICTION;
+                }
+
+                if (dt < _touch_timer.fc / 2) {
+                    more = 1;
+                } else {
+                    touch->evt |= EVE_TOUCH_ETYPE_TRACK_DONE;
+                    dt = _touch_timer.fc / 2;
+                }
+                touch->x = _touch_timer.x0 + (touch->vx * dt - touch->vx * dt / _touch_timer.fc * dt ) / (int)(RTC_FREQ);
+                touch->y = _touch_timer.y0 + (touch->vy * dt - touch->vy * dt / _touch_timer.fc * dt ) / (int)(RTC_FREQ);
+
+                if (more) eos_timer_set(EVE_TIMEOUT_TRACK, EOS_TIMER_ETYPE_UI, 0);
+            }
+
+
+            eos_spi_dev_start(EOS_DEV_DISP);
+            _touch_handler(_touch_handler_param, _touch_timer.tag, _touch_timer.idx);
+            eos_spi_dev_stop();
 
-    eve_touch[0].evt &= ~EOS_TOUCH_ETYPE_LPRESS;
-    eve_touch_timer_t0 = 0;
-    eve_touch_timer_tag = 0;
+            if (!more) _touch_timer_clear();
+            touch->evt = _evt;
+            touch->x = _x;
+            touch->y = _y;
+        }
+    }
 }
 
-static void eve_handler_evt(unsigned char type, unsigned char *buffer, uint16_t len) {
+static void handle_evt(unsigned char type, unsigned char *buffer, uint16_t len) {
     uint8_t flags;
 
-    eos_spi_dev_start(EOS_SPI_DEV_DISP);
-    flags = eos_eve_read8(REG_INT_FLAGS) & eve_int_mask;
-    eve_handle_touch(flags);
+    eos_spi_dev_start(EOS_DEV_DISP);
+    flags = eve_read8(REG_INT_FLAGS) & _intr_mask;
+    handle_touch(flags);
     eos_spi_dev_stop();
 
-    GPIO_REG(GPIO_LOW_IP) = (1 << EVE_PIN_INT);
-    GPIO_REG(GPIO_LOW_IE) |= (1 << EVE_PIN_INT);
+    GPIO_REG(GPIO_LOW_IP) = (1 << EVE_PIN_INTR);
+    GPIO_REG(GPIO_LOW_IE) |= (1 << EVE_PIN_INTR);
 }
 
-static void eve_handler_int(void) {
-    GPIO_REG(GPIO_LOW_IE) &= ~(1 << EVE_PIN_INT);
-    eos_evtq_push_isr(EOS_EVT_UI | EVE_ETYPE_INT, NULL, 0);
+static void handle_intr(void) {
+    GPIO_REG(GPIO_LOW_IE) &= ~(1 << EVE_PIN_INTR);
+    eos_evtq_push_isr(EOS_EVT_UI | EVE_ETYPE_INTR, NULL, 0);
     return;
 }
 
-int eos_eve_init(void) {
+int eve_init(uint32_t *touch_transform) {
     int i;
 	uint8_t chipid = 0;
 	uint16_t timeout = 0;
-    uint32_t touch_transform[6] = {0xfa46,0xfffffcf6,0x422fe,0xffffff38,0x10002,0xf3cb0};
 
-    eos_eve_command(EVE_RST_PULSE, 0);
-    eos_eve_command(EVE_CLKEXT, 0);
-    eos_eve_command(EVE_ACTIVE, 0);     /* start EVE */
+    eve_command(EVE_RST_PULSE, 0);
+    eve_command(EVE_CLKEXT, 0);
+    eve_command(EVE_ACTIVE, 0);     /* start EVE */
 
     while(chipid != 0x7C) {             /* if chipid is not 0x7c, continue to read it until it is, EVE needs a moment for it's power on self-test and configuration */
 		eos_timer_sleep(1);
-		chipid = eos_eve_read8(REG_ID);
+		chipid = eve_read8(REG_ID);
 		timeout++;
 		if (timeout > 400) return EOS_ERR;
 	}
 
-    eos_eve_write8(REG_PWM_DUTY, 0);
+    eve_write8(REG_PWM_DUTY, 0);
 
     /* Initialize Display */
-	eos_eve_write16(REG_HCYCLE,  EVE_HCYCLE);   /* total number of clocks per line, incl front/back porch */
-	eos_eve_write16(REG_HOFFSET, EVE_HOFFSET);  /* start of active line */
-	eos_eve_write16(REG_HSYNC0,  EVE_HSYNC0);   /* start of horizontal sync pulse */
-	eos_eve_write16(REG_HSYNC1,  EVE_HSYNC1);   /* end of horizontal sync pulse */
-	eos_eve_write16(REG_VCYCLE,  EVE_VCYCLE);   /* total number of lines per screen, including pre/post */
-	eos_eve_write16(REG_VOFFSET, EVE_VOFFSET);  /* start of active screen */
-	eos_eve_write16(REG_VSYNC0,  EVE_VSYNC0);   /* start of vertical sync pulse */
-	eos_eve_write16(REG_VSYNC1,  EVE_VSYNC1);   /* end of vertical sync pulse */
-	eos_eve_write8(REG_SWIZZLE,  EVE_SWIZZLE);  /* FT8xx output to LCD - pin order */
-	eos_eve_write8(REG_PCLK_POL, EVE_PCLKPOL);  /* LCD data is clocked in on this PCLK edge */
-	eos_eve_write8(REG_CSPREAD,	 EVE_CSPREAD);  /* helps with noise, when set to 1 fewer signals are changed simultaneously, reset-default: 1 */
-	eos_eve_write16(REG_HSIZE,   EVE_HSIZE);    /* active display width */
-	eos_eve_write16(REG_VSIZE,   EVE_VSIZE);    /* active display height */
+	eve_write16(REG_HCYCLE,  EVE_HCYCLE);   /* total number of clocks per line, incl front/back porch */
+	eve_write16(REG_HOFFSET, EVE_HOFFSET);  /* start of active line */
+	eve_write16(REG_HSYNC0,  EVE_HSYNC0);   /* start of horizontal sync pulse */
+	eve_write16(REG_HSYNC1,  EVE_HSYNC1);   /* end of horizontal sync pulse */
+	eve_write16(REG_VCYCLE,  EVE_VCYCLE);   /* total number of lines per screen, including pre/post */
+	eve_write16(REG_VOFFSET, EVE_VOFFSET);  /* start of active screen */
+	eve_write16(REG_VSYNC0,  EVE_VSYNC0);   /* start of vertical sync pulse */
+	eve_write16(REG_VSYNC1,  EVE_VSYNC1);   /* end of vertical sync pulse */
+	eve_write8(REG_SWIZZLE,  EVE_SWIZZLE);  /* FT8xx output to LCD - pin order */
+	eve_write8(REG_PCLK_POL, EVE_PCLKPOL);  /* LCD data is clocked in on this PCLK edge */
+	eve_write8(REG_CSPREAD,	 EVE_CSPREAD);  /* helps with noise, when set to 1 fewer signals are changed simultaneously, reset-default: 1 */
+	eve_write16(REG_HSIZE,   EVE_HSIZE);    /* active display width */
+	eve_write16(REG_VSIZE,   EVE_VSIZE);    /* active display height */
 
 	/* do not set PCLK yet - wait for just after the first display list */
 
 	/* configure Touch */
-	eos_eve_write8(REG_TOUCH_MODE, EVE_TMODE_CONTINUOUS);       /* enable touch */
-	eos_eve_write16(REG_TOUCH_RZTHRESH, EVE_TOUCH_RZTHRESH);    /* eliminate any false touches */
+	eve_write8(REG_TOUCH_MODE, EVE_TMODE_CONTINUOUS);       /* enable touch */
+	eve_write16(REG_TOUCH_RZTHRESH, EVE_TOUCH_RZTHRESH);    /* eliminate any false touches */
 
 	/* disable Audio for now */
-	eos_eve_write8(REG_VOL_PB, 0x00);       /* turn recorded audio volume down */
-	eos_eve_write8(REG_VOL_SOUND, 0x00);    /* turn synthesizer volume off */
-	eos_eve_write16(REG_SOUND, 0x6000);     /* set synthesizer to mute */
+	eve_write8(REG_VOL_PB, 0x00);       /* turn recorded audio volume down */
+	eve_write8(REG_VOL_SOUND, 0x00);    /* turn synthesizer volume off */
+	eve_write16(REG_SOUND, 0x6000);     /* set synthesizer to mute */
 
 	/* write a basic display-list to get things started */
-    eos_eve_dl_start(EVE_RAM_DL);
-    eos_eve_dl_write(CLEAR_COLOR_RGB(0,0,0));
-	eos_eve_dl_write(CLEAR(1,1,1));
-    eos_eve_dl_write(DISPLAY());
-    eos_eve_dl_swap();
+    eve_dl_start(EVE_RAM_DL);
+    eve_dl_write(CLEAR_COLOR_RGB(0,0,0));
+	eve_dl_write(CLEAR(1,1,1));
+    eve_dl_write(DISPLAY());
+    eve_dl_swap();
 
 	/* nothing is being displayed yet... the pixel clock is still 0x00 */
-	eos_eve_write8(REG_GPIO, 0x80);         /* enable the DISP signal to the LCD panel, it is set to output in REG_GPIO_DIR by default */
-	eos_eve_write8(REG_PCLK, EVE_PCLK);     /* now start clocking data to the LCD panel */
-
-    eos_eve_write8(REG_INT_EN, 0x01);
-    eos_eve_write8(REG_INT_MASK, eve_int_mask);
-    while(eos_eve_read8(REG_INT_FLAGS));
-
-    /*
-	eos_eve_cmd_dl(CMD_DLSTART);
-	eos_eve_cmd_dl(CLEAR_COLOR_RGB(0,0,0));
-	eos_eve_cmd_dl(CLEAR(1,1,1));
-    eos_eve_cmd(CMD_TEXT, "hhhhs", EVE_HSIZE/2, EVE_VSIZE/2, 27, EVE_OPT_CENTER, "Please tap on the dot.");
-    eos_eve_cmd(CMD_CALIBRATE, "w", 0);
-	eos_eve_cmd_dl(DISPLAY());
-	eos_eve_cmd_dl(CMD_SWAP);
-	eos_eve_cmd_exec(1);
-
-    uint32_t touch_transform[0] = eos_eve_read32(REG_TOUCH_TRANSFORM_A);
-    uint32_t touch_transform[1] = eos_eve_read32(REG_TOUCH_TRANSFORM_B);
-    uint32_t touch_transform[2] = eos_eve_read32(REG_TOUCH_TRANSFORM_C);
-    uint32_t touch_transform[3] = eos_eve_read32(REG_TOUCH_TRANSFORM_D);
-    uint32_t touch_transform[4] = eos_eve_read32(REG_TOUCH_TRANSFORM_E);
-    uint32_t touch_transform[5] = eos_eve_read32(REG_TOUCH_TRANSFORM_F);
-
-    printf("TOUCH TRANSFORM:{0x%x,0x%x,0x%x,0x%x,0x%x,0x%x}\n", touch_transform[0], touch_transform[1], touch_transform[2], touch_transform[3], touch_transform[4], touch_transform[5]);
-    */
-
-    eos_eve_write32(REG_TOUCH_TRANSFORM_A, touch_transform[0]);
-    eos_eve_write32(REG_TOUCH_TRANSFORM_B, touch_transform[1]);
-    eos_eve_write32(REG_TOUCH_TRANSFORM_C, touch_transform[2]);
-    eos_eve_write32(REG_TOUCH_TRANSFORM_D, touch_transform[3]);
-    eos_eve_write32(REG_TOUCH_TRANSFORM_E, touch_transform[4]);
-    eos_eve_write32(REG_TOUCH_TRANSFORM_F, touch_transform[5]);
-    eos_eve_write32(REG_CTOUCH_EXTENDED, 0x00);
+	eve_write8(REG_GPIO, 0x80);         /* enable the DISP signal to the LCD panel, it is set to output in REG_GPIO_DIR by default */
+	eve_write8(REG_PCLK, EVE_PCLK);     /* now start clocking data to the LCD panel */
+
+    eve_write8(REG_INT_EN, 0x01);
+    eve_write8(REG_INT_MASK, _intr_mask);
+    while(eve_read8(REG_INT_FLAGS));
+
+    if (touch_transform) {
+        eve_write32(REG_TOUCH_TRANSFORM_A, touch_transform[0]);
+        eve_write32(REG_TOUCH_TRANSFORM_B, touch_transform[1]);
+        eve_write32(REG_TOUCH_TRANSFORM_C, touch_transform[2]);
+        eve_write32(REG_TOUCH_TRANSFORM_D, touch_transform[3]);
+        eve_write32(REG_TOUCH_TRANSFORM_E, touch_transform[4]);
+        eve_write32(REG_TOUCH_TRANSFORM_F, touch_transform[5]);
+    } else {
+        uint32_t touch_transform[6];
+        eve_cmd_dl(CMD_DLSTART);
+        eve_cmd_dl(CLEAR_COLOR_RGB(0,0,0));
+        eve_cmd_dl(CLEAR(1,1,1));
+        eve_cmd(CMD_TEXT, "hhhhs", EVE_HSIZE/2, EVE_VSIZE/2, 27, EVE_OPT_CENTER, "Please tap on the dot.");
+        eve_cmd(CMD_CALIBRATE, "w", 0);
+        eve_cmd_dl(DISPLAY());
+        eve_cmd_dl(CMD_SWAP);
+        eve_cmd_exec(1);
+
+        touch_transform[0] = eve_read32(REG_TOUCH_TRANSFORM_A);
+        touch_transform[1] = eve_read32(REG_TOUCH_TRANSFORM_B);
+        touch_transform[2] = eve_read32(REG_TOUCH_TRANSFORM_C);
+        touch_transform[3] = eve_read32(REG_TOUCH_TRANSFORM_D);
+        touch_transform[4] = eve_read32(REG_TOUCH_TRANSFORM_E);
+        touch_transform[5] = eve_read32(REG_TOUCH_TRANSFORM_F);
+
+        printf("TOUCH TRANSFORM:{0x%x,0x%x,0x%x,0x%x,0x%x,0x%x}\n", touch_transform[0], touch_transform[1], touch_transform[2], touch_transform[3], touch_transform[4], touch_transform[5]);
+    }
 
-    eos_eve_cmd(CMD_SETROTATE, "w", 2);
-    eos_eve_cmd_exec(1);
+    eve_write32(REG_CTOUCH_EXTENDED, 0x00);
+    eve_cmd(CMD_SETROTATE, "w", 2);
+    eve_cmd_exec(1);
 
     eos_timer_sleep(500);
-    eos_eve_command(EVE_STANDBY, 0);
+    eve_command(EVE_STANDBY, 0);
 
     for (i=0; i<EVE_MAX_TOUCH; i++) {
-        EOSTouch *touch = &eve_touch[i];
-        touch->x = 0x8000;
-        touch->y = 0x8000;
+        EVETouch *touch = &_touch[i];
+        touch->x = EVE_NOTOUCH;
+        touch->y = EVE_NOTOUCH;
     }
-    eos_evtq_set_handler(EOS_EVT_UI, eve_handler_evt, 0);
-    eos_timer_set_handler(EOS_TIMER_ETYPE_UI, eve_handler_time, 0);
+    eos_evtq_set_handler(EOS_EVT_UI, handle_evt);
+    eos_timer_set_handler(EOS_TIMER_ETYPE_UI, handle_time);
 
-    GPIO_REG(GPIO_INPUT_EN)     |=  (1 << EVE_PIN_INT);
-    GPIO_REG(GPIO_OUTPUT_EN)    &= ~(1 << EVE_PIN_INT);
-    GPIO_REG(GPIO_PULLUP_EN)    &= ~(1 << EVE_PIN_INT);
-    GPIO_REG(GPIO_OUTPUT_XOR)   &= ~(1 << EVE_PIN_INT);
+    GPIO_REG(GPIO_INPUT_EN)     |=  (1 << EVE_PIN_INTR);
+    GPIO_REG(GPIO_OUTPUT_EN)    &= ~(1 << EVE_PIN_INTR);
+    GPIO_REG(GPIO_PULLUP_EN)    &= ~(1 << EVE_PIN_INTR);
+    GPIO_REG(GPIO_OUTPUT_XOR)   &= ~(1 << EVE_PIN_INTR);
 
-    GPIO_REG(GPIO_LOW_IE)       |=  (1 << EVE_PIN_INT);
-    eos_intr_set(INT_GPIO_BASE + EVE_PIN_INT, IRQ_PRIORITY_UI, eve_handler_int);
+    GPIO_REG(GPIO_LOW_IE)       |=  (1 << EVE_PIN_INTR);
+    eos_intr_set(INT_GPIO_BASE + EVE_PIN_INTR, IRQ_PRIORITY_UI, handle_intr);
 
     return EOS_OK;
 }
 
-void eos_eve_set_renderer(eos_eve_fptr_t renderer, uint8_t flags) {
-    eve_renderer = renderer;
-    eos_evtq_set_hflags(EOS_EVT_UI | EVE_ETYPE_INT, flags);
+void eve_touch_set_handler(eve_touch_handler_t handler, void *param) {
+    _touch_handler = handler;
+    _touch_handler_param = param;
+    /*
+    eos_evtq_set_hflags(EOS_EVT_UI | EVE_ETYPE_INTR, flags);
     eos_timer_set_hflags(EOS_TIMER_ETYPE_UI, flags);
+    */
 }
 
-EOSTouch *eos_touch_evt(uint8_t tag0, int touch_idx, uint8_t tag_min, uint8_t tag_max, uint8_t *evt) {
+EVETouch *eve_touch_evt(uint8_t tag0, int touch_idx, uint8_t tag_min, uint8_t tag_max, uint16_t *evt) {
     uint8_t _tag;
-    uint8_t _evt;
-    EOSTouch *ret = NULL;
+    uint16_t _evt;
+    EVETouch *ret = NULL;
 
     *evt = 0;
     if ((touch_idx < 0) || (touch_idx > 4)) return ret;
-
-    ret = &eve_touch[touch_idx];
     if ((tag0 < tag_min) || (tag0 > tag_max)) return ret;
 
+    ret = &_touch[touch_idx];
     _evt = ret->evt;
-    if (tag0 == 0xff) *evt |= _evt & EOS_TOUCH_ETYPE_POINT_MASK;
 
-    if (_evt & EOS_TOUCH_ETYPE_TAG_UP) {
-        _tag = ret->tag_up;
-        if ((_tag >= tag_min) && (_tag <= tag_max)) *evt |= EOS_TOUCH_ETYPE_TAG_UP;
+    *evt |= _evt & EVE_TOUCH_ETYPE_POINT_MASK;
+    if (_evt & EVE_TOUCH_ETYPE_TAG) {
+        _tag = ret->tag;
+        if ((_tag >= tag_min) && (_tag <= tag_max)) *evt |= EVE_TOUCH_ETYPE_TAG;
     }
-    if (_evt & EOS_TOUCH_ETYPE_TAG_DOWN) {
-        _tag = ret->tag_down;
-        if ((_tag >= tag_min) && (_tag <= tag_max)) *evt |= EOS_TOUCH_ETYPE_TAG_DOWN;
+    if (_evt & EVE_TOUCH_ETYPE_TAG_UP) {
+        _tag = ret->tag_up;
+        if ((_tag >= tag_min) && (_tag <= tag_max)) *evt |= EVE_TOUCH_ETYPE_TAG_UP;
     }
-    if (_evt & EOS_TOUCH_ETYPE_TRACK) {
+    if (_evt & EVE_TOUCH_ETYPE_TRACK) {
         _tag = ret->tracker.tag;
-        if ((_tag >= tag_min) && (_tag <= tag_max)) *evt |= EOS_TOUCH_ETYPE_TRACK;
+        if ((_tag >= tag_min) && (_tag <= tag_max)) *evt |= EVE_TOUCH_ETYPE_TRACK | (_evt & (EVE_TOUCH_ETYPE_TRACK_X | EVE_TOUCH_ETYPE_TRACK_Y));
     }
-    if (_evt & EOS_TOUCH_ETYPE_TRACK_REG) {
+    if (_evt & EVE_TOUCH_ETYPE_TRACK_REG) {
         _tag = ret->tracker.tag;
-        if ((_tag >= tag_min) && (_tag <= tag_max) && (_tag == ret->tag0)) *evt |= EOS_TOUCH_ETYPE_TRACK_REG;
+        if ((_tag >= tag_min) && (_tag <= tag_max)) *evt |= EVE_TOUCH_ETYPE_TRACK_REG;
     }
-    if (_evt & EOS_TOUCH_ETYPE_LPRESS) {
-        _tag = eve_touch_timer_tag;
-        if ((_tag >= tag_min) && (_tag <= tag_max)) *evt |= EOS_TOUCH_ETYPE_LPRESS;
+    if (_evt & (EVE_TOUCH_ETYPE_LPRESS | EVE_TOUCH_ETYPE_TAP1 | EVE_TOUCH_ETYPE_TAP2 | EVE_TOUCH_ETYPE_TRACK_DONE)) {
+        _tag = _touch_timer.tag;
+        if ((_tag >= tag_min) && (_tag <= tag_max)) *evt |= _evt & (EVE_TOUCH_ETYPE_LPRESS | EVE_TOUCH_ETYPE_TAP1 | EVE_TOUCH_ETYPE_TAP2 | EVE_TOUCH_ETYPE_TRACK_DONE);
     }
 
     return ret;
 }
 
-void eos_touch_evt_set(uint8_t tag, uint8_t evt) {
-    eve_tag_evt[tag] = evt;
+void eve_touch_set_opt(uint8_t tag, uint8_t opt) {
+    _tag_opt[tag] = opt;
+}
+
+EVETouchTimer *eve_touch_get_timer(void) {
+    return &_touch_timer;
 }
+
diff --git a/code/fe310/eos/eve.h b/code/fe310/eos/eve.h
index 71435e7..0e6979c 100644
--- a/code/fe310/eos/eve.h
+++ b/code/fe310/eos/eve.h
@@ -2,61 +2,104 @@
 
 #include "eve_def.h"
 
-#define EOS_TOUCH_ETYPE_TRACK           0x01
-#define EOS_TOUCH_ETYPE_TRACK_REG       0x02
-#define EOS_TOUCH_ETYPE_LPRESS          0x04
-#define EOS_TOUCH_ETYPE_POINT_UP        0x10
-#define EOS_TOUCH_ETYPE_POINT_DOWN      0x20
-#define EOS_TOUCH_ETYPE_TAG_UP          0x40
-#define EOS_TOUCH_ETYPE_TAG_DOWN        0x80
-
-#define EOS_TOUCH_ETYPE_TRACK_MASK      0x03
-#define EOS_TOUCH_ETYPE_POINT_MASK      0x30
-#define EOS_TOUCH_ETYPE_TAG_MASK        0xc0
-
-typedef struct EOSTouch {
-    uint16_t x;
-    uint16_t y;
-    uint16_t x0;
-    uint16_t y0;
+/* events */
+#define EVE_TOUCH_ETYPE_TRACK           0x01
+#define EVE_TOUCH_ETYPE_TRACK_REG       0x02
+#define EVE_TOUCH_ETYPE_TAG             0x10
+#define EVE_TOUCH_ETYPE_TAG_UP          0x20
+#define EVE_TOUCH_ETYPE_POINT           0x40
+#define EVE_TOUCH_ETYPE_POINT_UP        0x80
+
+#define EVE_TOUCH_ETYPE_TRACK_MASK      (EVE_TOUCH_ETYPE_TRACK      | EVE_TOUCH_ETYPE_TRACK_REG)
+#define EVE_TOUCH_ETYPE_TAG_MASK        (EVE_TOUCH_ETYPE_TAG        | EVE_TOUCH_ETYPE_TAG_UP)
+#define EVE_TOUCH_ETYPE_POINT_MASK      (EVE_TOUCH_ETYPE_POINT      | EVE_TOUCH_ETYPE_POINT_UP)
+
+/* extended events */
+#define EVE_TOUCH_ETYPE_LPRESS          0x0100
+#define EVE_TOUCH_ETYPE_TAP1            0x0200
+#define EVE_TOUCH_ETYPE_TAP2            0x0400
+#define EVE_TOUCH_ETYPE_TRACK_DONE      0x0800
+
+#define EVE_TOUCH_ETYPE_TRACK_LEFT      0x1000
+#define EVE_TOUCH_ETYPE_TRACK_RIGHT     0x2000
+#define EVE_TOUCH_ETYPE_TRACK_UP        0x4000
+#define EVE_TOUCH_ETYPE_TRACK_DOWN      0x8000
+
+#define EVE_TOUCH_ETYPE_TRACK_X         (EVE_TOUCH_ETYPE_TRACK_LEFT | EVE_TOUCH_ETYPE_TRACK_RIGHT)
+#define EVE_TOUCH_ETYPE_TRACK_Y         (EVE_TOUCH_ETYPE_TRACK_UP   | EVE_TOUCH_ETYPE_TRACK_DOWN)
+
+/* tag options */
+#define EVE_TOUCH_OPT_TRACK             EVE_TOUCH_ETYPE_TRACK
+#define EVE_TOUCH_OPT_TRACK_REG         EVE_TOUCH_ETYPE_TRACK_REG
+#define EVE_TOUCH_OPT_TRACK_X           0x04
+#define EVE_TOUCH_OPT_TRACK_Y           0x08
+#define EVE_TOUCH_OPT_INERT             0x10
+#define EVE_TOUCH_OPT_LPRESS            0x40
+#define EVE_TOUCH_OPT_DTAP              0x80
+
+#define EVE_TOUCH_OPT_TRACK_XY          (EVE_TOUCH_OPT_TRACK_X      | EVE_TOUCH_OPT_TRACK_Y)
+#define EVE_TOUCH_OPT_TRACK_MASK        (EVE_TOUCH_OPT_TRACK        | EVE_TOUCH_OPT_TRACK_REG)
+#define EVE_TOUCH_OPT_TIMER_MASK        (EVE_TOUCH_OPT_LPRESS       | EVE_TOUCH_OPT_DTAP)
+
+typedef struct EVETouch {
+    int x;
+    int y;
+    int vx;
+    int vy;
+    int x0;
+    int y0;
+    uint64_t t;
+    uint16_t evt;
     uint8_t tag0;
+    uint8_t tag;
     uint8_t tag_up;
-    uint8_t tag_down;
-    uint8_t evt;
     struct {
-        uint16_t tag;
+        uint8_t tag;
+        uint8_t track;
         uint16_t val;
     } tracker;
-} EOSTouch;
-
-typedef void (*eos_eve_fptr_t) (uint8_t, int);
-
-void eos_eve_command(uint8_t command, uint8_t parameter);
-
-uint8_t eos_eve_read8(uint32_t addr);
-uint16_t eos_eve_read16(uint32_t addr);
-uint32_t eos_eve_read32(uint32_t addr);
-void eos_eve_write8(uint32_t addr, uint8_t data);
-void eos_eve_write16(uint32_t addr, uint16_t data);
-void eos_eve_write32(uint32_t addr, uint32_t data);
-
-void eos_eve_active(void);
-void eos_eve_brightness(uint8_t b);
-
-void eos_eve_dl_start(uint32_t addr);
-void eos_eve_dl_write(uint32_t dl);
-void eos_eve_dl_swap(void);
-uint32_t eos_eve_dl_addr(void);
-
-void eos_eve_cmd(uint32_t cmd, const char *fmt, ...);
-uint32_t eos_eve_cmd_result(uint16_t offset);
-void eos_eve_cmd_dl(uint32_t dl);
-int eos_eve_cmd_done(void);
-int eos_eve_cmd_exec(int w);
-void eos_eve_cmd_burst_start(void);
-void eos_eve_cmd_burst_end(void);
-
-int eos_eve_init(void);
-void eos_eve_set_renderer(eos_eve_fptr_t renderer, uint8_t flags);
-EOSTouch *eos_touch_evt(uint8_t tag0, int touch_idx, uint8_t tag_min, uint8_t tag_max, uint8_t *evt);
-void eos_touch_evt_set(uint8_t tag, uint8_t evt);
+} EVETouch;
+
+typedef struct EVETouchTimer {
+    uint8_t tag;
+    uint8_t idx;
+    uint16_t evt;
+    int x0;
+    int y0;
+    int fc;
+} EVETouchTimer;
+
+typedef void (*eve_touch_handler_t) (void *, uint8_t, int);
+
+void eve_command(uint8_t command, uint8_t parameter);
+
+uint8_t eve_read8(uint32_t addr);
+uint16_t eve_read16(uint32_t addr);
+uint32_t eve_read32(uint32_t addr);
+void eve_write8(uint32_t addr, uint8_t data);
+void eve_write16(uint32_t addr, uint16_t data);
+void eve_write32(uint32_t addr, uint32_t data);
+
+void eve_active(void);
+void eve_brightness(uint8_t b);
+
+void eve_dl_start(uint32_t addr);
+void eve_dl_write(uint32_t dl);
+void eve_dl_swap(void);
+uint32_t eve_dl_get_addr(void);
+
+void eve_cmd(uint32_t cmd, const char *fmt, ...);
+uint32_t eve_cmd_result(uint16_t offset);
+void eve_cmd_dl(uint32_t dl);
+int eve_cmd_done(void);
+int eve_cmd_exec(int w);
+void eve_cmd_burst_start(void);
+void eve_cmd_burst_end(void);
+
+int eve_init(uint32_t *touch_transform);
+
+void eve_touch_set_handler(eve_touch_handler_t handler, void *handler_param);
+EVETouch *eve_touch_evt(uint8_t tag0, int touch_idx, uint8_t tag_min, uint8_t tag_max, uint16_t *evt);
+void eve_touch_set_opt(uint8_t tag, uint8_t opt);
+
+EVETouchTimer *eve_touch_get_timer(void);
\ No newline at end of file
diff --git a/code/fe310/eos/eve_config.h b/code/fe310/eos/eve_config.h
index bbfc0f0..a7d3c42 100755
--- a/code/fe310/eos/eve_config.h
+++ b/code/fe310/eos/eve_config.h
@@ -1,43 +1,3 @@
-/*
-@file    EVE_config.h
-@brief   configuration information for some TFTs
-@version 4.0
-@date    2019-09-14
-@author  Rudolph Riedel
-
-@section LICENSE
-
-MIT License
-
-Copyright (c) 2016-2019 Rudolph Riedel
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute,
-sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-@section History
-
-4.0
-- renamed from EVE_config.h to EVE_config.h
-- renamed EVE_81X_ENABLE to FT81X_ENABLE
-- added a fictitious BT81x entry under the made-up name EVE_EVE3_70G, just to see the project compile with additional BT81x includes and functions
-- added profiles for the BT81x 4.3", 5" and 7" modules from Riverdi - the only tested is the 4.3" with a RVT43ULBNWC00
-- moved all target specific lines from EVE_config.h to EVE_target.h
-- cleaned up history
-- added profiles for EVE3-35G, EVE3-43G, EVE3-50G
-- added a profile for the CFAF800480E0-050SC from Crystalfontz
-- changed EVE_RiTFT50 to use the RVT70 config instead of the RVT50 config since RVT50 uses a different HOFFSET value
-- added EVE_PAF90, a profile for the PAF90B5WFNWC01 from Panasys
-
-*/
-
 #ifndef EVE_CONFIG_H_
 #define EVE_CONFIG_H_
 
diff --git a/code/fe310/eos/eve_kbd.c b/code/fe310/eos/eve_kbd.c
index 995d0ca..f42b376 100644
--- a/code/fe310/eos/eve_kbd.c
+++ b/code/fe310/eos/eve_kbd.c
@@ -17,28 +17,32 @@
 #define KEYS_HEIGHT 40
 #define KEYS_RSIZE  45
 
-void eos_kbd_init(EOSKbd *kbd, eos_kbd_fptr_t key_down_f, uint32_t mem_addr, uint32_t *mem_next) {
-    eos_eve_write16(REG_CMD_DL, 0);
-    eos_kbd_update(kbd);
-    eos_eve_cmd_exec(1);
+void eve_kbd_init(EVEKbd *kbd, eve_kbd_input_handler_t putc, uint32_t mem_addr, uint32_t *mem_next) {
+    uint16_t mem_size;
+
+    eve_write16(REG_CMD_DL, 0);
+    eve_kbd_draw(kbd, 1);
+    eve_cmd_exec(1);
+    mem_size = eve_read16(REG_CMD_DL);
+    eve_cmd(CMD_MEMCPY, "www", mem_addr, EVE_RAM_DL, mem_size);
+    eve_cmd_exec(1);
+
     kbd->mem_addr = mem_addr;
-    kbd->mem_size = eos_eve_read16(REG_CMD_DL);
+    kbd->mem_size = mem_size;
     kbd->key_modifier = 0;
     kbd->key_count = 0;
     kbd->key_down = 0;
-    kbd->key_down_f = key_down_f;
-    eos_eve_cmd(CMD_MEMCPY, "www", kbd->mem_addr, EVE_RAM_DL, kbd->mem_size);
-    eos_eve_cmd_exec(1);
+    kbd->putc = putc;
     *mem_next = kbd->mem_addr + kbd->mem_size;
 }
 
-void eos_kbd_draw(EOSKbd *kbd, uint8_t tag0, int touch_idx) {
-    uint8_t evt;
-    EOSTouch *t = eos_touch_evt(tag0, touch_idx, 1, 127, &evt);
+int eve_kbd_touch(EVEKbd *kbd, uint8_t tag0, int touch_idx, void *w) {
+    uint16_t evt;
+    EVETouch *t = eve_touch_evt(tag0, touch_idx, 1, 0x7e, &evt);
 
     if (t && evt) {
-        if (evt & EOS_TOUCH_ETYPE_TAG_DOWN) {
-            uint8_t _tag = t->tag_down;
+        if (evt & EVE_TOUCH_ETYPE_TAG) {
+            uint8_t _tag = t->tag;
 
             if (_tag >= KEY_SHIFT && _tag <= KEY_FN) {
                 if (touch_idx == 0) {
@@ -59,15 +63,15 @@ void eos_kbd_draw(EOSKbd *kbd, uint8_t tag0, int touch_idx) {
             } else {
                 kbd->key_count++;
                 kbd->key_down = _tag;
-                if (kbd->key_down_f) {
+                if (kbd->putc) {
                     int c = _tag;
 
                     if ((kbd->key_modifier & FLAG_CTRL) && (_tag >= '?') && (_tag <= '_')) c = (_tag - '@') & 0x7f;
-                    kbd->key_down_f(c);
+                    kbd->putc(w, c);
                 }
             }
         }
-        if (evt & EOS_TOUCH_ETYPE_TAG_UP) {
+        if (evt & EVE_TOUCH_ETYPE_TAG_UP) {
             uint8_t _tag = t->tag_up;
 
             if (_tag >= KEY_SHIFT && _tag <= KEY_FN) {
@@ -87,29 +91,34 @@ void eos_kbd_draw(EOSKbd *kbd, uint8_t tag0, int touch_idx) {
                 }
             }
         }
-        eos_kbd_update(kbd);
+        return 1;
     } else {
-        eos_eve_cmd(CMD_APPEND, "ww", kbd->mem_addr, kbd->mem_size);
+        return 0;
     }
 }
 
-void eos_kbd_update(EOSKbd *kbd) {
-    eos_eve_cmd_dl(SAVE_CONTEXT());
-    eos_eve_cmd(CMD_KEYS, "hhhhhhs", 0, KEYS_Y + KEYS_RSIZE * 0, 480, KEYS_HEIGHT, KEYS_FSIZE, kbd->key_down, kbd->key_modifier & (FLAG_FN | FLAG_SHIFT) ? "!@#$%^&*()" : (kbd->key_modifier & FLAG_CTRL ? " @[\\]^_?  " : "1234567890"));
-    eos_eve_cmd(CMD_KEYS, "hhhhhhs", 0, KEYS_Y + KEYS_RSIZE * 1, 480, KEYS_HEIGHT, KEYS_FSIZE, kbd->key_down, kbd->key_modifier & FLAG_FN ? "-_=+[]{}\\|" : kbd->key_modifier & (FLAG_SHIFT | FLAG_CTRL) ? "QWERTYUIOP" : "qwertyuiop");
-    eos_eve_cmd(CMD_KEYS, "hhhhhhs", 24, KEYS_Y + KEYS_RSIZE * 2, 432, KEYS_HEIGHT, KEYS_FSIZE, kbd->key_down, kbd->key_modifier & FLAG_FN ? "`~   ;:'\"" : kbd->key_modifier & (FLAG_SHIFT | FLAG_CTRL) ? "ASDFGHJKL" : "asdfghjkl");
-    eos_eve_cmd(CMD_KEYS, "hhhhhhs", 72, KEYS_Y + KEYS_RSIZE * 3, 335, KEYS_HEIGHT, KEYS_FSIZE, kbd->key_down, kbd->key_modifier & FLAG_FN ? " ,.<>/?" : kbd->key_modifier & (FLAG_SHIFT | FLAG_CTRL) ? "ZXCVBNM" : "zxcvbnm");
-    eos_eve_cmd_dl(TAG(KEY_SHIFT));
-    eos_eve_cmd(CMD_BUTTON, "hhhhhhs", 0, KEYS_Y + KEYS_RSIZE * 3, 69, KEYS_HEIGHT, 21, kbd->key_modifier & FLAG_SHIFT ? EVE_OPT_FLAT : 0, "shift");
-    eos_eve_cmd_dl(TAG(KEY_DEL));
-    eos_eve_cmd(CMD_BUTTON, "hhhhhhs", 410, KEYS_Y + KEYS_RSIZE * 3, 70, KEYS_HEIGHT, 21, kbd->key_down == KEY_DEL ? EVE_OPT_FLAT : 0, "del");
-    eos_eve_cmd_dl(TAG(KEY_FN));
-    eos_eve_cmd(CMD_BUTTON, "hhhhhhs", 0, KEYS_Y + KEYS_RSIZE * 4, 69, KEYS_HEIGHT, 21, kbd->key_modifier & FLAG_FN ? EVE_OPT_FLAT : 0, "fn");
-    eos_eve_cmd_dl(TAG(KEY_CTRL));
-    eos_eve_cmd(CMD_BUTTON, "hhhhhhs", 72, KEYS_Y + KEYS_RSIZE * 4, 69, KEYS_HEIGHT, 21, kbd->key_modifier & FLAG_CTRL ? EVE_OPT_FLAT : 0, "ctrl");
-    eos_eve_cmd_dl(TAG(' '));
-    eos_eve_cmd(CMD_BUTTON, "hhhhhhs", 144, KEYS_Y + KEYS_RSIZE * 4, 263, KEYS_HEIGHT, 21, kbd->key_down == ' ' ? EVE_OPT_FLAT : 0, "");
-    eos_eve_cmd_dl(TAG(KEY_RET));
-    eos_eve_cmd(CMD_BUTTON, "hhhhhhs", 410, KEYS_Y + KEYS_RSIZE * 4, 69, KEYS_HEIGHT, 21, kbd->key_down == KEY_RET ? EVE_OPT_FLAT : 0, "ret");
-    eos_eve_cmd_dl(RESTORE_CONTEXT());
-}
\ No newline at end of file
+uint8_t eve_kbd_draw(EVEKbd *kbd, char active) {
+    if (active) {
+        eve_cmd_dl(SAVE_CONTEXT());
+        eve_cmd(CMD_KEYS, "hhhhhhs", 0, KEYS_Y + KEYS_RSIZE * 0, 480, KEYS_HEIGHT, KEYS_FSIZE, kbd->key_down, kbd->key_modifier & (FLAG_FN | FLAG_SHIFT) ? "!@#$%^&*()" : (kbd->key_modifier & FLAG_CTRL ? " @[\\]^_?  " : "1234567890"));
+        eve_cmd(CMD_KEYS, "hhhhhhs", 0, KEYS_Y + KEYS_RSIZE * 1, 480, KEYS_HEIGHT, KEYS_FSIZE, kbd->key_down, kbd->key_modifier & FLAG_FN ? "-_=+[]{}\\|" : kbd->key_modifier & (FLAG_SHIFT | FLAG_CTRL) ? "QWERTYUIOP" : "qwertyuiop");
+        eve_cmd(CMD_KEYS, "hhhhhhs", 24, KEYS_Y + KEYS_RSIZE * 2, 432, KEYS_HEIGHT, KEYS_FSIZE, kbd->key_down, kbd->key_modifier & FLAG_FN ? "`~   ;:'\"" : kbd->key_modifier & (FLAG_SHIFT | FLAG_CTRL) ? "ASDFGHJKL" : "asdfghjkl");
+        eve_cmd(CMD_KEYS, "hhhhhhs", 72, KEYS_Y + KEYS_RSIZE * 3, 335, KEYS_HEIGHT, KEYS_FSIZE, kbd->key_down, kbd->key_modifier & FLAG_FN ? " ,.<>/?" : kbd->key_modifier & (FLAG_SHIFT | FLAG_CTRL) ? "ZXCVBNM" : "zxcvbnm");
+        eve_cmd_dl(TAG(KEY_SHIFT));
+        eve_cmd(CMD_BUTTON, "hhhhhhs", 0, KEYS_Y + KEYS_RSIZE * 3, 69, KEYS_HEIGHT, 21, kbd->key_modifier & FLAG_SHIFT ? EVE_OPT_FLAT : 0, "shift");
+        eve_cmd_dl(TAG(KEY_DEL));
+        eve_cmd(CMD_BUTTON, "hhhhhhs", 410, KEYS_Y + KEYS_RSIZE * 3, 70, KEYS_HEIGHT, 21, kbd->key_down == KEY_DEL ? EVE_OPT_FLAT : 0, "del");
+        eve_cmd_dl(TAG(KEY_FN));
+        eve_cmd(CMD_BUTTON, "hhhhhhs", 0, KEYS_Y + KEYS_RSIZE * 4, 69, KEYS_HEIGHT, 21, kbd->key_modifier & FLAG_FN ? EVE_OPT_FLAT : 0, "fn");
+        eve_cmd_dl(TAG(KEY_CTRL));
+        eve_cmd(CMD_BUTTON, "hhhhhhs", 72, KEYS_Y + KEYS_RSIZE * 4, 69, KEYS_HEIGHT, 21, kbd->key_modifier & FLAG_CTRL ? EVE_OPT_FLAT : 0, "ctrl");
+        eve_cmd_dl(TAG(' '));
+        eve_cmd(CMD_BUTTON, "hhhhhhs", 144, KEYS_Y + KEYS_RSIZE * 4, 263, KEYS_HEIGHT, 21, kbd->key_down == ' ' ? EVE_OPT_FLAT : 0, "");
+        eve_cmd_dl(TAG(KEY_RET));
+        eve_cmd(CMD_BUTTON, "hhhhhhs", 410, KEYS_Y + KEYS_RSIZE * 4, 69, KEYS_HEIGHT, 21, kbd->key_down == KEY_RET ? EVE_OPT_FLAT : 0, "ret");
+        eve_cmd_dl(RESTORE_CONTEXT());
+    } else {
+        eve_cmd(CMD_APPEND, "ww", kbd->mem_addr, kbd->mem_size);
+    }
+    return 0x7e;
+}
diff --git a/code/fe310/eos/eve_kbd.h b/code/fe310/eos/eve_kbd.h
index 60a2ff2..c65f7d3 100644
--- a/code/fe310/eos/eve_kbd.h
+++ b/code/fe310/eos/eve_kbd.h
@@ -1,8 +1,8 @@
 #include <stdint.h>
 
-typedef void (*eos_kbd_fptr_t) (int);
+typedef void (*eve_kbd_input_handler_t) (void *, int);
 
-typedef struct EOSKbd {
+typedef struct EVEKbd {
     uint32_t mem_addr;
     uint16_t mem_size;
     uint8_t key_count;
@@ -10,9 +10,9 @@ typedef struct EOSKbd {
     uint8_t key_modifier;
     uint8_t key_modifier_sticky;
     uint8_t key_modifier_lock;
-    eos_kbd_fptr_t key_down_f;
-} EOSKbd;
+    eve_kbd_input_handler_t putc;
+} EVEKbd;
 
-void eos_kbd_init(EOSKbd *kbd, eos_kbd_fptr_t key_down_f, uint32_t mem_addr, uint32_t *mem_next);
-void eos_kbd_draw(EOSKbd *kbd, uint8_t tag0, int touch_idx);
-void eos_kbd_update(EOSKbd *kbd);
\ No newline at end of file
+void eve_kbd_init(EVEKbd *kbd, eve_kbd_input_handler_t putc_f, uint32_t mem_addr, uint32_t *mem_next);
+int eve_kbd_touch(EVEKbd *kbd, uint8_t tag0, int touch_idx, void *w);
+uint8_t eve_kbd_draw(EVEKbd *kbd, char active);
\ No newline at end of file
diff --git a/code/fe310/eos/eve_text.c b/code/fe310/eos/eve_text.c
index c944455..0f93b20 100644
--- a/code/fe310/eos/eve_text.c
+++ b/code/fe310/eos/eve_text.c
@@ -1,3 +1,4 @@
+#include "eos.h"
 #include "eve.h"
 #include "eve_text.h"
 
@@ -8,16 +9,16 @@
 #define LINE_IDX_SUB(l1,l2,s)       (((((l1) - (l2)) % (s)) + (s)) % (s))
 
 #define LINE_IDX_LTE(l1,l2,s,h)     (LINE_IDX_SUB(l2,l1,s) <= (s) - (h))
-#define LINE_IDX_DIFF(l1,l2,s)      ((l1) > (l2) ? (l1) - (l2) : (s) - (l2) + (l1))
+#define LINE_IDX_DIFF(l1,l2,s)      ((l1) > (l2) ? (l1) - (l2) : (s) + (l1) - (l2))
 
-static void scroll1(EOSText *box) {
-    box->line_idx = (box->line_idx + 1) % box->buf_line_h;
-    eos_eve_cmd(CMD_MEMSET, "www", box->buf_addr + box->buf_idx, 0x0, box->w * 2);
-    eos_eve_cmd_exec(1);
+static void scroll1(EVEText *box) {
+    box->line0 = (box->line0 + 1) % box->line_size;
+    eve_cmd(CMD_MEMSET, "www", box->mem_addr + box->ch_idx, 0x0, box->w * 2);
+    eve_cmd_exec(1);
     box->dirty = 1;
 }
 
-void eos_text_init(EOSText *box, int x, int y, int w, int h, double scale_x, double scale_y, uint8_t tag, int buf_line_h, uint32_t mem_addr, uint32_t *mem_next) {
+void eve_text_init(EVEText *box, uint16_t x, uint16_t y, uint16_t w, uint16_t h, double scale_x, double scale_y, uint8_t tag, uint16_t line_size, uint32_t mem_addr, uint32_t *mem_next) {
     box->x = x;
     box->y = y;
     box->w = w;
@@ -28,10 +29,12 @@ void eos_text_init(EOSText *box, int x, int y, int w, int h, double scale_x, dou
     box->ch_w = scale_x * 8;
     box->ch_h = scale_y * 16;
     box->dl_size = 17;
-    box->buf_addr = mem_addr;
-    box->buf_line_h = buf_line_h;
-    box->buf_idx = 0;
-    box->line_idx = 0;
+    box->mem_addr = mem_addr;
+    box->line_size = line_size;
+    box->line0 = 0;
+    box->line_top = -1;
+    box->line_top0 = -1;
+    box->ch_idx = 0;
     if (box->transform_a != 256) {
         box->dl_size += 1;
     }
@@ -39,140 +42,146 @@ void eos_text_init(EOSText *box, int x, int y, int w, int h, double scale_x, dou
         box->dl_size += 1;
     }
 
-    eos_touch_evt_set(tag, EOS_TOUCH_ETYPE_TRACK);
+    eve_touch_set_opt(tag, EVE_TOUCH_ETYPE_TRACK);
 
-    eos_eve_cmd(CMD_MEMSET, "www", mem_addr, 0x0, w * 2 * buf_line_h);
-    eos_eve_cmd_exec(1);
+    eve_cmd(CMD_MEMSET, "www", mem_addr, 0x0, box->w * 2 * box->line_size);
+    eve_cmd_exec(1);
 
-    eos_text_update(box, -1);
-    *mem_next = box->buf_addr + box->w * 2 * box->buf_line_h + box->dl_size * 4;
+    eve_text_update(box);
+    *mem_next = box->mem_addr + box->w * 2 * box->line_size + box->dl_size * 4;
 }
 
-void eos_text_draw(EOSText *box, uint8_t tag0, int touch_idx) {
-    static int line_idx = -1;
-    static int line_idx_last;
-    uint8_t evt;
-    EOSTouch *t = eos_touch_evt(tag0, touch_idx, box->tag, box->tag, &evt);
+int eve_text_touch(EVEText *box, uint8_t tag0, int touch_idx) {
+    uint16_t evt;
+    EVETouch *t = eve_touch_evt(tag0, touch_idx, box->tag, box->tag, &evt);
 
     if (t && evt) {
-        if (evt & EOS_TOUCH_ETYPE_TAG_DOWN) {
-            if (line_idx < 0) {
-                line_idx = box->line_idx;
-                line_idx_last = line_idx;
+        if (evt & EVE_TOUCH_ETYPE_TAG) {
+            if (box->line_top < 0) {
+                box->line_top = box->line0;
+                box->line_top0 = box->line0;
             }
         }
-        if (evt & EOS_TOUCH_ETYPE_TAG_UP) {
-            line_idx = line_idx_last;
+        if (evt & EVE_TOUCH_ETYPE_TAG_UP) {
+            box->line_top0 = box->line_top;
         }
-        if (evt & EOS_TOUCH_ETYPE_TRACK) {
-            int _line_idx = LINE_IDX_ADD(line_idx, ((int)t->y0 - t->y) / box->ch_h, box->buf_line_h);
-            if (LINE_IDX_LTE(_line_idx, box->line_idx, box->buf_line_h, box->h)) {
-                eos_text_update(box, _line_idx);
-                line_idx_last = _line_idx;
+        if ((evt & EVE_TOUCH_ETYPE_TRACK) && (box->line_top0 >=0)) {
+            int line = LINE_IDX_ADD(box->line_top0, (t->y0 - t->y) / box->ch_h, box->line_size);
+            if (LINE_IDX_LTE(line, box->line0, box->line_size, box->h)) {
+                box->line_top = line;
+                box->dirty = 1;
             }
         }
-    } else if (line_idx >= 0) {
-        line_idx = -1;
+        return 1;
+    } else if (box->line_top >= 0) {
+        box->line_top = -1;
+        box->line_top0 = -1;
         box->dirty = 1;
     }
+    return 0;
+}
 
+uint8_t eve_text_draw(EVEText *box) {
     if (box->dirty) {
-        eos_text_update(box, -1);
+        eve_text_update(box);
         box->dirty = 0;
     }
-    eos_eve_cmd(CMD_APPEND, "ww", box->buf_addr + box->w * 2 * box->buf_line_h, box->dl_size * 4);
+    eve_cmd(CMD_APPEND, "ww", box->mem_addr + box->w * 2 * box->line_size, box->dl_size * 4);
+    return box->tag;
+}
+
+int eve_text_putc(EVEText *box, int c) {
+    int line_c, line_n;
+
+    switch (c) {
+        case '\b':
+            eve_text_backspace(box);
+            break;
+        case '\r':
+        case '\n':
+            eve_text_newline(box);
+            break;
+        default:
+            line_c = box->ch_idx / 2 / box->w;
+
+            eve_write16(box->mem_addr + box->ch_idx, 0x0200 | (c & 0xff));
+            box->ch_idx = (box->ch_idx + 2) % (box->line_size * box->w * 2);
+            eve_write16(box->mem_addr + box->ch_idx, TEXT_CRSR);
+
+            line_n = box->ch_idx / 2 / box->w;
+            if ((line_c != line_n) && (LINE_IDX_DIFF(line_n, box->line0, box->line_size) == box->h)) scroll1(box);
+            break;
+    }
+    return EOS_OK;
 }
 
-void eos_text_update(EOSText *box, int line_idx) {
+void eve_text_update(EVEText *box) {
     int text_h1;
     int text_h2;
+    int line_top;
 
-    if (line_idx < 0) line_idx = box->line_idx;
+    line_top = box->line_top >= 0 ? box->line_top : box->line0;
 
-    if (line_idx + box->h > box->buf_line_h) {
-        text_h1 = box->buf_line_h - line_idx;
+    if (line_top + box->h > box->line_size) {
+        text_h1 = box->line_size - line_top;
         text_h2 = box->h - text_h1;
     } else {
         text_h1 = box->h;
         text_h2 = 0;
     }
-    eos_eve_dl_start(box->buf_addr + box->w * 2 * box->buf_line_h);
+    eve_dl_start(box->mem_addr + box->w * 2 * box->line_size);
 
-    eos_eve_dl_write(SAVE_CONTEXT());
-    eos_eve_dl_write(BEGIN(EVE_BITMAPS));
-    eos_eve_dl_write(TAG(box->tag));
-    eos_eve_dl_write(VERTEX_FORMAT(0));
-    eos_eve_dl_write(BITMAP_HANDLE(15));
+    eve_dl_write(SAVE_CONTEXT());
+    eve_dl_write(BEGIN(EVE_BITMAPS));
+    eve_dl_write(TAG(box->tag));
+    eve_dl_write(VERTEX_FORMAT(0));
+    eve_dl_write(BITMAP_HANDLE(15));
     if (box->transform_a != 256) {
-        eos_eve_dl_write(BITMAP_TRANSFORM_A(box->transform_a));
+        eve_dl_write(BITMAP_TRANSFORM_A(box->transform_a));
     }
     if (box->transform_e != 256) {
-        eos_eve_dl_write(BITMAP_TRANSFORM_E(box->transform_e));
+        eve_dl_write(BITMAP_TRANSFORM_E(box->transform_e));
     }
-    eos_eve_dl_write(BITMAP_SOURCE(box->buf_addr + line_idx * box->w * 2));
-    eos_eve_dl_write(BITMAP_LAYOUT(EVE_TEXTVGA, box->w * 2, text_h1));
-    eos_eve_dl_write(BITMAP_SIZE(EVE_NEAREST, EVE_BORDER, EVE_BORDER, box->w * box->ch_w, text_h1 * box->ch_h));
-    eos_eve_dl_write(BITMAP_SIZE_H(box->w * box->ch_w, text_h1 * box->ch_h));
-    eos_eve_dl_write(VERTEX2F(box->x, box->y));
+    eve_dl_write(BITMAP_SOURCE(box->mem_addr + line_top * box->w * 2));
+    eve_dl_write(BITMAP_LAYOUT(EVE_TEXTVGA, box->w * 2, text_h1));
+    eve_dl_write(BITMAP_SIZE(EVE_NEAREST, EVE_BORDER, EVE_BORDER, box->w * box->ch_w, text_h1 * box->ch_h));
+    eve_dl_write(BITMAP_SIZE_H(box->w * box->ch_w, text_h1 * box->ch_h));
+    eve_dl_write(VERTEX2F(box->x, box->y));
 
     if (text_h2) {
-        eos_eve_dl_write(BITMAP_SOURCE(box->buf_addr));
-        eos_eve_dl_write(BITMAP_LAYOUT(EVE_TEXTVGA, box->w * 2, text_h2));
-        eos_eve_dl_write(BITMAP_SIZE(EVE_NEAREST, EVE_BORDER, EVE_BORDER, box->w * box->ch_w, text_h2 * box->ch_h));
-        eos_eve_dl_write(BITMAP_SIZE_H(box->w * box->ch_w, text_h2 * box->ch_h));
-        eos_eve_dl_write(VERTEX2F(box->x, box->y + text_h1 * box->ch_h));
+        eve_dl_write(BITMAP_SOURCE(box->mem_addr));
+        eve_dl_write(BITMAP_LAYOUT(EVE_TEXTVGA, box->w * 2, text_h2));
+        eve_dl_write(BITMAP_SIZE(EVE_NEAREST, EVE_BORDER, EVE_BORDER, box->w * box->ch_w, text_h2 * box->ch_h));
+        eve_dl_write(BITMAP_SIZE_H(box->w * box->ch_w, text_h2 * box->ch_h));
+        eve_dl_write(VERTEX2F(box->x, box->y + text_h1 * box->ch_h));
     } else {
-        eos_eve_dl_write(NOP());
-        eos_eve_dl_write(NOP());
-        eos_eve_dl_write(NOP());
-        eos_eve_dl_write(NOP());
-        eos_eve_dl_write(NOP());
+        eve_dl_write(NOP());
+        eve_dl_write(NOP());
+        eve_dl_write(NOP());
+        eve_dl_write(NOP());
+        eve_dl_write(NOP());
     }
 
-    eos_eve_dl_write(END());
-    eos_eve_dl_write(RESTORE_CONTEXT());
-}
-
-void eos_text_putc(EOSText *box, int c) {
-    int line_c, line_n;
-
-    switch (c) {
-        case '\b':
-            eos_text_backspace(box);
-            break;
-        case '\r':
-        case '\n':
-            eos_text_newline(box);
-            break;
-        default:
-            line_c = box->buf_idx / 2 / box->w;
-
-            eos_eve_write16(box->buf_addr + box->buf_idx, 0x0200 | (c & 0xff));
-            box->buf_idx = (box->buf_idx + 2) % (box->buf_line_h * box->w * 2);
-            eos_eve_write16(box->buf_addr + box->buf_idx, TEXT_CRSR);
-
-            line_n = box->buf_idx / 2 / box->w;
-            if ((line_c != line_n) && (LINE_IDX_DIFF(line_n, box->line_idx, box->buf_line_h) == box->h)) scroll1(box);
-            break;
-    }
+    eve_dl_write(END());
+    eve_dl_write(RESTORE_CONTEXT());
 }
 
-void eos_text_newline(EOSText *box) {
-    int line = (box->buf_idx / 2 / box->w + 1) % box->buf_line_h;
+void eve_text_newline(EVEText *box) {
+    int line = (box->ch_idx / 2 / box->w + 1) % box->line_size;
 
-    eos_eve_write16(box->buf_addr + box->buf_idx, 0);
-    box->buf_idx = line * box->w * 2;
-    if (LINE_IDX_DIFF(line, box->line_idx, box->buf_line_h) == box->h) scroll1(box);
-    eos_eve_write16(box->buf_addr + box->buf_idx, TEXT_CRSR);
+    eve_write16(box->mem_addr + box->ch_idx, 0);
+    box->ch_idx = line * box->w * 2;
+    if (LINE_IDX_DIFF(line, box->line0, box->line_size) == box->h) scroll1(box);
+    eve_write16(box->mem_addr + box->ch_idx, TEXT_CRSR);
 }
 
-void eos_text_backspace(EOSText *box) {
+void eve_text_backspace(EVEText *box) {
     uint16_t c;
 
-    eos_eve_write16(box->buf_addr + box->buf_idx, 0);
-    box->buf_idx = (box->buf_idx - 2) % (box->buf_line_h * box->w * 2);
-    if (eos_eve_read16(box->buf_addr + box->buf_idx) == 0) {
-        box->buf_idx = (box->buf_idx + 2) % (box->buf_line_h * box->w * 2);
+    eve_write16(box->mem_addr + box->ch_idx, 0);
+    box->ch_idx = (box->ch_idx - 2) % (box->line_size * box->w * 2);
+    if (eve_read16(box->mem_addr + box->ch_idx) == 0) {
+        box->ch_idx = (box->ch_idx + 2) % (box->line_size * box->w * 2);
     }
-    eos_eve_write16(box->buf_addr + box->buf_idx, TEXT_CRSR);
+    eve_write16(box->mem_addr + box->ch_idx, TEXT_CRSR);
 }
\ No newline at end of file
diff --git a/code/fe310/eos/eve_text.h b/code/fe310/eos/eve_text.h
index 794f430..814a0cd 100644
--- a/code/fe310/eos/eve_text.h
+++ b/code/fe310/eos/eve_text.h
@@ -1,14 +1,16 @@
 #include <stdint.h>
 
-typedef struct EOSText {
-    int x;
-    int y;
-    int w;
-    int h;
-    int buf_line_h;
-    int buf_idx;
-    int line_idx;
-    uint32_t buf_addr;
+typedef struct EVEText {
+    uint16_t x;
+    uint16_t y;
+    uint16_t w;
+    uint16_t h;
+    uint32_t mem_addr;
+    uint16_t line_size;
+    uint16_t line0;
+    int line_top;
+    int line_top0;
+    uint16_t ch_idx;
     uint16_t transform_a;
     uint16_t transform_e;
     uint8_t tag;
@@ -16,11 +18,12 @@ typedef struct EOSText {
     uint8_t ch_w;
     uint8_t dl_size;
     char dirty;
-} EOSText;
+} EVEText;
 
-void eos_text_init(EOSText *box, int x, int y, int w, int h, double scale_x, double scale_y, uint8_t tag, int buf_line_h, uint32_t mem_addr, uint32_t *mem_next);
-void eos_text_draw(EOSText *box, uint8_t tag0, int touch_idx);
-void eos_text_update(EOSText *box, int line_idx);
-void eos_text_putc(EOSText *box, int c);
-void eos_text_newline(EOSText *box);
-void eos_text_backspace(EOSText *box);
+void eve_text_init(EVEText *box, uint16_t x, uint16_t y, uint16_t w, uint16_t h, double scale_x, double scale_y, uint8_t tag, uint16_t line_size, uint32_t mem_addr, uint32_t *mem_next);
+int eve_text_touch(EVEText *box, uint8_t tag0, int touch_idx);
+uint8_t eve_text_draw(EVEText *box);
+int eve_text_putc(EVEText *box, int c);
+void eve_text_update(EVEText *box);
+void eve_text_newline(EVEText *box);
+void eve_text_backspace(EVEText *box);
diff --git a/code/fe310/eos/event.c b/code/fe310/eos/event.c
index bf11729..8469101 100644
--- a/code/fe310/eos/event.c
+++ b/code/fe310/eos/event.c
@@ -6,22 +6,30 @@
 #include "encoding.h"
 #include "platform.h"
 
-#include "net.h"
 #include "msgq.h"
 #include "event.h"
 
 EOSMsgQ _eos_event_q;
 static EOSMsgItem event_q_array[EOS_EVT_SIZE_Q];
 
-static eos_evt_fptr_t evt_handler[EOS_EVT_MAX_EVT];
-static uint16_t evt_handler_wrapper_acq[EOS_EVT_MAX_EVT];
-static uint16_t evt_handler_flags_buf_acq[EOS_EVT_MAX_EVT];
+static eos_evt_handler_t evt_handler[EOS_EVT_MAX_EVT + 1];
+
+static void evtq_handler(unsigned char type, unsigned char *buffer, uint16_t len) {
+    unsigned char idx = (type & EOS_EVT_MASK) >> 4;
+
+    if (idx && (idx <= EOS_EVT_MAX_EVT)) {
+        evt_handler[idx](type, buffer, len);
+    } else {
+        eos_evtq_bad_handler(type, buffer, len);
+    }
+}
 
 void eos_evtq_init(void) {
     int i;
 
+    evt_handler[0] = evtq_handler;
     for (i=0; i<EOS_EVT_MAX_EVT; i++) {
-        evt_handler[i] = eos_evtq_bad_handler;
+        evt_handler[i + 1] = eos_evtq_bad_handler;
     }
     eos_msgq_init(&_eos_event_q, event_q_array, EOS_EVT_SIZE_Q);
 }
@@ -47,54 +55,17 @@ void eos_evtq_bad_handler(unsigned char type, unsigned char *buffer, uint16_t le
     printf("evt bad handler:%d\n", type);
 }
 
-static void evtq_handler_wrapper(unsigned char type, unsigned char *buffer, uint16_t len) {
-    unsigned char idx = ((type & EOS_EVT_MASK) >> 4) - 1;
-    uint16_t flag = (uint16_t)1 << ((type & ~EOS_EVT_MASK) - 1);
-    int ok;
+void eos_evtq_set_handler(unsigned char type, eos_evt_handler_t handler) {
+    unsigned char idx = (type & EOS_EVT_MASK) >> 4;
 
-    ok = _eos_net_acquire(evt_handler_wrapper_acq[idx] & flag);
-    if (ok) {
-        evt_handler[idx](type, buffer, len);
-        eos_net_release();
-        evt_handler_wrapper_acq[idx] &= ~flag;
-    } else {
-        evt_handler_wrapper_acq[idx] |= flag;
-        eos_evtq_push(type, buffer, len);
-    }
+    if (idx <= EOS_EVT_MAX_EVT) evt_handler[idx] = handler;
 }
 
-static void evtq_handler(unsigned char type, unsigned char *buffer, uint16_t len) {
-    unsigned char idx = ((type & EOS_EVT_MASK) >> 4) - 1;
-    uint16_t flag = (uint16_t)1 << ((type & ~EOS_EVT_MASK) - 1);
+eos_evt_handler_t eos_evtq_get_handler(unsigned char type) {
+    unsigned char idx = (type & EOS_EVT_MASK) >> 4;
 
-    if (idx >= EOS_EVT_MAX_EVT) {
-        eos_evtq_bad_handler(type, buffer, len);
-        return;
-    }
-    if (flag & evt_handler_flags_buf_acq[idx]) {
-        evtq_handler_wrapper(type, buffer, len);
-    } else {
-        evt_handler[idx](type, buffer, len);
-    }
-}
-
-void eos_evtq_set_handler(unsigned char type, eos_evt_fptr_t handler, uint8_t flags) {
-    unsigned char idx = ((type & EOS_EVT_MASK) >> 4) - 1;
-
-    if (idx < EOS_EVT_MAX_EVT) {
-        evt_handler[idx] = handler;
-        eos_evtq_set_hflags(type, flags);
-    }
-}
-
-void eos_evtq_set_hflags(unsigned char type, uint8_t flags) {
-    unsigned char idx = ((type & EOS_EVT_MASK) >> 4) - 1;
-    uint16_t flag = type & ~EOS_EVT_MASK ? (uint16_t)1 << ((type & ~EOS_EVT_MASK) - 1) : 0xFFFF;
-
-    if (idx < EOS_EVT_MAX_EVT) {
-        evt_handler_flags_buf_acq[idx] &= ~flag;
-        if (flags & EOS_NET_FLAG_BACQ) evt_handler_flags_buf_acq[idx] |= flag;
-    }
+    if (idx <= EOS_EVT_MAX_EVT) return evt_handler[idx];
+    return NULL;
 }
 
 void eos_evtq_get(unsigned char type, unsigned char *selector, uint16_t sel_len, unsigned char **buffer, uint16_t *len) {
@@ -111,7 +82,7 @@ void eos_evtq_get(unsigned char type, unsigned char *selector, uint16_t sel_len,
             eos_msgq_pop(&_eos_event_q, &_type, &_buffer, &_len);
             if (_type) {
                 set_csr(mstatus, MSTATUS_MIE);
-                evtq_handler(_type, _buffer, _len);
+                evt_handler[0](_type, _buffer, _len);
             } else {
                 asm volatile ("wfi");
                 set_csr(mstatus, MSTATUS_MIE);
@@ -133,7 +104,7 @@ void eos_evtq_loop(void) {
         eos_msgq_pop(&_eos_event_q, &type, &buffer, &len);
         if (type) {
             set_csr(mstatus, MSTATUS_MIE);
-            evtq_handler(type, buffer, len);
+            evt_handler[0](type, buffer, len);
         } else {
             asm volatile ("wfi");
             set_csr(mstatus, MSTATUS_MIE);
diff --git a/code/fe310/eos/event.h b/code/fe310/eos/event.h
index a706412..1705389 100644
--- a/code/fe310/eos/event.h
+++ b/code/fe310/eos/event.h
@@ -2,15 +2,15 @@
 
 #include "evt_def.h"
 
-typedef void (*eos_evt_fptr_t) (unsigned char, unsigned char *, uint16_t);
+typedef void (*eos_evt_handler_t) (unsigned char, unsigned char *, uint16_t);
 
 void eos_evtq_init(void);
 int eos_evtq_push(unsigned char type, unsigned char *buffer, uint16_t len);
 int eos_evtq_push_isr(unsigned char type, unsigned char *buffer, uint16_t len);
 void eos_evtq_pop(unsigned char *type, unsigned char **buffer, uint16_t *len);
 void eos_evtq_bad_handler(unsigned char type, unsigned char *buffer, uint16_t len);
-void eos_evtq_set_handler(unsigned char type, eos_evt_fptr_t handler, uint8_t flags);
-void eos_evtq_set_hflags(unsigned char type, uint8_t flags);
+void eos_evtq_set_handler(unsigned char type, eos_evt_handler_t handler);
+eos_evt_handler_t eos_evtq_get_handler(unsigned char type);
 void eos_evtq_get(unsigned char type, unsigned char *selector, uint16_t sel_len, unsigned char **buffer, uint16_t *len);
 void eos_evtq_loop(void);
 
diff --git a/code/fe310/eos/evt_def.h b/code/fe310/eos/evt_def.h
index 028dd3e..afd8a69 100644
--- a/code/fe310/eos/evt_def.h
+++ b/code/fe310/eos/evt_def.h
@@ -4,7 +4,7 @@
 #define EOS_EVT_SPI                 0x40
 #define EOS_EVT_UART                0x50
 #define EOS_EVT_UI                  0x60
-#define EOS_EVT_USER                0x70
+#define EOS_EVT_USER                0x80
 
 #define EOS_EVT_MAX_EVT             8
 #define EOS_EVT_MASK                0xF0
diff --git a/code/fe310/eos/i2s.c b/code/fe310/eos/i2s.c
index 5b8d2cb..83fd148 100644
--- a/code/fe310/eos/i2s.c
+++ b/code/fe310/eos/i2s.c
@@ -8,7 +8,6 @@
 #include "eos.h"
 #include "interrupt.h"
 #include "event.h"
-#include "net.h"
 
 #include "i2s.h"
 #include "i2s_def.h"
@@ -31,8 +30,8 @@ uint32_t _eos_i2s_spk_wm = 0;
 uint32_t _eos_i2s_mic_evt_enable = 0;
 uint32_t _eos_i2s_spk_evt_enable = 0;
 
-static eos_i2s_fptr_t i2s_spk_handler = NULL;
-static eos_i2s_fptr_t i2s_mic_handler = NULL;
+static eos_i2s_handler_t i2s_spk_handler = NULL;
+static eos_i2s_handler_t i2s_mic_handler = NULL;
 static uint32_t i2s_clk_period;
 static uint8_t i2s_mic_volume = 0;      /* 0 - 8 */
 static uint8_t i2s_spk_volume = 16;     /* 0 - 16 */
@@ -92,7 +91,7 @@ static uint16_t _abuf_len(EOSABuf *buf) {
     return buf->idx_w - buf->idx_r;
 }
 
-static void i2s_handler_evt(unsigned char type, unsigned char *buffer, uint16_t len) {
+static void i2s_handle_evt(unsigned char type, unsigned char *buffer, uint16_t len) {
     switch(type & ~EOS_EVT_MASK) {
         case I2S_ETYPE_MIC:
             if (i2s_mic_handler) i2s_mic_handler(type);
@@ -136,7 +135,7 @@ static void _spk_vol_set(uint8_t vol) {
 extern void _eos_i2s_start_pwm(void);
 
 void eos_i2s_init(void) {
-    eos_evtq_set_handler(EOS_EVT_AUDIO, i2s_handler_evt, 0);
+    eos_evtq_set_handler(EOS_EVT_AUDIO, i2s_handle_evt);
 
     GPIO_REG(GPIO_INPUT_EN)     &= ~(1 << I2S_PIN_CK);
     GPIO_REG(GPIO_OUTPUT_EN)    |=  (1 << I2S_PIN_CK);
@@ -267,12 +266,10 @@ void eos_i2s_mic_init(uint8_t *mic_arr, uint16_t mic_arr_size) {
     set_csr(mstatus, MSTATUS_MIE);
 }
 
-void eos_i2s_mic_set_handler(eos_i2s_fptr_t wm_handler, uint8_t flags) {
+void eos_i2s_mic_set_handler(eos_i2s_handler_t wm_handler) {
     clear_csr(mstatus, MSTATUS_MIE);
     i2s_mic_handler = wm_handler;
     set_csr(mstatus, MSTATUS_MIE);
-
-    eos_evtq_set_hflags(EOS_EVT_AUDIO | I2S_ETYPE_MIC, flags);
 }
 
 void eos_i2s_mic_set_wm(uint16_t wm) {
@@ -343,12 +340,10 @@ void eos_i2s_spk_init(uint8_t *spk_arr, uint16_t spk_arr_size) {
     set_csr(mstatus, MSTATUS_MIE);
 }
 
-void eos_i2s_spk_set_handler(eos_i2s_fptr_t wm_handler, uint8_t flags) {
+void eos_i2s_spk_set_handler(eos_i2s_handler_t wm_handler) {
     clear_csr(mstatus, MSTATUS_MIE);
     i2s_spk_handler = wm_handler;
     set_csr(mstatus, MSTATUS_MIE);
-
-    eos_evtq_set_hflags(EOS_EVT_AUDIO | I2S_ETYPE_SPK, flags);
 }
 
 void eos_i2s_spk_set_wm(uint16_t wm) {
diff --git a/code/fe310/eos/i2s.h b/code/fe310/eos/i2s.h
index 83c39b3..81d13f4 100644
--- a/code/fe310/eos/i2s.h
+++ b/code/fe310/eos/i2s.h
@@ -10,13 +10,13 @@ typedef struct EOSABuf {
     uint8_t *array;
 } EOSABuf;
 
-typedef void (*eos_i2s_fptr_t) (unsigned char);
+typedef void (*eos_i2s_handler_t) (unsigned char);
 
 void eos_i2s_init(void);
 void eos_i2s_start(uint32_t sample_rate, unsigned char fmt);
 void eos_i2s_stop(void);
 void eos_i2s_mic_init(uint8_t *mic_arr, uint16_t mic_arr_size);
-void eos_i2s_mic_set_handler(eos_i2s_fptr_t wm_handler, uint8_t flags);
+void eos_i2s_mic_set_handler(eos_i2s_handler_t wm_handler);
 void eos_i2s_mic_set_wm(uint16_t wm);
 uint16_t eos_i2s_mic_len(void);
 uint16_t eos_i2s_mic_read(uint8_t *sample, uint16_t ssize);
@@ -25,7 +25,7 @@ int eos_i2s_mic_pop16(uint16_t *sample);
 int eos_i2s_mic_vol_get(void);
 void eos_i2s_mic_vol_set(int vol);
 void eos_i2s_spk_init(uint8_t *mic_arr, uint16_t mic_arr_size);
-void eos_i2s_spk_set_handler(eos_i2s_fptr_t wm_handler, uint8_t flags);
+void eos_i2s_spk_set_handler(eos_i2s_handler_t wm_handler);
 void eos_i2s_spk_set_wm(uint16_t wm);
 uint16_t eos_i2s_spk_len(void);
 uint16_t eos_i2s_spk_write(uint8_t *sample, uint16_t ssize);
diff --git a/code/fe310/eos/interrupt.c b/code/fe310/eos/interrupt.c
index b9b289b..820d1fa 100644
--- a/code/fe310/eos/interrupt.c
+++ b/code/fe310/eos/interrupt.c
@@ -13,7 +13,7 @@
 // for use by the PLIC Driver.
 static plic_instance_t plic;
 
-static eos_intr_fptr_t ext_interrupt_handler[PLIC_NUM_INTERRUPTS];
+static eos_intr_handler_t ext_interrupt_handler[PLIC_NUM_INTERRUPTS];
 
 uintptr_t eos_intr_handle(uintptr_t int_num) {
     if ((int_num >=1) && (int_num <= PLIC_NUM_INTERRUPTS) && (ext_interrupt_handler[int_num-1])) {
@@ -45,13 +45,13 @@ void eos_intr_init(void) {
     set_csr(mstatus, MSTATUS_MIE);
 }
 
-void eos_intr_set(uint8_t int_num, uint8_t priority, eos_intr_fptr_t handler) {
+void eos_intr_set(uint8_t int_num, uint8_t priority, eos_intr_handler_t handler) {
     ext_interrupt_handler[int_num-1] = handler;
     PLIC_set_priority(&plic, int_num, priority);
     PLIC_enable_interrupt(&plic, int_num);
 }
 
-void eos_intr_set_handler(uint8_t int_num, eos_intr_fptr_t handler) {
+void eos_intr_set_handler(uint8_t int_num, eos_intr_handler_t handler) {
     ext_interrupt_handler[int_num-1] = handler;
 }
 
diff --git a/code/fe310/eos/interrupt.h b/code/fe310/eos/interrupt.h
index 3b5dc7e..075e7eb 100644
--- a/code/fe310/eos/interrupt.h
+++ b/code/fe310/eos/interrupt.h
@@ -1,12 +1,10 @@
 #include <stdint.h>
 
-// Structures for registering different interrupt handlers
-// for different parts of the application.
-typedef void (*eos_intr_fptr_t) (void);
+typedef void (*eos_intr_handler_t) (void);
 
 void eos_intr_init(void);
-void eos_intr_set(uint8_t int_num, uint8_t priority, eos_intr_fptr_t handler);
-void eos_intr_set_handler(uint8_t int_num, eos_intr_fptr_t handler);
+void eos_intr_set(uint8_t int_num, uint8_t priority, eos_intr_handler_t handler);
+void eos_intr_set_handler(uint8_t int_num, eos_intr_handler_t handler);
 void eos_intr_set_priority(uint8_t int_num, uint8_t priority);
 void eos_intr_enable(uint8_t int_num);
 void eos_intr_disable(uint8_t int_num);
diff --git a/code/fe310/eos/net.c b/code/fe310/eos/net.c
index 36695bc..afe7997 100644
--- a/code/fe310/eos/net.c
+++ b/code/fe310/eos/net.c
@@ -30,24 +30,19 @@ static uint8_t net_state_flags = 0;
 static unsigned char net_state_type = 0;
 static uint32_t net_state_len_tx = 0;
 static uint32_t net_state_len_rx = 0;
+unsigned char *net_state_buf = NULL;
 
 static uint8_t net_state_next_cnt = 0;
 static unsigned char *net_state_next_buf = NULL;
 
-static eos_evt_fptr_t evt_handler[EOS_NET_MAX_MTYPE];
-static uint16_t evt_handler_flags_buf_free = 0;
-static uint16_t evt_handler_flags_buf_acq = 0;
-
-extern uint32_t _eos_spi_state_len;
-extern uint32_t _eos_spi_state_idx_tx;
-extern uint32_t _eos_spi_state_idx_rx;
-extern unsigned char *_eos_spi_state_buf;
+static eos_evt_handler_t net_handler[EOS_NET_MAX_MTYPE];
+static uint16_t net_wrapper_acq[EOS_EVT_MAX_EVT];
+static uint16_t net_flags_acq[EOS_EVT_MAX_EVT];
 
 static void net_xchg_reset(void) {
     net_state_flags &= ~NET_STATE_FLAG_CTS;
     net_state_flags |= (NET_STATE_FLAG_RST | NET_STATE_FLAG_XCHG);
 
-    // before starting a transaction, set SPI peripheral to desired mode
     SPI1_REG(SPI_REG_CSMODE) = SPI_CSMODE_HOLD;
 
     SPI1_REG(SPI_REG_TXFIFO) = 0;
@@ -66,10 +61,8 @@ static void net_xchg_start(unsigned char type, unsigned char *buffer, uint16_t l
     net_state_type = type;
     net_state_len_tx = len;
     net_state_len_rx = 0;
+    net_state_buf = buffer;
 
-    _eos_spi_state_buf = buffer;
-
-    // before starting a transaction, set SPI peripheral to desired mode
     SPI1_REG(SPI_REG_CSMODE) = SPI_CSMODE_HOLD;
 
     SPI1_REG(SPI_REG_TXFIFO) = ((type << 3) | (len >> 8)) & 0xFF;
@@ -97,25 +90,12 @@ static int net_xchg_next(unsigned char *_buffer) {
     return 1;
 }
 
-void eos_net_xchg_done(void) {
-    SPI1_REG(SPI_REG_CSMODE) = SPI_CSMODE_AUTO;
-    if (net_state_type) {
-        int r = eos_evtq_push_isr(EOS_EVT_NET | net_state_type, _eos_spi_state_buf, net_state_len_rx);
-        if (r) eos_bufq_push(&net_buf_q, _eos_spi_state_buf);
-    } else if (((net_state_flags & NET_STATE_FLAG_ONEW) || net_state_next_cnt) && (net_state_next_buf == NULL)) {
-        net_state_next_buf = _eos_spi_state_buf;
-        net_state_flags &= ~NET_STATE_FLAG_ONEW;
-    } else {
-        eos_bufq_push(&net_buf_q, _eos_spi_state_buf);
-    }
-    net_state_flags &= ~NET_STATE_FLAG_XCHG;
-}
-
-static void net_handler_xchg(void) {
+static void net_handle_xchg(void) {
     volatile uint32_t r1, r2;
+    uint32_t len;
 
     if (net_state_flags & NET_STATE_FLAG_RST) {
-        net_state_flags &= ~NET_STATE_FLAG_RST;
+        net_state_flags &= ~(NET_STATE_FLAG_RST | NET_STATE_FLAG_XCHG);
 
         r1 = SPI1_REG(SPI_REG_RXFIFO);
         SPI1_REG(SPI_REG_CSMODE) = SPI_CSMODE_AUTO;
@@ -124,8 +104,6 @@ static void net_handler_xchg(void) {
         return;
     } else if (net_state_flags & NET_STATE_FLAG_INIT) {
         net_state_flags &= ~NET_STATE_FLAG_INIT;
-        SPI1_REG(SPI_REG_TXCTRL) = SPI_TXWM(SPI_SIZE_WM);
-        SPI1_REG(SPI_REG_IE) = SPI_IP_TXWM;
 
         r1 = SPI1_REG(SPI_REG_RXFIFO);
         r2 = SPI1_REG(SPI_REG_RXFIFO);
@@ -138,29 +116,44 @@ static void net_handler_xchg(void) {
         net_state_type = ((r1 & 0xFF) >> 3);
         net_state_len_rx = ((r1 & 0x07) << 8);
         net_state_len_rx |= (r2 & 0xFF);
-        _eos_spi_state_len = MAX(net_state_len_tx, net_state_len_rx);
-        _eos_spi_state_idx_tx = 0;
-        _eos_spi_state_idx_rx = 0;
-
-        // Work around esp32 bug
-        if (_eos_spi_state_len < 6) {
-            _eos_spi_state_len = 6;
-        } else if ((_eos_spi_state_len + 2) % 4 != 0) {
-            _eos_spi_state_len = ((_eos_spi_state_len + 2)/4 + 1) * 4 - 2;
+        len = MAX(net_state_len_tx, net_state_len_rx);
+
+        // esp32 bug workaraund
+        if (len < 6) {
+            len = 6;
+        } else if ((len + 2) % 4 != 0) {
+            len = ((len + 2)/4 + 1) * 4 - 2;
         }
 
-        if (_eos_spi_state_len > EOS_NET_SIZE_BUF) {
+        if (len > EOS_NET_SIZE_BUF) {
+            net_state_flags &= ~NET_STATE_FLAG_XCHG;
             SPI1_REG(SPI_REG_CSMODE) = SPI_CSMODE_AUTO;
             SPI1_REG(SPI_REG_IE) = 0x0;
+            return;
         }
 
+        _eos_spi_xchg_init(net_state_buf, len, 0);
+        SPI1_REG(SPI_REG_TXCTRL) = SPI_TXWM(SPI_SIZE_WM);
+        SPI1_REG(SPI_REG_IE) = SPI_IP_TXWM;
         return;
     }
 
-    eos_spi_xchg_handler();
+    eos_spi_handle_xchg();
+    if (SPI1_REG(SPI_REG_CSMODE) == SPI_CSMODE_AUTO) {  // exchange done
+        if (net_state_type) {
+            int r = eos_evtq_push_isr(EOS_EVT_NET | net_state_type, net_state_buf, net_state_len_rx);
+            if (r) eos_bufq_push(&net_buf_q, net_state_buf);
+        } else if (((net_state_flags & NET_STATE_FLAG_ONEW) || net_state_next_cnt) && (net_state_next_buf == NULL)) {
+            net_state_next_buf = net_state_buf;
+            net_state_flags &= ~NET_STATE_FLAG_ONEW;
+        } else {
+            eos_bufq_push(&net_buf_q, net_state_buf);
+        }
+        net_state_flags &= ~NET_STATE_FLAG_XCHG;
+    }
 }
 
-static void net_handler_cts(void) {
+static void net_handle_cts(void) {
     GPIO_REG(GPIO_RISE_IP) = (1 << NET_PIN_CTS);
     net_state_flags |= NET_STATE_FLAG_CTS;
 
@@ -169,7 +162,7 @@ static void net_handler_cts(void) {
     }
 }
 
-static void net_handler_rts(void) {
+static void net_handle_rts(void) {
     uint32_t rts_offset = (1 << NET_PIN_RTS);
     if (GPIO_REG(GPIO_RISE_IP) & rts_offset) {
         GPIO_REG(GPIO_RISE_IP) = rts_offset;
@@ -181,15 +174,67 @@ static void net_handler_rts(void) {
     }
 }
 
-static void net_handler_evt(unsigned char type, unsigned char *buffer, uint16_t len) {
+static void net_handle_evt(unsigned char type, unsigned char *buffer, uint16_t len) {
     unsigned char idx = (type & ~EOS_EVT_MASK) - 1;
 
-    if (idx >= EOS_NET_MAX_MTYPE) {
+    if (idx < EOS_NET_MAX_MTYPE) {
+        net_handler[idx](type, buffer, len);
+    } else {
         eos_evtq_bad_handler(type, buffer, len);
         eos_net_free(buffer, 0);
-        return;
     }
-    _eos_net_handle(type, buffer, len, idx, evt_handler, &evt_handler_flags_buf_free, &evt_handler_flags_buf_acq);
+}
+
+static int net_acquire(unsigned char reserved) {
+    int ret = 0;
+
+    if (reserved) {
+        while (!ret) {
+            clear_csr(mstatus, MSTATUS_MIE);
+            if (net_state_next_buf) {
+                ret = 1;
+                net_state_next_cnt--;
+            } else {
+                asm volatile ("wfi");
+            }
+            set_csr(mstatus, MSTATUS_MIE);
+        }
+    } else {
+        clear_csr(mstatus, MSTATUS_MIE);
+        if (net_state_next_buf == NULL) net_state_next_buf = eos_bufq_pop(&net_buf_q);
+        ret = (net_state_next_buf != NULL);
+        if (!ret) net_state_next_cnt++;
+        set_csr(mstatus, MSTATUS_MIE);
+    }
+    return ret;
+}
+
+static void evt_handler_wrapper(unsigned char type, unsigned char *buffer, uint16_t len, unsigned char idx, uint16_t flag) {
+    int ok;
+
+    ok = net_acquire(net_wrapper_acq[idx] & flag);
+    if (ok) {
+        eos_evtq_get_handler(type)(type, buffer, len);
+        net_wrapper_acq[idx] &= ~flag;
+    } else {
+        net_wrapper_acq[idx] |= flag;
+        eos_evtq_push(type, buffer, len);
+    }
+}
+
+static void evt_handler(unsigned char type, unsigned char *buffer, uint16_t len) {
+    unsigned char idx = ((type & EOS_EVT_MASK) >> 4) - 1;
+    uint16_t flag = (uint16_t)1 << ((type & ~EOS_EVT_MASK) - 1);
+
+    if (idx < EOS_EVT_MAX_EVT) {
+        if (flag & net_flags_acq[idx]) {
+            evt_handler_wrapper(type, buffer, len, idx, flag);
+        } else {
+            eos_evtq_get_handler(type)(type, buffer, len);
+        }
+    } else {
+        eos_evtq_bad_handler(type, buffer, len);
+    }
 }
 
 void eos_net_init(void) {
@@ -202,9 +247,10 @@ void eos_net_init(void) {
     }
 
     for (i=0; i<EOS_NET_MAX_MTYPE; i++) {
-        evt_handler[i] = eos_evtq_bad_handler;
+        net_handler[i] = eos_evtq_bad_handler;
     }
-    eos_evtq_set_handler(EOS_EVT_NET, net_handler_evt, 0);
+    eos_evtq_set_handler(0, evt_handler);
+    eos_evtq_set_handler(EOS_EVT_NET, net_handle_evt);
 
     GPIO_REG(GPIO_INPUT_EN)     |=  (1 << NET_PIN_CTS);
     GPIO_REG(GPIO_OUTPUT_EN)    &= ~(1 << NET_PIN_CTS);
@@ -212,7 +258,7 @@ void eos_net_init(void) {
     GPIO_REG(GPIO_OUTPUT_XOR)   &= ~(1 << NET_PIN_CTS);
 
     GPIO_REG(GPIO_RISE_IE)      |=  (1 << NET_PIN_CTS);
-    eos_intr_set(INT_GPIO_BASE + NET_PIN_CTS, IRQ_PRIORITY_NET_CTS, net_handler_cts);
+    eos_intr_set(INT_GPIO_BASE + NET_PIN_CTS, IRQ_PRIORITY_NET_CTS, net_handle_cts);
 
     GPIO_REG(GPIO_INPUT_EN)     |=  (1 << NET_PIN_RTS);
     GPIO_REG(GPIO_OUTPUT_EN)    &= ~(1 << NET_PIN_RTS);
@@ -221,13 +267,13 @@ void eos_net_init(void) {
 
     GPIO_REG(GPIO_RISE_IE)      |=  (1 << NET_PIN_RTS);
     GPIO_REG(GPIO_FALL_IE)      |=  (1 << NET_PIN_RTS);
-    eos_intr_set(INT_GPIO_BASE + NET_PIN_RTS, IRQ_PRIORITY_NET_RTS, net_handler_rts);
+    eos_intr_set(INT_GPIO_BASE + NET_PIN_RTS, IRQ_PRIORITY_NET_RTS, net_handle_rts);
 }
 
 void eos_net_start(void) {
-    eos_intr_set_handler(INT_SPI1_BASE, net_handler_xchg);
-    SPI1_REG(SPI_REG_SCKDIV) = SPI_DIV_NET;
-    SPI1_REG(SPI_REG_CSID) = SPI_CS_IDX_NET;
+    eos_intr_set_handler(INT_SPI1_BASE, net_handle_xchg);
+    SPI1_REG(SPI_REG_SCKDIV) = NET_SPI_DIV;
+    SPI1_REG(SPI_REG_CSID) = NET_SPI_CSID;
 
     net_state_flags |= NET_STATE_FLAG_RUN;
     if (net_state_flags & NET_STATE_FLAG_CTS) {
@@ -251,68 +297,24 @@ void eos_net_stop(void) {
     }
 }
 
-void _eos_net_handle(unsigned char type, unsigned char *buffer, uint16_t len, unsigned char idx, eos_evt_fptr_t handlers[], uint16_t *flags_buf_free, uint16_t *flags_buf_acq) {
-    uint16_t buf_free = ((uint16_t)1 << idx) & *flags_buf_free;
-    uint16_t buf_acq = ((uint16_t)1 << idx) & *flags_buf_acq;
-
-    if (buf_free) {
-        eos_net_free(buffer, buf_acq);
-        buffer = NULL;
-        len = 0;
-    }
-
-    handlers[idx](type, buffer, len);
-
-    if (buf_free && buf_acq) eos_net_release();
-}
-
-void _eos_net_set_handler(unsigned char idx, eos_evt_fptr_t handler, eos_evt_fptr_t handlers[], uint8_t flags, uint16_t *flags_buf_free, uint16_t *flags_buf_acq) {
-    if (flags) {
-        uint16_t flag = (uint16_t)1 << idx;
-        *flags_buf_free &= ~flag;
-        *flags_buf_acq &= ~flag;
-        if (flags & EOS_NET_FLAG_BFREE) *flags_buf_free |= flag;
-        if (flags & EOS_NET_FLAG_BACQ) *flags_buf_acq |= flag;
-    }
-    handlers[idx] = handler;
-}
-
-void eos_net_set_handler(unsigned char mtype, eos_evt_fptr_t handler, uint8_t flags) {
-    if (mtype && (mtype <= EOS_NET_MAX_MTYPE)) {
-        mtype--;
-    } else {
-        return;
-    }
-    _eos_net_set_handler(mtype, handler, evt_handler, flags, &evt_handler_flags_buf_free, &evt_handler_flags_buf_acq);
+void eos_net_set_handler(unsigned char mtype, eos_evt_handler_t handler) {
+    if (handler == NULL) handler = eos_evtq_bad_handler;
+    if (mtype && (mtype <= EOS_NET_MAX_MTYPE)) net_handler[mtype - 1] = handler;
 }
 
-int _eos_net_acquire(unsigned char reserved) {
-    int ret = 0;
+void eos_net_set_acquire_for_evt(unsigned char type, char acq) {
+    unsigned char idx = ((type & EOS_EVT_MASK) >> 4) - 1;
+    uint16_t flag = type & ~EOS_EVT_MASK ? (uint16_t)1 << ((type & ~EOS_EVT_MASK) - 1) : 0xFFFF;
 
-    if (reserved) {
-        while (!ret) {
-            clear_csr(mstatus, MSTATUS_MIE);
-            if (net_state_next_buf) {
-                ret = 1;
-                net_state_next_cnt--;
-            } else {
-                asm volatile ("wfi");
-            }
-            set_csr(mstatus, MSTATUS_MIE);
-        }
-    } else {
-        clear_csr(mstatus, MSTATUS_MIE);
-        if (net_state_next_buf == NULL) net_state_next_buf = eos_bufq_pop(&net_buf_q);
-        ret = (net_state_next_buf != NULL);
-        if (!ret) net_state_next_cnt++;
-        set_csr(mstatus, MSTATUS_MIE);
+    if (idx < EOS_EVT_MAX_EVT) {
+        net_flags_acq[idx] &= ~flag;
+        if (acq) net_flags_acq[idx] |= flag;
     }
-    return ret;
 }
 
 void eos_net_acquire(void) {
-    unsigned char acq = _eos_net_acquire(0);
-    if (!acq) _eos_net_acquire(1);
+    unsigned char acq = net_acquire(0);
+    if (!acq) net_acquire(1);
 }
 
 void eos_net_release(void) {
diff --git a/code/fe310/eos/net.h b/code/fe310/eos/net.h
index 59cc6eb..ba394b8 100644
--- a/code/fe310/eos/net.h
+++ b/code/fe310/eos/net.h
@@ -4,9 +4,6 @@
 #define EOS_NET_SIZE_BUF        1500
 #define EOS_NET_SIZE_BUFQ       2
 
-#define EOS_NET_FLAG_BACQ       0x1
-#define EOS_NET_FLAG_BFREE      0x2
-
 #define EOS_NET_MTYPE_SOCK      1
 #define EOS_NET_MTYPE_AUDIO     2
 
@@ -17,16 +14,11 @@
 
 #define EOS_NET_MAX_MTYPE       8
 
-void eos_net_xchg_done(void);
-
 void eos_net_init(void);
 void eos_net_start(void);
 void eos_net_stop(void);
-void _eos_net_handle(unsigned char type, unsigned char *buffer, uint16_t len, unsigned char idx, eos_evt_fptr_t handlers[], uint16_t *flags_buf_free, uint16_t *flags_buf_acq);
-void _eos_net_set_handler(unsigned char idx, eos_evt_fptr_t handler, eos_evt_fptr_t handlers[], uint8_t flags, uint16_t *flags_buf_free, uint16_t *flags_buf_acq);
-void eos_net_set_handler(unsigned char type, eos_evt_fptr_t handler, uint8_t flags);
+void eos_net_set_handler(unsigned char type, eos_evt_handler_t handler);
 
-int _eos_net_acquire(unsigned char reserved);
 void eos_net_acquire(void);
 void eos_net_release(void);
 unsigned char *eos_net_alloc(void);
diff --git a/code/fe310/eos/net_def.h b/code/fe310/eos/net_def.h
index ec795b1..40c55d1 100644
--- a/code/fe310/eos/net_def.h
+++ b/code/fe310/eos/net_def.h
@@ -11,3 +11,5 @@
 
 #define NET_MTYPE_FLAG_ONEW     0x10
 
+#define NET_SPI_DIV             16
+#define NET_SPI_CSID            3
diff --git a/code/fe310/eos/sock.c b/code/fe310/eos/sock.c
index 077c93d..5e3dc67 100644
--- a/code/fe310/eos/sock.c
+++ b/code/fe310/eos/sock.c
@@ -8,27 +8,33 @@
 
 #include "sock.h"
 
-static eos_evt_fptr_t evt_handler[EOS_SOCK_MAX_SOCK];
+static eos_evt_handler_t evt_handler[EOS_SOCK_MAX_SOCK];
 static uint16_t evt_handler_flags_buf_free = 0;
 static uint16_t evt_handler_flags_buf_acq = 0;
 
-static void sock_handler_evt(unsigned char type, unsigned char *buffer, uint16_t len) {
+static void sock_handle_evt(unsigned char type, unsigned char *buffer, uint16_t len) {
+    unsigned char sock;
     if ((buffer == NULL) || (len < 2)) {
         eos_evtq_bad_handler(type, buffer, len);
         eos_net_free(buffer, 0);
         return;
     }
 
-    if (buffer[0] == EOS_SOCK_MTYPE_PKT) {
-        uint8_t sock = buffer[1];
-        if (sock && (sock <= EOS_SOCK_MAX_SOCK)) {
-            sock--;
-        } else {
+    sock = buffer[1];
+    if ((sock == 0) || (sock > EOS_SOCK_MAX_SOCK)) {
+        eos_evtq_bad_handler(type, buffer, len);
+        eos_net_free(buffer, 0);
+    }
+
+    sock--;
+    switch(buffer[0]) {
+        case EOS_SOCK_MTYPE_PKT:
+            evt_handler[sock](type, buffer, len);
+            break;
+        default:
             eos_evtq_bad_handler(type, buffer, len);
             eos_net_free(buffer, 0);
-            return;
-        }
-        _eos_net_handle(type, buffer, len, sock, evt_handler, &evt_handler_flags_buf_free, &evt_handler_flags_buf_acq);
+            break;
     }
 }
 
@@ -38,16 +44,12 @@ void eos_sock_init(void) {
     for (i=0; i<EOS_SOCK_MAX_SOCK; i++) {
         evt_handler[i] = eos_evtq_bad_handler;
     }
-    eos_net_set_handler(EOS_NET_MTYPE_SOCK, sock_handler_evt, 0);
+    eos_net_set_handler(EOS_NET_MTYPE_SOCK, sock_handle_evt);
 }
 
-void eos_sock_set_handler(int sock, eos_evt_fptr_t handler, uint8_t flags) {
-    if (sock && (sock <= EOS_SOCK_MAX_SOCK)) {
-        sock--;
-    } else {
-        return;
-    }
-    _eos_net_set_handler(sock, handler, evt_handler, flags, &evt_handler_flags_buf_free, &evt_handler_flags_buf_acq);
+void eos_sock_set_handler(unsigned char sock, eos_evt_handler_t handler) {
+    if (handler == NULL) handler = eos_evtq_bad_handler;
+    if (sock && (sock <= EOS_SOCK_MAX_SOCK)) evt_handler[sock - 1] = handler;
 }
 
 int eos_sock_open_udp(void) {
@@ -73,14 +75,14 @@ int eos_sock_open_udp(void) {
     return sock;
 }
 
-void eos_sock_close(int sock) {
+void eos_sock_close(unsigned char sock) {
     unsigned char *buffer = eos_net_alloc();
     buffer[0] = EOS_SOCK_MTYPE_CLOSE;
     buffer[1] = sock;
     eos_net_send(EOS_NET_MTYPE_SOCK, buffer, 2, 1);
 }
 
-int eos_sock_sendto(int sock, unsigned char *buffer, uint16_t size, unsigned char more, EOSNetAddr *addr) {
+int eos_sock_sendto(unsigned char sock, unsigned char *buffer, uint16_t size, unsigned char more, EOSNetAddr *addr) {
     unsigned char type = EOS_NET_MTYPE_SOCK;
 
     buffer[0] = EOS_SOCK_MTYPE_PKT;
diff --git a/code/fe310/eos/sock.h b/code/fe310/eos/sock.h
index db1db21..d647381 100644
--- a/code/fe310/eos/sock.h
+++ b/code/fe310/eos/sock.h
@@ -17,9 +17,9 @@ typedef struct EOSNetAddr {
 } EOSNetAddr;
 
 void eos_sock_init(void);
-void eos_sock_set_handler(int sock, eos_evt_fptr_t handler, uint8_t flags);
+void eos_sock_set_handler(unsigned char sock, eos_evt_handler_t handler);
 
 int eos_sock_open_udp(void);
-void eos_sock_close(int sock);
-int eos_sock_sendto(int sock, unsigned char *buffer, uint16_t size, unsigned char more, EOSNetAddr *addr);
+void eos_sock_close(unsigned char sock);
+int eos_sock_sendto(unsigned char sock, unsigned char *buffer, uint16_t size, unsigned char more, EOSNetAddr *addr);
 void eos_sock_getfrom(unsigned char *buffer, EOSNetAddr *addr);
diff --git a/code/fe310/eos/spi.c b/code/fe310/eos/spi.c
index ae12f40..725db13 100644
--- a/code/fe310/eos/spi.c
+++ b/code/fe310/eos/spi.c
@@ -23,14 +23,14 @@ static uint8_t spi_dev_cs_pin;
 static uint8_t spi_state_flags;
 static unsigned char spi_in_xchg;
 
-uint32_t _eos_spi_state_len = 0;
-uint32_t _eos_spi_state_idx_tx = 0;
-uint32_t _eos_spi_state_idx_rx = 0;
-unsigned char *_eos_spi_state_buf = NULL;
+static uint32_t spi_state_len = 0;
+static uint32_t spi_state_idx_tx = 0;
+static uint32_t spi_state_idx_rx = 0;
+static unsigned char *spi_state_buf = NULL;
 
-static eos_evt_fptr_t evt_handler[EOS_SPI_MAX_DEV];
+static eos_evt_handler_t evt_handler[EOS_SPI_MAX_DEV];
 
-static void spi_handler_evt(unsigned char type, unsigned char *buffer, uint16_t len) {
+static void spi_handle_evt(unsigned char type, unsigned char *buffer, uint16_t len) {
     unsigned char idx = (type & ~EOS_EVT_MASK) - 1;
     if (idx < EOS_SPI_MAX_DEV) {
         evt_handler[idx](type, buffer, len);
@@ -39,39 +39,15 @@ static void spi_handler_evt(unsigned char type, unsigned char *buffer, uint16_t
     }
 }
 
-static void spi_flush(void) {
-    SPI1_REG(SPI_REG_TXCTRL) = SPI_TXWM(1);
-    while (!(SPI1_REG(SPI_REG_IP) & SPI_IP_TXWM));
-    while (!(SPI1_REG(SPI_REG_RXFIFO) & SPI_RXFIFO_EMPTY));
-}
-
-static void spi_xchg_wait(void) {
-    volatile uint8_t done = 0;
-
-    while (!done) {
-        clear_csr(mstatus, MSTATUS_MIE);
-        done = !(spi_state_flags & SPI_FLAG_XCHG);
-        if (!done) asm volatile ("wfi");
-        set_csr(mstatus, MSTATUS_MIE);
-    }
-    spi_in_xchg = 0;
-}
-
 void eos_spi_init(void) {
     int i;
 
     for (i=0; i<EOS_SPI_MAX_DEV; i++) {
         evt_handler[i] = eos_evtq_bad_handler;
     }
-    eos_evtq_set_handler(EOS_EVT_SPI, spi_handler_evt, 0);
+    eos_evtq_set_handler(EOS_EVT_SPI, spi_handle_evt);
     eos_intr_set(INT_SPI1_BASE, IRQ_PRIORITY_SPI_XCHG, NULL);
 
-    GPIO_REG(GPIO_INPUT_EN)     &= ~(1 << SPI_CS_PIN_CAM);
-    GPIO_REG(GPIO_OUTPUT_EN)    |=  (1 << SPI_CS_PIN_CAM);
-    GPIO_REG(GPIO_PULLUP_EN)    &= ~(1 << SPI_CS_PIN_CAM);
-    GPIO_REG(GPIO_OUTPUT_XOR)   &= ~(1 << SPI_CS_PIN_CAM);
-    GPIO_REG(GPIO_OUTPUT_VAL)   |=  (1 << SPI_CS_PIN_CAM);
-
     SPI1_REG(SPI_REG_SCKMODE) = SPI_MODE0;
     SPI1_REG(SPI_REG_FMT) = SPI_FMT_PROTO(SPI_PROTO_S) |
       SPI_FMT_ENDIAN(SPI_ENDIAN_MSB) |
@@ -85,102 +61,88 @@ void eos_spi_init(void) {
     // SPI1_REG(SPI_REG_CSDEF) = 0xFFFF;
 }
 
-void eos_spi_dev_start(unsigned char dev) {
-    eos_net_stop();
+void eos_spi_start(unsigned char dev, uint32_t div, uint32_t csid, uint8_t pin) {
     spi_dev = dev;
-    spi_state_flags = SPI_FLAG_CS;
-    switch (dev) {
-        case EOS_SPI_DEV_DISP:
-            SPI1_REG(SPI_REG_SCKDIV) = SPI_DIV_DISP;
-            SPI1_REG(SPI_REG_CSMODE) = SPI_CSMODE_AUTO;
-            SPI1_REG(SPI_REG_CSID) = SPI_CS_IDX_DISP;
-            break;
-        case EOS_SPI_DEV_CARD:
-            SPI1_REG(SPI_REG_SCKDIV) = SPI_DIV_CARD;
-            SPI1_REG(SPI_REG_CSMODE) = SPI_CSMODE_AUTO;
-            SPI1_REG(SPI_REG_CSID) = SPI_CS_IDX_CARD;
-            break;
-        case EOS_SPI_DEV_CAM:
-            spi_dev_cs_pin = SPI_CS_PIN_CAM;
-            SPI1_REG(SPI_REG_SCKDIV) = SPI_DIV_CAM;
-            SPI1_REG(SPI_REG_CSMODE) = SPI_CSMODE_OFF;
-            SPI1_REG(SPI_REG_CSID) = SPI_CS_IDX_NONE;
-            break;
+    spi_state_flags = 0;
+    SPI1_REG(SPI_REG_SCKDIV) = div;
+    SPI1_REG(SPI_REG_CSID) = csid;
+    if (csid != SPI_CSID_NONE) {
+        SPI1_REG(SPI_REG_CSMODE) = SPI_CSMODE_AUTO;
+    } else {
+        SPI1_REG(SPI_REG_CSMODE) = SPI_CSMODE_OFF;
+        spi_dev_cs_pin = pin;
     }
-    eos_intr_set_handler(INT_SPI1_BASE, eos_spi_xchg_handler);
+    eos_intr_set_handler(INT_SPI1_BASE, eos_spi_handle_xchg);
 }
 
-void eos_spi_dev_stop(void) {
-    if (spi_in_xchg) spi_xchg_wait();
-    if (spi_state_flags & EOS_SPI_FLAG_TX) spi_flush();
-    if (!(spi_state_flags & SPI_FLAG_CS)) eos_spi_cs_clear();
+void eos_spi_stop(void) {
+    eos_spi_flush();
+    spi_dev = 0;
+}
 
-    spi_dev = EOS_SPI_DEV_NET;
-    eos_net_start();
+void eos_spi_set_handler(unsigned char dev, eos_evt_handler_t handler) {
+    if (handler == NULL) handler = eos_evtq_bad_handler;
+    if (dev && (dev <= EOS_NET_MAX_MTYPE)) evt_handler[dev - 1] = handler;
 }
 
-void eos_spi_set_handler(unsigned char dev, eos_evt_fptr_t handler, uint8_t flags) {
-    if (dev && (dev <= EOS_SPI_MAX_DEV)) {
-        dev--;
-    } else {
-        return;
-    }
-    evt_handler[dev] = handler;
+void _eos_spi_xchg_init(unsigned char *buffer, uint16_t len, uint8_t flags) {
+    spi_state_flags &= 0xF0;
+    spi_state_flags |= (SPI_FLAG_XCHG | flags);
+    spi_state_buf = buffer;
+    spi_state_len = len;
+    spi_state_idx_tx = 0;
+    spi_state_idx_rx = 0;
+}
+
+static void spi_xchg_wait(void) {
+    volatile uint8_t done = 0;
 
-    eos_evtq_set_hflags(EOS_EVT_SPI | dev + 1, flags);
+    while (!done) {
+        clear_csr(mstatus, MSTATUS_MIE);
+        done = !(spi_state_flags & SPI_FLAG_XCHG);
+        if (!done) asm volatile ("wfi");
+        set_csr(mstatus, MSTATUS_MIE);
+    }
+    spi_in_xchg = 0;
 }
 
 void eos_spi_xchg(unsigned char *buffer, uint16_t len, uint8_t flags) {
     if (spi_in_xchg) spi_xchg_wait();
-    if (!(flags & EOS_SPI_FLAG_TX) && (spi_state_flags & EOS_SPI_FLAG_TX)) spi_flush();
 
     spi_in_xchg=1;
-    spi_state_flags &= 0xF0;
-    spi_state_flags |= (SPI_FLAG_XCHG | flags);
-    _eos_spi_state_buf = buffer;
-    _eos_spi_state_len = len;
-    _eos_spi_state_idx_tx = 0;
-    _eos_spi_state_idx_rx = 0;
+    _eos_spi_xchg_init(buffer, len, flags);
 
-    if (spi_state_flags & SPI_FLAG_CS) eos_spi_cs_set();
+    eos_spi_cs_set();
     SPI1_REG(SPI_REG_TXCTRL) = SPI_TXWM(SPI_SIZE_WM);
     SPI1_REG(SPI_REG_IE) = SPI_IP_TXWM;
 }
 
-static void spi_xchg_done(void) {
-    SPI1_REG(SPI_REG_IE) = 0x0;
-    if (spi_dev == EOS_SPI_DEV_NET) {
-        eos_net_xchg_done();
-    } else {
-        spi_state_flags &= ~SPI_FLAG_XCHG;
-        if (!(spi_state_flags & (EOS_SPI_FLAG_MORE | SPI_FLAG_CS))) eos_spi_cs_clear();
-        eos_evtq_push_isr(EOS_EVT_SPI | spi_dev, _eos_spi_state_buf, _eos_spi_state_len);
-    }
-}
-
-void eos_spi_xchg_handler(void) {
+void eos_spi_handle_xchg(void) {
     int i;
-    uint16_t sz_chunk = MIN(_eos_spi_state_len - _eos_spi_state_idx_tx, SPI_SIZE_CHUNK);
+    uint16_t sz_chunk = MIN(spi_state_len - spi_state_idx_tx, SPI_SIZE_CHUNK);
 
     for (i=0; i<sz_chunk; i++) {
         volatile uint32_t x = SPI1_REG(SPI_REG_TXFIFO);
         if (x & SPI_TXFIFO_FULL) break;
-        SPI1_REG(SPI_REG_TXFIFO) = _eos_spi_state_buf[_eos_spi_state_idx_tx+i];
+        SPI1_REG(SPI_REG_TXFIFO) = spi_state_buf[spi_state_idx_tx+i];
     }
-    _eos_spi_state_idx_tx += i;
+    spi_state_idx_tx += i;
 
-    for (i=0; i<_eos_spi_state_idx_tx - _eos_spi_state_idx_rx; i++) {
+    for (i=0; i<spi_state_idx_tx - spi_state_idx_rx; i++) {
         volatile uint32_t x = SPI1_REG(SPI_REG_RXFIFO);
         if (x & SPI_RXFIFO_EMPTY) break;
-        _eos_spi_state_buf[_eos_spi_state_idx_rx+i] = x & 0xFF;
+        spi_state_buf[spi_state_idx_rx+i] = x & 0xFF;
     }
-    _eos_spi_state_idx_rx += i;
-
-    if (_eos_spi_state_idx_tx == _eos_spi_state_len) {
-        if ((_eos_spi_state_idx_rx == _eos_spi_state_len) || (spi_state_flags & EOS_SPI_FLAG_TX)) {
-            spi_xchg_done();
+    spi_state_idx_rx += i;
+
+    if (spi_state_idx_tx == spi_state_len) {
+        if ((spi_state_idx_rx == spi_state_len) || (spi_state_flags & EOS_SPI_FLAG_TX)) {
+            spi_state_flags &= ~SPI_FLAG_XCHG;
+            if (!(spi_state_flags & EOS_SPI_FLAG_MORE)) eos_spi_cs_clear();
+            SPI1_REG(SPI_REG_IE) = 0x0;
+            if (spi_dev) eos_evtq_push_isr(EOS_EVT_SPI | spi_dev, spi_state_buf, spi_state_len);
         } else {
-            SPI1_REG(SPI_REG_RXCTRL) = SPI_RXWM(MIN(_eos_spi_state_len - _eos_spi_state_idx_rx - 1, SPI_SIZE_WM - 1));
+            SPI1_REG(SPI_REG_RXCTRL) = SPI_RXWM(MIN(spi_state_len - spi_state_idx_rx - 1, SPI_SIZE_WM - 1));
             SPI1_REG(SPI_REG_IE) = SPI_IP_RXWM;
         }
     }
@@ -193,7 +155,6 @@ void eos_spi_cs_set(void) {
     } else {
         SPI1_REG(SPI_REG_CSMODE) = SPI_CSMODE_HOLD;
     }
-    spi_state_flags &= ~SPI_FLAG_CS;
 }
 
 void eos_spi_cs_clear(void) {
@@ -203,29 +164,22 @@ void eos_spi_cs_clear(void) {
     } else {
         SPI1_REG(SPI_REG_CSMODE) = SPI_CSMODE_AUTO;
     }
-    spi_state_flags |= SPI_FLAG_CS;
 }
 
 uint8_t eos_spi_xchg8(uint8_t data, uint8_t flags) {
     volatile uint32_t x = 0;
     uint8_t rx = !(flags & EOS_SPI_FLAG_TX);
 
-    if (spi_in_xchg) spi_xchg_wait();
-    if (rx && (spi_state_flags & EOS_SPI_FLAG_TX)) spi_flush();
-
     spi_state_flags &= 0xF0;
     spi_state_flags |= flags;
-    if ((flags & EOS_SPI_FLAG_AUTOCS) && (spi_state_flags & SPI_FLAG_CS)) eos_spi_cs_set();
 
-    while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL);
+    while ((x = SPI1_REG(SPI_REG_TXFIFO)) & SPI_TXFIFO_FULL);
     SPI1_REG(SPI_REG_TXFIFO) = data;
 
     if (rx) {
         while ((x = SPI1_REG(SPI_REG_RXFIFO)) & SPI_RXFIFO_EMPTY);
     }
 
-    if ((flags & EOS_SPI_FLAG_AUTOCS) && !(flags & EOS_SPI_FLAG_MORE)) eos_spi_cs_clear();
-
     return x & 0xFF;
 }
 
@@ -234,22 +188,18 @@ uint16_t eos_spi_xchg16(uint16_t data, uint8_t flags) {
     uint8_t rx = !(flags & EOS_SPI_FLAG_TX);
     uint16_t r = 0;
 
-    if (spi_in_xchg) spi_xchg_wait();
-    if (rx && (spi_state_flags & EOS_SPI_FLAG_TX)) spi_flush();
-
     spi_state_flags &= 0xF0;
     spi_state_flags |= flags;
-    if ((flags & EOS_SPI_FLAG_AUTOCS) && (spi_state_flags & SPI_FLAG_CS)) eos_spi_cs_set();
 
     if (flags & EOS_SPI_FLAG_BSWAP) {
-        while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL);
+        while ((x = SPI1_REG(SPI_REG_TXFIFO)) & SPI_TXFIFO_FULL);
         SPI1_REG(SPI_REG_TXFIFO) = (data & 0x00FF);
-        while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL);
+        while ((x = SPI1_REG(SPI_REG_TXFIFO)) & SPI_TXFIFO_FULL);
         SPI1_REG(SPI_REG_TXFIFO) = (data & 0xFF00) >> 8;
     } else {
-        while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL);
+        while ((x = SPI1_REG(SPI_REG_TXFIFO)) & SPI_TXFIFO_FULL);
         SPI1_REG(SPI_REG_TXFIFO) = (data & 0xFF00) >> 8;
-        while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL);
+        while ((x = SPI1_REG(SPI_REG_TXFIFO)) & SPI_TXFIFO_FULL);
         SPI1_REG(SPI_REG_TXFIFO) = (data & 0x00FF);
     }
 
@@ -267,8 +217,6 @@ uint16_t eos_spi_xchg16(uint16_t data, uint8_t flags) {
         }
     }
 
-    if ((flags & EOS_SPI_FLAG_AUTOCS) && !(flags & EOS_SPI_FLAG_MORE)) eos_spi_cs_clear();
-
     return r;
 }
 
@@ -277,26 +225,22 @@ uint32_t eos_spi_xchg24(uint32_t data, uint8_t flags) {
     uint8_t rx = !(flags & EOS_SPI_FLAG_TX);
     uint32_t r = 0;
 
-    if (spi_in_xchg) spi_xchg_wait();
-    if (rx && (spi_state_flags & EOS_SPI_FLAG_TX)) spi_flush();
-
     spi_state_flags &= 0xF0;
     spi_state_flags |= flags;
-    if ((flags & EOS_SPI_FLAG_AUTOCS) && (spi_state_flags & SPI_FLAG_CS)) eos_spi_cs_set();
 
     if (flags & EOS_SPI_FLAG_BSWAP) {
-        while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL);
+        while ((x = SPI1_REG(SPI_REG_TXFIFO)) & SPI_TXFIFO_FULL);
         SPI1_REG(SPI_REG_TXFIFO) = (data & 0x000000FF);
-        while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL);
+        while ((x = SPI1_REG(SPI_REG_TXFIFO)) & SPI_TXFIFO_FULL);
         SPI1_REG(SPI_REG_TXFIFO) = (data & 0x0000FF00) >> 8;
-        while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL);
+        while ((x = SPI1_REG(SPI_REG_TXFIFO)) & SPI_TXFIFO_FULL);
         SPI1_REG(SPI_REG_TXFIFO) = (data & 0x00FF0000) >> 16;
     } else {
-        while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL);
+        while ((x = SPI1_REG(SPI_REG_TXFIFO)) & SPI_TXFIFO_FULL);
         SPI1_REG(SPI_REG_TXFIFO) = (data & 0x00FF0000) >> 16;
-        while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL);
+        while ((x = SPI1_REG(SPI_REG_TXFIFO)) & SPI_TXFIFO_FULL);
         SPI1_REG(SPI_REG_TXFIFO) = (data & 0x0000FF00) >> 8;
-        while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL);
+        while ((x = SPI1_REG(SPI_REG_TXFIFO)) & SPI_TXFIFO_FULL);
         SPI1_REG(SPI_REG_TXFIFO) = (data & 0x000000FF);
     }
 
@@ -318,8 +262,6 @@ uint32_t eos_spi_xchg24(uint32_t data, uint8_t flags) {
         }
     }
 
-    if ((flags & EOS_SPI_FLAG_AUTOCS) && !(flags & EOS_SPI_FLAG_MORE)) eos_spi_cs_clear();
-
     return r;
 }
 
@@ -328,30 +270,26 @@ uint32_t eos_spi_xchg32(uint32_t data, uint8_t flags) {
     uint8_t rx = !(flags & EOS_SPI_FLAG_TX);
     uint32_t r = 0;
 
-    if (spi_in_xchg) spi_xchg_wait();
-    if (rx && (spi_state_flags & EOS_SPI_FLAG_TX)) spi_flush();
-
     spi_state_flags &= 0xF0;
     spi_state_flags |= flags;
-    if ((flags & EOS_SPI_FLAG_AUTOCS) && (spi_state_flags & SPI_FLAG_CS)) eos_spi_cs_set();
 
     if (flags & EOS_SPI_FLAG_BSWAP) {
-        while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL);
+        while ((x = SPI1_REG(SPI_REG_TXFIFO)) & SPI_TXFIFO_FULL);
         SPI1_REG(SPI_REG_TXFIFO) = (data & 0x000000FF);
-        while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL);
+        while ((x = SPI1_REG(SPI_REG_TXFIFO)) & SPI_TXFIFO_FULL);
         SPI1_REG(SPI_REG_TXFIFO) = (data & 0x0000FF00) >> 8;
-        while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL);
+        while ((x = SPI1_REG(SPI_REG_TXFIFO)) & SPI_TXFIFO_FULL);
         SPI1_REG(SPI_REG_TXFIFO) = (data & 0x00FF0000) >> 16;
-        while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL);
+        while ((x = SPI1_REG(SPI_REG_TXFIFO)) & SPI_TXFIFO_FULL);
         SPI1_REG(SPI_REG_TXFIFO) = (data & 0xFF000000) >> 24;
     } else {
-        while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL);
+        while ((x = SPI1_REG(SPI_REG_TXFIFO)) & SPI_TXFIFO_FULL);
         SPI1_REG(SPI_REG_TXFIFO) = (data & 0xFF000000) >> 24;
-        while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL);
+        while ((x = SPI1_REG(SPI_REG_TXFIFO)) & SPI_TXFIFO_FULL);
         SPI1_REG(SPI_REG_TXFIFO) = (data & 0x00FF0000) >> 16;
-        while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL);
+        while ((x = SPI1_REG(SPI_REG_TXFIFO)) & SPI_TXFIFO_FULL);
         SPI1_REG(SPI_REG_TXFIFO) = (data & 0x0000FF00) >> 8;
-        while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL);
+        while ((x = SPI1_REG(SPI_REG_TXFIFO)) & SPI_TXFIFO_FULL);
         SPI1_REG(SPI_REG_TXFIFO) = (data & 0x000000FF);
     }
 
@@ -377,7 +315,16 @@ uint32_t eos_spi_xchg32(uint32_t data, uint8_t flags) {
         }
     }
 
-    if ((flags & EOS_SPI_FLAG_AUTOCS) && !(flags & EOS_SPI_FLAG_MORE)) eos_spi_cs_clear();
-
     return r;
 }
+
+void eos_spi_flush(void) {
+    volatile uint32_t x = 0;
+
+    if (spi_in_xchg) spi_xchg_wait();
+
+    SPI1_REG(SPI_REG_TXCTRL) = SPI_TXWM(1);
+    while (!x) {
+        if (SPI1_REG(SPI_REG_IP) & SPI_IP_TXWM) x = SPI1_REG(SPI_REG_RXFIFO) & SPI_RXFIFO_EMPTY;
+    }
+}
diff --git a/code/fe310/eos/spi.h b/code/fe310/eos/spi.h
index 1619b18..b291ad3 100644
--- a/code/fe310/eos/spi.h
+++ b/code/fe310/eos/spi.h
@@ -1,25 +1,21 @@
 #include <stdint.h>
 #include "event.h"
+#include "spi_dev.h"
 
-#define EOS_SPI_DEV_NET     0
-#define EOS_SPI_DEV_DISP    1
-#define EOS_SPI_DEV_CARD    2
-#define EOS_SPI_DEV_CAM     3
-
-#define EOS_SPI_MAX_DEV     3
+#define EOS_SPI_MAX_DEV     EOS_DEV_MAX_DEV
 
 #define EOS_SPI_FLAG_TX     0x01
 #define EOS_SPI_FLAG_MORE   0x02
-#define EOS_SPI_FLAG_AUTOCS 0x04
-#define EOS_SPI_FLAG_BSWAP  0x08
+#define EOS_SPI_FLAG_BSWAP  0x04
 
 void eos_spi_init(void);
-void eos_spi_dev_start(unsigned char dev);
-void eos_spi_dev_stop(void);
-void eos_spi_set_handler(unsigned char dev, eos_evt_fptr_t handler, uint8_t flags);
+void eos_spi_start(unsigned char dev, uint32_t div, uint32_t csid, uint8_t pin);
+void eos_spi_stop(void);
+void eos_spi_set_handler(unsigned char dev, eos_evt_handler_t handler);
 
+void _eos_spi_xchg_init(unsigned char *buffer, uint16_t len, uint8_t flags);
 void eos_spi_xchg(unsigned char *buffer, uint16_t len, uint8_t flags);
-void eos_spi_xchg_handler(void);
+void eos_spi_handle_xchg(void);
 
 void eos_spi_cs_set(void);
 void eos_spi_cs_clear(void);
@@ -27,3 +23,4 @@ uint8_t eos_spi_xchg8(uint8_t data, uint8_t flags);
 uint16_t eos_spi_xchg16(uint16_t data, uint8_t flags);
 uint32_t eos_spi_xchg24(uint32_t data, uint8_t flags);
 uint32_t eos_spi_xchg32(uint32_t data, uint8_t flags);
+void eos_spi_flush(void);
diff --git a/code/fe310/eos/spi_def.h b/code/fe310/eos/spi_def.h
index 7c7f817..06f7251 100644
--- a/code/fe310/eos/spi_def.h
+++ b/code/fe310/eos/spi_def.h
@@ -8,17 +8,5 @@
 #define SPI_SIZE_WM             2
 
 #define SPI_FLAG_XCHG           0x10
-#define SPI_FLAG_CS             0x20
 
-#define SPI_DIV_NET             16
-#define SPI_DIV_DISP            16
-#define SPI_DIV_CARD            16
-#define SPI_DIV_CAM             16
-
-
-#define SPI_CS_IDX_NET          3
-#define SPI_CS_IDX_DISP         2
-#define SPI_CS_IDX_CARD         0
-#define SPI_CS_IDX_NONE         1
-
-#define SPI_CS_PIN_CAM          23
+#define SPI_CSID_NONE           1
\ No newline at end of file
diff --git a/code/fe310/eos/spi_dev.c b/code/fe310/eos/spi_dev.c
new file mode 100644
index 0000000..dd956f3
--- /dev/null
+++ b/code/fe310/eos/spi_dev.c
@@ -0,0 +1,50 @@
+#include <stdlib.h>
+#include <stdint.h>
+
+#include "encoding.h"
+#include "platform.h"
+
+#include "spi.h"
+#include "net.h"
+
+#include "spi_def.h"
+#include "spi_dev.h"
+
+
+#define SPI_DIV_DISP        16
+#define SPI_DIV_CARD        16
+#define SPI_DIV_CAM         16
+
+#define SPI_CSID_DISP       2
+#define SPI_CSID_CARD       0
+
+#define SPI_CSPIN_CAM       23
+
+void eos_spi_dev_start(unsigned char dev) {
+    eos_net_stop();
+    switch (dev) {
+        case EOS_DEV_DISP:
+            eos_spi_start(dev, SPI_DIV_DISP, SPI_CSID_DISP, 0);
+            break;
+        case EOS_DEV_CARD:
+            eos_spi_start(dev, SPI_DIV_CARD, SPI_CSID_CARD, 0);
+            break;
+        case EOS_DEV_CAM:
+            eos_spi_start(dev, SPI_DIV_CAM, SPI_CSID_NONE, SPI_CSPIN_CAM);
+            break;
+    }
+}
+
+void eos_spi_dev_stop(void) {
+    eos_spi_stop();
+    eos_net_start();
+}
+
+void eos_spi_dev_init(void) {
+    GPIO_REG(GPIO_INPUT_EN)     &= ~(1 << SPI_CSPIN_CAM);
+    GPIO_REG(GPIO_OUTPUT_EN)    |=  (1 << SPI_CSPIN_CAM);
+    GPIO_REG(GPIO_PULLUP_EN)    &= ~(1 << SPI_CSPIN_CAM);
+    GPIO_REG(GPIO_OUTPUT_XOR)   &= ~(1 << SPI_CSPIN_CAM);
+    GPIO_REG(GPIO_OUTPUT_VAL)   |=  (1 << SPI_CSPIN_CAM);
+}
+
diff --git a/code/fe310/eos/spi_dev.h b/code/fe310/eos/spi_dev.h
new file mode 100644
index 0000000..256c48c
--- /dev/null
+++ b/code/fe310/eos/spi_dev.h
@@ -0,0 +1,9 @@
+#define EOS_DEV_DISP        1
+#define EOS_DEV_CARD        2
+#define EOS_DEV_CAM         3
+
+#define EOS_DEV_MAX_DEV     3
+
+void eos_spi_dev_init(void);
+void eos_spi_dev_start(unsigned char dev);
+void eos_spi_dev_stop(void);
diff --git a/code/fe310/eos/timer.c b/code/fe310/eos/timer.c
index c629866..4eb80b4 100644
--- a/code/fe310/eos/timer.c
+++ b/code/fe310/eos/timer.c
@@ -11,13 +11,13 @@
 #define MIN(X, Y)               (((X) < (Y)) ? (X) : (Y))
 #define MAX(X, Y)               (((X) > (Y)) ? (X) : (Y))
 
-static eos_timer_fptr_t timer_handler[EOS_TIMER_MAX_ETYPE + 1];
+static eos_timer_handler_t timer_handler[EOS_TIMER_MAX_ETYPE + 1];
 static uint64_t timer_next[EOS_TIMER_MAX_ETYPE + 1];
 
-static void timer_handler_evt(unsigned char type, unsigned char *buffer, uint16_t len) {
-    unsigned char idx = (type & ~EOS_EVT_MASK) - 1;
+static void timer_handle_evt(unsigned char type, unsigned char *buffer, uint16_t len) {
+    unsigned char idx = (type & ~EOS_EVT_MASK);
 
-    if ((idx < EOS_TIMER_MAX_ETYPE) && timer_handler[idx]) {
+    if (idx && (idx <= EOS_TIMER_MAX_ETYPE) && timer_handler[idx]) {
         timer_handler[idx](type);
     } else {
         eos_evtq_bad_handler(type, buffer, len);
@@ -34,10 +34,10 @@ void _eos_timer_handle(void) {
     for (i = 0; i <= EOS_TIMER_MAX_ETYPE; i++) {
         if (timer_next[i] && (timer_next[i] <= now)) {
             timer_next[i] = 0;
-            if (i == EOS_TIMER_MAX_ETYPE) {
-                timer_handler[EOS_TIMER_MAX_ETYPE](0);
+            if (i == 0) {
+                timer_handler[0](0);
             } else {
-                eos_evtq_push_isr(EOS_EVT_TIMER | i + 1, NULL, 0);
+                eos_evtq_push_isr(EOS_EVT_TIMER | i, NULL, 0);
             }
         }
         next = next && timer_next[i] ? MIN(next, timer_next[i]) : (next ? next : timer_next[i]);
@@ -56,43 +56,21 @@ void eos_timer_init(void) {
         timer_next[i] = 0;
         timer_handler[i] = NULL;
     }
-    eos_evtq_set_handler(EOS_EVT_TIMER, timer_handler_evt, 0);
+    eos_evtq_set_handler(EOS_EVT_TIMER, timer_handle_evt);
 }
 
-void eos_timer_set_handler(unsigned char evt, eos_timer_fptr_t handler, uint8_t flags) {
+void eos_timer_set_handler(unsigned char evt, eos_timer_handler_t handler) {
     uint64_t *mtimecmp = (uint64_t *) (CLINT_CTRL_ADDR + CLINT_MTIMECMP);
 
-    if (evt && (evt <= EOS_TIMER_MAX_ETYPE)) {
-        evt--;
-    } else if (evt == 0) {
-        evt = EOS_TIMER_MAX_ETYPE;
-    } else {
-        return;
-    }
-
     clear_csr(mie, MIP_MTIP);
     timer_handler[evt] = handler;
     if (*mtimecmp != 0) set_csr(mie, MIP_MTIP);
-
-    if (evt != EOS_TIMER_MAX_ETYPE) eos_evtq_set_hflags(EOS_EVT_TIMER | evt + 1, flags);
-}
-
-void eos_timer_set_hflags(unsigned char evt, uint8_t flags) {
-    if (evt && (evt < EOS_TIMER_MAX_ETYPE)) eos_evtq_set_hflags(EOS_EVT_TIMER | evt, flags);
 }
 
 uint64_t eos_timer_get(unsigned char evt) {
     uint64_t *mtimecmp = (uint64_t *) (CLINT_CTRL_ADDR + CLINT_MTIMECMP);
     uint64_t ret = 0;
 
-    if (evt && (evt <= EOS_TIMER_MAX_ETYPE)) {
-        evt--;
-    } else if (evt == 0) {
-        evt = EOS_TIMER_MAX_ETYPE;
-    } else {
-        return 0;
-    }
-
     clear_csr(mie, MIP_MTIP);
     ret = timer_next[evt];
     if (*mtimecmp != 0) set_csr(mie, MIP_MTIP);
@@ -107,14 +85,6 @@ void eos_timer_set(uint32_t msec, unsigned char evt, unsigned char b) {
     uint64_t tick = *mtime + msec * (uint64_t)RTC_FREQ / 1000;
     uint64_t next = 0;
 
-    if (evt && (evt <= EOS_TIMER_MAX_ETYPE)) {
-        evt--;
-    } else if (evt == 0) {
-        evt = EOS_TIMER_MAX_ETYPE;
-    } else {
-        return;
-    }
-
     clear_csr(mie, MIP_MTIP);
     if (!b || (timer_next[evt] == 0) || (tick < timer_next[evt])) {
         timer_next[evt] = tick;
@@ -131,14 +101,6 @@ void eos_timer_clear(unsigned char evt) {
     uint64_t *mtimecmp = (uint64_t *) (CLINT_CTRL_ADDR + CLINT_MTIMECMP);
     uint64_t next = 0;
 
-    if (evt && (evt <= EOS_TIMER_MAX_ETYPE)) {
-        evt--;
-    } else if (evt == 0) {
-        evt = EOS_TIMER_MAX_ETYPE;
-    } else {
-        return;
-    }
-
     clear_csr(mie, MIP_MTIP);
     if (timer_next[evt]) {
         timer_next[evt] = 0;
diff --git a/code/fe310/eos/timer.h b/code/fe310/eos/timer.h
index 52efc30..edf422d 100644
--- a/code/fe310/eos/timer.h
+++ b/code/fe310/eos/timer.h
@@ -6,11 +6,10 @@
 
 #define EOS_TIMER_MAX_ETYPE     4
 
-typedef void (*eos_timer_fptr_t) (unsigned char);
+typedef void (*eos_timer_handler_t) (unsigned char);
 
 void eos_timer_init(void);
-void eos_timer_set_handler(unsigned char evt, eos_timer_fptr_t handler, uint8_t flags);
-void eos_timer_set_hflags(unsigned char evt, uint8_t flags);
+void eos_timer_set_handler(unsigned char evt, eos_timer_handler_t handler);
 
 uint64_t eos_timer_get(unsigned char evt);
 void eos_timer_set(uint32_t msec, unsigned char evt, unsigned char b);
diff --git a/code/fe310/eos/trap_entry.S b/code/fe310/eos/trap_entry.S
index a55d6c1..4172570 100644
--- a/code/fe310/eos/trap_entry.S
+++ b/code/fe310/eos/trap_entry.S
@@ -63,14 +63,14 @@ eos_trap_entry:
 
   csrr x8, mcause
   li x18, MCAUSE_EXT
-  bne x8, x18, handler
+  bne x8, x18, handle_intr
   li x18, PLIC_CLAIM
   lw x9, 0(x18)
   li x18, I2S_IRQ_WS_ID
-  beq x9, x18, i2s_handler_ws
+  beq x9, x18, i2s_handle_ws
   li x18, I2S_IRQ_SD_ID
-  beq x9, x18, i2s_handler_sd
-  j handler
+  beq x9, x18, i2s_handle_sd
+  j handle_intr
 
 evtq_push:
   la x9, _eos_event_q
@@ -97,12 +97,12 @@ evtq_push:
   mv x20, x0
   jalr x0, x21
 
-i2s_handler_sd:
+i2s_handle_sd:
   # exit if too early
   li x18, I2S_PWM_CTRL_ADDR_WS_SPK
   lw x8, PWM_COUNT(x18)
   lw x9, PWM_CMP3(x18)
-  bltu x8, x9, i2s_handler_sd_exit
+  bltu x8, x9, i2s_handle_sd_exit
 
   # disable sd irq
   li x18, PLIC_PRIORITY
@@ -119,7 +119,7 @@ i2s_abuf_pop:
   lhu x19, I2S_ABUF_OFF_IDXW(x9)
   lhu x20, I2S_ABUF_OFF_SIZE(x9)
 
-  beq x18, x19, i2s_handler_sd_xchg
+  beq x18, x19, i2s_handle_sd_xchg
 
   addi x20, x20, -1
   and x20, x20, x18
@@ -160,7 +160,7 @@ i2s_abuf_pop:
   sb x18, MSGQ_ITEM_OFF_TYPE(x21)
 
 i2s_decode:
-  bnez x23, i2s_handler_sd_xchg
+  bnez x23, i2s_handle_sd_xchg
   # aLaw decode -> x8
   xori x8, x8, 0x55
   andi x9, x8, 0x80
@@ -195,10 +195,10 @@ i2s_decode:
   slli x8, x8, 1
   ori x8, x8, 1
 2:
-  beqz x9, i2s_handler_sd_xchg
+  beqz x9, i2s_handle_sd_xchg
   mul x8, x8, x9
 
-i2s_handler_sd_xchg:
+i2s_handle_sd_xchg:
   # read/write shift reg: x8 -> sr -> x8
   li x18, GPIO_CTRL_ADDR
   li x19, (0x1 << I2S_PIN_SD_IN)
@@ -315,7 +315,7 @@ i2s_abuf_push:
 
   sub x18, x19, x18
   and x18, x18, x21
-  beq x18, x20, i2s_handler_sd_exit
+  beq x18, x20, i2s_handle_sd_exit
 
   addi x20, x20, -1
   and x20, x20, x19
@@ -338,21 +338,21 @@ i2s_abuf_push:
   # check for push to event queue
   la x9, _eos_i2s_mic_wm
   lw x20, 0(x9)
-  beqz x20, i2s_handler_sd_exit
-  bltu x18, x20, i2s_handler_sd_exit
+  beqz x20, i2s_handle_sd_exit
+  bltu x18, x20, i2s_handle_sd_exit
 
   la x9, _eos_i2s_mic_evt_enable
   lw x18, 0(x9)
-  beqz x18, i2s_handler_sd_exit
+  beqz x18, i2s_handle_sd_exit
   sw x0, 0(x9)
 
   # push to event queue
   jal x22, evtq_push
-  beqz x21, i2s_handler_sd_exit
+  beqz x21, i2s_handle_sd_exit
   li x18, (EOS_EVT_AUDIO | I2S_ETYPE_MIC)
   sb x18, MSGQ_ITEM_OFF_TYPE(x21)
 
-i2s_handler_sd_exit:
+i2s_handle_sd_exit:
   # complete
   li x18, I2S_IRQ_SD_ID
   li x19, PLIC_CLAIM
@@ -361,7 +361,7 @@ i2s_handler_sd_exit:
   # exit
   j trap_exit_data
 
-i2s_handler_ws:
+i2s_handle_ws:
   # enable sd irq
   li x18, PLIC_PRIORITY
   li x19, IRQ_PRIORITY_I2S_SD
@@ -436,7 +436,7 @@ trap_exit_data:
 
   mret
 
-handler:
+handle_intr:
   lui x18,       %hi(trap_entry_text)
   addi x18, x18, %lo(trap_entry_text)
   jalr x0, x18
diff --git a/code/fe310/eos/uart.c b/code/fe310/eos/uart.c
index 95c9057..e9349a7 100644
--- a/code/fe310/eos/uart.c
+++ b/code/fe310/eos/uart.c
@@ -12,9 +12,9 @@
 #include "uart.h"
 #include "irq_def.h"
 
-static eos_uart_fptr_t uart_handler[EOS_UART_MAX_ETYPE];
+static eos_uart_handler_t uart_handler[EOS_UART_MAX_ETYPE];
 
-static void uart_handler_evt(unsigned char type, unsigned char *buffer, uint16_t len) {
+static void uart_handle_evt(unsigned char type, unsigned char *buffer, uint16_t len) {
     unsigned char idx = (type & ~EOS_EVT_MASK) - 1;
 
     if ((idx < EOS_UART_MAX_ETYPE) && uart_handler[idx]) {
@@ -24,7 +24,7 @@ static void uart_handler_evt(unsigned char type, unsigned char *buffer, uint16_t
     }
 }
 
-static void uart_handler_intr(void) {
+static void uart_handle_intr(void) {
     if (UART0_REG(UART_REG_IP) & UART_IP_TXWM) {
         UART0_REG(UART_REG_IE) &= ~UART_IP_TXWM;
         eos_evtq_push_isr(EOS_EVT_UART | EOS_UART_ETYPE_TX, NULL, 0);
@@ -41,19 +41,12 @@ void eos_uart_init(void) {
     for (i=0; i<EOS_UART_MAX_ETYPE; i++) {
         uart_handler[i] = NULL;
     }
-    eos_evtq_set_handler(EOS_EVT_UART, uart_handler_evt, 0);
-    eos_intr_set(INT_UART0_BASE, IRQ_PRIORITY_UART, uart_handler_intr);
+    eos_evtq_set_handler(EOS_EVT_UART, uart_handle_evt);
+    eos_intr_set(INT_UART0_BASE, IRQ_PRIORITY_UART, uart_handle_intr);
 }
 
-void eos_uart_set_handler(unsigned char type, eos_uart_fptr_t handler, uint8_t flags) {
-    if (type && (type <= EOS_UART_MAX_ETYPE)) {
-        type--;
-    } else {
-        return;
-    }
-    uart_handler[type] = handler;
-
-    eos_evtq_set_hflags(EOS_EVT_UART | type + 1, flags);
+void eos_uart_set_handler(unsigned char type, eos_uart_handler_t handler) {
+    if (type && (type <= EOS_UART_MAX_ETYPE)) uart_handler[type - 1] = handler;
 }
 
 void eos_uart_txwm_set(uint8_t wm) {
diff --git a/code/fe310/eos/uart.h b/code/fe310/eos/uart.h
index e6ce990..da5faab 100644
--- a/code/fe310/eos/uart.h
+++ b/code/fe310/eos/uart.h
@@ -5,10 +5,10 @@
 
 #define EOS_UART_MAX_ETYPE      2
 
-typedef void (*eos_uart_fptr_t) (unsigned char);
+typedef void (*eos_uart_handler_t) (unsigned char);
 
 void eos_uart_init(void);
-void eos_uart_set_handler(unsigned char type, eos_uart_fptr_t handler, uint8_t flags);
+void eos_uart_set_handler(unsigned char type, eos_uart_handler_t handler);
 
 void eos_uart_txwm_set(uint8_t wm);
 void eos_uart_txwm_clear(void);
diff --git a/code/fe310/eos/wifi.c b/code/fe310/eos/wifi.c
index 688e675..c6b1d73 100644
--- a/code/fe310/eos/wifi.c
+++ b/code/fe310/eos/wifi.c
@@ -8,25 +8,25 @@
 
 #include "wifi.h"
 
-static eos_evt_fptr_t evt_handler[EOS_WIFI_MAX_MTYPE];
+static eos_evt_handler_t evt_handler[EOS_WIFI_MAX_MTYPE];
 static uint16_t evt_handler_flags_buf_free = 0;
 static uint16_t evt_handler_flags_buf_acq = 0;
 
-static void wifi_handler_evt(unsigned char type, unsigned char *buffer, uint16_t len) {
+static void wifi_handle_evt(unsigned char type, unsigned char *buffer, uint16_t len) {
     if ((buffer == NULL) || (len < 1)) {
         eos_evtq_bad_handler(type, buffer, len);
         eos_net_free(buffer, 0);
         return;
     }
 
-    uint8_t mtype = buffer[0];
-    if (mtype >= EOS_WIFI_MAX_MTYPE) {
+    unsigned char mtype = buffer[0];
+    if (mtype < EOS_WIFI_MAX_MTYPE) {
+        evt_handler[mtype](type, buffer, len);
+    } else {
         eos_evtq_bad_handler(type, buffer, len);
         eos_net_free(buffer, 0);
         return;
     }
-
-    _eos_net_handle(type, buffer, len, mtype, evt_handler, &evt_handler_flags_buf_free, &evt_handler_flags_buf_acq);
 }
 
 void eos_wifi_init(void) {
@@ -35,14 +35,12 @@ void eos_wifi_init(void) {
     for (i=0; i<EOS_WIFI_MAX_MTYPE; i++) {
         evt_handler[i] = eos_evtq_bad_handler;
     }
-    eos_net_set_handler(EOS_NET_MTYPE_WIFI, wifi_handler_evt, 0);
+    eos_net_set_handler(EOS_NET_MTYPE_WIFI, wifi_handle_evt);
 }
 
-void eos_wifi_set_handler(int mtype, eos_evt_fptr_t handler, uint8_t flags) {
-    if (mtype >= EOS_WIFI_MAX_MTYPE) {
-        return;
-    }
-    _eos_net_set_handler(mtype, handler, evt_handler, flags, &evt_handler_flags_buf_free, &evt_handler_flags_buf_acq);
+void eos_wifi_set_handler(unsigned char mtype, eos_evt_handler_t handler) {
+    if (handler == NULL) handler = eos_evtq_bad_handler;
+    if (mtype < EOS_WIFI_MAX_MTYPE) evt_handler[mtype] = handler;
 }
 
 void eos_wifi_connect(const char *ssid, const char *pass) {
diff --git a/code/fe310/eos/wifi.h b/code/fe310/eos/wifi.h
index 3587d1d..732a7a9 100644
--- a/code/fe310/eos/wifi.h
+++ b/code/fe310/eos/wifi.h
@@ -8,7 +8,7 @@
 #define EOS_WIFI_MAX_MTYPE          3
 
 void eos_wifi_init(void);
-void eos_wifi_set_handler(int mtype, eos_evt_fptr_t handler, uint8_t flags);
+void eos_wifi_set_handler(unsigned char mtype, eos_evt_handler_t handler);
 
 void eos_wifi_connect(const char *ssid, const char *pass);
 void eos_wifi_disconnect(void);
-- 
cgit v1.2.3