summaryrefslogtreecommitdiff
path: root/fw/fe310/eos/eve
diff options
context:
space:
mode:
Diffstat (limited to 'fw/fe310/eos/eve')
-rw-r--r--fw/fe310/eos/eve/Makefile17
-rw-r--r--fw/fe310/eos/eve/clipb.c19
-rw-r--r--fw/fe310/eos/eve/clipb.h6
-rw-r--r--fw/fe310/eos/eve/eve.c476
-rw-r--r--fw/fe310/eos/eve/eve.h70
-rwxr-xr-xfw/fe310/eos/eve/eve_config.h39
-rwxr-xr-xfw/fe310/eos/eve/eve_def.h872
-rw-r--r--fw/fe310/eos/eve/eve_font.c59
-rw-r--r--fw/fe310/eos/eve/eve_font.h16
-rw-r--r--fw/fe310/eos/eve/eve_kbd.c162
-rw-r--r--fw/fe310/eos/eve/eve_kbd.h23
-rw-r--r--fw/fe310/eos/eve/eve_phy.c77
-rw-r--r--fw/fe310/eos/eve/eve_phy.h28
-rw-r--r--fw/fe310/eos/eve/eve_platform.c80
-rw-r--r--fw/fe310/eos/eve/eve_platform.h39
-rw-r--r--fw/fe310/eos/eve/eve_text.c209
-rw-r--r--fw/fe310/eos/eve/eve_text.h32
-rw-r--r--fw/fe310/eos/eve/eve_touch.c419
-rw-r--r--fw/fe310/eos/eve/eve_touch.h121
-rw-r--r--fw/fe310/eos/eve/eve_vtrack.c65
-rw-r--r--fw/fe310/eos/eve/eve_vtrack.h28
-rw-r--r--fw/fe310/eos/eve/screen/Makefile17
-rw-r--r--fw/fe310/eos/eve/screen/form.c165
-rw-r--r--fw/fe310/eos/eve/screen/form.h23
-rw-r--r--fw/fe310/eos/eve/screen/page.c349
-rw-r--r--fw/fe310/eos/eve/screen/page.h56
-rw-r--r--fw/fe310/eos/eve/screen/uievt.h14
-rw-r--r--fw/fe310/eos/eve/screen/view.c94
-rw-r--r--fw/fe310/eos/eve/screen/view.h42
-rw-r--r--fw/fe310/eos/eve/screen/window.c300
-rw-r--r--fw/fe310/eos/eve/screen/window.h60
-rw-r--r--fw/fe310/eos/eve/widget/Makefile17
-rw-r--r--fw/fe310/eos/eve/widget/freew.c54
-rw-r--r--fw/fe310/eos/eve/widget/freew.h25
-rw-r--r--fw/fe310/eos/eve/widget/label.c23
-rw-r--r--fw/fe310/eos/eve/widget/label.h10
-rw-r--r--fw/fe310/eos/eve/widget/pagew.c59
-rw-r--r--fw/fe310/eos/eve/widget/pagew.h20
-rw-r--r--fw/fe310/eos/eve/widget/selectw.c248
-rw-r--r--fw/fe310/eos/eve/widget/selectw.h30
-rw-r--r--fw/fe310/eos/eve/widget/spacerw.c36
-rw-r--r--fw/fe310/eos/eve/widget/spacerw.h14
-rw-r--r--fw/fe310/eos/eve/widget/strw.c446
-rw-r--r--fw/fe310/eos/eve/widget/strw.h43
-rw-r--r--fw/fe310/eos/eve/widget/textw.c545
-rw-r--r--fw/fe310/eos/eve/widget/textw.h46
-rw-r--r--fw/fe310/eos/eve/widget/widget.c77
-rw-r--r--fw/fe310/eos/eve/widget/widget.h31
-rw-r--r--fw/fe310/eos/eve/widget/widgets.h39
49 files changed, 5740 insertions, 0 deletions
diff --git a/fw/fe310/eos/eve/Makefile b/fw/fe310/eos/eve/Makefile
new file mode 100644
index 0000000..e55ef7a
--- /dev/null
+++ b/fw/fe310/eos/eve/Makefile
@@ -0,0 +1,17 @@
+include ../../common.mk
+
+CFLAGS += -I.. -I../../bsp/include
+
+obj = eve.o eve_platform.o eve_touch.o eve_phy.o eve_vtrack.o eve_font.o eve_kbd.o eve_text.o clipb.o
+
+
+%.o: %.c %.h
+ $(CC) $(CFLAGS) -c $<
+
+%.o: %.S
+ $(CC) $(CFLAGS) -c $<
+
+all: $(obj)
+
+clean:
+ rm -f *.o
diff --git a/fw/fe310/eos/eve/clipb.c b/fw/fe310/eos/eve/clipb.c
new file mode 100644
index 0000000..974b631
--- /dev/null
+++ b/fw/fe310/eos/eve/clipb.c
@@ -0,0 +1,19 @@
+#include <string.h>
+
+#include "eve.h"
+#include "clipb.h"
+
+static uint8_t clipb[EVE_CLIPB_SIZE_BUF];
+
+int eve_clipb_push(uint8_t *str, uint16_t len) {
+ if (len >= EVE_CLIPB_SIZE_BUF) return EVE_ERR;
+
+ memcpy(clipb, str, len);
+ clipb[len] = '\0';
+
+ return EVE_OK;
+}
+
+uint8_t *eve_clipb_get(void) {
+ return clipb;
+} \ No newline at end of file
diff --git a/fw/fe310/eos/eve/clipb.h b/fw/fe310/eos/eve/clipb.h
new file mode 100644
index 0000000..2d6fae6
--- /dev/null
+++ b/fw/fe310/eos/eve/clipb.h
@@ -0,0 +1,6 @@
+#include <stdint.h>
+
+#define EVE_CLIPB_SIZE_BUF 256
+
+int eve_clipb_push(uint8_t *str, uint16_t len);
+uint8_t *eve_clipb_get(void); \ No newline at end of file
diff --git a/fw/fe310/eos/eve/eve.c b/fw/fe310/eos/eve/eve.c
new file mode 100644
index 0000000..d625fec
--- /dev/null
+++ b/fw/fe310/eos/eve/eve.c
@@ -0,0 +1,476 @@
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include "eve.h"
+
+#define EVE_MEM_WRITE 0x800000
+#define EVE_SPI_FLAGS(b) ( (b) ? (EVE_SPI_FLAG_TX | EVE_SPI_FLAG_BSWAP) : EVE_SPI_FLAG_BSWAP )
+
+static char cmd_burst;
+static uint16_t cmd_offset;
+
+static char dl_burst;
+static uint32_t dl_addr;
+
+static uint8_t brigtness;
+static uint8_t power_state;
+
+void eve_command(uint8_t command, uint8_t parameter) {
+ eve_spi_cs_set();
+ eve_spi_xchg24(((uint32_t)command << 16) | ((uint32_t)parameter << 8), 0);
+ eve_spi_cs_clear();
+}
+
+uint8_t eve_read8(uint32_t addr) {
+ uint8_t r;
+ eve_spi_cs_set();
+ eve_spi_xchg32(addr << 8, 0);
+ r = eve_spi_xchg8(0, EVE_SPI_FLAG_BSWAP);
+ eve_spi_cs_clear();
+
+ return r;
+}
+
+uint16_t eve_read16(uint32_t addr) {
+ uint16_t r;
+ eve_spi_cs_set();
+ eve_spi_xchg32(addr << 8, 0);
+ r = eve_spi_xchg16(0, EVE_SPI_FLAG_BSWAP);
+ eve_spi_cs_clear();
+
+ return r;
+}
+
+uint32_t eve_read32(uint32_t addr) {
+ uint32_t r;
+ eve_spi_cs_set();
+ eve_spi_xchg32(addr << 8, 0);
+ r = eve_spi_xchg32(0, EVE_SPI_FLAG_BSWAP);
+ eve_spi_cs_clear();
+
+ return r;
+}
+
+void eve_write8(uint32_t addr, uint8_t data) {
+ eve_spi_cs_set();
+ eve_spi_xchg24(addr | EVE_MEM_WRITE, 0);
+ eve_spi_xchg8(data, EVE_SPI_FLAG_BSWAP);
+ eve_spi_cs_clear();
+}
+
+void eve_write16(uint32_t addr, uint16_t data) {
+ eve_spi_cs_set();
+ eve_spi_xchg24(addr | EVE_MEM_WRITE, 0);
+ eve_spi_xchg16(data, EVE_SPI_FLAG_BSWAP);
+ eve_spi_cs_clear();
+}
+
+void eve_write32(uint32_t addr, uint32_t data) {
+ eve_spi_cs_set();
+ eve_spi_xchg24(addr | EVE_MEM_WRITE, 0);
+ eve_spi_xchg32(data, EVE_SPI_FLAG_BSWAP);
+ eve_spi_cs_clear();
+}
+
+void eve_readb(uint32_t addr, uint8_t *buf, size_t size) {
+ int i;
+
+ eve_spi_cs_set();
+ eve_spi_xchg32(addr << 8, 0);
+ for (i=0; i<size; i++) {
+ buf[i] = eve_spi_xchg8(0, 0);
+ }
+ eve_spi_cs_clear();
+}
+
+void eve_writeb(uint32_t addr, uint8_t *buf, size_t size) {
+ int i;
+
+ eve_spi_cs_set();
+ eve_spi_xchg24(addr | EVE_MEM_WRITE, 0);
+ for (i=0; i<size; i++) {
+ eve_spi_xchg8(buf[i], 0);
+ }
+ eve_spi_cs_clear();
+}
+
+static void dl_inc(uint32_t i) {
+ dl_addr += i;
+}
+
+void eve_dl_start(uint32_t addr, char burst) {
+ dl_addr = addr;
+ dl_burst = burst;
+ if (burst) {
+ eve_spi_lock();
+ eve_spi_cs_set();
+ eve_spi_xchg24(addr | EVE_MEM_WRITE, EVE_SPI_FLAG_TX);
+ }
+}
+
+void eve_dl_write(uint32_t dl) {
+ if (dl_burst) {
+ eve_spi_xchg32(dl, EVE_SPI_FLAGS(dl_burst));
+ } else {
+ eve_write32(dl_addr, dl);
+ }
+ dl_inc(4);
+}
+
+void eve_dl_end(void) {
+ if (dl_burst) {
+ eve_spi_flush();
+ eve_spi_cs_clear();
+ eve_spi_unlock();
+ dl_burst = 0;
+ }
+}
+
+void eve_dl_swap(void) {
+ eve_write8(REG_DLSWAP, EVE_DLSWAP_FRAME);
+}
+
+uint32_t eve_dl_get_addr(void) {
+ return dl_addr;
+}
+
+static void cmd_inc(uint16_t i) {
+ cmd_offset += i;
+ cmd_offset &= 0x0fff;
+}
+
+static void cmd_begin(uint32_t command, uint8_t flags) {
+ if (!cmd_burst) {
+ uint32_t addr = EVE_RAM_CMD + cmd_offset;
+ eve_spi_cs_set();
+ eve_spi_xchg24(addr | EVE_MEM_WRITE, 0);
+ }
+ eve_spi_xchg32(command, flags);
+ cmd_inc(4);
+}
+
+static void cmd_end(void) {
+ if (!cmd_burst) eve_spi_cs_clear();
+}
+
+static void cmd_string(const char *str, uint8_t flags) {
+ int i = 0;
+
+ while (str[i] != 0) {
+ eve_spi_xchg8(str[i], flags);
+ i++;
+ }
+ eve_spi_xchg8(0, flags);
+ i++;
+ cmd_inc(i);
+}
+
+static void cmd_buffer(const char *buf, int size, uint8_t flags) {
+ int i = 0;
+
+ for (i=0; i<size; i++) {
+ eve_spi_xchg8(buf[i], flags);
+ }
+ cmd_inc(size);
+}
+
+static void cmd_padding(uint8_t flags) {
+ int i = cmd_offset & 3; /* equivalent to cmd_offset % 4 */
+
+ if (i) {
+ i = 4 - i; /* 3, 2 or 1 */
+ cmd_inc(i);
+
+ while (i > 0) {
+ eve_spi_xchg8(0, flags);
+ i--;
+ }
+ }
+}
+
+void eve_cmd(uint32_t cmd, const char *fmt, ...) {
+ uint8_t flags = EVE_SPI_FLAGS(cmd_burst);
+ va_list argv;
+ uint16_t *p;
+ int i = 0;
+ int cont = 0;
+
+ va_start(argv, fmt);
+ cmd_begin(cmd, flags);
+ while (fmt[i]) {
+ switch (fmt[i]) {
+ case 'b':
+ eve_spi_xchg8(va_arg(argv, int), flags);
+ cmd_inc(1);
+ break;
+ case 'h':
+ eve_spi_xchg16(va_arg(argv, int), flags);
+ cmd_inc(2);
+ break;
+ case 'w':
+ eve_spi_xchg32(va_arg(argv, int), flags);
+ cmd_inc(4);
+ break;
+ case '&':
+ p = va_arg(argv, uint16_t *);
+ *p = cmd_offset;
+ eve_spi_xchg32(0, flags);
+ cmd_inc(4);
+ break;
+ case 's':
+ cmd_string(va_arg(argv, const char *), flags);
+ break;
+ case 'p':
+ cmd_buffer(va_arg(argv, const char *), va_arg(argv, int), flags);
+ break;
+ case '+':
+ cont = 1;
+ break;
+ }
+ if (cont) break;
+ i++;
+ }
+ va_end(argv);
+ if (!cont) eve_cmd_end();
+}
+
+void eve_cmd_write(uint8_t *buffer, size_t size) {
+ cmd_buffer(buffer, size, EVE_SPI_FLAGS(cmd_burst));
+}
+
+void eve_cmd_end(void) {
+ cmd_padding(EVE_SPI_FLAGS(cmd_burst));
+ cmd_end();
+}
+
+uint32_t eve_cmd_result(uint16_t offset) {
+ return eve_read32(EVE_RAM_CMD + offset);
+}
+
+void eve_cmd_dl(uint32_t dl) {
+ cmd_begin(dl, EVE_SPI_FLAGS(cmd_burst));
+ cmd_end();
+}
+
+int eve_cmd_done(void) {
+ uint16_t r = eve_read16(REG_CMD_READ);
+ if (r == 0xfff) {
+ 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 == cmd_offset);
+}
+
+int eve_cmd_exec(int w) {
+ eve_write16(REG_CMD_WRITE, cmd_offset);
+ if (w) {
+ int r;
+ do {
+ r = eve_cmd_done();
+ } while (!r);
+ if (r < 0) return EVE_ERR;
+ }
+ return EVE_OK;
+}
+
+void eve_cmd_burst_start(void) {
+ uint32_t addr = EVE_RAM_CMD + cmd_offset;
+ eve_spi_lock();
+ eve_spi_cs_set();
+ eve_spi_xchg24(addr | EVE_MEM_WRITE, EVE_SPI_FLAG_TX);
+ cmd_burst = 1;
+}
+
+void eve_cmd_burst_end(void) {
+ eve_spi_flush();
+ eve_spi_cs_clear();
+ eve_spi_unlock();
+ cmd_burst = 0;
+}
+
+int eve_gpio_get(int gpio) {
+ uint16_t reg = eve_read16(REG_GPIOX);
+ return !!(reg & (1 << gpio));
+}
+
+void eve_gpio_set(int gpio, int val) {
+ uint16_t reg = eve_read16(REG_GPIOX);
+ uint16_t reg_val = (1 << gpio);
+ if (val) {
+ reg |= reg_val;
+ } else {
+ reg &= ~reg_val;
+ }
+ eve_write16(REG_GPIOX, reg);
+}
+
+uint8_t eve_gpio_get_dir(void) {
+ uint16_t reg = eve_read16(REG_GPIOX_DIR);
+ return reg & 0x000f;
+}
+
+void eve_gpio_set_dir(uint8_t dir) {
+ uint16_t reg = eve_read16(REG_GPIOX_DIR);
+ reg &= 0xfff0;
+ reg |= dir & 0x0f;
+ eve_write16(REG_GPIOX_DIR, reg);
+}
+
+void eve_active(void) {
+ eve_command(EVE_ACTIVE, 0);
+ if (power_state == EVE_PSTATE_SLEEP) eve_time_sleep(40);
+
+ eve_write8(REG_PWM_DUTY, brigtness);
+ if (power_state != EVE_PSTATE_SLEEP) return;
+
+ eve_write8(REG_TOUCH_MODE, EVE_TMODE_CONTINUOUS);
+ eve_write8(REG_CTOUCH_EXTENDED, 0x00);
+
+ power_state = EVE_PSTATE_ACTIVE;
+}
+
+void eve_standby(void) {
+ if (power_state != EVE_PSTATE_ACTIVE) return;
+
+ brigtness = eve_read8(REG_PWM_DUTY);
+ eve_command(EVE_STANDBY, 0);
+
+ power_state = EVE_PSTATE_STANDBY;
+}
+
+void eve_sleep(void) {
+ if (power_state != EVE_PSTATE_ACTIVE) return;
+
+ brigtness = eve_read8(REG_PWM_DUTY);
+ eve_write8(REG_PWM_DUTY, 0x0);
+
+ eve_write8(REG_CTOUCH_EXTENDED, 0x01);
+ eve_write8(REG_TOUCH_MODE, EVE_TMODE_OFF);
+
+ eve_time_sleep(500);
+ eve_command(EVE_SLEEP, 0);
+
+ power_state = EVE_PSTATE_SLEEP;
+}
+
+void eve_brightness(uint8_t b) {
+ eve_write8(REG_PWM_DUTY, b);
+}
+
+static int _init(int touch_calibrate, uint32_t *touch_matrix, uint8_t gpio_dir) {
+ uint8_t chipid = 0;
+ uint16_t timeout = 0;
+
+ 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 */
+ eve_time_sleep(1);
+ chipid = eve_read8(REG_ID);
+ timeout++;
+ if (timeout > 400) return EVE_ERR;
+ }
+
+ eve_write8(REG_PWM_DUTY, 0);
+ eve_write16(REG_GPIOX_DIR, 0x8000 | (gpio_dir & 0x0f));
+ eve_write16(REG_GPIOX, 0);
+
+ /* Initialize Display */
+ 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 */
+
+ /* disable Audio */
+ eve_write16(REG_SOUND, 0x0000); /* set synthesizer to silence */
+ eve_write8(REG_VOL_SOUND, 0x00); /* turn synthesizer volume off */
+ eve_write8(REG_VOL_PB, 0x00); /* turn recorded audio volume off */
+
+ /* write a basic display-list to get things started */
+ eve_dl_start(EVE_RAM_DL, 0);
+ 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 */
+ eve_write16(REG_GPIOX, 0x8000); /* enable the DISP signal to the LCD panel, it is set to output in REG_GPIOX_DIR by default */
+ eve_write8(REG_PCLK, EVE_PCLK); /* now start clocking data to the LCD panel */
+
+ /* configure Touch */
+ eve_write16(REG_TOUCH_CONFIG, 0xb81); /* enable touch low power mode: 0xb81 - default: 0x381 */
+ eve_write8(REG_TOUCH_MODE, EVE_TMODE_CONTINUOUS); /* enable touch */
+ eve_write16(REG_TOUCH_RZTHRESH, EVE_TOUCH_RZTHRESH); /* eliminate any false touches */
+
+ if (touch_calibrate) {
+ eve_write8(REG_PWM_DUTY, 0x40);
+ 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);
+ eve_write8(REG_PWM_DUTY, 0);
+
+ touch_matrix[0] = eve_read32(REG_TOUCH_TRANSFORM_A);
+ touch_matrix[1] = eve_read32(REG_TOUCH_TRANSFORM_B);
+ touch_matrix[2] = eve_read32(REG_TOUCH_TRANSFORM_C);
+ touch_matrix[3] = eve_read32(REG_TOUCH_TRANSFORM_D);
+ touch_matrix[4] = eve_read32(REG_TOUCH_TRANSFORM_E);
+ touch_matrix[5] = eve_read32(REG_TOUCH_TRANSFORM_F);
+ } else {
+ eve_write32(REG_TOUCH_TRANSFORM_A, touch_matrix[0]);
+ eve_write32(REG_TOUCH_TRANSFORM_B, touch_matrix[1]);
+ eve_write32(REG_TOUCH_TRANSFORM_C, touch_matrix[2]);
+ eve_write32(REG_TOUCH_TRANSFORM_D, touch_matrix[3]);
+ eve_write32(REG_TOUCH_TRANSFORM_E, touch_matrix[4]);
+ eve_write32(REG_TOUCH_TRANSFORM_F, touch_matrix[5]);
+ }
+
+ eve_write8(REG_CTOUCH_EXTENDED, 0x00);
+
+ eve_cmd(CMD_SETROTATE, "w", 2);
+ eve_cmd_exec(1);
+
+ return EVE_OK;
+}
+
+int eve_init(int pwr_on, int touch_calibrate, uint32_t *touch_matrix, uint8_t gpio_dir) {
+ eve_spi_start();
+
+ pwr_on = 1; // override this for now
+
+ if (pwr_on) {
+ int rv = _init(touch_calibrate, touch_matrix, gpio_dir);
+ if (rv) return rv;
+ } else {
+ power_state = EVE_PSTATE_SLEEP;
+ eve_active();
+ }
+
+ eve_touch_init();
+ eve_platform_init();
+
+ eve_spi_stop();
+
+ return EVE_OK;
+}
diff --git a/fw/fe310/eos/eve/eve.h b/fw/fe310/eos/eve/eve.h
new file mode 100644
index 0000000..2f26edf
--- /dev/null
+++ b/fw/fe310/eos/eve/eve.h
@@ -0,0 +1,70 @@
+#include <stdint.h>
+
+#include "eve_def.h"
+#include "eve_touch.h"
+#include "eve_phy.h"
+#include "eve_vtrack.h"
+#include "eve_platform.h"
+
+#define EVE_OK 0
+#define EVE_ERR -1
+
+#define EVE_ERR_FULL -10
+#define EVE_ERR_EMPTY -11
+
+#define EVE_ERR_NOMEM -100
+
+#define EVE_PSTATE_ACTIVE 0
+#define EVE_PSTATE_STANDBY 1
+#define EVE_PSTATE_SLEEP 3
+
+#define COLOR_RGBC(c) ((4UL<<24)|((c)&16777215UL))
+#define CLEAR_COLOR_RGBC(c) ((2UL<<24)|((c)&16777215UL))
+
+typedef struct EVERect {
+ int16_t x;
+ int16_t y;
+ uint16_t w;
+ uint16_t h;
+} EVERect;
+
+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_readb(uint32_t addr, uint8_t *buf, size_t size);
+void eve_writeb(uint32_t addr, uint8_t *buf, size_t size);
+
+void eve_dl_start(uint32_t addr, char burst);
+void eve_dl_write(uint32_t dl);
+void eve_dl_end(void);
+void eve_dl_swap(void);
+uint32_t eve_dl_get_addr(void);
+
+void eve_cmd(uint32_t cmd, const char *fmt, ...);
+void eve_cmd_write(uint8_t *buffer, size_t size);
+void eve_cmd_end(void);
+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_gpio_get(int gpio);
+void eve_gpio_set(int gpio, int val);
+uint8_t eve_gpio_get_dir(void);
+void eve_gpio_set_dir(uint8_t dir);
+
+void eve_active(void);
+void eve_standby(void);
+void eve_sleep(void);
+void eve_wake(void);
+void eve_brightness(uint8_t b);
+
+int eve_init(int pwr_on, int touch_calibrate, uint32_t *touch_matrix, uint8_t gpio_dir);
diff --git a/fw/fe310/eos/eve/eve_config.h b/fw/fe310/eos/eve/eve_config.h
new file mode 100755
index 0000000..882ea89
--- /dev/null
+++ b/fw/fe310/eos/eve/eve_config.h
@@ -0,0 +1,39 @@
+#ifndef EVE_CONFIG_H_
+#define EVE_CONFIG_H_
+
+/* my display */
+
+#define EVE_TH 1200L
+#define EVE_THD 800L
+#define EVE_THF 210L
+#define EVE_THP 20L
+#define EVE_THB 46L
+
+#define EVE_TV 650L
+#define EVE_TVD 480L
+#define EVE_TVF 22L
+#define EVE_TVP 12L
+#define EVE_TVB 23L
+
+
+#define EVE_HSIZE (EVE_THD) /* Thd Length of visible part of line (in PCLKs) - display width */
+#define EVE_HSYNC0 (EVE_THF) /* Thf Horizontal Front Porch */
+#define EVE_HSYNC1 (EVE_THF + EVE_THP) /* Thf + Thp Horizontal Front Porch plus Hsync Pulse width */
+#define EVE_HOFFSET (EVE_THF + EVE_THP + EVE_THB) /* Thf + Thp + Thb Length of non-visible part of line (in PCLK cycles) */
+#define EVE_HCYCLE (EVE_TH) /* Th Total length of line (visible and non-visible) (in PCLKs) */
+
+#define EVE_VSIZE (EVE_TVD) /* Tvd Number of visible lines (in lines) - display height */
+#define EVE_VSYNC0 (EVE_TVF) /* Tvf Vertical Front Porch */
+#define EVE_VSYNC1 (EVE_TVF + EVE_TVP) /* Tvf + Tvp Vertical Front Porch plus Vsync Pulse width */
+#define EVE_VOFFSET (EVE_TVF + EVE_TVP + EVE_TVB) /* Tvf + Tvp + Tvb Number of non-visible lines (in lines) */
+#define EVE_VCYCLE (EVE_TV) /* Tv Total number of lines (visible and non-visible) (in lines) */
+
+#define EVE_PCLKPOL (1L) /* PCLK polarity (0 = rising edge, 1 = falling edge) */
+#define EVE_SWIZZLE (0L) /* Defines the arrangement of the RGB pins of the FT800 */
+#define EVE_PCLK (1L) /* 60MHz / REG_PCLK = PCLK frequency - 30 MHz */
+#define EVE_CSPREAD (0L) /* helps with noise, when set to 1 fewer signals are changed simultaneously, reset-default: 1 */
+#define EVE_TOUCH_RZTHRESH (1200L) /* touch-sensitivity */
+#define EVE_HAS_CRYSTAL
+#define FT81X_ENABLE
+
+#endif /* EVE_CONFIG_H */
diff --git a/fw/fe310/eos/eve/eve_def.h b/fw/fe310/eos/eve/eve_def.h
new file mode 100755
index 0000000..25e4927
--- /dev/null
+++ b/fw/fe310/eos/eve/eve_def.h
@@ -0,0 +1,872 @@
+/*
+@file EVE.h
+@brief Contains FT80x/FT81x/BT81x API definitions
+@version 4.0
+@date 2019-11-17
+@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
+
+2.1
+- changes to this header
+
+2.2
+- commented out "#define DISPLAY() ((0UL<<24))" as it collides with a define in the Arduino IDE - the whole section of "macros" needs a rework...
+
+3.0
+- renamed from FT800.h to FT8.h
+- changed FT_ prefixes to FT8_
+- switched to standard-C compliant comment-style
+- changed FT81x register definitions from decimal to hex
+- verified all FT81x register definitions
+- moved FT81x registers marked as "reserved" to an #if 0 block
+
+3.1
+- moved several undocumented commands to an #if 0 block
+
+3.2
+- moved CMD_CRC to the block of undocumented commands as well
+
+3.3
+- changed macros BITMAP_LAYOUT_H and BITMAP_SIZE_H as submitted to github by "jventerprises"
+ These macros provide the extended bits for bitmaps bigger than 511 pixels, FTDIs original implementation that I used and never touched takes the arguments
+ as already processed and not the original values.
+ Note the one example in "FT81x Series Programmers Guide" Version 1.1 for displaying a 800x480 sized bitmap:
+ dl(BITMAP_SIZE_H(1, 0));
+ dl(BITMAP_SIZE(NEAREST, BORDER, BORDER, 288, 480));
+ Now you can use it like this:
+ EVE_cmd_dl(BITMAP_SIZE_H(800, 480));
+ EVE_cmd_dl(BITMAP_SIZE(NEAREST, BORDER, BORDER, 800, 480));
+
+4.0
+- renamed from FT8.h to EVE.h
+- renamed EVE_81X_ENABLE to FT81X_ENABLE
+- changed FT8_ prefixes to EVE_
+- rearranged things a bit with FT80x specific includes moved to the end and a "#if defined (BT81X_ENABLE)" block on top of the chip-specific includes
+- started to add specific BT81x defines
+- minor maintenance
+- changed OPT_FLASH to EVE_OPT_FLASH and OPT_FORMAT to EVE_OPT_FORMAT for consistency
+- added EVE_OPT_FILL which has been left out of the documentation for the BT81x so far
+- added a few BT81x specific macros
+- added a few FT81x/BT81x specific host commands
+- removed the preceding underscore from the include guard define to avoid potential undefined behavior
+- removed a bunch of defines for FT80x that I never implemented for FT81x
+
+*/
+
+#include "eve_config.h"
+
+#ifndef EVE_H_
+#define EVE_H_
+
+
+#define DL_CLEAR 0x26000000UL /* requires OR'd arguments */
+#define DL_CLEAR_RGB 0x02000000UL /* requires OR'd arguments */
+#define DL_COLOR_RGB 0x04000000UL /* requires OR'd arguments */
+#define DL_POINT_SIZE 0x0D000000UL /* requires OR'd arguments */
+#define DL_END 0x21000000UL
+#define DL_BEGIN 0x1F000000UL /* requires OR'd arguments */
+#define DL_DISPLAY 0x00000000UL
+
+#define CLR_COL 0x4
+#define CLR_STN 0x2
+#define CLR_TAG 0x1
+
+
+/* Host commands */
+#define EVE_ACTIVE 0x00 /* place FT8xx in active state */
+#define EVE_STANDBY 0x41 /* place FT8xx in Standby (clk running) */
+#define EVE_SLEEP 0x42 /* place FT8xx in Sleep (clk off) */
+#define EVE_PWRDOWN 0x50 /* place FT8xx in Power Down (core off) */
+#define EVE_CLKEXT 0x44 /* select external clock source */
+#define EVE_CLKINT 0x48 /* select internal clock source */
+#define EVE_CORERST 0x68 /* reset core - all registers default and processors reset */
+#define EVE_CLK48M 0x62 /* select 48MHz PLL output */
+#define EVE_CLK36M 0x61 /* select 36MHz PLL output */
+
+
+/* defines used for graphics commands */
+#define EVE_NEVER 0UL
+#define EVE_LESS 1UL
+#define EVE_LEQUAL 2UL
+#define EVE_GREATER 3UL
+#define EVE_GEQUAL 4UL
+#define EVE_EQUAL 5UL
+#define EVE_NOTEQUAL 6UL
+#define EVE_ALWAYS 7UL
+
+
+/* Bitmap formats */
+#define EVE_ARGB1555 0UL
+#define EVE_L1 1UL
+#define EVE_L4 2UL
+#define EVE_L8 3UL
+#define EVE_RGB332 4UL
+#define EVE_ARGB2 5UL
+#define EVE_ARGB4 6UL
+#define EVE_RGB565 7UL
+#define EVE_PALETTED 8UL
+#define EVE_TEXT8X8 9UL
+#define EVE_TEXTVGA 10UL
+#define EVE_BARGRAPH 11UL
+
+
+/* Bitmap filter types */
+#define EVE_NEAREST 0UL
+#define EVE_BILINEAR 1UL
+
+
+/* Bitmap wrap types */
+#define EVE_BORDER 0UL
+#define EVE_REPEAT 1UL
+
+
+/* Stencil defines */
+#define EVE_KEEP 1UL
+#define EVE_REPLACE 2UL
+#define EVE_INCR 3UL
+#define EVE_DECR 4UL
+#define EVE_INVERT 5UL
+
+
+/* Graphics display list swap defines */
+#define EVE_DLSWAP_DONE 0UL
+#define EVE_DLSWAP_LINE 1UL
+#define EVE_DLSWAP_FRAME 2UL
+
+
+/* Interrupt bits */
+#define EVE_INT_SWAP 0x01
+#define EVE_INT_TOUCH 0x02
+#define EVE_INT_TAG 0x04
+#define EVE_INT_SOUND 0x08
+#define EVE_INT_PLAYBACK 0x10
+#define EVE_INT_CMDEMPTY 0x20
+#define EVE_INT_CMDFLAG 0x40
+#define EVE_INT_CONVCOMPLETE 0x80
+
+
+/* Touch mode */
+#define EVE_TMODE_OFF 0
+#define EVE_TMODE_ONESHOT 1
+#define EVE_TMODE_FRAME 2
+#define EVE_TMODE_CONTINUOUS 3
+
+
+/* Alpha blending */
+#define EVE_ZERO 0UL
+#define EVE_ONE 1UL
+#define EVE_SRC_ALPHA 2UL
+#define EVE_DST_ALPHA 3UL
+#define EVE_ONE_MINUS_SRC_ALPHA 4UL
+#define EVE_ONE_MINUS_DST_ALPHA 5UL
+
+
+/* Graphics primitives */
+#define EVE_BITMAPS 1UL
+#define EVE_POINTS 2UL
+#define EVE_LINES 3UL
+#define EVE_LINE_STRIP 4UL
+#define EVE_EDGE_STRIP_R 5UL
+#define EVE_EDGE_STRIP_L 6UL
+#define EVE_EDGE_STRIP_A 7UL
+#define EVE_EDGE_STRIP_B 8UL
+#define EVE_RECTS 9UL
+
+
+/* Widget command */
+#define EVE_OPT_MONO 1
+#define EVE_OPT_NODL 2
+#define EVE_OPT_FLAT 256
+#define EVE_OPT_CENTERX 512
+#define EVE_OPT_CENTERY 1024
+#define EVE_OPT_CENTER (EVE_OPT_CENTERX | EVE_OPT_CENTERY)
+#define EVE_OPT_NOBACK 4096
+#define EVE_OPT_NOTICKS 8192
+#define EVE_OPT_NOHM 16384
+#define EVE_OPT_NOPOINTER 16384
+#define EVE_OPT_NOSECS 32768
+#define EVE_OPT_NOHANDS 49152
+#define EVE_OPT_RIGHTX 2048
+#define EVE_OPT_SIGNED 256
+
+
+/* Defines related to inbuilt font */
+#define EVE_NUMCHAR_PERFONT (128L) /* number of font characters per bitmap handle */
+#define EVE_FONT_TABLE_SIZE (148L) /* size of the font table - utilized for loopup by the graphics engine */
+#define EVE_FONT_TABLE_POINTER (0xFFFFCUL) /* pointer to the inbuilt font tables starting from bitmap handle 16 */
+
+
+/* Audio sample type defines */
+#define EVE_LINEAR_SAMPLES 0UL /* 8bit signed samples */
+#define EVE_ULAW_SAMPLES 1UL /* 8bit ulaw samples */
+#define EVE_ADPCM_SAMPLES 2UL /* 4bit ima adpcm samples */
+
+
+/* Synthesized sound */
+#define EVE_SILENCE 0x00
+#define EVE_SQUAREWAVE 0x01
+#define EVE_SINEWAVE 0x02
+#define EVE_SAWTOOTH 0x03
+#define EVE_TRIANGLE 0x04
+#define EVE_BEEPING 0x05
+#define EVE_ALARM 0x06
+#define EVE_WARBLE 0x07
+#define EVE_CAROUSEL 0x08
+#define EVE_PIPS(n) (0x0F + (n))
+#define EVE_HARP 0x40
+#define EVE_XYLOPHONE 0x41
+#define EVE_TUBA 0x42
+#define EVE_GLOCKENSPIEL 0x43
+#define EVE_ORGAN 0x44
+#define EVE_TRUMPET 0x45
+#define EVE_PIANO 0x46
+#define EVE_CHIMES 0x47
+#define EVE_MUSICBOX 0x48
+#define EVE_BELL 0x49
+#define EVE_CLICK 0x50
+#define EVE_SWITCH 0x51
+#define EVE_COWBELL 0x52
+#define EVE_NOTCH 0x53
+#define EVE_HIHAT 0x54
+#define EVE_KICKDRUM 0x55
+#define EVE_POP 0x56
+#define EVE_CLACK 0x57
+#define EVE_CHACK 0x58
+#define EVE_MUTE 0x60
+#define EVE_UNMUTE 0x61
+
+
+/* Synthesized sound frequencies, midi note */
+#define EVE_MIDI_A0 21
+#define EVE_MIDI_A_0 22
+#define EVE_MIDI_B0 23
+#define EVE_MIDI_C1 24
+#define EVE_MIDI_C_1 25
+#define EVE_MIDI_D1 26
+#define EVE_MIDI_D_1 27
+#define EVE_MIDI_E1 28
+#define EVE_MIDI_F1 29
+#define EVE_MIDI_F_1 30
+#define EVE_MIDI_G1 31
+#define EVE_MIDI_G_1 32
+#define EVE_MIDI_A1 33
+#define EVE_MIDI_A_1 34
+#define EVE_MIDI_B1 35
+#define EVE_MIDI_C2 36
+#define EVE_MIDI_C_2 37
+#define EVE_MIDI_D2 38
+#define EVE_MIDI_D_2 39
+#define EVE_MIDI_E2 40
+#define EVE_MIDI_F2 41
+#define EVE_MIDI_F_2 42
+#define EVE_MIDI_G2 43
+#define EVE_MIDI_G_2 44
+#define EVE_MIDI_A2 45
+#define EVE_MIDI_A_2 46
+#define EVE_MIDI_B2 47
+#define EVE_MIDI_C3 48
+#define EVE_MIDI_C_3 49
+#define EVE_MIDI_D3 50
+#define EVE_MIDI_D_3 51
+#define EVE_MIDI_E3 52
+#define EVE_MIDI_F3 53
+#define EVE_MIDI_F_3 54
+#define EVE_MIDI_G3 55
+#define EVE_MIDI_G_3 56
+#define EVE_MIDI_A3 57
+#define EVE_MIDI_A_3 58
+#define EVE_MIDI_B3 59
+#define EVE_MIDI_C4 60
+#define EVE_MIDI_C_4 61
+#define EVE_MIDI_D4 62
+#define EVE_MIDI_D_4 63
+#define EVE_MIDI_E4 64
+#define EVE_MIDI_F4 65
+#define EVE_MIDI_F_4 66
+#define EVE_MIDI_G4 67
+#define EVE_MIDI_G_4 68
+#define EVE_MIDI_A4 69
+#define EVE_MIDI_A_4 70
+#define EVE_MIDI_B4 71
+#define EVE_MIDI_C5 72
+#define EVE_MIDI_C_5 73
+#define EVE_MIDI_D5 74
+#define EVE_MIDI_D_5 75
+#define EVE_MIDI_E5 76
+#define EVE_MIDI_F5 77
+#define EVE_MIDI_F_5 78
+#define EVE_MIDI_G5 79
+#define EVE_MIDI_G_5 80
+#define EVE_MIDI_A5 81
+#define EVE_MIDI_A_5 82
+#define EVE_MIDI_B5 83
+#define EVE_MIDI_C6 84
+#define EVE_MIDI_C_6 85
+#define EVE_MIDI_D6 86
+#define EVE_MIDI_D_6 87
+#define EVE_MIDI_E6 88
+#define EVE_MIDI_F6 89
+#define EVE_MIDI_F_6 90
+#define EVE_MIDI_G6 91
+#define EVE_MIDI_G_6 92
+#define EVE_MIDI_A6 93
+#define EVE_MIDI_A_6 94
+#define EVE_MIDI_B6 95
+#define EVE_MIDI_C7 96
+#define EVE_MIDI_C_7 97
+#define EVE_MIDI_D7 98
+#define EVE_MIDI_D_7 99
+#define EVE_MIDI_E7 100
+#define EVE_MIDI_F7 101
+#define EVE_MIDI_F_7 102
+#define EVE_MIDI_G7 103
+#define EVE_MIDI_G_7 104
+#define EVE_MIDI_A7 105
+#define EVE_MIDI_A_7 106
+#define EVE_MIDI_B7 107
+#define EVE_MIDI_C8 108
+
+
+/* GPIO bits */
+#define EVE_GPIO0 0
+#define EVE_GPIO1 1 /* default gpio pin for audio shutdown, 1 - enable, 0 - disable */
+#define EVE_GPIO7 7 /* default gpio pin for display enable, 1 - enable, 0 - disable */
+
+
+/* Display rotation */
+#define EVE_DISPLAY_0 0 /* 0 degrees rotation */
+#define EVE_DISPLAY_180 1 /* 180 degrees rotation */
+
+
+/* commands common to EVE/EVE2/EVE3 */
+#define CMD_APPEND 0xFFFFFF1E
+#define CMD_BGCOLOR 0xFFFFFF09
+#define CMD_BUTTON 0xFFFFFF0D
+#define CMD_CALIBRATE 0xFFFFFF15
+#define CMD_CLOCK 0xFFFFFF14
+#define CMD_COLDSTART 0xFFFFFF32
+#define CMD_DIAL 0xFFFFFF2D
+#define CMD_DLSTART 0xFFFFFF00
+#define CMD_FGCOLOR 0xFFFFFF0A
+#define CMD_GAUGE 0xFFFFFF13
+#define CMD_GETMATRIX 0xFFFFFF33
+#define CMD_GETPROPS 0xFFFFFF25
+#define CMD_GETPTR 0xFFFFFF23
+#define CMD_GRADCOLOR 0xFFFFFF34
+#define CMD_GRADIENT 0xFFFFFF0B
+#define CMD_INFLATE 0xFFFFFF22
+#define CMD_INTERRUPT 0xFFFFFF02
+#define CMD_KEYS 0xFFFFFF0E
+#define CMD_LOADIDENTITY 0xFFFFFF26
+#define CMD_LOADIMAGE 0xFFFFFF24
+#define CMD_LOGO 0xFFFFFF31
+#define CMD_MEMCPY 0xFFFFFF1D
+#define CMD_MEMCRC 0xFFFFFF18
+#define CMD_MEMSET 0xFFFFFF1B
+#define CMD_MEMWRITE 0xFFFFFF1A
+#define CMD_MEMZERO 0xFFFFFF1C
+#define CMD_NUMBER 0xFFFFFF2E
+#define CMD_PROGRESS 0xFFFFFF0F
+#define CMD_REGREAD 0xFFFFFF19
+#define CMD_ROTATE 0xFFFFFF29
+#define CMD_SCALE 0xFFFFFF28
+#define CMD_SCREENSAVER 0xFFFFFF2F
+#define CMD_SCROLLBAR 0xFFFFFF11
+#define CMD_SETFONT 0xFFFFFF2B
+#define CMD_SETMATRIX 0xFFFFFF2A
+#define CMD_SKETCH 0xFFFFFF30
+#define CMD_SLIDER 0xFFFFFF10
+#define CMD_SNAPSHOT 0xFFFFFF1F
+#define CMD_SPINNER 0xFFFFFF16
+#define CMD_STOP 0xFFFFFF17
+#define CMD_SWAP 0xFFFFFF01
+#define CMD_TEXT 0xFFFFFF0C
+#define CMD_TOGGLE 0xFFFFFF12
+#define CMD_TRACK 0xFFFFFF2C
+#define CMD_TRANSLATE 0xFFFFFF27
+
+
+/* the following are undocumented commands that therefore should not be used */
+#if 0
+#define CMD_CRC 0xFFFFFF03
+#define CMD_HAMMERAUX 0xFFFFFF04
+#define CMD_MARCH 0xFFFFFF05
+#define CMD_IDCT 0xFFFFFF06
+#define CMD_EXECUTE 0xFFFFFF07
+#define CMD_GETPOINT 0xFFFFFF08
+#define CMD_TOUCH_TRANSFORM 0xFFFFFF20
+#endif
+
+
+/* FT8xx graphics engine specific macros useful for static display list generation */
+#define ALPHA_FUNC(func,ref) ((9UL<<24)|(((func)&7UL)<<8)|(((ref)&255UL)<<0))
+#define BEGIN(prim) ((31UL<<24)|(((prim)&15UL)<<0))
+#define BITMAP_HANDLE(handle) ((5UL<<24)|(((handle)&31UL)<<0))
+#define BITMAP_LAYOUT(format,linestride,height) ((7UL<<24)|(((format)&31UL)<<19)|(((linestride)&1023UL)<<9)|(((height)&511UL)<<0))
+#define BITMAP_SIZE(filter,wrapx,wrapy,width,height) ((8UL<<24)|(((filter)&1UL)<<20)|(((wrapx)&1UL)<<19)|(((wrapy)&1UL)<<18)|(((width)&511UL)<<9)|(((height)&511UL)<<0))
+#define BITMAP_TRANSFORM_A(a) ((21UL<<24)|(((a)&131071UL)<<0))
+#define BITMAP_TRANSFORM_B(b) ((22UL<<24)|(((b)&131071UL)<<0))
+#define BITMAP_TRANSFORM_C(c) ((23UL<<24)|(((c)&16777215UL)<<0))
+#define BITMAP_TRANSFORM_D(d) ((24UL<<24)|(((d)&131071UL)<<0))
+#define BITMAP_TRANSFORM_E(e) ((25UL<<24)|(((e)&131071UL)<<0))
+#define BITMAP_TRANSFORM_F(f) ((26UL<<24)|(((f)&16777215UL)<<0))
+#define BLEND_FUNC(src,dst) ((11UL<<24)|(((src)&7UL)<<3)|(((dst)&7UL)<<0))
+#define CALL(dest) ((29UL<<24)|(((dest)&65535UL)<<0))
+#define CELL(cell) ((6UL<<24)|(((cell)&127UL)<<0))
+#define CLEAR(c,s,t) ((38UL<<24)|(((c)&1UL)<<2)|(((s)&1UL)<<1)|(((t)&1UL)<<0))
+#define CLEAR_COLOR_A(alpha) ((15UL<<24)|(((alpha)&255UL)<<0))
+#define CLEAR_COLOR_RGB(red,green,blue) ((2UL<<24)|(((red)&255UL)<<16)|(((green)&255UL)<<8)|(((blue)&255UL)<<0))
+#define CLEAR_STENCIL(s) ((17UL<<24)|(((s)&255UL)<<0))
+#define CLEAR_TAG(s) ((18UL<<24)|(((s)&255UL)<<0))
+#define COLOR_A(alpha) ((16UL<<24)|(((alpha)&255UL)<<0))
+#define COLOR_MASK(r,g,b,a) ((32UL<<24)|(((r)&1UL)<<3)|(((g)&1UL)<<2)|(((b)&1UL)<<1)|(((a)&1UL)<<0))
+#define COLOR_RGB(red,green,blue) ((4UL<<24)|(((red)&255UL)<<16)|(((green)&255UL)<<8)|(((blue)&255UL)<<0))
+#define DISPLAY() ((0UL<<24))
+#define END() ((33UL<<24))
+#define JUMP(dest) ((30UL<<24)|(((dest)&65535UL)<<0))
+#define LINE_WIDTH(width) ((14UL<<24)|(((width)&4095UL)<<0))
+#define MACRO(m) ((37UL<<24)|(((m)&1UL)<<0))
+#define POINT_SIZE(size) ((13UL<<24)|(((size)&8191UL)<<0))
+#define RESTORE_CONTEXT() ((35UL<<24))
+#define RETURN() ((36UL<<24))
+#define SAVE_CONTEXT() ((34UL<<24))
+#define STENCIL_FUNC(func,ref,mask) ((10UL<<24)|(((func)&7UL)<<16)|(((ref)&255UL)<<8)|(((mask)&255UL)<<0))
+#define STENCIL_MASK(mask) ((19UL<<24)|(((mask)&255UL)<<0))
+#define STENCIL_OP(sfail,spass) ((12UL<<24)|(((sfail)&7UL)<<3)|(((spass)&7UL)<<0))
+#define TAG(s) ((3UL<<24)|(((s)&255UL)<<0))
+#define TAG_MASK(mask) ((20UL<<24)|(((mask)&1UL)<<0))
+#define VERTEX2F(x,y) ((1UL<<30)|(((x)&32767UL)<<15)|(((y)&32767UL)<<0))
+#define VERTEX2II(x,y,handle,cell) ((2UL<<30)|(((x)&511UL)<<21)|(((y)&511UL)<<12)|(((handle)&31UL)<<7)|(((cell)&127UL)<<0))
+
+
+/* ----------------- BT81x exclusive definitions -----------------*/
+#if defined (BT81X_ENABLE)
+
+#define EVE_GLFORMAT 31UL /* used with BITMAP_LAYOUT to indicate bitmap-format is specified by BITMAP_EXT_FORMAT */
+
+#define DL_BITMAP_EXT_FORMAT 0x2E000000 /* requires OR'd arguments */
+
+/* extended Bitmap formats */
+#define EVE_COMPRESSED_RGBA_ASTC_4x4_KHR 37808UL
+#define EVE_COMPRESSED_RGBA_ASTC_5x4_KHR 37809UL
+#define EVE_COMPRESSED_RGBA_ASTC_5x5_KHR 37810UL
+#define EVE_COMPRESSED_RGBA_ASTC_6x5_KHR 37811UL
+#define EVE_COMPRESSED_RGBA_ASTC_6x6_KHR 37812UL
+#define EVE_COMPRESSED_RGBA_ASTC_8x5_KHR 37813UL
+#define EVE_COMPRESSED_RGBA_ASTC_8x6_KHR 37814UL
+#define EVE_COMPRESSED_RGBA_ASTC_8x8_KHR 37815UL
+#define EVE_COMPRESSED_RGBA_ASTC_10x5_KHR 37816UL
+#define EVE_COMPRESSED_RGBA_ASTC_10x6_KHR 37817UL
+#define EVE_COMPRESSED_RGBA_ASTC_10x8_KHR 37818UL
+#define EVE_COMPRESSED_RGBA_ASTC_10x10_KHR 37819UL
+#define EVE_COMPRESSED_RGBA_ASTC_12x10_KHR 37820UL
+#define EVE_COMPRESSED_RGBA_ASTC_12x12_KHR 37821UL
+
+
+#define EVE_RAM_ERR_REPORT 0x309800UL /* max 128 bytes null terminated string */
+#define EVE_RAM_FLASH 0x800000UL
+#define EVE_RAM_FLASH_POSTBLOB 0x801000UL
+
+#define EVE_OPT_FLASH 64UL
+#define EVE_OPT_FORMAT 4096UL
+#define EVE_OPT_FILL 8192UL
+
+
+/* additional commands for BT81x */
+#define CMD_BITMAP_TRANSFORM 0xFFFFFF21
+#define CMD_SYNC 0xFFFFFF42 /* does not need a dedicated function, just use EVE_cmd_dl(CMD_SYNC) */
+#define CMD_FLASHERASE 0xFFFFFF44 /* does not need a dedicated function, just use EVE_cmd_dl(CMD_FLASHERASE) */
+#define CMD_FLASHWRITE 0xFFFFFF45
+#define CMD_FLASHREAD 0xFFFFFF46
+#define CMD_FLASHUPDATE 0xFFFFFF47
+#define CMD_FLASHDETACH 0xFFFFFF48 /* does not need a dedicated function, just use EVE_cmd_dl(CMD_FLASHDETACH) */
+#define CMD_FLASHATTACH 0xFFFFFF49 /* does not need a dedicated function, just use EVE_cmd_dl(CMD_FLASHATTACH) */
+#define CMD_FLASHFAST 0xFFFFFF4A
+#define CMD_FLASHSPIDESEL 0xFFFFFF4B /* does not need a dedicated function, just use EVE_cmd_dl(CMD_FLASHSPIDESEL) */
+#define CMD_FLASHSPITX 0xFFFFFF4C
+#define CMD_FLASHSPIRX 0xFFFFFF4D
+#define CMD_FLASHSOURCE 0xFFFFFF4E
+#define CMD_CLEARCACHE 0xFFFFFF4F /* does not need a dedicated function, just use EVE_cmd_dl(CMD_CLEARCACHE) */
+#define CMD_INFLATE2 0xFFFFFF50
+#define CMD_ROTATEAROUND 0xFFFFFF51
+#define CMD_RESETFONTS 0xFFFFFF52 /* does not need a dedicated function, just use EVE_cmd_dl(CMD_RESETFONTS) */
+#define CMD_ANIMSTART 0xFFFFFF53
+#define CMD_ANIMSTOP 0xFFFFFF54
+#define CMD_ANIMXY 0xFFFFFF55
+#define CMD_ANIMDRAW 0xFFFFFF56
+#define CMD_GRADIENTA 0xFFFFFF57
+#define CMD_FILLWIDTH 0xFFFFFF58
+#define CMD_APPENDF 0xFFFFFF59
+#define CMD_ANIMFRAME 0xFFFFFF5A
+#define CMD_VIDEOSTARTF 0xFFFFFF5F /* does not need a dedicated function, just use EVE_cmd_dl(CMD_VIDEOSTARTF) */
+
+#if 0
+/* some undocumented commands for BT81x */
+#define CMD_NOP 0xFFFFFF5B
+#define CMD_SHA1 0xFFFFFF5C
+#define CMD_HMAC 0xFFFFFF5D
+#define CMD_LAST_ 0xFFFFFF5E
+
+#endif
+
+
+/* additional registers for BT81x */
+#define REG_ADAPTIVE_FRAMERATE 0x30257cUL
+#define REG_PLAYBACK_PAUSE 0x3025ecUL
+#define REG_FLASH_STATUS 0x3025f0UL
+#define REG_FLASH_SIZE 0x309024UL
+#define REG_PLAY_CONTROL 0x30914eUL
+#define REG_COPRO_PATCH_DTR 0x309162UL
+
+
+/* BT81x graphics engine specific macros */
+#define BITMAP_EXT_FORMAT(format) ((46UL<<24)|(((format)&65535UL)<<0))
+#define BITMAP_SWIZZLE(r,g,b,a) ((47UL<<24)|(((r)&7UL)<<9)|(((g)&7UL)<<6)|(((b)&7UL)<<3)|(((a)&7UL)<<0))
+#define BITMAP_SOURCE2(flash_or_ram, addr) ((1UL<<24)|((flash_or_ram) << 23)|(((addr)&8388607UL)<<0))
+#define INT_FRR() ((48UL<<24))
+
+#undef BITMAP_TRANSFORM_A
+#undef BITMAP_TRANSFORM_B
+#undef BITMAP_TRANSFORM_D
+#undef BITMAP_TRANSFORM_E
+
+#define BITMAP_TRANSFORM_A_EXT(p,v) ((21UL<<24)|(((p)&1UL)<<17)|(((v)&131071UL)<<0))
+#define BITMAP_TRANSFORM_B_EXT(p,v) ((22UL<<24)|(((p)&1UL)<<17)|(((v)&131071UL)<<0))
+#define BITMAP_TRANSFORM_D_EXT(p,v) ((24UL<<24)|(((p)&1UL)<<17)|(((v)&131071UL)<<0))
+#define BITMAP_TRANSFORM_E_EXT(p,v) ((25UL<<24)|(((p)&1UL)<<17)|(((v)&131071UL)<<0))
+
+#define BITMAP_TRANSFORM_A(a) BITMAP_TRANSFORM_A_EXT(0,a)
+#define BITMAP_TRANSFORM_B(b) BITMAP_TRANSFORM_B_EXT(0,b)
+#define BITMAP_TRANSFORM_D(d) BITMAP_TRANSFORM_D_EXT(0,d)
+#define BITMAP_TRANSFORM_E(e) BITMAP_TRANSFORM_E_EXT(0,e)
+
+#endif
+
+/* ----------------- FT81x / BT81x exclusive definitions -----------------*/
+#if defined (FT81X_ENABLE)
+
+
+/* Host commands */
+#define EVE_CLKSEL 0x61 /* configure system clock */
+#define EVE_RST_PULSE 0x68 /* reset core - all registers default and processors reset */
+#define EVE_PINDRIVE 0x70 /* setup drive strength for various pins */
+#define EVE_PIN_PD_STATE 0x71 /* setup how pins behave during power down */
+
+
+/* Memory definitions */
+#define EVE_RAM_G 0x000000UL
+#define EVE_ROM_CHIPID 0x0C0000UL
+#define EVE_ROM_FONT 0x1E0000UL
+#define EVE_ROM_FONT_ADDR 0x2FFFFCUL
+#define EVE_RAM_DL 0x300000UL
+#define EVE_RAM_REG 0x302000UL
+#define EVE_RAM_CMD 0x308000UL
+
+
+/* Memory buffer sizes */
+#define EVE_RAM_G_SIZE 1024*1024L
+#define EVE_CMDFIFO_SIZE 4*1024L
+#define EVE_RAM_DL_SIZE 8*1024L
+
+
+/* various additional defines for FT81x */
+#define EVE_ADC_DIFFERENTIAL 1UL
+#define EVE_ADC_SINGLE_ENDED 0UL
+
+#define EVE_INT_G8 18UL
+#define EVE_INT_L8C 12UL
+#define EVE_INT_VGA 13UL
+
+#define EVE_OPT_MEDIAFIFO 16UL
+#define EVE_OPT_FULLSCREEN 8UL
+#define EVE_OPT_NOTEAR 4UL
+#define EVE_OPT_SOUND 32UL
+
+#define EVE_PALETTED565 14UL
+#define EVE_PALETTED4444 15UL
+#define EVE_PALETTED8 16UL
+#define EVE_L2 17UL
+
+
+/* additional commands for FT81x */
+#define CMD_MEDIAFIFO 0xFFFFFF39
+#define CMD_PLAYVIDEO 0xFFFFFF3A
+#define CMD_ROMFONT 0xFFFFFF3F
+#define CMD_SETBASE 0xFFFFFF38
+#define CMD_SETBITMAP 0xFFFFFF43
+#define CMD_SETFONT2 0xFFFFFF3B
+#define CMD_SETROTATE 0xFFFFFF36
+#define CMD_SETSCRATCH 0xFFFFFF3C
+#define CMD_SNAPSHOT2 0xFFFFFF37
+#define CMD_VIDEOFRAME 0xFFFFFF41
+#define CMD_VIDEOSTART 0xFFFFFF40
+
+
+/* the following are undocumented commands that therefore should not be used */
+#if 0
+#define CMD_CSKETCH 0xFFFFFF35
+#define CMD_INT_RAMSHARED 0xFFFFFF3D
+#define CMD_INT_SWLOADIMAGE 0xFFFFFF3E
+#endif
+
+
+/* Register definitions */
+#define REG_ANA_COMP 0x302184UL /* only listed in datasheet */
+#define REG_BIST_EN 0x302174UL /* only listed in datasheet */
+#define REG_CLOCK 0x302008UL
+#define REG_CMDB_SPACE 0x302574UL
+#define REG_CMDB_WRITE 0x302578UL
+#define REG_CMD_DL 0x302100UL
+#define REG_CMD_READ 0x3020f8UL
+#define REG_CMD_WRITE 0x3020fcUL
+#define REG_CPURESET 0x302020UL
+#define REG_CSPREAD 0x302068UL
+#define REG_CTOUCH_EXTENDED 0x302108UL
+#define REG_CTOUCH_TOUCH0_XY 0x302124UL /* only listed in datasheet */
+#define REG_CTOUCH_TOUCH4_X 0x30216cUL
+#define REG_CTOUCH_TOUCH4_Y 0x302120UL
+#define REG_CTOUCH_TOUCH1_XY 0x30211cUL
+#define REG_CTOUCH_TOUCH2_XY 0x30218cUL
+#define REG_CTOUCH_TOUCH3_XY 0x302190UL
+#define REG_TOUCH_CONFIG 0x302168UL
+#define REG_DATESTAMP 0x302564UL /* only listed in datasheet */
+#define REG_DITHER 0x302060UL
+#define REG_DLSWAP 0x302054UL
+#define REG_FRAMES 0x302004UL
+#define REG_FREQUENCY 0x30200cUL
+#define REG_GPIO 0x302094UL
+#define REG_GPIOX 0x30209cUL
+#define REG_GPIOX_DIR 0x302098UL
+#define REG_GPIO_DIR 0x302090UL
+#define REG_HCYCLE 0x30202cUL
+#define REG_HOFFSET 0x302030UL
+#define REG_HSIZE 0x302034UL
+#define REG_HSYNC0 0x302038UL
+#define REG_HSYNC1 0x30203cUL
+#define REG_ID 0x302000UL
+#define REG_INT_EN 0x3020acUL
+#define REG_INT_FLAGS 0x3020a8UL
+#define REG_INT_MASK 0x3020b0UL
+#define REG_MACRO_0 0x3020d8UL
+#define REG_MACRO_1 0x3020dcUL
+#define REG_MEDIAFIFO_READ 0x309014UL /* only listed in programmers guide */
+#define REG_MEDIAFIFO_WRITE 0x309018UL /* only listed in programmers guide */
+#define REG_OUTBITS 0x30205cUL
+#define REG_PCLK 0x302070UL
+#define REG_PCLK_POL 0x30206cUL
+#define REG_PLAY 0x30208cUL
+#define REG_PLAYBACK_FORMAT 0x3020c4UL
+#define REG_PLAYBACK_FREQ 0x3020c0UL
+#define REG_PLAYBACK_LENGTH 0x3020b8UL
+#define REG_PLAYBACK_LOOP 0x3020c8UL
+#define REG_PLAYBACK_PLAY 0x3020ccUL
+#define REG_PLAYBACK_READPTR 0x3020bcUL
+#define REG_PLAYBACK_START 0x3020b4UL
+#define REG_PWM_DUTY 0x3020d4UL
+#define REG_PWM_HZ 0x3020d0UL
+#define REG_RENDERMODE 0x302010UL /* only listed in datasheet */
+#define REG_ROTATE 0x302058UL
+#define REG_SNAPFORMAT 0x30201cUL /* only listed in datasheet */
+#define REG_SNAPSHOT 0x302018UL /* only listed in datasheet */
+#define REG_SNAPY 0x302014UL /* only listed in datasheet */
+#define REG_SOUND 0x302088UL
+#define REG_SPI_WIDTH 0x302188UL /* listed with false offset in programmers guide V1.1 */
+#define REG_SWIZZLE 0x302064UL
+#define REG_TAG 0x30207cUL
+#define REG_TAG_X 0x302074UL
+#define REG_TAG_Y 0x302078UL
+#define REG_TAP_CRC 0x302024UL /* only listed in datasheet */
+#define REG_TAP_MASK 0x302028UL /* only listed in datasheet */
+#define REG_TOUCH_ADC_MODE 0x302108UL
+#define REG_TOUCH_CHARGE 0x30210cUL
+#define REG_TOUCH_DIRECT_XY 0x30218cUL
+#define REG_TOUCH_DIRECT_Z1Z2 0x302190UL
+#define REG_TOUCH_MODE 0x302104UL
+#define REG_TOUCH_OVERSAMPLE 0x302114UL
+#define REG_TOUCH_RAW_XY 0x30211cUL
+#define REG_TOUCH_RZ 0x302120UL
+#define REG_TOUCH_RZTHRESH 0x302118UL
+#define REG_TOUCH_SCREEN_XY 0x302124UL
+#define REG_TOUCH_SETTLE 0x302110UL
+#define REG_TOUCH_TAG 0x30212cUL
+#define REG_TOUCH_TAG1 0x302134UL /* only listed in datasheet */
+#define REG_TOUCH_TAG1_XY 0x302130UL /* only listed in datasheet */
+#define REG_TOUCH_TAG2 0x30213cUL /* only listed in datasheet */
+#define REG_TOUCH_TAG2_XY 0x302138UL /* only listed in datasheet */
+#define REG_TOUCH_TAG3 0x302144UL /* only listed in datasheet */
+#define REG_TOUCH_TAG3_XY 0x302140UL /* only listed in datasheet */
+#define REG_TOUCH_TAG4 0x30214cUL /* only listed in datasheet */
+#define REG_TOUCH_TAG4_XY 0x302148UL /* only listed in datasheet */
+#define REG_TOUCH_TAG_XY 0x302128UL
+#define REG_TOUCH_TRANSFORM_A 0x302150UL
+#define REG_TOUCH_TRANSFORM_B 0x302154UL
+#define REG_TOUCH_TRANSFORM_C 0x302158UL
+#define REG_TOUCH_TRANSFORM_D 0x30215cUL
+#define REG_TOUCH_TRANSFORM_E 0x302160UL
+#define REG_TOUCH_TRANSFORM_F 0x302164UL
+#define REG_TRACKER 0x309000UL /* only listed in programmers guide */
+#define REG_TRACKER_1 0x309004UL /* only listed in programmers guide */
+#define REG_TRACKER_2 0x309008UL /* only listed in programmers guide */
+#define REG_TRACKER_3 0x30900cUL /* only listed in programmers guide */
+#define REG_TRACKER_4 0x309010UL /* only listed in programmers guide */
+#define REG_TRIM 0x302180UL
+#define REG_VCYCLE 0x302040UL
+#define REG_VOFFSET 0x302044UL
+#define REG_VOL_PB 0x302080UL
+#define REG_VOL_SOUND 0x302084UL
+#define REG_VSIZE 0x302048UL
+#define REG_VSYNC0 0x30204cUL
+#define REG_VSYNC1 0x302050UL
+
+#if 0
+#define REG_BUSYBITS 0x3020e8UL /* only listed as "reserved" in datasheet */
+#define REG_CRC 0x302178UL /* only listed as "reserved" in datasheet */
+#define REG_SPI_EARLY_TX 0x30217cUL /* only listed as "reserved" in datasheet */
+#define REG_ROMSUB_SEL 0x3020f0UL /* only listed as "reserved" in datasheet */
+#define REG_TOUCH_FAULT 0x302170UL /* only listed as "reserved" in datasheet */
+#endif
+
+
+/* FT81x graphics engine specific macros useful for static display list generation */
+
+/* beware, these are different to FTDIs implementation as these take the original values as parameters and not only the upper bits */
+#define BITMAP_LAYOUT_H(linestride,height) ((40UL<<24)|((((linestride&0xC00)>>10)&3UL)<<2)|((((height&0x600)>>9)&3UL)<<0))
+#define BITMAP_SIZE_H(width,height) ((41UL<<24)|((((width&0x600)>>9)&3UL)<<2)|((((height&0x600)>>9)&3UL)<<0))
+
+#define BITMAP_SOURCE(addr) ((1UL<<24)|(((addr)&4194303UL)<<0))
+#define NOP() ((45UL<<24))
+#define PALETTE_SOURCE(addr) ((42UL<<24)|(((addr)&4194303UL)<<0))
+#define SCISSOR_SIZE(width,height) ((28UL<<24)|(((width)&4095UL)<<12)|(((height)&4095UL)<<0))
+#define SCISSOR_XY(x,y) ((27UL<<24)|(((x)&2047UL)<<11)|(((y)&2047UL)<<0))
+#define VERTEX_FORMAT(frac) ((39UL<<24)|(((frac)&7UL)<<0))
+#define VERTEX_TRANSLATE_X(x) ((43UL<<24)|(((x)&131071UL)<<0))
+#define VERTEX_TRANSLATE_Y(y) ((44UL<<24)|(((y)&131071UL)<<0))
+
+
+
+/* ----------------- FT80x exclusive definitions -----------------*/
+#else
+
+/* Memory definitions */
+#define EVE_RAM_G 0x000000UL
+#define EVE_ROM_CHIPID 0x0C0000UL
+#define EVE_ROM_FONT 0x0BB23CUL
+#define EVE_ROM_FONT_ADDR 0x0FFFFCUL
+#define EVE_RAM_DL 0x100000UL
+#define EVE_RAM_PAL 0x102000UL
+#define EVE_RAM_CMD 0x108000UL
+#define EVE_RAM_SCREENSHOT 0x1C2000UL
+
+
+/* Memory buffer sizes */
+#define EVE_RAM_G_SIZE 256*1024L
+#define EVE_CMDFIFO_SIZE 4*1024L
+#define EVE_RAM_DL_SIZE 8*1024L
+#define EVE_RAM_PAL_SIZE 1*1024L
+
+
+/* Register definitions */
+#define REG_ID 0x102400UL
+#define REG_FRAMES 0x102404UL
+#define REG_CLOCK 0x102408UL
+#define REG_FREQUENCY 0x10240CUL
+#define REG_SCREENSHOT_EN 0x102410UL
+#define REG_SCREENSHOT_Y 0x102414UL
+#define REG_SCREENSHOT_START 0x102418UL
+#define REG_CPURESET 0x10241CUL
+#define REG_TAP_CRC 0x102420UL
+#define REG_TAP_MASK 0x102424UL
+#define REG_HCYCLE 0x102428UL
+#define REG_HOFFSET 0x10242CUL
+#define REG_HSIZE 0x102430UL
+#define REG_HSYNC0 0x102434UL
+#define REG_HSYNC1 0x102438UL
+#define REG_VCYCLE 0x10243CUL
+#define REG_VOFFSET 0x102440UL
+#define REG_VSIZE 0x102444UL
+#define REG_VSYNC0 0x102448UL
+#define REG_VSYNC1 0x10244CUL
+#define REG_DLSWAP 0x102450UL
+#define REG_ROTATE 0x102454UL
+#define REG_OUTBITS 0x102458UL
+#define REG_DITHER 0x10245CUL
+#define REG_SWIZZLE 0x102460UL
+#define REG_CSPREAD 0x102464UL
+#define REG_PCLK_POL 0x102468UL
+#define REG_PCLK 0x10246CUL
+#define REG_TAG_X 0x102470UL
+#define REG_TAG_Y 0x102474UL
+#define REG_TAG 0x102478UL
+#define REG_VOL_PB 0x10247CUL
+#define REG_VOL_SOUND 0x102480UL
+#define REG_SOUND 0x102484UL
+#define REG_PLAY 0x102488UL
+#define REG_GPIO_DIR 0x10248CUL
+#define REG_GPIO 0x102490UL
+#define REG_INT_FLAGS 0x102498UL
+#define REG_INT_EN 0x10249CUL
+#define REG_INT_MASK 0x1024A0UL
+#define REG_PLAYBACK_START 0x1024A4UL
+#define REG_PLAYBACK_LENGTH 0x1024A8UL
+#define REG_PLAYBACK_READPTR 0x1024ACUL
+#define REG_PLAYBACK_FREQ 0x1024B0UL
+#define REG_PLAYBACK_FORMAT 0x1024B4UL
+#define REG_PLAYBACK_LOOP 0x1024B8UL
+#define REG_PLAYBACK_PLAY 0x1024BCUL
+#define REG_PWM_HZ 0x1024C0UL
+#define REG_PWM_DUTY 0x1024C4UL
+#define REG_MACRO_0 0x1024C8UL
+#define REG_MACRO_1 0x1024CCUL
+#define REG_SCREENSHOT_BUSY 0x1024D8UL
+#define REG_CMD_READ 0x1024E4UL
+#define REG_CMD_WRITE 0x1024E8UL
+#define REG_CMD_DL 0x1024ECUL
+#define REG_TOUCH_MODE 0x1024F0UL
+#define REG_TOUCH_ADC_MODE 0x1024F4UL
+#define REG_TOUCH_CHARGE 0x1024F8UL
+#define REG_TOUCH_SETTLE 0x1024FCUL
+#define REG_TOUCH_OVERSAMPLE 0x102500UL
+#define REG_TOUCH_RZTHRESH 0x102504UL
+#define REG_TOUCH_RAW_XY 0x102508UL
+#define REG_TOUCH_RZ 0x10250CUL
+#define REG_TOUCH_SCREEN_XY 0x102510UL
+#define REG_TOUCH_TAG_XY 0x102514UL
+#define REG_TOUCH_TAG 0x102518UL
+#define REG_TOUCH_TRANSFORM_A 0x10251CUL
+#define REG_TOUCH_TRANSFORM_B 0x102520UL
+#define REG_TOUCH_TRANSFORM_C 0x102524UL
+#define REG_TOUCH_TRANSFORM_D 0x102528UL
+#define REG_TOUCH_TRANSFORM_E 0x10252CUL
+#define REG_TOUCH_TRANSFORM_F 0x102530UL
+#define REG_SCREENSHOT_READ 0x102554UL
+#define REG_TRIM 0x10256CUL
+#define REG_TOUCH_DIRECT_XY 0x102574UL
+#define REG_TOUCH_DIRECT_Z1Z2 0x102578UL
+#define REG_TRACKER 0x109000UL
+
+/* FT80x graphics engine specific macros useful for static display list generation */
+#define BITMAP_SOURCE(addr) ((1UL<<24)|(((addr)&1048575UL)<<0))
+#define SCISSOR_SIZE(width,height) ((28UL<<24)|(((width)&1023UL)<<10)|(((height)&1023UL)<<0))
+#define SCISSOR_XY(x,y) ((27UL<<24)|(((x)&511UL)<<9)|(((y)&511UL)<<0))
+
+#endif
+
+#endif /* EVE_H_ */
diff --git a/fw/fe310/eos/eve/eve_font.c b/fw/fe310/eos/eve/eve_font.c
new file mode 100644
index 0000000..e1e3aee
--- /dev/null
+++ b/fw/fe310/eos/eve/eve_font.c
@@ -0,0 +1,59 @@
+#include <stdlib.h>
+
+#include "eve.h"
+#include "eve_font.h"
+
+void eve_font_init(EVEFont *font, uint8_t font_id) {
+ uint32_t p;
+
+ p = eve_read32(EVE_ROM_FONT_ADDR);
+ p += (148 * (font_id - 16));
+ font->id = font_id;
+ font->w = eve_read32(p + 136);
+ font->h = eve_read32(p + 140);
+ eve_readb(p, font->w_ch, 128);
+}
+
+uint8_t eve_font_ch_w(EVEFont *font, utf32_t ch) {
+ if (ch < 128) return font->w_ch[ch];
+ return 0;
+}
+
+uint16_t eve_font_str_w(EVEFont *font, utf8_t *str) {
+ uint16_t r = 0;
+ utf32_t ch;
+ uint8_t ch_w;
+ uint8_t ch_l;
+
+ if (str == NULL) return 0;
+
+ while (*str) {
+ ch_l = utf8_dec(str, &ch);
+ ch_w = eve_font_ch_w(font, ch);
+ r += ch_w;
+ str += ch_l;
+ }
+
+ return r;
+}
+
+uint16_t eve_font_buf_w(EVEFont *font, utf8_t *buf, uint16_t buf_len) {
+ int i = 0;
+ uint16_t r = 0;
+ utf32_t ch;
+ uint8_t ch_w;
+ uint8_t ch_l;
+
+ while (i < buf_len) {
+ ch_l = utf8_dec(buf + i, &ch);
+ ch_w = eve_font_ch_w(font, ch);
+ r += ch_w;
+ i += ch_l;
+ }
+
+ return r;
+}
+
+uint8_t eve_font_h(EVEFont *font) {
+ return font->h;
+}
diff --git a/fw/fe310/eos/eve/eve_font.h b/fw/fe310/eos/eve/eve_font.h
new file mode 100644
index 0000000..87ef41f
--- /dev/null
+++ b/fw/fe310/eos/eve/eve_font.h
@@ -0,0 +1,16 @@
+#include <stdint.h>
+
+#include "unicode.h"
+
+typedef struct EVEFont {
+ uint8_t id;
+ uint8_t w;
+ uint8_t h;
+ uint8_t w_ch[128];
+} EVEFont;
+
+void eve_font_init(EVEFont *font, uint8_t font_id);
+uint8_t eve_font_ch_w(EVEFont *font, utf32_t ch);
+uint16_t eve_font_str_w(EVEFont *font, utf8_t *str);
+uint16_t eve_font_buf_w(EVEFont *font, utf8_t *buf, uint16_t buf_len);
+uint8_t eve_font_h(EVEFont *font);
diff --git a/fw/fe310/eos/eve/eve_kbd.c b/fw/fe310/eos/eve/eve_kbd.c
new file mode 100644
index 0000000..c8c1362
--- /dev/null
+++ b/fw/fe310/eos/eve/eve_kbd.c
@@ -0,0 +1,162 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include "eve.h"
+#include "eve_kbd.h"
+
+#define KEY_SPACERX 3
+#define KEY_SPACERY 5
+#define KEY_FONT 29
+#define MOD_FONT 21
+
+#define KEY_BS 0x08
+#define KEY_RET 0x0a
+
+#define FLAG_SHIFT 0x01
+#define FLAG_CTRL 0x02
+#define FLAG_FN 0x04
+
+#define TAG_SHIFT 0x11
+#define TAG_CTRL 0x12
+#define TAG_FN 0x13
+
+void eve_kbd_init(EVEKbd *kbd, EVERect *g, uint32_t mem_addr, uint32_t *mem_next) {
+ uint16_t mem_size;
+
+ kbd->g = *g;
+ kbd->mem_addr = mem_addr;
+ kbd->key_modifier = 0;
+ kbd->key_modifier_sticky = 0;
+ kbd->key_modifier_lock = 0;
+ kbd->key_count = 0;
+ kbd->key_down = 0;
+ kbd->putc = NULL;
+ kbd->param = NULL;
+
+ kbd->key_down = 0xff;
+ eve_write16(REG_CMD_DL, 0);
+ eve_kbd_draw(kbd);
+ 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->key_down = 0;
+ kbd->mem_size = mem_size;
+
+ *mem_next = kbd->mem_addr + kbd->mem_size;
+}
+
+void eve_kbd_close(EVEKbd *kbd) {
+ kbd->key_modifier = 0;
+ kbd->key_modifier_sticky = 0;
+ kbd->key_modifier_lock = 0;
+ kbd->key_count = 0;
+ kbd->key_down = 0;
+ kbd->putc = NULL;
+ kbd->param = NULL;
+}
+
+void eve_kbd_set_handler(EVEKbd *kbd, eve_kbd_input_handler_t putc, void *param) {
+ kbd->putc = putc;
+ kbd->param = param;
+}
+
+int eve_kbd_touch(EVEKbd *kbd, EVETouch *touch, uint16_t evt, uint8_t tag0) {
+ int ret;
+
+ evt = eve_touch_evt(touch, evt, tag0, 1, 126);
+ if (touch && evt) {
+ int8_t touch_idx = eve_touch_get_idx(touch);
+
+ if (evt & EVE_TOUCH_ETYPE_TAG) {
+ uint8_t _tag = touch->tag;
+
+ if (_tag >= TAG_SHIFT && _tag <= TAG_FN) {
+ if (touch_idx == 0) {
+ uint8_t f = (1 << (_tag - TAG_SHIFT));
+
+ kbd->key_modifier = f;
+ kbd->key_modifier_sticky &= f;
+ kbd->key_modifier_lock &= f;
+ if (kbd->key_modifier_lock & f) {
+ kbd->key_modifier_lock &= ~f;
+ } else if (kbd->key_modifier_sticky & f) {
+ kbd->key_modifier_sticky &= ~f;
+ kbd->key_modifier_lock |= f;
+ } else {
+ kbd->key_modifier_sticky |= f;
+ }
+ }
+ } else {
+ kbd->key_count++;
+ kbd->key_down = _tag;
+ if (kbd->putc) {
+ int c = _tag;
+
+ if ((kbd->key_modifier & FLAG_CTRL) && (_tag >= '?') && (_tag <= '_')) c = (_tag - '@') & 0x7f;
+ kbd->putc(kbd->param, c);
+ }
+ }
+ }
+ if (evt & EVE_TOUCH_ETYPE_TAG_UP) {
+ uint8_t _tag = touch->tag_up;
+
+ if (_tag >= TAG_SHIFT && _tag <= TAG_FN) {
+ if (touch_idx == 0) {
+ uint8_t f = (1 << (_tag - TAG_SHIFT));
+
+ if (!((kbd->key_modifier_lock | kbd->key_modifier_sticky) & f)) {
+ kbd->key_modifier &= ~f;
+ }
+ }
+ } else {
+ if (kbd->key_count) kbd->key_count--;
+ if (!kbd->key_count) kbd->key_down = 0;
+ if (kbd->key_modifier_sticky) {
+ if (touch_idx == 0) kbd->key_modifier &= ~kbd->key_modifier_sticky;
+ kbd->key_modifier_sticky = 0;
+ }
+ }
+ }
+ ret = 1;
+ } else {
+ ret = 0;
+ }
+
+ return ret;
+}
+
+uint8_t eve_kbd_draw(EVEKbd *kbd) {
+ if (kbd->key_down || kbd->key_modifier) {
+ int x = kbd->g.x;
+ int y = kbd->g.y;
+ int w = kbd->g.w;
+ int row_h = kbd->g.h / 5;
+ int key_w = (w - 9 * KEY_SPACERX) / 10 + 1;
+ int mod_w = key_w + key_w / 2;
+ int key_h = row_h - KEY_SPACERY;
+
+ eve_cmd_dl(SAVE_CONTEXT());
+ eve_cmd(CMD_KEYS, "hhhhhhs", x, y + row_h * 0, w, key_h, KEY_FONT, kbd->key_down, kbd->key_modifier & (FLAG_FN | FLAG_SHIFT) ? "!@#$%^&*()" : (kbd->key_modifier & FLAG_CTRL ? " @[\\]^_? " : "1234567890"));
+ eve_cmd(CMD_KEYS, "hhhhhhs", x, y + row_h * 1, w, key_h, KEY_FONT, kbd->key_down, kbd->key_modifier & FLAG_FN ? "-_=+[]{}\\|" : kbd->key_modifier & (FLAG_SHIFT | FLAG_CTRL) ? "QWERTYUIOP" : "qwertyuiop");
+ eve_cmd(CMD_KEYS, "hhhhhhs", x + key_w / 2, y + row_h * 2, w - key_w, key_h, KEY_FONT, kbd->key_down, kbd->key_modifier & FLAG_FN ? "`~ ;:'\"" : kbd->key_modifier & (FLAG_SHIFT | FLAG_CTRL) ? "ASDFGHJKL" : "asdfghjkl");
+ eve_cmd(CMD_KEYS, "hhhhhhs", x + mod_w + KEY_SPACERX, y + row_h * 3, w - 2 * (mod_w + KEY_SPACERX), key_h, KEY_FONT, kbd->key_down, kbd->key_modifier & FLAG_FN ? " ,.<>/?" : kbd->key_modifier & (FLAG_SHIFT | FLAG_CTRL) ? "ZXCVBNM" : "zxcvbnm");
+ eve_cmd_dl(TAG(TAG_SHIFT));
+ eve_cmd(CMD_BUTTON, "hhhhhhs", x, y + row_h * 3, mod_w, key_h, MOD_FONT, kbd->key_modifier & FLAG_SHIFT ? EVE_OPT_FLAT : 0, "shift");
+ eve_cmd_dl(TAG(KEY_BS));
+ eve_cmd(CMD_BUTTON, "hhhhhhs", x + w - mod_w, y + row_h * 3, mod_w, key_h, MOD_FONT, kbd->key_down == KEY_BS ? EVE_OPT_FLAT : 0, "del");
+ eve_cmd_dl(TAG(TAG_FN));
+ eve_cmd(CMD_BUTTON, "hhhhhhs", x, y + row_h * 4, mod_w, key_h, MOD_FONT, kbd->key_modifier & FLAG_FN ? EVE_OPT_FLAT : 0, "fn");
+ eve_cmd_dl(TAG(TAG_CTRL));
+ eve_cmd(CMD_BUTTON, "hhhhhhs", x + mod_w + KEY_SPACERX, y + row_h * 4, mod_w, key_h, MOD_FONT, kbd->key_modifier & FLAG_CTRL ? EVE_OPT_FLAT : 0, "ctrl");
+ eve_cmd_dl(TAG(' '));
+ eve_cmd(CMD_BUTTON, "hhhhhhs", x + 2 * (mod_w + KEY_SPACERX), y + row_h * 4, w - 3 * (mod_w + KEY_SPACERX), key_h, MOD_FONT, kbd->key_down == ' ' ? EVE_OPT_FLAT : 0, "");
+ eve_cmd_dl(TAG(KEY_RET));
+ eve_cmd(CMD_BUTTON, "hhhhhhs", x + w - mod_w, y + row_h * 4, mod_w, key_h, MOD_FONT, 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 0x80;
+}
diff --git a/fw/fe310/eos/eve/eve_kbd.h b/fw/fe310/eos/eve/eve_kbd.h
new file mode 100644
index 0000000..b4f9874
--- /dev/null
+++ b/fw/fe310/eos/eve/eve_kbd.h
@@ -0,0 +1,23 @@
+#include <stdint.h>
+
+typedef void (*eve_kbd_input_handler_t) (void *, int);
+
+typedef struct EVEKbd {
+ EVERect g;
+ uint32_t mem_addr;
+ uint16_t mem_size;
+ uint8_t key_count;
+ uint8_t key_down;
+ uint8_t key_modifier;
+ uint8_t key_modifier_sticky;
+ uint8_t key_modifier_lock;
+ char active;
+ eve_kbd_input_handler_t putc;
+ void *param;
+} EVEKbd;
+
+void eve_kbd_init(EVEKbd *kbd, EVERect *g, uint32_t mem_addr, uint32_t *mem_next);
+void eve_kbd_close(EVEKbd *kbd);
+void eve_kbd_set_handler(EVEKbd *kbd, eve_kbd_input_handler_t putc, void *param);
+int eve_kbd_touch(EVEKbd *kbd, EVETouch *touch, uint16_t evt, uint8_t tag0);
+uint8_t eve_kbd_draw(EVEKbd *kbd);
diff --git a/fw/fe310/eos/eve/eve_phy.c b/fw/fe310/eos/eve/eve_phy.c
new file mode 100644
index 0000000..1e255fe
--- /dev/null
+++ b/fw/fe310/eos/eve/eve_phy.c
@@ -0,0 +1,77 @@
+#include <stdlib.h>
+#include <math.h>
+
+#include "eve_platform.h"
+#include "eve_phy.h"
+
+/* Constant accelerator */
+void eve_phy_acc_init(EVEPhyAcc *param, int a) {
+ param->a = a;
+}
+
+void eve_phy_acc_start(EVEPhyAcc *param, int x0, int y0, int v0x, int v0y) {
+ double v0 = sqrt(v0x * v0x + v0y * v0y);
+
+ param->x0 = x0;
+ param->y0 = y0;
+ param->v0x = v0x;
+ param->v0y = v0y;
+ param->k = 2 * v0 / param->a * EVE_RTC_FREQ;
+}
+
+int eve_phy_acc_tick(EVEPhyAcc *param, int dt, int *x, int *y) {
+ int k = param->k;
+ int x0 = param->x0;
+ int y0 = param->y0;
+ int v0x = param->v0x;
+ int v0y = param->v0y;
+ int more = 1;
+
+ if ((k < 0) && (dt >= -k / 2)) {
+ dt = -k / 2;
+ more = 0;
+ }
+ if (x) *x = x0 + (v0x * dt + v0x * dt / k * dt) / (int)(EVE_RTC_FREQ);
+ if (y) *y = y0 + (v0y * dt + v0y * dt / k * dt) / (int)(EVE_RTC_FREQ);
+
+ return more;
+}
+
+/* Linear harmonic oscillator */
+void eve_phy_lho_init(EVEPhyLHO *param, int x, int y, uint32_t T, double d, uint32_t t_max) {
+ double f0 = 2 * M_PI / (T * EVE_RTC_FREQ / 1000);
+
+ if (d < 0) d = 0;
+ if (d > 1) d = 1;
+ param->x = x;
+ param->y = y;
+ param->f = f0 * sqrt(1 - d * d);
+ param->a = -d * f0;
+ param->t_max = t_max * EVE_RTC_FREQ / 1000;
+}
+
+int eve_phy_lho_start(EVEPhyLHO *param, int x0, int y0) {
+ param->x0 = x0;
+ param->y0 = y0;
+}
+
+int eve_phy_lho_tick(EVEPhyLHO *param, int dt, int *x, int *y) {
+ int ax = param->x0 - param->x;
+ int ay = param->y0 - param->y;
+ int more = 1;
+
+ if (param->t_max && (dt >= param->t_max)) {
+ dt = param->t_max;
+ more = 0;
+ }
+ if (param->a) {
+ double e = exp(param->a * dt);
+ ax = ax * e;
+ ay = ay * e;
+ if ((ax == 0) && (ay == 0)) more = 0;
+ }
+ if (x) *x = param->x + ax * cos(param->f * dt);
+ if (y) *y = param->y + ay * cos(param->f * dt);
+
+ return more;
+}
diff --git a/fw/fe310/eos/eve/eve_phy.h b/fw/fe310/eos/eve/eve_phy.h
new file mode 100644
index 0000000..1be5fd0
--- /dev/null
+++ b/fw/fe310/eos/eve/eve_phy.h
@@ -0,0 +1,28 @@
+#include <stdint.h>
+
+typedef struct EVEPhyAcc {
+ int a;
+ int k;
+ int x0;
+ int y0;
+ int v0x;
+ int v0y;
+} EVEPhyAcc;
+
+void eve_phy_acc_init(EVEPhyAcc *param, int a);
+void eve_phy_acc_start(EVEPhyAcc *param, int x0, int y0, int v0x, int v0y);
+int eve_phy_acc_tick(EVEPhyAcc *param, int dt, int *x, int *y);
+
+typedef struct EVEPhyLHO {
+ int x;
+ int y;
+ double f;
+ double a;
+ uint32_t t_max;
+ int x0;
+ int y0;
+} EVEPhyLHO;
+
+void eve_phy_lho_init(EVEPhyLHO *param, int x, int y, uint32_t T, double d, uint32_t t_max);
+int eve_phy_lho_start(EVEPhyLHO *param, int x0, int y0);
+int eve_phy_lho_tick(EVEPhyLHO *param, int dt, int *x, int *y); \ No newline at end of file
diff --git a/fw/fe310/eos/eve/eve_platform.c b/fw/fe310/eos/eve/eve_platform.c
new file mode 100644
index 0000000..6bc87bb
--- /dev/null
+++ b/fw/fe310/eos/eve/eve_platform.c
@@ -0,0 +1,80 @@
+#include <stdlib.h>
+
+#include "platform.h"
+
+#include "eos.h"
+#include "interrupt.h"
+#include "event.h"
+
+#include "eve.h"
+#include "eve_platform.h"
+
+
+static void handle_time(unsigned char type) {
+ eve_handle_time();
+}
+
+static void handle_evt(unsigned char type, unsigned char *buffer, uint16_t len) {
+ eve_handle_touch();
+
+ GPIO_REG(GPIO_LOW_IP) = (1 << EVE_PIN_INTR);
+ GPIO_REG(GPIO_LOW_IE) |= (1 << EVE_PIN_INTR);
+}
+
+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;
+}
+
+void eve_time_sleep(uint32_t ms) {
+ eos_time_sleep(ms);
+}
+
+void eve_timer_set(uint32_t ms) {
+ eos_timer_set(ms, EOS_TIMER_ETYPE_UI);
+}
+
+void eve_timer_clear(void) {
+ eos_timer_clear(EOS_TIMER_ETYPE_UI);
+}
+
+uint64_t eve_time_get_tick(void) {
+ return eos_time_get_tick();
+}
+
+void eve_platform_init(void) {
+ 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_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_INTR);
+ eos_intr_set(INT_GPIO_BASE + EVE_PIN_INTR, IRQ_PRIORITY_UI, handle_intr);
+
+ eos_spi_set_div(EOS_SPI_DEV_EVE, 4);
+}
+
+void eve_spi_start(void) {
+ eos_spi_select(EOS_SPI_DEV_EVE);
+}
+
+void eve_spi_stop(void) {
+ eos_spi_deselect();
+}
+
+#include <stdio.h>
+
+void *eve_malloc(size_t size) {
+ void *p = malloc(size);
+ printf("MALLOC:%p %d\n", p, size);
+ return p;
+}
+
+void eve_free(void *p) {
+ printf("FREE:%p\n", p);
+ free(p);
+}
diff --git a/fw/fe310/eos/eve/eve_platform.h b/fw/fe310/eos/eve/eve_platform.h
new file mode 100644
index 0000000..7975fbc
--- /dev/null
+++ b/fw/fe310/eos/eve/eve_platform.h
@@ -0,0 +1,39 @@
+#include <stdint.h>
+
+#include "spi.h"
+#include "spi_dev.h"
+#include "timer.h"
+
+#define EVE_ETYPE_INTR 1
+#define EVE_PIN_INTR 0
+
+#define EVE_RTC_FREQ EOS_TIMER_RTC_FREQ
+
+#define EVE_SPI_FLAG_BSWAP EOS_SPI_FLAG_BSWAP
+#define EVE_SPI_FLAG_TX EOS_SPI_FLAG_TX
+
+void *eve_malloc(size_t);
+void eve_free(void *);
+
+//#define eve_malloc malloc
+//#define eve_free free
+
+void eve_spi_start(void);
+void eve_spi_stop(void);
+
+#define eve_spi_cs_set eos_spi_cs_set
+#define eve_spi_cs_clear eos_spi_cs_clear
+#define eve_spi_flush eos_spi_flush
+#define eve_spi_xchg8 eos_spi_xchg8
+#define eve_spi_xchg16 eos_spi_xchg16
+#define eve_spi_xchg24 eos_spi_xchg24
+#define eve_spi_xchg32 eos_spi_xchg32
+#define eve_spi_lock eos_spi_lock
+#define eve_spi_unlock eos_spi_unlock
+
+void eve_time_sleep(uint32_t ms);
+void eve_timer_set(uint32_t ms);
+void eve_timer_clear(void);
+uint64_t eve_time_get_tick(void);
+
+void eve_platform_init(void);
diff --git a/fw/fe310/eos/eve/eve_text.c b/fw/fe310/eos/eve/eve_text.c
new file mode 100644
index 0000000..b52678d
--- /dev/null
+++ b/fw/fe310/eos/eve/eve_text.c
@@ -0,0 +1,209 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include "eve.h"
+#include "eve_text.h"
+
+#define TEXT_ATTR 0x0A
+#define TEXT_CRSR 0x02DB
+
+#define LINE_IDX_ADD(l1,l2,s) (((((l1) + (l2)) % (s)) + (s)) % (s))
+#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) + (l1) - (l2))
+
+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);
+ eve_text_update(box);
+ box->dirty = 1;
+}
+
+void eve_text_init(EVEText *box, EVERect *g, uint16_t w, uint16_t h, uint16_t line_size, uint32_t mem_addr, uint32_t *mem_next) {
+ double scale_x, scale_y;
+
+ if (g->w == 0) {
+ g->w = w * 8;
+ }
+ if (g->h == 0) {
+ g->h = h * 16;
+ }
+
+ scale_x = (double)g->w / (w * 8);
+ scale_y = (double)g->h / (h * 16);
+ box->g = *g;
+ box->w = w;
+ box->h = h;
+ box->tag = EVE_NOTAG;
+ box->transform_a = 256 / scale_x;
+ box->transform_e = 256 / scale_y;
+ box->ch_w = scale_x * 8;
+ box->ch_h = scale_y * 16;
+ box->dl_size = 14;
+ 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;
+ }
+ if (box->transform_e != 256) {
+ box->dl_size += 1;
+ }
+
+ eve_cmd(CMD_MEMSET, "www", mem_addr, 0x0, box->w * 2 * box->line_size);
+ eve_cmd_exec(1);
+
+ eve_text_update(box);
+ *mem_next = box->mem_addr + box->w * 2 * box->line_size + box->dl_size * 4;
+}
+
+void eve_text_update(EVEText *box) {
+ int text_h1;
+ int text_h2;
+ int line_top;
+
+ line_top = box->line_top >= 0 ? box->line_top : box->line0;
+
+ 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;
+ }
+
+ eve_dl_start(box->mem_addr + box->w * 2 * box->line_size, 1);
+ eve_dl_write(BEGIN(EVE_BITMAPS));
+ eve_dl_write(VERTEX_FORMAT(0));
+ eve_dl_write(BITMAP_HANDLE(15));
+ if (box->transform_a != 256) {
+ eve_dl_write(BITMAP_TRANSFORM_A(box->transform_a));
+ }
+ if (box->transform_e != 256) {
+ eve_dl_write(BITMAP_TRANSFORM_E(box->transform_e));
+ }
+ 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->g.x, box->g.y));
+
+ if (text_h2) {
+ 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->g.x, box->g.y + text_h1 * box->ch_h));
+ } else {
+ eve_dl_write(NOP());
+ eve_dl_write(NOP());
+ eve_dl_write(NOP());
+ eve_dl_write(NOP());
+ eve_dl_write(NOP());
+ }
+
+ eve_dl_write(END());
+ eve_dl_end();
+}
+
+void eve_text_scroll0(EVEText *box) {
+ if (box->line_top >= 0) {
+ box->line_top = -1;
+ box->line_top0 = -1;
+ eve_text_update(box);
+ }
+}
+
+int eve_text_touch(EVEText *box, EVETouch *touch, uint16_t evt, uint8_t tag0) {
+ evt = eve_touch_evt(touch, evt, tag0, box->tag, 1);
+ if (touch && evt) {
+ if ((evt & EVE_TOUCH_ETYPE_TRACK_START) && (box->line_top < 0)) {
+ box->line_top = box->line0;
+ box->line_top0 = box->line0;
+ }
+ if ((evt & EVE_TOUCH_ETYPE_TRACK) && (box->line_top0 >=0)) {
+ int line = LINE_IDX_ADD(box->line_top0, (touch->y0 - touch->y) / box->ch_h, box->line_size);
+ if (LINE_IDX_LTE(line, box->line0, box->line_size, box->h)) {
+ box->line_top = line;
+ eve_text_update(box);
+ }
+ }
+ if (evt & EVE_TOUCH_ETYPE_TRACK_STOP) {
+ box->line_top0 = box->line_top;
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+
+uint8_t eve_text_draw(EVEText *box, uint8_t tag) {
+ eve_cmd_dl(SAVE_CONTEXT());
+ box->tag = tag;
+ if (tag != EVE_NOTAG) {
+ eve_cmd_dl(TAG(tag));
+ eve_touch_set_opt(tag, EVE_TOUCH_OPT_TRACK | EVE_TOUCH_OPT_TRACK_EXT_Y);
+ tag++;
+ }
+ eve_cmd(CMD_APPEND, "ww", box->mem_addr + box->w * 2 * box->line_size, box->dl_size * 4);
+ eve_cmd_dl(RESTORE_CONTEXT());
+
+ return tag;
+}
+
+void 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;
+ }
+}
+
+void eve_text_backspace(EVEText *box) {
+ uint16_t c;
+
+ 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);
+ }
+ eve_write16(box->mem_addr + box->ch_idx, TEXT_CRSR);
+}
+
+void eve_text_newline(EVEText *box) {
+ int line = (box->ch_idx / 2 / box->w + 1) % box->line_size;
+
+ 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 eve_text_puts(EVEText *box, char *s) {
+ while (*s) {
+ eve_text_putc(box, *s);
+ s++;
+ }
+}
diff --git a/fw/fe310/eos/eve/eve_text.h b/fw/fe310/eos/eve/eve_text.h
new file mode 100644
index 0000000..3b282c9
--- /dev/null
+++ b/fw/fe310/eos/eve/eve_text.h
@@ -0,0 +1,32 @@
+#include <stdint.h>
+
+typedef struct EVEText {
+ EVERect g;
+ 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;
+ uint8_t ch_h;
+ uint8_t ch_w;
+ uint8_t dl_size;
+ char dirty;
+} EVEText;
+
+void eve_text_init(EVEText *box, EVERect *g, uint16_t w, uint16_t h, uint16_t line_size, uint32_t mem_addr, uint32_t *mem_next);
+void eve_text_update(EVEText *box);
+void eve_text_scroll0(EVEText *box);
+
+int eve_text_touch(EVEText *box, EVETouch *touch, uint16_t evt, uint8_t tag0);
+uint8_t eve_text_draw(EVEText *box, uint8_t tag);
+
+void eve_text_putc(EVEText *box, int c);
+void eve_text_backspace(EVEText *box);
+void eve_text_newline(EVEText *box);
+void eve_text_puts(EVEText *box, char *s);
diff --git a/fw/fe310/eos/eve/eve_touch.c b/fw/fe310/eos/eve/eve_touch.c
new file mode 100644
index 0000000..e75cf4e
--- /dev/null
+++ b/fw/fe310/eos/eve/eve_touch.c
@@ -0,0 +1,419 @@
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "eve.h"
+
+static int touch_intr_mask = EVE_INT_TAG | EVE_INT_TOUCH;
+static int touch_multi;
+static uint8_t touch_tag0;
+
+static EVETouch touch_obj[EVE_MAX_TOUCH];
+static EVETouchTimer touch_timer;
+
+static eve_touch_handler_t touch_handler;
+static void *touch_handler_param;
+static uint8_t touch_tag_opt[256];
+
+static const uint32_t _reg_touch[] = {
+ REG_CTOUCH_TOUCH0_XY,
+ REG_CTOUCH_TOUCH1_XY,
+ REG_CTOUCH_TOUCH2_XY,
+ REG_CTOUCH_TOUCH3_XY
+};
+
+static const uint32_t _reg_tag[] = {
+ REG_TOUCH_TAG,
+ REG_TOUCH_TAG1,
+ REG_TOUCH_TAG2,
+ REG_TOUCH_TAG3,
+ REG_TOUCH_TAG4
+};
+
+static const uint32_t _reg_track[] = {
+ REG_TRACKER,
+ REG_TRACKER_1,
+ REG_TRACKER_2,
+ REG_TRACKER_3,
+ REG_TRACKER_4
+};
+
+void eve_handle_touch(void) {
+ int i;
+ char touch_ex = 0;
+ char int_ccomplete = 0;
+ uint8_t flags;
+
+ eve_spi_start();
+
+ flags = eve_read8(REG_INT_FLAGS) & touch_intr_mask;
+ if (!touch_multi && (flags & EVE_INT_TOUCH)) touch_multi = 1;
+ for (i=0; i<EVE_MAX_TOUCH; i++) {
+ uint8_t touch_tag;
+ uint32_t touch_xy;
+ uint64_t now = 0;
+ uint16_t touch_evt = 0;
+ EVETouch *touch = &touch_obj[i];
+
+ 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 != EVE_NOTOUCH) {
+ int16_t touch_x = touch_xy >> 16;
+ int16_t touch_y = touch_xy & 0xffff;
+ now = eve_time_get_tick();
+ if (touch->eevt & EVE_TOUCH_EETYPE_NOTOUCH) {
+ uint16_t _evt = 0;
+ uint16_t _eevt = 0;
+ uint16_t _ttevt = eve_touch_timer_get_evt(touch);
+
+ if (_ttevt) {
+ touch->eevt &= ~EVE_TOUCH_EETYPE_NOTOUCH;
+
+ if (_ttevt & EVE_TOUCH_ETYPE_TAP2) {
+ 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_TOUCH_THRESHOLD_X) || (dy > EVE_TOUCH_THRESHOLD_Y)) {
+ touch_evt |= EVE_TOUCH_ETYPE_TAP1;
+ } else {
+ _evt |= EVE_TOUCH_ETYPE_TAP2;
+ _eevt |= EVE_TOUCH_EETYPE_TAP2;
+ }
+ }
+ if (_ttevt & EVE_TOUCH_ETYPE_TRACK) {
+ EVEVTrack *vtrack = eve_vtrack_get();
+
+ _eevt |= EVE_TOUCH_EETYPE_TRACK_ABORT;
+ touch_evt |= (EVE_TOUCH_ETYPE_TRACK_STOP | EVE_TOUCH_ETYPE_TRACK_ABORT);
+ if (vtrack->stop) vtrack->stop(touch, vtrack->param);
+ }
+ if (_ttevt & EVE_TOUCH_ETYPE_TIMER) {
+ _eevt |= EVE_TOUCH_EETYPE_TIMER_ABORT;
+ touch_evt |= EVE_TOUCH_ETYPE_TIMER_ABORT;
+ }
+
+ eve_touch_timer_clear(touch);
+ if (touch_handler && touch_evt) {
+ touch_handler(touch_timer.touch, touch_evt, touch_timer.tag0, touch_handler_param);
+ }
+ }
+ touch_evt = EVE_TOUCH_ETYPE_POINT | _evt;
+ touch->eevt = _eevt;
+ 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)(EVE_RTC_FREQ) / dt;
+ int vy = ((int)touch_y - touch->y) * (int)(EVE_RTC_FREQ) / dt;
+ touch->vx = touch->vx ? (vx + touch->vx * EVE_TOUCH_TRAVG) / (EVE_TOUCH_TRAVG + 1) : vx;
+ touch->vy = touch->vy ? (vy + touch->vy * EVE_TOUCH_TRAVG) / (EVE_TOUCH_TRAVG + 1) : vy;
+ touch->t = now;
+ }
+ touch->x = touch_x;
+ touch->y = touch_y;
+ if (touch_multi || (flags & EVE_INT_TAG)) {
+ touch_tag = eve_read8(_reg_tag[i]);
+ } else {
+ touch_tag = touch->tag;
+ }
+ touch_ex = 1;
+ } else {
+ touch_tag = 0;
+ if (!(touch->eevt & EVE_TOUCH_EETYPE_NOTOUCH)) {
+ uint16_t _ttevt = eve_touch_timer_get_evt(touch);
+
+ touch_evt = EVE_TOUCH_ETYPE_POINT_UP;
+ touch->eevt |= EVE_TOUCH_EETYPE_NOTOUCH;
+ if (_ttevt & EVE_TOUCH_ETYPE_LPRESS) {
+ eve_touch_timer_set_evt(touch, _ttevt & ~EVE_TOUCH_ETYPE_LPRESS);
+ }
+ if (touch->tracker.tag && touch->tracker.track) {
+ uint8_t opt = touch_tag_opt[touch->tracker.tag];
+ char track_ext = ((opt & EVE_TOUCH_OPT_TRACK_EXT_X) && (touch->eevt & EVE_TOUCH_EETYPE_TRACK_X)) ||
+ ((opt & EVE_TOUCH_OPT_TRACK_EXT_Y) && (touch->eevt & EVE_TOUCH_EETYPE_TRACK_Y));
+ if (!eve_touch_timer_get_evt(NULL) && track_ext) {
+ EVEVTrack *vtrack = eve_vtrack_get();
+
+ eve_touch_timer_set(touch, EVE_TOUCH_ETYPE_TRACK, touch_tag0, EVE_TOUCH_TIMEOUT_TRACK);
+ if (vtrack->start) vtrack->start(touch, vtrack->param);
+ } else {
+ touch_evt |= EVE_TOUCH_ETYPE_TRACK_STOP;
+ }
+ }
+ }
+ }
+ if (touch_tag != touch->tag) {
+ if (touch_tag) {
+ if (!touch_tag0) touch_tag0 = touch_tag;
+ if (!touch->tag0) {
+ touch->tag0 = touch_tag;
+ if (touch_tag_opt[touch_tag] & (EVE_TOUCH_OPT_TRACK | EVE_TOUCH_OPT_TRACK_REG)) {
+ touch->tracker.tag = touch_tag;
+ }
+ if (touch->tracker.tag && !(touch_tag_opt[touch->tracker.tag] & EVE_TOUCH_OPT_TRACK_XY)) {
+ touch_evt |= EVE_TOUCH_ETYPE_TRACK_START;
+ touch->tracker.track = 1;
+ touch->t = now;
+ }
+ if (!eve_touch_timer_get_evt(NULL) && (touch_tag_opt[touch_tag] & (EVE_TOUCH_OPT_LPRESS | EVE_TOUCH_OPT_TAP2))) {
+ uint16_t _evt = 0;
+
+ if (touch_tag_opt[touch_tag] & EVE_TOUCH_OPT_LPRESS) _evt |= EVE_TOUCH_ETYPE_LPRESS;
+ if (touch_tag_opt[touch_tag] & EVE_TOUCH_OPT_TAP2) _evt |= EVE_TOUCH_ETYPE_TAP2;
+ eve_touch_timer_set(touch, _evt, touch_tag0, EVE_TOUCH_TIMEOUT_TAP);
+ }
+ }
+ }
+ 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_xy != EVE_NOTOUCH) {
+ uint16_t _ttevt = eve_touch_timer_get_evt(touch);
+ int _track = touch->tracker.tag && !touch->tracker.track;
+ int _timer = _ttevt & (EVE_TOUCH_ETYPE_LPRESS | EVE_TOUCH_ETYPE_TAP2);
+ if (_track || _timer) {
+ 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_TOUCH_THRESHOLD_X) && !(touch_tag_opt[touch->tracker.tag] & EVE_TOUCH_OPT_TRACK_X)) {
+ touch->tracker.tag = 0;
+ }
+ if ((dy > EVE_TOUCH_THRESHOLD_Y) && !(touch_tag_opt[touch->tracker.tag] & EVE_TOUCH_OPT_TRACK_Y)) {
+ touch->tracker.tag = 0;
+ }
+ if (touch->tracker.tag && ((dx > EVE_TOUCH_THRESHOLD_X) || (dy > EVE_TOUCH_THRESHOLD_Y))) {
+ if (dx > EVE_TOUCH_THRESHOLD_X) {
+ touch->eevt |= touch->x > touch->x0 ? EVE_TOUCH_EETYPE_TRACK_RIGHT : EVE_TOUCH_EETYPE_TRACK_LEFT;
+ }
+ if (dy > EVE_TOUCH_THRESHOLD_Y) {
+ touch->eevt |= touch->y > touch->y0 ? EVE_TOUCH_EETYPE_TRACK_DOWN : EVE_TOUCH_EETYPE_TRACK_UP;
+ }
+ touch_evt |= EVE_TOUCH_ETYPE_TRACK_START;
+ touch->tracker.track = 1;
+ touch->t = now;
+ }
+ }
+ if (_timer && ((dx > EVE_TOUCH_THRESHOLD_X) || (dy > EVE_TOUCH_THRESHOLD_Y))) {
+ eve_touch_timer_set_evt(touch, _ttevt & ~(EVE_TOUCH_ETYPE_LPRESS | EVE_TOUCH_ETYPE_TAP2));
+ _timer = 0;
+ }
+ }
+ if (touch->tracker.tag && touch->tracker.track) {
+ if (touch_tag_opt[touch->tracker.tag] & EVE_TOUCH_OPT_TRACK) touch_evt |= EVE_TOUCH_ETYPE_TRACK;
+ if (touch_tag_opt[touch->tracker.tag] & EVE_TOUCH_OPT_TRACK_REG) touch_evt |= EVE_TOUCH_ETYPE_TRACK_REG;
+ }
+ 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 || _timer) int_ccomplete = 1;
+ }
+ if (touch_handler && touch_evt) {
+ touch_handler(touch, touch_evt, touch_tag0, touch_handler_param);
+ }
+ if (!touch_multi) break;
+ }
+
+ if (!touch_ex) {
+ touch_tag0 = 0;
+ touch_multi = 0;
+ }
+
+ if (touch_multi) int_ccomplete = 1;
+
+ if (int_ccomplete && !(touch_intr_mask & EVE_INT_CONVCOMPLETE)) {
+ touch_intr_mask |= EVE_INT_CONVCOMPLETE;
+ eve_write8(REG_INT_MASK, touch_intr_mask);
+ }
+ if (!int_ccomplete && (touch_intr_mask & EVE_INT_CONVCOMPLETE)) {
+ touch_intr_mask &= ~EVE_INT_CONVCOMPLETE;
+ eve_write8(REG_INT_MASK, touch_intr_mask);
+ }
+
+ eve_spi_stop();
+}
+
+void eve_handle_time(void) {
+ EVETouch *touch = touch_timer.touch;
+
+ if (touch_timer.evt) {
+ int more = 0;
+ uint16_t touch_evt = 0;
+
+ eve_spi_start();
+
+ if (touch_timer.evt & EVE_TOUCH_ETYPE_LPRESS) {
+ touch_evt |= EVE_TOUCH_ETYPE_LPRESS;
+ if (touch) touch->eevt |= EVE_TOUCH_EETYPE_LPRESS;
+ }
+ if (touch_timer.evt & EVE_TOUCH_ETYPE_TAP2) {
+ touch_evt |= EVE_TOUCH_ETYPE_TAP1;
+ }
+ if (touch_timer.evt & EVE_TOUCH_ETYPE_TRACK) {
+ EVEVTrack *vtrack = eve_vtrack_get();
+
+ if (vtrack->tick) {
+ touch_evt |= EVE_TOUCH_ETYPE_TRACK;
+ more = vtrack->tick(touch, vtrack->param);
+ }
+ if (!more) {
+ touch_evt |= EVE_TOUCH_ETYPE_TRACK_STOP;
+ if (vtrack->stop) vtrack->stop(touch, vtrack->param);
+ }
+ }
+ if (touch_timer.evt & EVE_TOUCH_ETYPE_TIMER) {
+ touch_evt |= EVE_TOUCH_ETYPE_TIMER;
+ more = 1;
+ }
+
+ if (more) {
+ eve_timer_set(touch_timer.to);
+ } else {
+ touch_timer.evt = 0;
+ }
+
+ if (touch_handler && touch_evt) {
+ touch_handler(touch, touch_evt, touch_timer.tag0, touch_handler_param);
+ }
+
+ eve_spi_stop();
+ }
+}
+
+void eve_touch_init(void) {
+ int i;
+
+ eve_vtrack_init();
+
+ for (i=0; i<EVE_MAX_TOUCH; i++) {
+ EVETouch *touch = &touch_obj[i];
+ touch->eevt |= EVE_TOUCH_EETYPE_NOTOUCH;
+ }
+
+ eve_write8(REG_INT_MASK, touch_intr_mask);
+ eve_write8(REG_INT_EN, 0x01);
+ while(eve_read8(REG_INT_FLAGS));
+}
+
+void eve_touch_set_handler(eve_touch_handler_t handler, void *param) {
+ touch_handler = handler;
+ touch_handler_param = param;
+}
+
+EVETouch *eve_touch_get(int i) {
+ return &touch_obj[i];
+}
+
+int8_t eve_touch_get_idx(EVETouch *touch) {
+ if (touch == NULL) return -1;
+ return touch - touch_obj;
+}
+
+uint16_t eve_touch_evt(EVETouch *touch, uint16_t evt, uint8_t tag0, uint8_t tag_min, uint8_t tag_n) {
+ int tag_max;
+ uint8_t _tag;
+ uint16_t _evt;
+
+ if (tag_min == EVE_NOTAG) return 0;
+
+ tag_max = tag_min + tag_n;
+ if ((tag0 < tag_min) || (tag0 >= tag_max)) return 0;
+
+ _evt = evt & (EVE_TOUCH_ETYPE_TIMER_MASK | EVE_TOUCH_ETYPE_USR_MASK);
+ if (touch == NULL) return _evt;
+
+ _evt |= evt & EVE_TOUCH_ETYPE_POINT_MASK;
+ if (evt & EVE_TOUCH_ETYPE_TAG) {
+ _tag = touch->tag;
+ if ((_tag >= tag_min) && (_tag < tag_max)) _evt |= EVE_TOUCH_ETYPE_TAG;
+ }
+ if (evt & EVE_TOUCH_ETYPE_TAG_UP) {
+ _tag = touch->tag_up;
+ if ((_tag >= tag_min) && (_tag < tag_max)) _evt |= EVE_TOUCH_ETYPE_TAG_UP;
+ }
+ if (evt & EVE_TOUCH_ETYPE_TRACK_MASK) {
+ _tag = touch->tracker.tag;
+ if ((_tag >= tag_min) && (_tag < tag_max)) _evt |= evt & EVE_TOUCH_ETYPE_TRACK_MASK;
+ }
+ if (evt & (EVE_TOUCH_ETYPE_LPRESS | EVE_TOUCH_ETYPE_TAP1 | EVE_TOUCH_ETYPE_TAP2)) {
+ _tag = touch->tag0;
+ if ((_tag >= tag_min) && (_tag < tag_max)) _evt |= evt & (EVE_TOUCH_ETYPE_LPRESS | EVE_TOUCH_ETYPE_TAP1 | EVE_TOUCH_ETYPE_TAP2);
+ }
+
+ return _evt;
+}
+
+void eve_touch_set_opt(uint8_t tag, uint8_t opt) {
+ touch_tag_opt[tag] = opt;
+}
+
+uint8_t eve_touch_get_opt(uint8_t tag) {
+ return touch_tag_opt[tag];
+}
+
+void eve_touch_clear_opt(void) {
+ memset(touch_tag_opt, 0, sizeof(touch_tag_opt));
+}
+
+void eve_touch_timer_set(EVETouch *touch, uint16_t evt, uint8_t tag0, uint32_t to) {
+ touch_timer.touch = touch;
+ touch_timer.evt = evt;
+ touch_timer.tag0 = tag0;
+ touch_timer.to = to;
+ eve_timer_set(to);
+}
+
+void eve_touch_timer_clear(EVETouch *touch) {
+ eve_touch_timer_set_evt(touch, 0);
+}
+
+uint16_t eve_touch_timer_get_evt(EVETouch *touch) {
+ uint16_t ret = 0;
+
+ if ((touch == NULL) || (touch_timer.touch == touch)) {
+ ret = touch_timer.evt;
+ } else if (touch_timer.touch == NULL) {
+ ret = touch_timer.evt & EVE_TOUCH_ETYPE_TIMER;
+ }
+ return ret;
+}
+
+void eve_touch_timer_set_evt(EVETouch *touch, uint16_t evt) {
+ if (touch == touch_timer.touch) {
+ touch_timer.evt = evt;
+ } else if (touch_timer.touch == NULL) {
+ touch_timer.evt = evt & EVE_TOUCH_ETYPE_TIMER;
+ }
+ if (!touch_timer.evt) eve_timer_clear();
+}
+
+void eve_touch_timer_start(uint8_t tag0, uint32_t to) {
+ eve_touch_timer_set(NULL, EVE_TOUCH_ETYPE_TIMER, tag0, to);
+}
+
+void eve_touch_timer_stop(void) {
+ eve_touch_timer_clear(NULL);
+}
+
+EVETouchTimer *eve_touch_timer_get(void) {
+ return &touch_timer;
+}
diff --git a/fw/fe310/eos/eve/eve_touch.h b/fw/fe310/eos/eve/eve_touch.h
new file mode 100644
index 0000000..1bb77ba
--- /dev/null
+++ b/fw/fe310/eos/eve/eve_touch.h
@@ -0,0 +1,121 @@
+#include <stdint.h>
+
+#define EVE_TOUCH_TIMEOUT_TAP 1000
+#define EVE_TOUCH_TIMEOUT_TRACK 20
+
+#define EVE_TOUCH_THRESHOLD_X 5
+#define EVE_TOUCH_THRESHOLD_Y 5
+#define EVE_TOUCH_TRAVG 3
+
+#define EVE_NOTAG 0
+#define EVE_NOTOUCH 0x80008000
+#define EVE_MAX_TOUCH 5
+
+/* events */
+#define EVE_TOUCH_ETYPE_TAG 0x0001
+#define EVE_TOUCH_ETYPE_TAG_UP 0x0002
+#define EVE_TOUCH_ETYPE_POINT 0x0004
+#define EVE_TOUCH_ETYPE_POINT_UP 0x0008
+#define EVE_TOUCH_ETYPE_TRACK 0x0010
+#define EVE_TOUCH_ETYPE_TRACK_START 0x0020
+#define EVE_TOUCH_ETYPE_TRACK_STOP 0x0040
+#define EVE_TOUCH_ETYPE_TRACK_ABORT 0x0080
+#define EVE_TOUCH_ETYPE_TIMER 0x0100
+#define EVE_TOUCH_ETYPE_TIMER_ABORT 0x0200
+#define EVE_TOUCH_ETYPE_TRACK_REG 0x0400
+#define EVE_TOUCH_ETYPE_LPRESS 0x0800
+#define EVE_TOUCH_ETYPE_TAP1 0x1000
+#define EVE_TOUCH_ETYPE_TAP2 0x2000
+#define EVE_TOUCH_ETYPE_USR 0x4000
+#define EVE_TOUCH_ETYPE_USR1 0x8000
+
+#define EVE_TOUCH_ETYPE_TRACK_MASK (EVE_TOUCH_ETYPE_TRACK | EVE_TOUCH_ETYPE_TRACK_START | EVE_TOUCH_ETYPE_TRACK_STOP | EVE_TOUCH_ETYPE_TRACK_ABORT | EVE_TOUCH_ETYPE_TRACK_REG)
+#define EVE_TOUCH_ETYPE_TIMER_MASK (EVE_TOUCH_ETYPE_TIMER | EVE_TOUCH_ETYPE_TIMER_ABORT)
+#define EVE_TOUCH_ETYPE_POINT_MASK (EVE_TOUCH_ETYPE_POINT | EVE_TOUCH_ETYPE_POINT_UP)
+#define EVE_TOUCH_ETYPE_USR_MASK (EVE_TOUCH_ETYPE_USR | EVE_TOUCH_ETYPE_USR1)
+
+/* extended events */
+#define EVE_TOUCH_EETYPE_NOTOUCH 0x0001
+#define EVE_TOUCH_EETYPE_LPRESS 0x0002
+#define EVE_TOUCH_EETYPE_TAP2 0x0004
+
+#define EVE_TOUCH_EETYPE_TRACK_LEFT 0x0010
+#define EVE_TOUCH_EETYPE_TRACK_RIGHT 0x0020
+#define EVE_TOUCH_EETYPE_TRACK_UP 0x0040
+#define EVE_TOUCH_EETYPE_TRACK_DOWN 0x0080
+
+#define EVE_TOUCH_EETYPE_TRACK_ABORT 0x0100
+#define EVE_TOUCH_EETYPE_TIMER_ABORT 0x0200
+
+#define EVE_TOUCH_EETYPE_USR 0x1000
+#define EVE_TOUCH_EETYPE_USR1 0x2000
+#define EVE_TOUCH_EETYPE_USR2 0x4000
+#define EVE_TOUCH_EETYPE_USR3 0x8000
+
+#define EVE_TOUCH_EETYPE_TRACK_X (EVE_TOUCH_EETYPE_TRACK_LEFT | EVE_TOUCH_EETYPE_TRACK_RIGHT)
+#define EVE_TOUCH_EETYPE_TRACK_Y (EVE_TOUCH_EETYPE_TRACK_UP | EVE_TOUCH_EETYPE_TRACK_DOWN)
+#define EVE_TOUCH_EETYPE_TRACK_XY (EVE_TOUCH_EETYPE_TRACK_X | EVE_TOUCH_EETYPE_TRACK_Y)
+#define EVE_TOUCH_EETYPE_ABORT (EVE_TOUCH_EETYPE_TRACK_ABORT | EVE_TOUCH_EETYPE_TIMER_ABORT)
+
+/* tag options */
+#define EVE_TOUCH_OPT_TRACK 0x01
+#define EVE_TOUCH_OPT_TRACK_REG 0x02
+#define EVE_TOUCH_OPT_TRACK_X 0x04
+#define EVE_TOUCH_OPT_TRACK_Y 0x08
+#define EVE_TOUCH_OPT_TRACK_EXT_X 0x10
+#define EVE_TOUCH_OPT_TRACK_EXT_Y 0x20
+#define EVE_TOUCH_OPT_LPRESS 0x40
+#define EVE_TOUCH_OPT_TAP2 0x80
+
+#define EVE_TOUCH_OPT_TRACK_XY (EVE_TOUCH_OPT_TRACK_X | EVE_TOUCH_OPT_TRACK_Y)
+#define EVE_TOUCH_OPT_TRACK_EXT_XY (EVE_TOUCH_OPT_TRACK_EXT_X | EVE_TOUCH_OPT_TRACK_EXT_Y)
+
+typedef struct EVETouch {
+ int x;
+ int y;
+ int vx;
+ int vy;
+ int x0;
+ int y0;
+ uint64_t t;
+ uint16_t eevt;
+ uint8_t tag0;
+ uint8_t tag;
+ uint8_t tag_up;
+ struct {
+ uint8_t tag;
+ uint8_t track;
+ uint16_t val;
+ } tracker;
+} EVETouch;
+
+typedef struct EVETouchTimer {
+ EVETouch *touch;
+ uint32_t to;
+ uint16_t evt;
+ uint8_t tag0;
+} EVETouchTimer;
+
+typedef void (*eve_touch_handler_t) (EVETouch *, uint16_t, uint8_t, void *);
+
+void eve_handle_touch(void);
+void eve_handle_time(void);
+
+void eve_touch_init(void);
+void eve_touch_set_handler(eve_touch_handler_t handler, void *handler_param);
+EVETouch *eve_touch_get(int i);
+int8_t eve_touch_get_idx(EVETouch *touch);
+uint16_t eve_touch_evt(EVETouch *touch, uint16_t evt, uint8_t tag0, uint8_t tag_min, uint8_t tag_n);
+
+void eve_touch_set_opt(uint8_t tag, uint8_t opt);
+uint8_t eve_touch_get_opt(uint8_t tag);
+void eve_touch_clear_opt(void);
+
+void eve_touch_timer_set(EVETouch *touch, uint16_t evt, uint8_t tag0, uint32_t to);
+void eve_touch_timer_clear(EVETouch *touch);
+uint16_t eve_touch_timer_get_evt(EVETouch *touch);
+void eve_touch_timer_set_evt(EVETouch *touch, uint16_t evt);
+void eve_touch_timer_start(uint8_t tag0, uint32_t to);
+void eve_touch_timer_stop(void);
+
+EVETouchTimer *eve_touch_timer_get(void);
diff --git a/fw/fe310/eos/eve/eve_vtrack.c b/fw/fe310/eos/eve/eve_vtrack.c
new file mode 100644
index 0000000..b9f28af
--- /dev/null
+++ b/fw/fe310/eos/eve/eve_vtrack.c
@@ -0,0 +1,65 @@
+#include <stdlib.h>
+#include <math.h>
+
+#include "eve.h"
+
+static EVEVTrack vtrack;
+static EVEPhyAcc vtrack_acc;
+
+void eve_vtrack_init(void) {
+ eve_phy_acc_init(&vtrack_acc, -EVE_VTRACK_ACC_A);
+ eve_vtrack_reset();
+}
+
+EVEVTrack *eve_vtrack_get(void) {
+ return &vtrack;
+}
+
+void eve_vtrack_set(eve_vtrack_start_t start, eve_vtrack_tick_t tick, eve_vtrack_stop_t stop, void *param) {
+ vtrack.start = start;
+ vtrack.tick = tick;
+ vtrack.stop = stop;
+ vtrack.param = param;
+}
+
+void eve_vtrack_reset(void) {
+ eve_vtrack_set(eve_vtrack_acc_start, eve_vtrack_acc_tick, NULL, &vtrack_acc);
+}
+
+void eve_vtrack_start(EVETouch *touch, uint8_t tag0, uint32_t to) {
+ eve_touch_timer_set(touch, EVE_TOUCH_ETYPE_TRACK, tag0, to);
+ if (vtrack.start) vtrack.start(touch, vtrack.param);
+}
+
+void eve_vtrack_stop(EVETouch *touch) {
+ eve_touch_timer_clear(touch);
+ eve_vtrack_reset();
+}
+
+void eve_vtrack_acc_start(EVETouch *touch, void *p) {
+ EVEPhyAcc *param = (EVEPhyAcc *)p;
+ eve_phy_acc_start(param, touch->x, touch->y, touch->vx, touch->vy);
+}
+
+int eve_vtrack_acc_tick(EVETouch *touch, void *p) {
+ EVEPhyAcc *param = (EVEPhyAcc *)p;
+
+ return eve_phy_acc_tick(param, eve_time_get_tick() - touch->t, &touch->x, &touch->y);
+}
+
+void eve_vtrack_lho_start(EVETouch *touch, void *p) {
+ EVEPhyLHO *param = (EVEPhyLHO *)p;
+
+ eve_phy_lho_start(param, touch->x, touch->y);
+}
+
+int eve_vtrack_lho_tick(EVETouch *touch, void *p) {
+ EVEPhyLHO *param = (EVEPhyLHO *)p;
+
+ return eve_phy_lho_tick(param, eve_time_get_tick() - touch->t, &touch->x, &touch->y);
+}
+
+void eve_vtrack_lho_stop(EVETouch *touch, void *p) {
+ eve_vtrack_reset();
+}
+
diff --git a/fw/fe310/eos/eve/eve_vtrack.h b/fw/fe310/eos/eve/eve_vtrack.h
new file mode 100644
index 0000000..b75f673
--- /dev/null
+++ b/fw/fe310/eos/eve/eve_vtrack.h
@@ -0,0 +1,28 @@
+#include <stdint.h>
+
+#define EVE_VTRACK_ACC_A 1000
+
+typedef void (*eve_vtrack_start_t) (EVETouch *, void *);
+typedef int (*eve_vtrack_tick_t) (EVETouch *, void *);
+typedef void (*eve_vtrack_stop_t) (EVETouch *, void *);
+
+typedef struct EVEVTrack {
+ eve_vtrack_start_t start;
+ eve_vtrack_tick_t tick;
+ eve_vtrack_stop_t stop;
+ void *param;
+} EVEVTrack;
+
+void eve_vtrack_init(void);
+EVEVTrack *eve_vtrack_get(void);
+void eve_vtrack_set(eve_vtrack_start_t start, eve_vtrack_tick_t tick, eve_vtrack_stop_t stop, void *param);
+void eve_vtrack_reset(void);
+void eve_vtrack_start(EVETouch *touch, uint8_t tag0, uint32_t to);
+void eve_vtrack_stop(EVETouch *touch);
+
+void eve_vtrack_acc_start(EVETouch *touch, void *p);
+int eve_vtrack_acc_tick(EVETouch *touch, void *p);
+
+void eve_vtrack_lho_start(EVETouch *touch, void *p);
+int eve_vtrack_lho_tick(EVETouch *touch, void *p);
+void eve_vtrack_lho_stop(EVETouch *touch, void *p);
diff --git a/fw/fe310/eos/eve/screen/Makefile b/fw/fe310/eos/eve/screen/Makefile
new file mode 100644
index 0000000..cc4a81d
--- /dev/null
+++ b/fw/fe310/eos/eve/screen/Makefile
@@ -0,0 +1,17 @@
+include ../../../common.mk
+
+CFLAGS += -I.. -I../..
+
+obj = window.o view.o page.o form.o
+
+
+%.o: %.c %.h
+ $(CC) $(CFLAGS) -c $<
+
+%.o: %.S
+ $(CC) $(CFLAGS) -c $<
+
+all: $(obj)
+
+clean:
+ rm -f *.o
diff --git a/fw/fe310/eos/eve/screen/form.c b/fw/fe310/eos/eve/screen/form.c
new file mode 100644
index 0000000..8555158
--- /dev/null
+++ b/fw/fe310/eos/eve/screen/form.c
@@ -0,0 +1,165 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include "eve.h"
+#include "eve_kbd.h"
+#include "eve_font.h"
+
+#include "window.h"
+#include "page.h"
+#include "form.h"
+
+#include "widget/widgets.h"
+
+#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
+#define MAX(X, Y) (((X) > (Y)) ? (X) : (Y))
+
+static void form_update_g(EVEForm *form, EVEWidget *_widget) {
+ EVEPage *page = &form->p;
+ EVEWidget *widget = page->widget;
+ int i;
+ uint16_t w = 0;
+ uint16_t h = 0;
+ uint16_t l_h = 0;
+
+ for (i=0; i<page->widget_size; i++) {
+ if (widget->label) {
+ h += l_h;
+ w = widget->label->g.w;
+ l_h = widget->label->g.h;
+ widget->label->g.x = 0;
+ widget->label->g.y = h;
+ }
+ if (w + widget->g.w > form->p.v.window->g.w) {
+ h += l_h;
+ w = 0;
+ l_h = 0;
+ }
+ widget->g.x = w;
+ widget->g.y = h;
+
+ w += widget->g.w;
+ l_h = MAX(l_h, widget->g.h);
+
+ widget = eve_widget_next(widget);
+ }
+ page->g.w = page->v.window->g.w;
+ page->g.h = h + l_h;
+}
+
+static void widgets_destroy(EVEWidget *widget, uint16_t widget_size) {
+ int i;
+
+ for (i=0; i<widget_size; i++) {
+ if (widget->label) eve_free(widget->label);
+ eve_widget_destroy(widget);
+ widget = eve_widget_next(widget);
+ }
+}
+
+EVEForm *eve_form_create(EVEWindow *window, EVEViewStack *stack, EVEWidgetSpec spec[], uint16_t spec_size, eve_form_uievt_t uievt, eve_form_action_t action, eve_form_destructor_t destructor) {
+ EVEWidget *widgets;
+ EVEWidget *widget;
+ EVELabel *label;
+ EVEForm *form;
+ int w_size = 0;
+ int i, r;
+
+ for (i=0; i<spec_size; i++) {
+ w_size += eve_widget_size(spec[i].widget.type);
+ }
+ form = eve_malloc(sizeof(EVEForm));
+ if (form == NULL) {
+ return NULL;
+ }
+ if (uievt == NULL) uievt = eve_form_uievt;
+ if (destructor == NULL) destructor = eve_form_destroy;
+ eve_form_init(form, window, stack, NULL, 0, uievt, action, destructor);
+
+ widgets = eve_malloc(w_size);
+ if (widgets == NULL) {
+ eve_free(form);
+ return NULL;
+ }
+
+ widget = widgets;
+ for (i=0; i<spec_size; i++) {
+ r = eve_widget_create(widget, spec[i].widget.type, &spec[i].widget.g, (EVEPage *)form, &spec[i].widget.spec);
+ if (r) {
+ widgets_destroy(widgets, i);
+ eve_free(widgets);
+ eve_free(form);
+ return NULL;
+ }
+ if (spec[i].label.title) {
+ EVEFont *font = spec[i].label.font ? spec[i].label.font : eve_window_font(window);
+ label = eve_malloc(sizeof(EVELabel));
+ if (label == NULL) {
+ eve_widget_destroy(widget);
+ widgets_destroy(widgets, i);
+ eve_free(widgets);
+ eve_free(form);
+ return NULL;
+ }
+ eve_label_init(label, &spec[i].label.g, font, spec[i].label.title);
+ eve_widget_set_label(widget, label);
+ if (label->g.w == 0) label->g.w = eve_font_str_w(font, label->title);
+ }
+ if (widget->label && (widget->label->g.w == 0)) eve_font_str_w(label->font, label->title) + EVE_FORM_LABEL_MARGIN;
+ if (widget->g.w == 0) widget->g.w = window->g.w - (widget->label ? widget->label->g.w : 0);
+ widget = eve_widget_next(widget);
+ }
+ eve_form_update(form, widgets, spec_size);
+
+ return form;
+}
+
+void eve_form_init(EVEForm *form, EVEWindow *window, EVEViewStack *stack, EVEWidget *widget, uint16_t widget_size, eve_form_uievt_t uievt, eve_form_action_t action, eve_form_destructor_t destructor) {
+ memset(form, 0, sizeof(EVEForm));
+ eve_page_init(&form->p, window, stack, NULL, 0, EVE_PAGE_OPT_SCROLL_Y | EVE_PAGE_OPT_SCROLL_BACK | EVE_PAGE_OPT_TRACK_EXT_Y, eve_page_draw, eve_page_touch, (eve_view_uievt_t)uievt, (eve_page_destructor_t)destructor);
+ form->action = action;
+ eve_form_update(form, widget, widget_size);
+}
+
+void eve_form_update(EVEForm *form, EVEWidget *widget, uint16_t widget_size) {
+ eve_page_update((EVEPage *)form, widget, widget_size);
+ form_update_g(form, NULL);
+}
+
+void eve_form_destroy(EVEForm *form) {
+ widgets_destroy(form->p.widget, form->p.widget_size);
+ eve_free(form->p.widget);
+ eve_free(form);
+}
+
+int eve_form_uievt(EVEForm *form, uint16_t evt, void *param) {
+ switch (evt) {
+ case EVE_UIEVT_WIDGET_UPDATE_G:
+ form_update_g(form, (EVEWidget *)param);
+ break;
+
+ case EVE_UIEVT_PAGE_SCROLL_START:
+ break;
+
+ case EVE_UIEVT_PAGE_SCROLL_STOP:
+ break;
+
+ case EVE_UIEVT_PAGE_TRACK_START:
+ break;
+
+ case EVE_UIEVT_PAGE_TRACK_STOP: {
+ EVEUIEvtTouch *touch_p = (EVEUIEvtTouch *)param;
+ if (touch_p->evt & EVE_TOUCH_ETYPE_TRACK_STOP) {
+ if (touch_p->touch->eevt & EVE_TOUCH_EETYPE_TRACK_RIGHT) {
+ eve_page_close((EVEPage *)form);
+ return 1;
+ }
+ if (touch_p->touch->eevt & EVE_TOUCH_EETYPE_TRACK_LEFT) {
+ if (form->action) form->action(form);
+ }
+ }
+ break;
+ }
+ }
+ return 0;
+}
diff --git a/fw/fe310/eos/eve/screen/form.h b/fw/fe310/eos/eve/screen/form.h
new file mode 100644
index 0000000..272b6ed
--- /dev/null
+++ b/fw/fe310/eos/eve/screen/form.h
@@ -0,0 +1,23 @@
+#include <stdint.h>
+
+#define EVE_FORM_LABEL_MARGIN 10
+
+struct EVEWidget;
+struct EVEWidgetSpec;
+struct EVEForm;
+
+typedef int (*eve_form_uievt_t) (struct EVEForm *, uint16_t, void *);
+typedef void (*eve_form_action_t) (struct EVEForm *);
+typedef void (*eve_form_destructor_t) (struct EVEForm *);
+
+typedef struct EVEForm {
+ EVEPage p;
+ eve_form_action_t action;
+} EVEForm;
+
+EVEForm *eve_form_create(EVEWindow *window, EVEViewStack *stack, struct EVEWidgetSpec *spec, uint16_t spec_size, eve_form_uievt_t uievt, eve_form_action_t action, eve_form_destructor_t destructor);
+void eve_form_init(EVEForm *form, EVEWindow *window, EVEViewStack *stack, struct EVEWidget *widget, uint16_t widget_size, eve_form_uievt_t uievt, eve_form_action_t action, eve_form_destructor_t destructor);
+void eve_form_update(EVEForm *form, struct EVEWidget *widget, uint16_t widget_size);
+void eve_form_destroy(EVEForm *form);
+
+int eve_form_uievt(EVEForm *form, uint16_t evt, void *param);
diff --git a/fw/fe310/eos/eve/screen/page.c b/fw/fe310/eos/eve/screen/page.c
new file mode 100644
index 0000000..65dd534
--- /dev/null
+++ b/fw/fe310/eos/eve/screen/page.c
@@ -0,0 +1,349 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include "eve.h"
+#include "eve_kbd.h"
+#include "eve_font.h"
+
+#include "window.h"
+#include "page.h"
+
+#include "widget/label.h"
+#include "widget/widget.h"
+
+#define PAGE_TMODE_NONE 0
+#define PAGE_TMODE_TRACK 1
+#define PAGE_TMODE_SCROLL 2
+
+void eve_page_init(EVEPage *page, EVEWindow *window, EVEViewStack *stack, EVEWidget *widget, uint16_t widget_size, uint8_t opt, eve_view_draw_t draw, eve_view_touch_t touch, eve_view_uievt_t uievt, eve_page_destructor_t destructor) {
+ memset(page, 0, sizeof(EVEPage));
+ eve_view_init(&page->v, window, draw, touch, uievt, NULL);
+ page->stack = stack;
+ page->opt = opt;
+ page->destructor = destructor;
+ eve_page_update(page, widget, widget_size);
+}
+
+void eve_page_update(EVEPage *page, EVEWidget *widget, uint16_t widget_size) {
+ page->widget = widget;
+ page->widget_size = widget_size;
+}
+
+void eve_page_open(EVEPage *parent, eve_view_constructor_t constructor) {
+ EVEWindow *window = parent->v.window;
+ EVEViewStack *stack = parent->stack;
+ eve_page_destructor_t destructor = parent->destructor;
+
+ if (destructor) destructor(parent);
+ eve_view_create(window, stack, constructor);
+}
+
+void eve_page_close(EVEPage *page) {
+ EVEWindow *window = page->v.window;
+ EVEViewStack *stack = page->stack;
+ eve_page_destructor_t destructor = page->destructor;
+
+ if (stack->level <= 1) return;
+
+ if (page->lho_t0) {
+ page->lho_t0 = 0;
+ eve_touch_timer_stop();
+ }
+ if (eve_window_scroll(window->root, NULL) == window) {
+ eve_window_scroll_stop(window);
+ }
+
+ if (destructor) destructor(page);
+ eve_window_kbd_detach(window);
+ eve_view_destroy(window, stack);
+}
+
+/* Screen to page coordinates */
+int16_t eve_page_x(EVEPage *page, int16_t x) {
+ return x + page->g.x - page->v.window->g.x;
+}
+
+int16_t eve_page_y(EVEPage *page, int16_t y) {
+ return y + page->g.y - page->v.window->g.y;
+}
+
+/* Page to window coordinates */
+int16_t eve_page_win_x(EVEPage *page, int16_t x) {
+ return x - page->g.x;
+}
+
+int16_t eve_page_win_y(EVEPage *page, int16_t y) {
+ return y - page->g.y;
+}
+
+/* Page to screen coordinates */
+int16_t eve_page_scr_x(EVEPage *page, int16_t x) {
+ return eve_page_win_x(page, x) + page->v.window->g.x;
+}
+
+int16_t eve_page_scr_y(EVEPage *page, int16_t y) {
+ return eve_page_win_y(page, y) + page->v.window->g.y;
+}
+
+int eve_page_rect_visible(EVEPage *page, EVERect *g) {
+ uint16_t w = page->v.window->g.w;
+ uint16_t h = page->v.window->g.h;
+
+ if (((g->x + g->w) >= page->g.x) && ((g->y + g->h) >= page->g.y) && (g->x <= (page->g.x + w)) && (g->y <= (page->g.y + h))) return 1;
+ return 0;
+}
+
+void eve_page_focus(EVEPage *page, EVERect *rect) {
+ if (rect) {
+ EVERect g;
+
+ eve_window_visible_g(page->v.window, &g);
+ g.x -= page->v.window->g.x;
+ g.y -= page->v.window->g.y;
+
+ if (rect->x < page->g.x + g.x) {
+ page->g.x = rect->x - g.x;
+ }
+ if (rect->y < page->g.y + g.y) {
+ page->g.y = rect->y - g.y;
+ }
+ if ((rect->x + rect->w) > (page->g.x + g.x + g.w)) {
+ page->g.x = (rect->x + rect->w) - (g.x + g.w);
+ }
+ if ((rect->y + rect->h) > (page->g.y + g.y + g.h)) {
+ page->g.y = (rect->y + rect->h) - (g.y + g.h);
+ }
+ }
+}
+
+void eve_page_focus_widget(EVEPage *page, EVEWidget *widget, EVERect *rect) {
+ if (page->widget_f != widget) {
+ EVEWindow *window = page->v.window;
+ EVEWidget *widget_f = page->widget_f;
+
+ if (widget_f && widget_f->putc) {
+ widget_f->putc(widget_f, EVE_PAGE_KBDCH_CLOSE);
+ if (!(widget && widget->putc)) eve_window_kbd_detach(window);
+ }
+ if (widget && widget->putc) {
+ EVEKbd *kbd = eve_window_kbd(window);
+
+ if (kbd) eve_kbd_set_handler(kbd, widget->putc, widget);
+ if (!(widget_f && widget_f->putc)) eve_window_kbd_attach(window);
+ }
+ page->widget_f = widget;
+ }
+ if (rect) eve_page_focus(page, rect);
+}
+
+EVEWidget *eve_page_focus_widget_get(EVEPage *page) {
+ return page->widget_f;
+}
+
+EVEWidget *eve_page_widget(EVEPage *page, uint16_t idx) {
+ EVEWidget *w = page->widget;
+ int i;
+
+ if (idx >= page->widget_size) return NULL;
+
+ for (i=0; i<idx; i++) {
+ w = eve_widget_next(w);
+ }
+ return w;
+}
+
+static int page_touch(EVEPage *page, EVETouch *touch, uint16_t evt, uint8_t tag0) {
+ EVEView *view = &page->v;
+ EVEWindow *window = view->window;
+ int scroll, scroll_x, scroll_y;
+ int ret = 0;
+
+ scroll_x = page->opt & (EVE_PAGE_OPT_SCROLL_X | EVE_PAGE_OPT_SCROLL_XY);
+ if (scroll_x && touch) scroll_x = touch->eevt & ((page->opt & EVE_PAGE_OPT_SCROLL_XY) ? EVE_TOUCH_EETYPE_TRACK_XY : EVE_TOUCH_EETYPE_TRACK_X);
+
+ scroll_y = page->opt & (EVE_PAGE_OPT_SCROLL_Y | EVE_PAGE_OPT_SCROLL_XY);
+ if (scroll_y && touch) scroll_y = touch->eevt & ((page->opt & EVE_PAGE_OPT_SCROLL_XY) ? EVE_TOUCH_EETYPE_TRACK_XY : EVE_TOUCH_EETYPE_TRACK_Y);
+
+ scroll = scroll_x || scroll_y;
+
+ if ((evt & EVE_TOUCH_ETYPE_POINT_UP) && !(touch->eevt & (EVE_TOUCH_EETYPE_TRACK_XY | EVE_TOUCH_EETYPE_ABORT))) {
+ int _ret = 0;
+
+ if (page->widget_f) eve_page_focus_widget(page, NULL, NULL);
+ _ret = eve_view_uievt_pusht(view, EVE_UIEVT_PAGE_TOUCH, touch, evt, tag0);
+ if (_ret) return _ret;
+ ret = 1;
+ }
+
+ /* Scroll start */
+ if ((evt & EVE_TOUCH_ETYPE_TRACK_START) && !(touch->eevt & EVE_TOUCH_EETYPE_ABORT)) {
+ int _ret = 0;
+
+ if (scroll) {
+ page->track_mode = PAGE_TMODE_SCROLL;
+ eve_window_scroll_start(window, touch->tracker.tag);
+ _ret = eve_view_uievt_pusht(view, EVE_UIEVT_PAGE_SCROLL_START, touch, evt, tag0);
+ } else {
+ page->track_mode = PAGE_TMODE_TRACK;
+ _ret = eve_view_uievt_pusht(view, EVE_UIEVT_PAGE_TRACK_START, touch, evt, tag0);
+ }
+ if (_ret) return _ret;
+ ret = 1;
+ }
+
+ /* Scroll stop */
+ if (((evt & EVE_TOUCH_ETYPE_TRACK_STOP) && !(evt & EVE_TOUCH_ETYPE_TRACK_ABORT)) ||
+ ((evt & EVE_TOUCH_ETYPE_POINT_UP) && (touch->eevt & EVE_TOUCH_EETYPE_ABORT) && !(touch->eevt & EVE_TOUCH_EETYPE_TRACK_XY))) {
+ if ((page->track_mode == PAGE_TMODE_SCROLL) && (page->opt & EVE_PAGE_OPT_SCROLL_BACK)) {
+ int wmax_x, wmax_y;
+ int lho_x, lho_y;
+ EVERect vg;
+
+ eve_window_visible_g(page->v.window, &vg);
+ wmax_x = page->g.w > vg.w ? page->g.w - vg.w : 0;
+ wmax_y = page->g.h > vg.h ? page->g.h - vg.h : 0;
+ lho_x = page->g.x < 0 ? 0 : wmax_x;
+ lho_y = page->g.y < 0 ? 0 : wmax_y;
+ if ((page->g.x < 0) || (page->g.x > wmax_x) ||
+ (page->g.y < 0) || (page->g.y > wmax_y)) {
+ EVEPhyLHO *lho = &page->lho;
+ uint8_t _tag;
+
+ eve_window_scroll(window->root, &_tag);
+
+ eve_phy_lho_init(lho, lho_x, lho_y, 1000, 0.5, 0);
+ eve_phy_lho_start(lho, page->g.x, page->g.y);
+ page->lho_t0 = eve_time_get_tick();
+ eve_touch_timer_start(_tag, 20);
+ }
+ }
+
+ if (!page->lho_t0) {
+ int _ret = 0;
+
+ if (page->track_mode == PAGE_TMODE_SCROLL) {
+ page->track_mode = PAGE_TMODE_NONE;
+ eve_window_scroll_stop(window);
+ _ret = eve_view_uievt_pusht(view, EVE_UIEVT_PAGE_SCROLL_STOP, touch, evt, tag0);
+ } else if (!(touch->eevt & EVE_TOUCH_EETYPE_ABORT)) {
+ page->track_mode = PAGE_TMODE_NONE;
+ _ret = eve_view_uievt_pusht(view, EVE_UIEVT_PAGE_TRACK_STOP, touch, evt, tag0);
+ }
+ if (_ret) return _ret;
+ ret = 1;
+ }
+ }
+
+ if (page->track_mode == PAGE_TMODE_SCROLL) {
+ if (evt & EVE_TOUCH_ETYPE_TRACK_START) {
+ if (scroll_x) {
+ page->x0 = page->g.x;
+ }
+ if (scroll_y) {
+ page->y0 = page->g.y;
+ }
+ }
+ if (evt & EVE_TOUCH_ETYPE_TRACK) {
+ if (scroll_x) {
+ page->g.x = page->x0 + touch->x0 - touch->x;
+ }
+ if (scroll_y) {
+ page->g.y = page->y0 + touch->y0 - touch->y;
+ }
+ ret = 1;
+ }
+ if ((evt & EVE_TOUCH_ETYPE_TIMER) && (page->opt & EVE_PAGE_OPT_SCROLL_BACK)) {
+ EVEPhyLHO *lho = &page->lho;
+ int x, y, more;
+
+ more = eve_phy_lho_tick(lho, eve_time_get_tick() - page->lho_t0, scroll_x ? &x : NULL, scroll_y ? &y : NULL);
+ if (scroll_x) page->g.x = x;
+ if (scroll_y) page->g.y = y;
+ if (!more) {
+ int _ret = 0;
+
+ page->lho_t0 = 0;
+ eve_touch_timer_stop();
+ page->track_mode = PAGE_TMODE_NONE;
+ eve_window_scroll_stop(window);
+ _ret = eve_view_uievt_pusht(view, EVE_UIEVT_PAGE_SCROLL_STOP, touch, evt, tag0);
+ if (_ret) return _ret;
+ }
+ ret = 1;
+ }
+ if (evt & EVE_TOUCH_EETYPE_TIMER_ABORT) {
+ page->lho_t0 = 0;
+ }
+ }
+
+ return ret;
+}
+
+uint8_t eve_page_draw(EVEView *view, uint8_t tag0) {
+ EVEPage *page = (EVEPage *)view;
+ EVEWidget *widget = page->widget;
+ int i;
+ uint8_t tagN = tag0;
+ uint8_t tag_opt;
+
+ tag_opt = EVE_TOUCH_OPT_TRACK | EVE_TOUCH_OPT_TRACK_XY;
+ if (page->opt & EVE_PAGE_OPT_TRACK_EXT_X) tag_opt |= EVE_TOUCH_OPT_TRACK_EXT_X;
+ if (page->opt & EVE_PAGE_OPT_TRACK_EXT_Y) tag_opt |= EVE_TOUCH_OPT_TRACK_EXT_Y;
+
+ tag0 = eve_view_clear(view, tag0, tag_opt);
+ tagN = tag0;
+ eve_cmd_dl(SAVE_CONTEXT());
+ eve_cmd_dl(VERTEX_FORMAT(0));
+ eve_cmd_dl(VERTEX_TRANSLATE_X(eve_page_scr_x(page, 0) * 16));
+ eve_cmd_dl(VERTEX_TRANSLATE_Y(eve_page_scr_y(page, 0) * 16));
+ for (i=0; i<page->widget_size; i++) {
+ if (widget->label && eve_page_rect_visible(page, &widget->label->g)) {
+ eve_cmd_dl(TAG_MASK(0));
+ eve_label_draw(widget->label);
+ eve_cmd_dl(TAG_MASK(1));
+ }
+ if (eve_page_rect_visible(page, &widget->g)) {
+ tagN = widget->draw(widget, tagN);
+ }
+ widget = eve_widget_next(widget);
+ }
+ eve_cmd_dl(RESTORE_CONTEXT());
+
+ for (i=tag0; i<tagN; i++) {
+ if (i != EVE_NOTAG) eve_touch_set_opt(i, eve_touch_get_opt(i) | tag_opt);
+ }
+
+ return tagN;
+}
+
+int eve_page_touch(EVEView *view, EVETouch *touch, uint16_t evt, uint8_t tag0) {
+ EVEPage *page = (EVEPage *)view;
+ EVEWidget *widget = page->widget;
+ int8_t touch_idx = eve_touch_get_idx(touch);
+ uint16_t _evt;
+ int i, ret;
+
+ if (touch_idx > 0) return 0;
+
+ _evt = eve_touch_evt(touch, evt, tag0, page->v.tag, 1);
+ if (_evt) {
+ ret = page_touch(page, touch, _evt, tag0);
+ if (ret) return 1;
+ }
+ for (i=0; i<page->widget_size; i++) {
+ if (eve_page_rect_visible(page, &widget->g)) {
+ _evt = eve_touch_evt(touch, evt, tag0, widget->tag0, widget->tagN - widget->tag0);
+ if (_evt) {
+ if (page->track_mode == PAGE_TMODE_NONE) {
+ ret = widget->touch(widget, touch, _evt);
+ if (ret) return 1;
+ }
+ ret = page_touch(page, touch, _evt, tag0);
+ if (ret) return 1;
+ }
+ }
+ widget = eve_widget_next(widget);
+ }
+
+ return 0;
+}
diff --git a/fw/fe310/eos/eve/screen/page.h b/fw/fe310/eos/eve/screen/page.h
new file mode 100644
index 0000000..26c33c5
--- /dev/null
+++ b/fw/fe310/eos/eve/screen/page.h
@@ -0,0 +1,56 @@
+#include <stdint.h>
+
+#define EVE_PAGE_KBDCH_CLOSE 0x1a
+
+#define EVE_PAGE_OPT_SCROLL_X 0x01
+#define EVE_PAGE_OPT_SCROLL_Y 0x02
+#define EVE_PAGE_OPT_SCROLL_BACK 0x04
+#define EVE_PAGE_OPT_SCROLL_XY 0x08
+#define EVE_PAGE_OPT_TRACK_EXT_X 0x10
+#define EVE_PAGE_OPT_TRACK_EXT_Y 0x20
+#define EVE_PAGE_OPT_TRACK_EXT_XY (EVE_PAGE_OPT_TRACK_EXT_X | EVE_PAGE_OPT_TRACK_EXT_Y)
+
+struct EVEWidget;
+struct EVEPage;
+
+typedef void (*eve_page_destructor_t) (struct EVEPage *);
+
+typedef struct EVEPage {
+ EVEView v;
+ EVERect g;
+ int16_t x0;
+ int16_t y0;
+ EVEViewStack *stack;
+ eve_page_destructor_t destructor;
+ struct EVEWidget *widget;
+ uint16_t widget_size;
+ struct EVEWidget *widget_f;
+ EVEPhyLHO lho;
+ uint64_t lho_t0;
+ uint8_t track_mode;
+ uint8_t opt;
+} EVEPage;
+
+void eve_page_init(EVEPage *page, EVEWindow *window, EVEViewStack *stack, struct EVEWidget *widget, uint16_t widget_size, uint8_t opt,eve_view_draw_t draw, eve_view_touch_t touch, eve_view_uievt_t uievt, eve_page_destructor_t destructor);
+void eve_page_update(EVEPage *page, struct EVEWidget *widget, uint16_t widget_size);
+void eve_page_open(EVEPage *parent, eve_view_constructor_t constructor);
+void eve_page_close(EVEPage *page);
+
+/* Screen to page coordinates */
+int16_t eve_page_x(EVEPage *page, int16_t x);
+int16_t eve_page_y(EVEPage *page, int16_t y);
+/* Page to window coordinates */
+int16_t eve_page_win_x(EVEPage *page, int16_t x);
+int16_t eve_page_win_y(EVEPage *page, int16_t y);
+/* Page to screen coordinates */
+int16_t eve_page_scr_x(EVEPage *page, int16_t x);
+int16_t eve_page_scr_y(EVEPage *page, int16_t y);
+int eve_page_rect_visible(EVEPage *page, EVERect *g);
+
+void eve_page_focus(EVEPage *page, EVERect *rect);
+void eve_page_focus_widget(EVEPage *page, struct EVEWidget *widget, EVERect *rect);
+struct EVEWidget *eve_page_focus_widget_get(EVEPage *page);
+struct EVEWidget *eve_page_widget(EVEPage *page, uint16_t idx);
+
+uint8_t eve_page_draw(EVEView *view, uint8_t tag0);
+int eve_page_touch(EVEView *view, EVETouch *touch, uint16_t evt, uint8_t tag0);
diff --git a/fw/fe310/eos/eve/screen/uievt.h b/fw/fe310/eos/eve/screen/uievt.h
new file mode 100644
index 0000000..98f0d95
--- /dev/null
+++ b/fw/fe310/eos/eve/screen/uievt.h
@@ -0,0 +1,14 @@
+#define EVE_UIEVT_WIN_UPDATE_G 1
+#define EVE_UIEVT_PAGE_UPDATE_G 2
+#define EVE_UIEVT_PAGE_TOUCH 3
+#define EVE_UIEVT_PAGE_SCROLL_START 4
+#define EVE_UIEVT_PAGE_SCROLL_STOP 5
+#define EVE_UIEVT_PAGE_TRACK_START 6
+#define EVE_UIEVT_PAGE_TRACK_STOP 7
+#define EVE_UIEVT_WIDGET_UPDATE_G 8
+
+typedef struct EVEUIEvtTouch {
+ EVETouch *touch;
+ uint16_t evt;
+ uint8_t tag0;
+} EVEUIEvtTouch;
diff --git a/fw/fe310/eos/eve/screen/view.c b/fw/fe310/eos/eve/screen/view.c
new file mode 100644
index 0000000..ac9aef4
--- /dev/null
+++ b/fw/fe310/eos/eve/screen/view.c
@@ -0,0 +1,94 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include "eve.h"
+#include "eve_kbd.h"
+#include "eve_font.h"
+
+#include "window.h"
+
+void eve_view_init(EVEView *view, EVEWindow *window, eve_view_draw_t draw, eve_view_touch_t touch, eve_view_uievt_t uievt, void *param) {
+ view->draw = draw;
+ view->touch = touch;
+ view->uievt = uievt;
+ view->param = param;
+ view->window = window;
+ view->color_bg = 0x000000;
+ view->color_fg = 0xffffff;
+ window->view = view;
+}
+
+void eve_view_set_color_bg(EVEView *view, uint8_t r, uint8_t g, uint8_t b) {
+ view->color_bg = (r << 16) | (g << 8) | b;
+}
+
+void eve_view_set_color_fg(EVEView *view, uint8_t r, uint8_t g, uint8_t b) {
+ view->color_fg = (r << 16) | (g << 8) | b;
+}
+
+uint8_t eve_view_clear(EVEView *view, uint8_t tag0, uint8_t tag_opt) {
+ EVEWindow *win_scroll = NULL;
+ EVEWindow *window = view->window;
+ uint8_t _tag;
+
+ win_scroll = eve_window_scroll(window->root, &_tag);
+ eve_cmd_dl(CLEAR_COLOR_RGBC(view->color_bg));
+ eve_cmd_dl(COLOR_RGBC(view->color_fg));
+ if (win_scroll == window) {
+ view->tag = _tag;
+ eve_touch_set_opt(view->tag, tag_opt);
+ eve_cmd_dl(TAG(view->tag));
+ eve_cmd_dl(CLEAR_TAG(view->tag));
+ } else if (win_scroll) {
+ view->tag = EVE_NOTAG;
+ eve_cmd_dl(TAG(view->tag));
+ eve_cmd_dl(CLEAR_TAG(view->tag));
+ } else {
+ view->tag = tag0;
+ if (tag0 != EVE_NOTAG) {
+ eve_touch_set_opt(tag0, tag_opt);
+ eve_cmd_dl(CLEAR_TAG(tag0));
+ tag0++;
+ }
+ }
+ eve_cmd_dl(CLEAR(1,1,1));
+ return tag0;
+}
+
+void eve_view_stack_init(EVEViewStack *stack) {
+ memset(stack, 0, sizeof(EVEViewStack));
+}
+
+void eve_view_create(EVEWindow *window, EVEViewStack *stack, eve_view_constructor_t constructor) {
+ if (stack->level < EVE_VIEW_SIZE_STACK - 1) {
+ stack->constructor[stack->level] = constructor;
+ stack->level++;
+ constructor(window, stack);
+ }
+}
+
+void eve_view_destroy(EVEWindow *window, EVEViewStack *stack) {
+ if (stack->level > 1) {
+ eve_view_constructor_t constructor;
+
+ stack->level--;
+ constructor = stack->constructor[stack->level - 1];
+ constructor(window, stack);
+ }
+}
+
+void eve_view_uievt_push(EVEView *view, uint16_t evt, void *param) {
+ if (view->uievt) view->uievt(view, evt, param);
+}
+
+int eve_view_uievt_pusht(EVEView *view, uint16_t evt, EVETouch *touch, uint16_t t_evt, uint8_t tag0) {
+ if (view->uievt) {
+ EVEUIEvtTouch param;
+
+ param.touch = touch;
+ param.evt = t_evt;
+ param.tag0 = tag0;
+ view->uievt(view, evt, &param);
+ }
+ return 0;
+}
diff --git a/fw/fe310/eos/eve/screen/view.h b/fw/fe310/eos/eve/screen/view.h
new file mode 100644
index 0000000..65999d7
--- /dev/null
+++ b/fw/fe310/eos/eve/screen/view.h
@@ -0,0 +1,42 @@
+#include <stdint.h>
+
+#include "uievt.h"
+
+#define EVE_VIEW_SIZE_STACK 16
+
+struct EVEView;
+struct EVEViewStack;
+struct EVEWindow;
+
+typedef uint8_t (*eve_view_draw_t) (struct EVEView *, uint8_t);
+typedef int (*eve_view_touch_t) (struct EVEView *, EVETouch *, uint16_t, uint8_t);
+typedef int (*eve_view_uievt_t) (struct EVEView *, uint16_t, void *);
+typedef void (*eve_view_constructor_t) (struct EVEWindow *window, struct EVEViewStack *);
+
+typedef struct EVEView {
+ eve_view_draw_t draw;
+ eve_view_touch_t touch;
+ eve_view_uievt_t uievt;
+ struct EVEWindow *window;
+ void *param;
+ uint32_t color_bg;
+ uint32_t color_fg;
+ uint8_t tag;
+} EVEView;
+
+typedef struct EVEViewStack {
+ eve_view_constructor_t constructor[EVE_VIEW_SIZE_STACK];
+ uint8_t level;
+} EVEViewStack;
+
+void eve_view_init(EVEView *view, struct EVEWindow *window, eve_view_draw_t draw, eve_view_touch_t touch, eve_view_uievt_t uievt, void *param);
+void eve_view_set_color_bg(EVEView *view, uint8_t r, uint8_t g, uint8_t b);
+void eve_view_set_color_fg(EVEView *view, uint8_t r, uint8_t g, uint8_t b);
+uint8_t eve_view_clear(EVEView *view, uint8_t tag0, uint8_t tag_opt);
+
+void eve_view_stack_init(EVEViewStack *stack);
+void eve_view_create(struct EVEWindow *window, EVEViewStack *stack, eve_view_constructor_t constructor);
+void eve_view_destroy(struct EVEWindow *window, EVEViewStack *stack);
+
+void eve_view_uievt_push(EVEView *view, uint16_t evt, void *param);
+int eve_view_uievt_pusht(EVEView *view, uint16_t evt, EVETouch *touch, uint16_t t_evt, uint8_t tag0);
diff --git a/fw/fe310/eos/eve/screen/window.c b/fw/fe310/eos/eve/screen/window.c
new file mode 100644
index 0000000..c259b19
--- /dev/null
+++ b/fw/fe310/eos/eve/screen/window.c
@@ -0,0 +1,300 @@
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "eve.h"
+#include "eve_kbd.h"
+#include "eve_font.h"
+
+#include "window.h"
+
+#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
+
+void eve_window_init(EVEWindow *window, EVERect *g, EVEWindow *parent, char *name) {
+ memset(window, 0, sizeof(EVEWindow));
+
+ if (g) window->g = *g;
+ window->root = parent ? parent->root : NULL;
+ window->parent = parent;
+ window->name = name;
+}
+
+void eve_window_init_root(EVEWindowRoot *root, EVERect *g, char *name, EVEFont *font) {
+ EVEWindow *_window = &root->w;
+
+ eve_window_init(_window, g, NULL, name);
+ _window->root = root;
+ root->mem_next = EVE_RAM_G;
+ root->font = font;
+ root->win_kbd = NULL;
+ root->tag0 = EVE_NOTAG;
+ eve_touch_set_handler(eve_window_root_touch, root);
+}
+
+static uint8_t kbd_draw(EVEView *view, uint8_t tag0) {
+ EVEKbd *kbd = view->param;
+
+ tag0 = eve_view_clear(view, tag0, 0);
+
+ eve_kbd_draw(kbd);
+ return tag0;
+}
+
+static int kbd_touch(EVEView *view, EVETouch *touch, uint16_t evt, uint8_t tag0) {
+ EVEKbd *kbd = view->param;
+
+ return eve_kbd_touch(kbd, touch, evt, tag0);
+}
+
+void eve_window_init_kbd(EVEWindowKbd *win_kbd, EVERect *g, EVEWindowRoot *root, char *name, EVEKbd *kbd) {
+ EVEWindow *_window = &win_kbd->w;
+
+ eve_window_init(_window, g, NULL, name);
+ _window->root = root;
+ win_kbd->kbd = kbd;
+ root->win_kbd = win_kbd;
+ eve_view_init(&win_kbd->v, _window, kbd_draw, kbd_touch, NULL, kbd);
+}
+
+void eve_window_set_parent(EVEWindow *window, EVEWindow *parent) {
+ window->parent = parent;
+ window->root = parent->root;
+}
+
+int eve_window_visible(EVEWindow *window) {
+ if (window->g.x >= window->root->w.g.w) return 0;
+ if (window->g.y >= window->root->w.g.h) return 0;
+ if ((window->g.x + window->g.w) <= 0) return 0;
+ if ((window->g.y + window->g.h) <= 0) return 0;
+ return 1;
+}
+
+static void window_visible_g(EVEWindow *w, EVERect *g) {
+ while (w) {
+ if (eve_window_visible(w)) {
+ if (w->g.x > g->x) g->w = MIN(g->w, w->g.x - g->x);
+ if (w->g.y > g->y) g->h = MIN(g->h, w->g.y - g->y);
+ if (w->g.x + w->g.w < g->x + g->w) {
+ uint16_t x0 = g->w - MIN(g->w, (g->x + g->w) - (w->g.x + w->g.w));
+ g->x += x0;
+ g->w -= x0;
+ }
+ if (w->g.y + w->g.h < g->y + g->h) {
+ uint16_t y0 = g->h - MIN(g->h, (g->y + g->h) - (w->g.y + w->g.h));
+ g->y += y0;
+ g->h -= y0;
+ }
+ }
+ if (w->child_head) window_visible_g(w->child_head, g);
+ w = w->next;
+ }
+}
+
+void eve_window_visible_g(EVEWindow *window, EVERect *g) {
+ *g = window->g;
+ if (window->child_head) window_visible_g(window->child_head, g);
+ window_visible_g(window->next, g);
+}
+
+void eve_window_append(EVEWindow *window) {
+ EVEWindow *parent = window->parent;
+
+ window->prev = parent->child_tail;
+ window->next = NULL;
+ if (parent->child_tail) {
+ parent->child_tail->next = window;
+ } else {
+ parent->child_head = window;
+ }
+ parent->child_tail = window;
+}
+
+void eve_window_insert_above(EVEWindow *window, EVEWindow *win_prev) {
+ EVEWindow *parent = window->parent;
+
+ window->prev = win_prev;
+ window->next = win_prev->next;
+
+ if (window->next) {
+ window->next->prev = window;
+ } else {
+ parent->child_tail = window;
+ }
+ win_prev->next = window;
+}
+
+void eve_window_insert_below(EVEWindow *window, EVEWindow *win_next) {
+ EVEWindow *parent = window->parent;
+
+ window->prev = win_next->prev;
+ window->next = win_next;
+
+ win_next->prev = window;
+ if (window->prev) {
+ window->prev->next = window;
+ } else {
+ parent->child_head = window;
+ }
+}
+
+void eve_window_remove(EVEWindow *window) {
+ EVEWindow *parent = window->parent;
+
+ if (window->prev) {
+ window->prev->next = window->next;
+ } else {
+ parent->child_head = window->next;
+ }
+ if (window->next) {
+ window->next->prev = window->prev;
+ } else {
+ parent->child_tail = window->prev;
+ }
+ window->parent = NULL;
+ window->prev = NULL;
+ window->next = NULL;
+}
+
+EVEWindow *eve_window_search(EVEWindow *window, char *name) {
+ while (window) {
+ if (window->name && (strcmp(name, window->name) == 0)) return window;
+ if (window->child_head) {
+ EVEWindow *ret = eve_window_search(window->child_head, name);
+ if (ret) return ret;
+ }
+ window = window->next;
+ }
+
+ return NULL;
+}
+
+uint8_t eve_window_draw(EVEWindow *window, uint8_t tag0) {
+ while (window) {
+ if (eve_window_visible(window) && window->view) {
+ int16_t s_x = window->g.x;
+ int16_t s_y = window->g.y;
+ uint16_t s_w = window->g.w;
+ uint16_t s_h = window->g.h;
+
+ if (s_x < 0) {
+ s_w += s_x;
+ s_x = 0;
+ }
+ if (s_y < 0) {
+ s_h += s_y;
+ s_y = 0;
+ }
+ if (s_x + s_w > window->root->w.g.w) s_w = window->root->w.g.w - s_x;
+ if (s_y + s_h > window->root->w.g.h) s_h = window->root->w.g.h - s_y;
+ eve_cmd_dl(SCISSOR_XY(s_x, s_y));
+ eve_cmd_dl(SCISSOR_SIZE(s_w, s_h));
+ tag0 = window->view->draw(window->view, tag0);
+ }
+ if (window->child_head) tag0 = eve_window_draw(window->child_head, tag0);
+ window = window->next;
+ }
+
+ return tag0;
+}
+
+int eve_window_touch(EVEWindow *window, EVETouch *touch, uint16_t evt, uint8_t tag0) {
+ int ret = 0;
+
+ while (window) {
+ if (window->child_tail) {
+ ret = eve_window_touch(window->child_tail, touch, evt, tag0);
+ if (ret) return 1;
+ }
+ if (eve_window_visible(window) && window->view) {
+ ret = window->view->touch(window->view, touch, evt, tag0);
+ if (ret) return 1;
+ }
+ window = window->prev;
+ }
+
+ return 0;
+}
+
+void eve_window_root_draw(EVEWindowRoot *root) {
+ uint8_t tag0 = 0x80;
+ int rv;
+
+ eve_cmd_burst_start();
+ eve_cmd_dl(CMD_DLSTART);
+
+ if (root->tag0 != EVE_NOTAG) tag0 = EVE_NOTAG;
+ eve_window_draw(&root->w, tag0);
+
+ eve_cmd_dl(DISPLAY());
+ eve_cmd_dl(CMD_SWAP);
+ eve_cmd_burst_end();
+ rv = eve_cmd_exec(1);
+ if (rv) printf("EVE EXEC ERR\n");
+}
+
+void eve_window_root_touch(EVETouch *touch, uint16_t evt, uint8_t tag0, void *win) {
+ EVEWindowRoot *root = (EVEWindowRoot *)win;
+ int ret;
+
+ if (root->tag0 != EVE_NOTAG) tag0 = root->tag0;
+ ret = eve_window_touch(&root->w, touch, evt, tag0);
+ if (ret) {
+ eve_touch_clear_opt();
+ eve_window_root_draw(root);
+ }
+}
+
+EVEKbd *eve_window_kbd(EVEWindow *window) {
+ EVEWindowRoot *root = window->root;
+ EVEWindowKbd *win_kbd = root->win_kbd;
+
+ if (win_kbd) return win_kbd->kbd;
+ return NULL;
+}
+
+void eve_window_kbd_attach(EVEWindow *window) {
+ EVEWindowRoot *root = window->root;
+ EVEWindowKbd *win_kbd = root->win_kbd;
+ EVEKbd *kbd = win_kbd ? win_kbd->kbd : NULL;
+
+ if (kbd) {
+ eve_window_set_parent(&win_kbd->w, window);
+ eve_window_append(&win_kbd->w);
+ }
+}
+
+void eve_window_kbd_detach(EVEWindow *window) {
+ EVEWindowRoot *root = window->root;
+ EVEWindowKbd *win_kbd = root->win_kbd;
+ EVEKbd *kbd = win_kbd ? win_kbd->kbd : NULL;
+
+ if (kbd && win_kbd->w.parent) {
+ eve_window_remove(&win_kbd->w);
+ eve_kbd_close(kbd);
+ }
+}
+
+EVEFont *eve_window_font(EVEWindow *window) {
+ EVEWindowRoot *root = window->root;
+
+ return root->font;
+}
+
+EVEWindow *eve_window_scroll(EVEWindowRoot *root, uint8_t *tag) {
+ if (tag) *tag = root->tag0;
+ return root->win_scroll;
+}
+
+void eve_window_scroll_start(EVEWindow *window, uint8_t tag) {
+ EVEWindowRoot *root = window->root;
+
+ root->win_scroll = window;
+ root->tag0 = tag;
+}
+
+void eve_window_scroll_stop(EVEWindow *window) {
+ EVEWindowRoot *root = window->root;
+
+ root->win_scroll = NULL;
+ root->tag0 = EVE_NOTAG;
+}
diff --git a/fw/fe310/eos/eve/screen/window.h b/fw/fe310/eos/eve/screen/window.h
new file mode 100644
index 0000000..27465c4
--- /dev/null
+++ b/fw/fe310/eos/eve/screen/window.h
@@ -0,0 +1,60 @@
+#include <stdint.h>
+
+#include "view.h"
+
+struct EVEWindowRoot;
+
+typedef struct EVEWindow {
+ EVERect g;
+ char *name;
+ EVEView *view;
+ struct EVEWindowRoot *root;
+ struct EVEWindow *parent;
+ struct EVEWindow *next;
+ struct EVEWindow *prev;
+ struct EVEWindow *child_head;
+ struct EVEWindow *child_tail;
+} EVEWindow;
+
+typedef struct EVEWindowKbd {
+ EVEWindow w;
+ EVEView v;
+ EVEKbd *kbd;
+} EVEWindowKbd;
+
+typedef struct EVEWindowRoot {
+ EVEWindow w;
+ uint32_t mem_next;
+ EVEFont *font;
+ EVEWindowKbd *win_kbd;
+ EVEWindow *win_scroll;
+ uint8_t tag0;
+} EVEWindowRoot;
+
+void eve_window_init(EVEWindow *window, EVERect *g, EVEWindow *parent, char *name);
+void eve_window_init_root(EVEWindowRoot *root, EVERect *g, char *name, EVEFont *font);
+void eve_window_init_kbd(EVEWindowKbd *win_kbd, EVERect *g, EVEWindowRoot *root, char *name, EVEKbd *kbd);
+void eve_window_set_parent(EVEWindow *window, EVEWindow *parent);
+
+int eve_window_visible(EVEWindow *window);
+void eve_window_visible_g(EVEWindow *window, EVERect *g);
+
+void eve_window_append(EVEWindow *window);
+void eve_window_insert_above(EVEWindow *window, EVEWindow *win_prev);
+void eve_window_insert_below(EVEWindow *window, EVEWindow *win_next);
+void eve_window_remove(EVEWindow *window);
+EVEWindow *eve_window_search(EVEWindow *window, char *name);
+
+uint8_t eve_window_draw(EVEWindow *window, uint8_t tag0);
+int eve_window_touch(EVEWindow *window, EVETouch *touch, uint16_t evt, uint8_t tag0);
+void eve_window_root_draw(EVEWindowRoot *root);
+void eve_window_root_touch(EVETouch *touch, uint16_t evt, uint8_t tag0, void *win);
+
+EVEKbd *eve_window_kbd(EVEWindow *window);
+void eve_window_kbd_attach(EVEWindow *window);
+void eve_window_kbd_detach(EVEWindow *window);
+EVEFont *eve_window_font(EVEWindow *window);
+
+EVEWindow *eve_window_scroll(EVEWindowRoot *root, uint8_t *tag);
+void eve_window_scroll_start(EVEWindow *window, uint8_t tag);
+void eve_window_scroll_stop(EVEWindow *window);
diff --git a/fw/fe310/eos/eve/widget/Makefile b/fw/fe310/eos/eve/widget/Makefile
new file mode 100644
index 0000000..95af16d
--- /dev/null
+++ b/fw/fe310/eos/eve/widget/Makefile
@@ -0,0 +1,17 @@
+include ../../../common.mk
+
+CFLAGS += -I.. -I../..
+
+obj = label.o widget.o freew.o spacerw.o pagew.o strw.o textw.o selectw.o
+
+
+%.o: %.c %.h
+ $(CC) $(CFLAGS) -c $<
+
+%.o: %.S
+ $(CC) $(CFLAGS) -c $<
+
+all: $(obj)
+
+clean:
+ rm -f *.o
diff --git a/fw/fe310/eos/eve/widget/freew.c b/fw/fe310/eos/eve/widget/freew.c
new file mode 100644
index 0000000..86c2686
--- /dev/null
+++ b/fw/fe310/eos/eve/widget/freew.c
@@ -0,0 +1,54 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include "eve.h"
+#include "eve_kbd.h"
+#include "eve_font.h"
+
+#include "screen/window.h"
+#include "screen/page.h"
+
+#include "label.h"
+#include "widget.h"
+#include "freew.h"
+
+int eve_freew_create(EVEFreeWidget *widget, EVERect *g, EVEPage *page, EVEFreeSpec *spec) {
+ eve_freew_init(widget, g, page, spec->draw, spec->touch, spec->putc);
+
+ return EVE_OK;
+}
+
+void eve_freew_init(EVEFreeWidget *widget, EVERect *g, EVEPage *page, eve_freew_draw_t draw, eve_freew_touch_t touch, eve_kbd_input_handler_t putc) {
+ EVEWidget *_widget = &widget->w;
+
+ memset(widget, 0, sizeof(EVEFreeWidget));
+ eve_widget_init(_widget, EVE_WIDGET_TYPE_FREE, g, page, eve_freew_draw, eve_freew_touch, putc);
+ widget->_draw = draw;
+ widget->_touch = touch;
+ widget->w.putc = putc;
+}
+
+void eve_freew_tag(EVEFreeWidget *widget) {
+ EVEWidget *_widget = &widget->w;
+
+ if (_widget->tagN != EVE_NOTAG) {
+ eve_cmd_dl(TAG(_widget->tagN));
+ _widget->tagN++;
+ }
+}
+
+uint8_t eve_freew_draw(EVEWidget *_widget, uint8_t tag0) {
+ EVEFreeWidget *widget = (EVEFreeWidget *)_widget;
+
+ _widget->tag0 = tag0;
+ _widget->tagN = tag0;
+ widget->_draw(widget);
+
+ return _widget->tagN;
+}
+
+int eve_freew_touch(EVEWidget *_widget, EVETouch *touch, uint16_t evt) {
+ EVEFreeWidget *widget = (EVEFreeWidget *)_widget;
+
+ return widget->_touch(widget, touch, evt);
+}
diff --git a/fw/fe310/eos/eve/widget/freew.h b/fw/fe310/eos/eve/widget/freew.h
new file mode 100644
index 0000000..7eda8c1
--- /dev/null
+++ b/fw/fe310/eos/eve/widget/freew.h
@@ -0,0 +1,25 @@
+#include <stdint.h>
+
+struct EVEFreeWidget;
+
+typedef void (*eve_freew_draw_t) (struct EVEFreeWidget *);
+typedef int (*eve_freew_touch_t) (struct EVEFreeWidget *, EVETouch *, uint16_t);
+
+typedef struct EVEFreeWidget {
+ EVEWidget w;
+ eve_freew_draw_t _draw;
+ eve_freew_touch_t _touch;
+} EVEFreeWidget;
+
+typedef struct EVEFreeSpec {
+ eve_freew_draw_t draw;
+ eve_freew_touch_t touch;
+ eve_kbd_input_handler_t putc;
+} EVEFreeSpec;
+
+int eve_freew_create(EVEFreeWidget *widget, EVERect *g, EVEPage *page, EVEFreeSpec *spec);
+void eve_freew_init(EVEFreeWidget *widget, EVERect *g, EVEPage *page, eve_freew_draw_t draw, eve_freew_touch_t touch, eve_kbd_input_handler_t putc);
+
+void eve_freew_tag(EVEFreeWidget *widget);
+uint8_t eve_freew_draw(EVEWidget *_widget, uint8_t tag0);
+int eve_freew_touch(EVEWidget *_widget, EVETouch *touch, uint16_t evt);
diff --git a/fw/fe310/eos/eve/widget/label.c b/fw/fe310/eos/eve/widget/label.c
new file mode 100644
index 0000000..f2d2e8e
--- /dev/null
+++ b/fw/fe310/eos/eve/widget/label.c
@@ -0,0 +1,23 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include "eve.h"
+#include "eve_kbd.h"
+#include "eve_font.h"
+
+#include "screen/window.h"
+#include "screen/page.h"
+
+#include "label.h"
+
+void eve_label_init(EVELabel *label, EVERect *g, EVEFont *font, char *title) {
+ memset(label, 0, sizeof(EVELabel));
+ if (g) label->g = *g;
+ label->font = font;
+ label->title = title;
+ if (label->g.h == 0) label->g.h = eve_font_h(font);
+}
+
+void eve_label_draw(EVELabel *label) {
+ eve_cmd(CMD_TEXT, "hhhhs", label->g.x, label->g.y, label->font->id, 0, label->title);
+} \ No newline at end of file
diff --git a/fw/fe310/eos/eve/widget/label.h b/fw/fe310/eos/eve/widget/label.h
new file mode 100644
index 0000000..659c057
--- /dev/null
+++ b/fw/fe310/eos/eve/widget/label.h
@@ -0,0 +1,10 @@
+#include <stdint.h>
+
+typedef struct EVELabel {
+ EVERect g;
+ EVEFont *font;
+ char *title;
+} EVELabel;
+
+void eve_label_init(EVELabel *label, EVERect *g, EVEFont *font, char *title);
+void eve_label_draw(EVELabel *label); \ No newline at end of file
diff --git a/fw/fe310/eos/eve/widget/pagew.c b/fw/fe310/eos/eve/widget/pagew.c
new file mode 100644
index 0000000..bd7819f
--- /dev/null
+++ b/fw/fe310/eos/eve/widget/pagew.c
@@ -0,0 +1,59 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include "eve.h"
+#include "eve_kbd.h"
+#include "eve_font.h"
+
+#include "screen/window.h"
+#include "screen/page.h"
+
+#include "label.h"
+#include "widget.h"
+#include "pagew.h"
+
+int eve_pagew_create(EVEPageWidget *widget, EVERect *g, EVEPage *page, EVEPageSpec *spec) {
+ EVEFont *font = spec->font ? spec->font : eve_window_font(page->v.window);
+
+ eve_pagew_init(widget, g, page, font, spec->title, spec->constructor);
+
+ return EVE_OK;
+}
+
+void eve_pagew_init(EVEPageWidget *widget, EVERect *g, EVEPage *page, EVEFont *font, char *title, eve_view_constructor_t constructor) {
+ EVEWidget *_widget = &widget->w;
+
+ memset(widget, 0, sizeof(EVEPageWidget));
+ eve_widget_init(_widget, EVE_WIDGET_TYPE_PAGE, g, page, eve_pagew_draw, eve_pagew_touch, NULL);
+ widget->font = font;
+ widget->title = title;
+ widget->constructor = constructor;
+ if (_widget->g.h == 0) _widget->g.h = eve_font_h(widget->font);
+}
+
+uint8_t eve_pagew_draw(EVEWidget *_widget, uint8_t tag0) {
+ EVEPageWidget *widget = (EVEPageWidget *)_widget;
+
+ _widget->tag0 = tag0;
+ if (tag0 != EVE_NOTAG) {
+ eve_cmd_dl(TAG(tag0));
+ tag0++;
+ }
+ _widget->tagN = tag0;
+
+ eve_cmd(CMD_TEXT, "hhhhs", _widget->g.x, _widget->g.y, widget->font->id, 0, widget->title);
+
+ return _widget->tagN;
+}
+
+int eve_pagew_touch(EVEWidget *_widget, EVETouch *touch, uint16_t evt) {
+ EVEPage *parent = _widget->page;
+ EVEPageWidget *widget = (EVEPageWidget *)_widget;
+
+ if (evt & EVE_TOUCH_ETYPE_TAG_UP) {
+ eve_page_open(parent, widget->constructor);
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/fw/fe310/eos/eve/widget/pagew.h b/fw/fe310/eos/eve/widget/pagew.h
new file mode 100644
index 0000000..76ac0d2
--- /dev/null
+++ b/fw/fe310/eos/eve/widget/pagew.h
@@ -0,0 +1,20 @@
+#include <stdint.h>
+
+typedef struct EVEPageWidget {
+ EVEWidget w;
+ EVEFont *font;
+ char *title;
+ eve_view_constructor_t constructor;
+} EVEPageWidget;
+
+typedef struct EVEPageSpec {
+ EVEFont *font;
+ char *title;
+ eve_view_constructor_t constructor;
+} EVEPageSpec;
+
+int eve_pagew_create(EVEPageWidget *widget, EVERect *g, EVEPage *page, EVEPageSpec *spec);
+void eve_pagew_init(EVEPageWidget *widget, EVERect *g, EVEPage *page, EVEFont *font, char *title, eve_view_constructor_t constructor);
+
+uint8_t eve_pagew_draw(EVEWidget *_widget, uint8_t tag0);
+int eve_pagew_touch(EVEWidget *_widget, EVETouch *touch, uint16_t evt);
diff --git a/fw/fe310/eos/eve/widget/selectw.c b/fw/fe310/eos/eve/widget/selectw.c
new file mode 100644
index 0000000..46ed3d1
--- /dev/null
+++ b/fw/fe310/eos/eve/widget/selectw.c
@@ -0,0 +1,248 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include "eve.h"
+#include "eve_kbd.h"
+#include "eve_font.h"
+
+#include "screen/window.h"
+#include "screen/page.h"
+
+#include "label.h"
+#include "widget.h"
+#include "selectw.h"
+
+#define SELECTW_NOSELECT 0xffffffff
+
+#define DIVC(x,y) ((x) / (y) + ((x) % (y) != 0))
+
+static int selectw_verify(utf8_t *option, uint16_t option_size) {
+ int o_len;
+ uint16_t o_curr;
+ int rv;
+
+ o_curr = 0;
+ while (o_curr < option_size) {
+ rv = utf8_verify(option + o_curr, option_size - o_curr, &o_len);
+ if (rv) return EVE_ERR;
+ if (o_len == 0) return EVE_OK;
+ o_curr += o_len + 1;
+ }
+
+ return EVE_OK;
+}
+
+static int selectw_count(EVESelectWidget *widget) {
+ int o_len;
+ int o_curr;
+ int i;
+
+ o_curr = 0;
+ i = 0;
+ do {
+ o_len = strnlen(widget->option + o_curr, widget->option_size - o_curr);
+ if (o_len == widget->option_size - o_curr) return i;
+ if (o_len) {
+ o_curr += o_len + 1;
+ i++;
+ }
+ } while (o_len);
+
+ return i;
+}
+
+static void selectw_update_sz(EVESelectWidget *widget, int uievt) {
+ EVEWidget *_widget = &widget->w;
+ EVEPage *page = _widget->page;
+
+ _widget->g.h = widget->option_count * widget->font->h;
+ if (uievt) eve_view_uievt_push(&page->v, EVE_UIEVT_WIDGET_UPDATE_G, _widget);
+}
+
+int eve_selectw_create(EVESelectWidget *widget, EVERect *g, EVEPage *page, EVESelectSpec *spec) {
+ EVEFont *font = spec->font ? spec->font : eve_window_font(page->v.window);
+ utf8_t *option;
+
+ option = eve_malloc(spec->option_size);
+ if (option == NULL) {
+ return EVE_ERR_NOMEM;
+ }
+ memset(option, 0, spec->option_size);
+
+ eve_selectw_init(widget, g, page, font, option, spec->option_size, spec->multi);
+
+ return EVE_OK;
+}
+
+void eve_selectw_init(EVESelectWidget *widget, EVERect *g, EVEPage *page, EVEFont *font, utf8_t *option, uint16_t option_size, uint8_t multi) {
+ EVEWidget *_widget = &widget->w;
+ int rv;
+
+ memset(widget, 0, sizeof(EVESelectWidget));
+ eve_widget_init(_widget, EVE_WIDGET_TYPE_SELECT, g, page, eve_selectw_draw, eve_selectw_touch, NULL);
+ widget->font = font;
+ rv = selectw_verify(option, option_size);
+ if (rv == EVE_OK) {
+ widget->option = option;
+ widget->option_size = option_size;
+ widget->option_count = selectw_count(widget);
+ selectw_update_sz(widget, 0);
+ }
+ widget->multi = multi;
+ widget->select = widget->multi ? 0 : SELECTW_NOSELECT;
+}
+
+void eve_selectw_destroy(EVESelectWidget *widget) {
+ eve_free(widget->option);
+}
+
+uint8_t eve_selectw_draw(EVEWidget *_widget, uint8_t tag0) {
+ EVEPage *page = _widget->page;
+ EVESelectWidget *widget = (EVESelectWidget *)_widget;
+ int o_len;
+ int o_curr;
+ int i, s;
+ int16_t x1, x2, y1, y2;
+ uint16_t new_h;
+
+ int line0, lineN;
+
+ line0 = -((int)eve_page_win_y(page, _widget->g.y)) / widget->font->h;
+ lineN = DIVC((-((int)eve_page_win_y(page, _widget->g.y)) + page->v.window->g.h), widget->font->h);
+ if (line0 < 0) line0 = 0;
+ if (lineN < 0) lineN = 0;
+ if (line0 > widget->option_count) line0 = widget->option_count;
+ if (lineN > widget->option_count) lineN = widget->option_count;
+
+ _widget->tag0 = tag0;
+ _widget->tagN = tag0;
+ widget->line0 = line0;
+
+ o_curr = 0;
+ i = 0;
+ do {
+ o_len = strnlen(widget->option + o_curr, widget->option_size - o_curr);
+ if (!o_len || (o_len == widget->option_size - o_curr)) break;
+ if ((i >= line0) && (i < lineN)) {
+ if (_widget->tagN != EVE_NOTAG) {
+ eve_cmd_dl(TAG(_widget->tagN));
+ _widget->tagN++;
+ }
+ s = widget->multi ? widget->select & (0x1 << i) : widget->select == i;
+ x1 = _widget->g.x;
+ x2 = x1 + _widget->g.w;
+ y1 = _widget->g.y + i * widget->font->h;
+ y2 = y1 + widget->font->h;
+ eve_cmd_dl(BEGIN(EVE_RECTS));
+ if (!s) eve_cmd_dl(COLOR_MASK(0 ,0 ,0 ,0));
+ eve_cmd_dl(VERTEX2F(x1, y1));
+ eve_cmd_dl(VERTEX2F(x2, y2));
+ if (!s) {
+ eve_cmd_dl(COLOR_MASK(1 ,1 ,1 ,1));
+ eve_cmd_dl(BEGIN(EVE_LINES));
+ eve_cmd_dl(VERTEX2F(x1, y2));
+ eve_cmd_dl(VERTEX2F(x2, y2));
+ }
+ eve_cmd_dl(END());
+ if (s) eve_cmd_dl(COLOR_RGBC(page->v.color_bg));
+ eve_cmd(CMD_TEXT, "hhhhs", x1, y1, widget->font->id, 0, widget->option + o_curr);
+ if (s) eve_cmd_dl(COLOR_RGBC(page->v.color_fg));
+ }
+
+ o_curr += o_len + 1;
+ i++;
+ } while (o_len);
+
+ return _widget->tagN;
+}
+
+int eve_selectw_touch(EVEWidget *_widget, EVETouch *touch, uint16_t evt) {
+ EVESelectWidget *widget = (EVESelectWidget *)_widget;
+
+ if (evt & EVE_TOUCH_ETYPE_TAG_UP) {
+ int i = touch->tag0 - _widget->tag0 + widget->line0;
+ if (widget->multi) {
+ uint32_t f = (0x1 << i);
+
+ if (widget->select & f) {
+ widget->select &= ~f;
+ } else {
+ widget->select |= f;
+ }
+ } else {
+ if (widget->select == i) {
+ widget->select = SELECTW_NOSELECT;
+ } else {
+ widget->select = i;
+ }
+ }
+ return 1;
+ }
+ return 0;
+}
+
+utf8_t *eve_selectw_option_get(EVESelectWidget *widget, int idx) {
+ int o_len;
+ int o_curr;
+ int i;
+
+ o_curr = 0;
+ i = 0;
+ do {
+ o_len = strnlen(widget->option + o_curr, widget->option_size - o_curr);
+ if (o_len == widget->option_size - o_curr) return NULL;
+ if (o_len && (i == idx)) return widget->option + o_curr;
+ o_curr += o_len + 1;
+ i++;
+ } while (o_len);
+
+ return NULL;
+}
+
+utf8_t *eve_selectw_option_get_select(EVESelectWidget *widget) {
+ return eve_selectw_option_get(widget, widget->select);
+}
+
+int eve_selectw_option_add(EVESelectWidget *widget, utf8_t *option) {
+ int o_len;
+ int o_curr;
+ int rv, i;
+
+ rv = utf8_verify(option, strlen(option) + 1, NULL);
+ if (rv) return EVE_ERR;
+
+ o_curr = 0;
+ i = 0;
+ do {
+ o_len = strnlen(widget->option + o_curr, widget->option_size - o_curr);
+ if (o_len == widget->option_size - o_curr) return EVE_ERR_FULL;
+ if (o_len) {
+ o_curr += o_len + 1;
+ i++;
+ }
+ } while (o_len);
+
+ if (o_curr + strlen(option) + 1 > widget->option_size) return EVE_ERR_FULL;
+ strcpy(widget->option + o_curr, option);
+
+ widget->option_count = i + 1;
+ selectw_update_sz(widget, 1);
+
+ return EVE_OK;
+}
+
+int eve_selectw_option_set(EVESelectWidget *widget, utf8_t *option, uint16_t option_size) {
+ int rv, i;
+
+ rv = selectw_verify(option, option_size);
+ if (rv) return rv;
+ if (option_size > widget->option_size) return EVE_ERR_FULL;
+
+ memcpy(widget->option, option, option_size);
+ memset(widget->option + option_size, 0, widget->option_size - option_size);
+
+ widget->option_count = selectw_count(widget);
+ selectw_update_sz(widget, 1);
+
+ return EVE_OK;
+}
diff --git a/fw/fe310/eos/eve/widget/selectw.h b/fw/fe310/eos/eve/widget/selectw.h
new file mode 100644
index 0000000..939e362
--- /dev/null
+++ b/fw/fe310/eos/eve/widget/selectw.h
@@ -0,0 +1,30 @@
+#include <stdint.h>
+
+typedef struct EVESelectWidget {
+ EVEWidget w;
+ EVEFont *font;
+ utf8_t *option;
+ uint16_t option_size;
+ uint16_t option_count;
+ uint32_t select;
+ uint16_t line0;
+ uint8_t multi;
+} EVESelectWidget;
+
+typedef struct EVESelectSpec {
+ EVEFont *font;
+ uint16_t option_size;
+ uint8_t multi;
+} EVESelectSpec;
+
+int eve_selectw_create(EVESelectWidget *widget, EVERect *g, EVEPage *page, EVESelectSpec *spec);
+void eve_selectw_init(EVESelectWidget *widget, EVERect *g, EVEPage *page, EVEFont *font, utf8_t *option, uint16_t option_size, uint8_t multi);
+void eve_selectw_destroy(EVESelectWidget *widget);
+
+uint8_t eve_selectw_draw(EVEWidget *_widget, uint8_t tag0);
+int eve_selectw_touch(EVEWidget *_widget, EVETouch *touch, uint16_t evt);
+
+utf8_t *eve_selectw_option_get(EVESelectWidget *widget, int idx);
+utf8_t *eve_selectw_option_get_select(EVESelectWidget *widget);
+int eve_selectw_option_add(EVESelectWidget *widget, utf8_t *option);
+int eve_selectw_option_set(EVESelectWidget *widget, utf8_t *option, uint16_t option_size);
diff --git a/fw/fe310/eos/eve/widget/spacerw.c b/fw/fe310/eos/eve/widget/spacerw.c
new file mode 100644
index 0000000..d9f9104
--- /dev/null
+++ b/fw/fe310/eos/eve/widget/spacerw.c
@@ -0,0 +1,36 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include "eve.h"
+#include "eve_kbd.h"
+#include "eve_font.h"
+
+#include "screen/window.h"
+#include "screen/page.h"
+
+#include "label.h"
+#include "widget.h"
+#include "spacerw.h"
+
+int eve_spacerw_create(EVESpacerWidget *widget, EVERect *g, EVEPage *page, EVESpacerSpec *spec) {
+ eve_spacerw_init(widget, g, page);
+
+ return EVE_OK;
+}
+
+void eve_spacerw_init(EVESpacerWidget *widget, EVERect *g, EVEPage *page) {
+ EVEWidget *_widget = &widget->w;
+
+ memset(widget, 0, sizeof(EVESpacerWidget));
+ eve_widget_init(_widget, EVE_WIDGET_TYPE_SPACER, g, page, eve_spacerw_draw, eve_spacerw_touch, NULL);
+}
+
+uint8_t eve_spacerw_draw(EVEWidget *_widget, uint8_t tag0) {
+ _widget->tag0 = tag0;
+ _widget->tagN = tag0;
+ return _widget->tagN;
+}
+
+int eve_spacerw_touch(EVEWidget *_widget, EVETouch *touch, uint16_t evt) {
+ return 0;
+}
diff --git a/fw/fe310/eos/eve/widget/spacerw.h b/fw/fe310/eos/eve/widget/spacerw.h
new file mode 100644
index 0000000..9dafa8b
--- /dev/null
+++ b/fw/fe310/eos/eve/widget/spacerw.h
@@ -0,0 +1,14 @@
+#include <stdint.h>
+
+typedef struct EVESpacerWidget {
+ EVEWidget w;
+} EVESpacerWidget;
+
+typedef struct EVESpacerSpec {
+} EVESpacerSpec;
+
+int eve_spacerw_create(EVESpacerWidget *widget, EVERect *g, EVEPage *page, EVESpacerSpec *spec);
+void eve_spacerw_init(EVESpacerWidget *widget, EVERect *g, EVEPage *page);
+
+uint8_t eve_spacerw_draw(EVEWidget *_widget, uint8_t tag0);
+int eve_spacerw_touch(EVEWidget *_widget, EVETouch *touch, uint16_t evt);
diff --git a/fw/fe310/eos/eve/widget/strw.c b/fw/fe310/eos/eve/widget/strw.c
new file mode 100644
index 0000000..e78cf46
--- /dev/null
+++ b/fw/fe310/eos/eve/widget/strw.c
@@ -0,0 +1,446 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include "clipb.h"
+
+#include "eve.h"
+#include "eve_kbd.h"
+#include "eve_font.h"
+
+#include "screen/window.h"
+#include "screen/page.h"
+
+#include "label.h"
+#include "widget.h"
+#include "strw.h"
+
+#define STRW_TOUCH_OPT EVE_TOUCH_OPT_TRACK | EVE_TOUCH_OPT_TRACK_X | EVE_TOUCH_OPT_TRACK_EXT_X | EVE_TOUCH_OPT_LPRESS
+
+#define STRW_TMODE_NONE 0
+#define STRW_TMODE_CRSR 1
+#define STRW_TMODE_TXT 2
+
+#define CH_BS 0x08
+#define CH_DEL 0x7f
+
+#define CH_CTRLX 0x18
+#define CH_CTRLC 0x03
+#define CH_CTRLV 0x16
+
+#define CHAR_VALID_INPUT(c) ((c >= 0x20) && (c < 0x7f))
+
+int eve_strw_create(EVEStrWidget *widget, EVERect *g, EVEPage *page, EVEStrSpec *spec) {
+ EVEFont *font = spec->font ? spec->font : eve_window_font(page->v.window);
+ utf8_t *str;
+ uint16_t *line;
+
+ str = eve_malloc(spec->str_size);
+ if (str == NULL) return EVE_ERR_NOMEM;
+ str[0] = '\0';
+
+ eve_strw_init(widget, g, page, font, str, spec->str_size);
+
+ return EVE_OK;
+}
+
+void eve_strw_init(EVEStrWidget *widget, EVERect *g, EVEPage *page, EVEFont *font, utf8_t *str, uint16_t str_size) {
+ EVEWidget *_widget = &widget->w;
+ int rv, str_len;
+
+ memset(widget, 0, sizeof(EVEStrWidget));
+ eve_widget_init(_widget, EVE_WIDGET_TYPE_STR, g, page, eve_strw_draw, eve_strw_touch, eve_strw_putc);
+ widget->font = font;
+ rv = utf8_verify(str, str_size, &str_len);
+ if (rv != UTF_OK) {
+ if (str_len >= str_size) str_len = 0;
+ str[str_len] = '\0';
+ }
+ widget->str = str;
+ widget->str_size = str_size;
+ widget->str_len = str_len;
+ widget->str_g.w = eve_font_str_w(widget->font, str);
+ if (_widget->g.h == 0) _widget->g.h = eve_font_h(widget->font);
+}
+
+int eve_strw_update(EVEStrWidget *widget) {
+ int rv, str_len;
+
+ rv = utf8_verify(widget->str, widget->str_size, &str_len);
+ if (rv != UTF_OK) {
+ if (str_len >= widget->str_size) str_len = 0;
+ widget->str[str_len] = '\0';
+ }
+ widget->str_len = str_len;
+ return (rv == UTF_OK) ? EVE_OK : EVE_ERR;
+}
+
+void eve_strw_destroy(EVEStrWidget *widget) {
+ eve_free(widget->str);
+}
+
+static void set_focus(EVEStrWidget *widget) {
+ EVEWidget *_widget = &widget->w;
+ EVERect focus;
+
+ focus.x = _widget->g.x;
+ focus.y = _widget->g.y;
+ focus.w = _widget->g.w;
+ focus.h = 2 * widget->font->h;
+ eve_widget_focus(_widget, &focus);
+}
+
+static EVEStrCursor *cursor_prox(EVEStrWidget *widget, EVEStrCursor *cursor, EVETouch *touch, short *dx) {
+ EVEWidget *_widget = &widget->w;
+ EVEPage *page = _widget->page;
+ int x = eve_page_x(page, touch->x0) - _widget->g.x + widget->str_g.x;
+ int _dx;
+
+ *dx = cursor->x - x;
+ _dx = *dx < 0 ? -(*dx) : *dx;
+
+ if (_dx <= widget->font->w) return cursor;
+ return NULL;
+}
+
+static void draw_string(EVEStrWidget *widget, uint16_t ch, uint16_t len, uint16_t x1, uint16_t x2, char s) {
+ int16_t x;
+ EVEWidget *_widget = &widget->w;
+ EVEPage *page = _widget->page;
+
+ x = _widget->g.x - widget->str_g.x;
+ if (x1 != x2) {
+ eve_cmd_dl(BEGIN(EVE_RECTS));
+ if (!s) eve_cmd_dl(COLOR_MASK(0 ,0 ,0 ,0));
+ eve_cmd_dl(VERTEX2F(x + x1, _widget->g.y));
+ eve_cmd_dl(VERTEX2F(x + x2, _widget->g.y + widget->font->h));
+ if (!s) {
+ eve_cmd_dl(COLOR_MASK(1 ,1 ,1 ,1));
+ eve_cmd_dl(BEGIN(EVE_LINES));
+ eve_cmd_dl(VERTEX2F(x + x1, _widget->g.y + widget->font->h));
+ eve_cmd_dl(VERTEX2F(x + x2, _widget->g.y + widget->font->h));
+ }
+ eve_cmd_dl(END());
+ if (len) {
+ if (s) eve_cmd_dl(COLOR_RGBC(page->v.color_bg));
+ eve_cmd(CMD_TEXT, "hhhhpb", x + x1, _widget->g.y, widget->font->id, 0, widget->str + ch, len, 0);
+ if (s) eve_cmd_dl(COLOR_RGBC(page->v.color_fg));
+ }
+ }
+}
+
+static void draw_cursor(EVEStrWidget *widget, EVEStrCursor *cursor) {
+ uint16_t x, y;
+ EVEWidget *_widget = &widget->w;
+
+ x = _widget->g.x - widget->str_g.x + cursor->x;
+ y = _widget->g.y;
+ eve_cmd_dl(BEGIN(EVE_LINES));
+ eve_cmd_dl(VERTEX2F(x, y));
+ eve_cmd_dl(VERTEX2F(x, y + widget->font->h));
+ eve_cmd_dl(END());
+}
+
+uint8_t eve_strw_draw(EVEWidget *_widget, uint8_t tag0) {
+ EVEStrWidget *widget = (EVEStrWidget *)_widget;
+ char cut = widget->str_g.x || (widget->str_g.w > _widget->g.w);
+
+ _widget->tag0 = tag0;
+ if (tag0 != EVE_NOTAG) {
+ eve_cmd_dl(TAG(tag0));
+ eve_touch_set_opt(tag0, STRW_TOUCH_OPT);
+ tag0++;
+ }
+ _widget->tagN = tag0;
+
+ if (cut) {
+ EVEPage *page = _widget->page;
+ EVEWindow *window = page->v.window;
+ int16_t x = eve_page_scr_x(page, _widget->g.x);
+ int16_t y = eve_page_scr_y(page, _widget->g.y);
+ uint16_t w = _widget->g.w;
+ uint16_t h = _widget->g.h;
+ int16_t win_x1 = window->g.x;
+ int16_t win_y1 = window->g.y;
+ int16_t win_x2 = win_x1 + window->g.w;
+ int16_t win_y2 = win_y1 + window->g.h;
+
+ if (win_x1 < 0) win_x1 = 0;
+ if (win_y1 < 0) win_y1 = 0;
+ if (win_x2 > window->root->w.g.w) win_x2 = window->root->w.g.w;
+ if (win_y2 > window->root->w.g.h) win_y2 = window->root->w.g.h;
+ if (x < win_x1) {
+ w += x - win_x1;
+ x = win_x1;
+ }
+ if (y < win_y1) {
+ h += y - win_y1;
+ y = win_y1;
+ }
+ if (x + w > win_x2) w = win_x2 - x;
+ if (y + h > win_y2) h = win_y2 - y;
+
+ eve_cmd_dl(SAVE_CONTEXT());
+ eve_cmd_dl(SCISSOR_XY(x, y));
+ eve_cmd_dl(SCISSOR_SIZE(w, h));
+ }
+
+ if (widget->cursor2.on) {
+ EVEStrCursor *c1, *c2;
+ int l1, l2, l3;
+
+ if (widget->cursor1.ch <= widget->cursor2.ch) {
+ c1 = &widget->cursor1;
+ c2 = &widget->cursor2;
+ } else {
+ c1 = &widget->cursor2;
+ c2 = &widget->cursor1;
+ }
+
+ l1 = c1->ch;
+ l2 = c2->ch - c1->ch;
+ l3 = widget->str_len - c2->ch;
+ draw_string(widget, 0, l1, 0, c1->x, 0);
+ draw_string(widget, c1->ch, l2, c1->x, c2->x, 1);
+ draw_string(widget, c2->ch, l3, c2->x, widget->str_g.x + _widget->g.w, 0);
+ } else {
+ if (widget->cursor1.on) draw_cursor(widget, &widget->cursor1);
+ draw_string(widget, 0, widget->str_len, 0, widget->str_g.x + _widget->g.w, 0);
+ }
+
+ if (cut) {
+ eve_cmd_dl(RESTORE_CONTEXT());
+ }
+
+ return _widget->tagN;
+}
+
+int eve_strw_touch(EVEWidget *_widget, EVETouch *touch, uint16_t evt) {
+ EVEPage *page = _widget->page;
+ EVEStrWidget *widget = (EVEStrWidget *)_widget;
+ EVEStrCursor *t_cursor = NULL;
+ short dx;
+ int ret = 0;
+
+ if (evt & (EVE_TOUCH_ETYPE_LPRESS | EVE_TOUCH_ETYPE_TRACK_START)) {
+ if (widget->cursor2.on) {
+ t_cursor = cursor_prox(widget, &widget->cursor2, touch, &dx);
+ }
+ if ((t_cursor == NULL) && widget->cursor1.on) {
+ t_cursor = cursor_prox(widget, &widget->cursor1, touch, &dx);
+ }
+ if (evt & EVE_TOUCH_ETYPE_TRACK_START) {
+ if (t_cursor) {
+ widget->track.mode = STRW_TMODE_CRSR;
+ widget->track.cursor = t_cursor;
+ widget->track.dx = dx;
+ } else if (touch->eevt & EVE_TOUCH_EETYPE_TRACK_X) {
+ widget->track.mode = STRW_TMODE_TXT;
+ }
+ }
+ }
+
+ if (widget->track.mode) {
+ int x, w1;
+
+ if (evt & EVE_TOUCH_ETYPE_TRACK) {
+ switch (widget->track.mode) {
+ case STRW_TMODE_TXT:
+ if (evt & EVE_TOUCH_ETYPE_TRACK_START) {
+ widget->str_g.x0 = widget->str_g.x;
+ }
+ x = widget->str_g.x0 + touch->x0 - touch->x;
+ w1 = _widget->g.w - widget->font->w;
+ if (x > widget->str_g.w - w1) x = widget->str_g.w - w1;
+ if (x < 0) x = 0;
+ widget->str_g.x = x;
+ break;
+
+ case STRW_TMODE_CRSR:
+ eve_strw_cursor_set(widget, widget->track.cursor, eve_page_x(page, touch->x) + widget->track.dx);
+ break;
+ }
+ }
+ ret = 1;
+ } else {
+ if (evt & EVE_TOUCH_ETYPE_LPRESS) {
+ if (widget->cursor2.on) {
+ // copy
+ } else if (widget->cursor1.on) {
+ if (t_cursor) {
+ // paste
+ } else {
+ eve_strw_cursor_set(widget, &widget->cursor2, eve_page_x(page, touch->x));
+ }
+ } else {
+ // select
+ }
+ ret = 1;
+ }
+ if ((evt & EVE_TOUCH_ETYPE_POINT_UP) && !(touch->eevt & (EVE_TOUCH_EETYPE_TRACK_XY | EVE_TOUCH_EETYPE_ABORT | EVE_TOUCH_EETYPE_LPRESS))) {
+ eve_strw_cursor_set(widget, &widget->cursor1, eve_page_x(page, touch->x0));
+ if (widget->cursor2.on) eve_strw_cursor_clear(widget, &widget->cursor2);
+ set_focus(widget);
+ ret = 1;
+ }
+ }
+
+ if (evt & EVE_TOUCH_ETYPE_TRACK_STOP) {
+ widget->track.mode = STRW_TMODE_NONE;
+ widget->track.cursor = NULL;
+ widget->track.dx = 0;
+ }
+
+ return ret;
+}
+
+void eve_strw_putc(void *w, int c) {
+ EVEStrWidget *widget = (EVEStrWidget *)w;
+ EVEWidget *_widget = &widget->w;
+ EVEStrCursor *cursor1 = &widget->cursor1;
+ EVEStrCursor *cursor2 = &widget->cursor2;
+ utf8_t *str;
+ utf8_t *clipb = NULL;
+ int w0 = widget->font->w;
+ int w1 = _widget->g.w - widget->font->w;
+ int ins_c = 0, del_c = 0;
+ int ins_w = 0, del_w = 0;
+
+
+ if (c == EVE_PAGE_KBDCH_CLOSE) {
+ if (cursor1->on) eve_strw_cursor_clear(widget, cursor1);
+ if (cursor2->on) eve_strw_cursor_clear(widget, cursor2);
+ return;
+ }
+
+ if (!cursor1->on) return;
+
+ if (!cursor2->on && ((c == CH_BS) || (c == CH_DEL))) {
+ utf32_t uc;
+
+ str = widget->str + cursor1->ch;
+ switch (c) {
+ case CH_BS:
+ if (cursor1->ch > 0) {
+ del_c = -utf8_seek(str, -1, &uc);
+ del_w = eve_font_ch_w(widget->font, uc);
+ memmove(str - del_c, str, widget->str_len - cursor1->ch + 1);
+ widget->str_len -= del_c;
+ widget->str_g.w -= del_w;
+ cursor1->ch -= del_c;
+ cursor1->x -= del_w;
+ }
+ break;
+
+ case CH_DEL:
+ if (cursor1->ch < widget->str_len) {
+ del_c = utf8_dec(str, &uc);
+ del_w = eve_font_ch_w(widget->font, uc);
+ memmove(str, str + del_c, widget->str_len - cursor1->ch - del_c + 1);
+ widget->str_len -= del_c;
+ widget->str_g.w -= del_w;
+ }
+ break;
+ }
+ if (widget->str_g.w - widget->str_g.x < w1) {
+ widget->str_g.x -= del_w;
+ if (widget->str_g.x < 0) widget->str_g.x = 0;
+ }
+ } else {
+ EVEStrCursor *c1 = cursor1;
+ EVEStrCursor *c2 = cursor1;
+ utf8_t utf8_buf[4];
+
+ if (cursor2->on) {
+ if (cursor1->ch <= cursor2->ch) {
+ c2 = cursor2;
+ } else {
+ c1 = cursor2;
+ }
+ del_c = c2->ch - c1->ch;
+ del_w = eve_font_buf_w(widget->font, str, del_c);
+ if ((c == CH_CTRLX) || (c == CH_CTRLC)) {
+ eve_clipb_push(str, del_c);
+ if (c == CH_CTRLC) return;
+ }
+ }
+
+ str = widget->str + c1->ch;
+ if (CHAR_VALID_INPUT(c)) {
+ ins_c = utf8_enc(c, utf8_buf);
+ ins_w = eve_font_ch_w(widget->font, c);
+ } else if (c == CH_CTRLV) {
+ int rv, clipb_len = 0;
+
+ clipb = eve_clipb_get();
+ if (clipb) {
+ rv = utf8_verify(clipb, EVE_CLIPB_SIZE_BUF, &clipb_len);
+ if (rv != UTF_OK) {
+ clipb = NULL;
+ clipb_len = 0;
+ }
+ }
+ ins_c = clipb_len;
+ ins_w = eve_font_str_w(widget->font, clipb);
+ }
+ if (widget->str_len + ins_c >= widget->str_size + del_c) {
+ ins_c = 0;
+ ins_w = 0;
+ }
+ if (ins_c != del_c) memmove(str + ins_c, str + del_c, widget->str_len - c2->ch + 1);
+ if (ins_c) {
+ if (c == CH_CTRLV) {
+ memcpy(str, clipb, ins_c);
+ } else if (ins_c > 1) {
+ memcpy(str, utf8_buf, ins_c);
+ } else {
+ *str = utf8_buf[0];
+ }
+ c1->ch += ins_c;
+ c1->x += ins_w;
+ }
+ widget->str_len += ins_c - del_c;
+ widget->str_g.w += ins_w - del_w;
+ if (c1 == cursor2) widget->cursor1 = widget->cursor2;
+ if (cursor2->on) eve_strw_cursor_clear(widget, cursor2);
+ }
+
+ if (cursor1->x - widget->str_g.x < w0) widget->str_g.x = cursor1->x > w0 ? cursor1->x - w0 : 0;
+ if (cursor1->x - widget->str_g.x > w1) widget->str_g.x = cursor1->x - w1;
+}
+
+void eve_strw_cursor_set(EVEStrWidget *widget, EVEStrCursor *cursor, int16_t x) {
+ int i;
+ int16_t _x, _d;
+ utf32_t ch;
+ uint8_t ch_w;
+ uint8_t ch_l;
+ EVEWidget *_widget = &widget->w;
+
+ x = x - _widget->g.x + widget->str_g.x;
+
+ _x = 0;
+ _d = x;
+ i = 0;
+ while (i < widget->str_len) {
+ ch_l = utf8_dec(widget->str + i, &ch);
+ ch_w = eve_font_ch_w(widget->font, ch);
+ _x += ch_w;
+ i += ch_l;
+ if (_x >= x) {
+ if (_x - x > _d) {
+ _x -= ch_w;
+ i -= ch_l;
+ }
+ break;
+ } else {
+ _d = x - _x;
+ }
+ }
+ cursor->x = _x;
+ cursor->ch = i;
+ cursor->on = 1;
+}
+
+void eve_strw_cursor_clear(EVEStrWidget *widget, EVEStrCursor *cursor) {
+ cursor->on = 0;
+}
diff --git a/fw/fe310/eos/eve/widget/strw.h b/fw/fe310/eos/eve/widget/strw.h
new file mode 100644
index 0000000..44e5e2d
--- /dev/null
+++ b/fw/fe310/eos/eve/widget/strw.h
@@ -0,0 +1,43 @@
+#include <stdint.h>
+
+typedef struct EVEStrCursor {
+ char on;
+ uint16_t x;
+ uint16_t ch;
+} EVEStrCursor;
+
+typedef struct EVEStrWidget {
+ EVEWidget w;
+ EVEFont *font;
+ utf8_t *str;
+ uint16_t str_size;
+ uint16_t str_len;
+ struct {
+ int16_t x;
+ int16_t x0;
+ uint16_t w;
+ } str_g;
+ EVEStrCursor cursor1;
+ EVEStrCursor cursor2;
+ struct {
+ EVEStrCursor *cursor;
+ short dx;
+ char mode;
+ } track;
+} EVEStrWidget;
+
+typedef struct EVEStrSpec {
+ EVEFont *font;
+ uint16_t str_size;
+} EVEStrSpec;
+
+int eve_strw_create(EVEStrWidget *widget, EVERect *g, EVEPage *page, EVEStrSpec *spec);
+void eve_strw_init(EVEStrWidget *widget, EVERect *g, EVEPage *page, EVEFont *font, utf8_t *str, uint16_t str_size);
+void eve_strw_destroy(EVEStrWidget *widget);
+int eve_strw_update(EVEStrWidget *widget);
+
+uint8_t eve_strw_draw(EVEWidget *_widget, uint8_t tag0);
+int eve_strw_touch(EVEWidget *_widget, EVETouch *touch, uint16_t evt);
+void eve_strw_putc(void *_page, int c);
+void eve_strw_cursor_set(EVEStrWidget *widget, EVEStrCursor *cursor, int16_t x);
+void eve_strw_cursor_clear(EVEStrWidget *widget, EVEStrCursor *cursor); \ No newline at end of file
diff --git a/fw/fe310/eos/eve/widget/textw.c b/fw/fe310/eos/eve/widget/textw.c
new file mode 100644
index 0000000..e994c0e
--- /dev/null
+++ b/fw/fe310/eos/eve/widget/textw.c
@@ -0,0 +1,545 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include "clipb.h"
+
+#include "eve.h"
+#include "eve_kbd.h"
+#include "eve_font.h"
+
+#include "screen/window.h"
+#include "screen/page.h"
+
+#include "label.h"
+#include "widget.h"
+#include "textw.h"
+
+#define TEXTW_TOUCH_OPT EVE_TOUCH_OPT_TRACK | EVE_TOUCH_OPT_TRACK_XY | EVE_TOUCH_OPT_TRACK_EXT_XY | EVE_TOUCH_OPT_LPRESS
+
+#define CH_BS 0x08
+#define CH_DEL 0x7f
+
+#define CH_CTRLX 0x18
+#define CH_CTRLC 0x03
+#define CH_CTRLV 0x16
+
+#define LINE_LEN(w,l) ((l) ? (w->line[l] ? w->line[l] - w->line[(l) - 1] - 1 : 0) : w->line[l])
+#define LINE_START(w,l) ((l) ? w->line[(l) - 1] + 1 : 0)
+#define LINE_END(w,l) (w->line[l])
+#define LINE_EMPTY 0xffff
+
+#define CHAR_VALID_INPUT(c) (((c >= 0x20) && (c < 0x7f)) || (c == '\n'))
+
+#define DIVC(x,y) ((x) / (y) + ((x) % (y) != 0))
+
+int eve_textw_create(EVETextWidget *widget, EVERect *g, EVEPage *page, EVETextSpec *spec) {
+ EVEFont *font = spec->font ? spec->font : eve_window_font(page->v.window);
+ utf8_t *text;
+ uint16_t *line;
+
+ text = eve_malloc(spec->text_size);
+ if (text == NULL) {
+ return EVE_ERR_NOMEM;
+ }
+ text[0] = '\0';
+ line = eve_malloc(sizeof(uint16_t) * spec->line_size);
+ if (line == NULL) {
+ free(text);
+ return EVE_ERR_NOMEM;
+ }
+
+ eve_textw_init(widget, g, page, font, text, spec->text_size, line, spec->line_size);
+
+ return EVE_OK;
+}
+
+void eve_textw_init(EVETextWidget *widget, EVERect *g, EVEPage *page, EVEFont *font, utf8_t *text, uint16_t text_size, uint16_t *line, uint16_t line_size) {
+ EVEWidget *_widget = &widget->w;
+ int rv, text_len;
+
+ memset(widget, 0, sizeof(EVETextWidget));
+ eve_widget_init(_widget, EVE_WIDGET_TYPE_TEXT, g, page, eve_textw_draw, eve_textw_touch, eve_textw_putc);
+ widget->font = font;
+ rv = utf8_verify(text, text_size, &text_len);
+ if (rv != UTF_OK) {
+ if (text_len >= text_size) text_len = 0;
+ text[text_len] = '\0';
+ }
+ widget->text = text;
+ widget->text_size = text_size;
+ widget->text_len = text_len;
+ widget->line = line;
+ widget->line_size = line_size;
+ memset(widget->line, 0xff, line_size * sizeof(uint16_t));
+ eve_textw_text_update(widget, 0, 0);
+}
+
+void eve_textw_destroy(EVETextWidget *widget) {
+ eve_free(widget->line);
+ eve_free(widget->text);
+}
+
+static void set_focus(EVETextWidget *widget, EVETextCursor *cursor) {
+ EVEWidget *_widget = &widget->w;
+ EVERect focus;
+
+ focus.x = _widget->g.x;
+ focus.y = _widget->g.y + cursor->line * widget->font->h;
+ focus.w = _widget->g.w;
+ focus.h = 2 * widget->font->h;
+ eve_widget_focus(_widget, &focus);
+}
+
+static EVETextCursor *cursor_prox(EVETextWidget *widget, EVETextCursor *cursor, EVETouch *touch, short *dx, short *dl) {
+ EVEWidget *_widget = &widget->w;
+ EVEPage *page = _widget->page;
+ int x = eve_page_x(page, touch->x0) - _widget->g.x;
+ int l = (int)touch->tag0 - _widget->tag0 + widget->line0;
+ int _dx, _dl;
+
+ *dx = cursor->x - x;
+ *dl = cursor->line - l;
+
+ _dx = *dx < 0 ? -(*dx) : *dx;
+ _dl = *dl < 0 ? -(*dl) : *dl;
+
+ if ((_dx <= widget->font->h) && (_dl <= 1)) return cursor;
+ return NULL;
+}
+
+static void draw_line(EVETextWidget *widget, uint16_t l, uint16_t ch, uint16_t len, uint16_t x1, uint16_t x2, char s) {
+ EVEWidget *_widget = &widget->w;
+ EVEPage *page = _widget->page;
+
+ if (x1 != x2) {
+ eve_cmd_dl(BEGIN(EVE_RECTS));
+ if (!s) eve_cmd_dl(COLOR_MASK(0 ,0 ,0 ,0));
+ eve_cmd_dl(VERTEX2F(_widget->g.x + x1, _widget->g.y + l * widget->font->h));
+ eve_cmd_dl(VERTEX2F(_widget->g.x + x2, _widget->g.y + (l + 1) * widget->font->h));
+ if (!s) {
+ eve_cmd_dl(COLOR_MASK(1 ,1 ,1 ,1));
+ eve_cmd_dl(BEGIN(EVE_LINES));
+ eve_cmd_dl(VERTEX2F(_widget->g.x + x1, _widget->g.y + (l + 1) * widget->font->h));
+ eve_cmd_dl(VERTEX2F(_widget->g.x + x2, _widget->g.y + (l + 1) * widget->font->h));
+ }
+ eve_cmd_dl(END());
+ if (len) {
+ if (s) eve_cmd_dl(COLOR_RGBC(page->v.color_bg));
+ eve_cmd(CMD_TEXT, "hhhhpb", _widget->g.x + x1, _widget->g.y + l * widget->font->h, widget->font->id, 0, widget->text + ch, len, 0);
+ if (s) eve_cmd_dl(COLOR_RGBC(page->v.color_fg));
+ }
+ }
+}
+
+static void draw_cursor(EVETextWidget *widget, EVETextCursor *cursor) {
+ uint16_t x, y;
+ EVEWidget *_widget = &widget->w;
+
+ x = _widget->g.x + cursor->x;
+ y = _widget->g.y + cursor->line * widget->font->h;
+ eve_cmd_dl(BEGIN(EVE_LINES));
+ eve_cmd_dl(VERTEX2F(x, y));
+ eve_cmd_dl(VERTEX2F(x, y + widget->font->h));
+ eve_cmd_dl(END());
+}
+
+uint8_t eve_textw_draw(EVEWidget *_widget, uint8_t tag0) {
+ EVEPage *page = _widget->page;
+ EVETextWidget *widget = (EVETextWidget *)_widget;
+ int line0, lineN;
+ int _line0, _lineN;
+ char lineNvisible;
+
+ _line0 = line0 = -((int)eve_page_win_y(page, _widget->g.y)) / widget->font->h;
+ _lineN = lineN = DIVC((-((int)eve_page_win_y(page, _widget->g.y)) + page->v.window->g.h), widget->font->h);
+ if (line0 < 0) line0 = 0;
+ if (lineN < 0) lineN = 0;
+ if (line0 > widget->line_len) line0 = widget->line_len;
+ if (lineN > widget->line_len) lineN = widget->line_len;
+ lineNvisible = (lineN >= _line0) && (lineN < _lineN);
+
+ if (lineNvisible || (line0 < lineN)) {
+ int i;
+ char s = 0;
+ EVETextCursor *c1, *c2;
+
+ widget->line0 = line0;
+ _widget->tag0 = tag0;
+ _widget->tagN = tag0;
+
+ if (widget->cursor2.on) {
+ if (widget->cursor1.ch <= widget->cursor2.ch) {
+ c1 = &widget->cursor1;
+ c2 = &widget->cursor2;
+ } else {
+ c1 = &widget->cursor2;
+ c2 = &widget->cursor1;
+ }
+ } else {
+ c1 = NULL;
+ c2 = NULL;
+ }
+
+ for (i=line0; i<lineN; i++) {
+ if (_widget->tagN != EVE_NOTAG) {
+ eve_cmd_dl(TAG(_widget->tagN));
+ eve_touch_set_opt(_widget->tagN, TEXTW_TOUCH_OPT);
+ _widget->tagN++;
+ }
+ if (!s && c1 && (c1->line == i)) {
+ int l1, l2, l3;
+
+ l1 = c1->ch - LINE_START(widget, i);
+ if (c2->line == i) {
+ l2 = c2->ch - c1->ch;
+ l3 = LINE_START(widget, i) + LINE_LEN(widget, i) - c2->ch;
+ } else {
+ l2 = LINE_START(widget, i) + LINE_LEN(widget, i) - c1->ch;
+ l3 = 0;
+ s = 1;
+ }
+ draw_line(widget, i, LINE_START(widget, i), l1, 0, c1->x, 0);
+ draw_line(widget, i, c1->ch, l2, c1->x, s ? _widget->g.w : c2->x, 1);
+ if (!s) {
+ draw_line(widget, i, c2->ch, l3, c2->x, _widget->g.w, 0);
+ c1 = NULL;
+ c2 = NULL;
+ }
+ } else if (s && (c2->line == i)) {
+ int l1 = c2->ch - LINE_START(widget, i);
+ int l2 = LINE_START(widget, i) + LINE_LEN(widget, i) - c2->ch;
+
+ draw_line(widget, i, LINE_START(widget, i), l1, 0, c2->x, 1);
+ draw_line(widget, i, c2->ch, l2, c2->x, _widget->g.w, 0);
+ c1 = NULL;
+ c2 = NULL;
+ s = 0;
+ } else {
+ if (widget->cursor1.on && (widget->cursor1.line == i)) draw_cursor(widget, &widget->cursor1);
+ draw_line(widget, i, LINE_START(widget, i), LINE_LEN(widget, i), 0, _widget->g.w, s);
+ }
+ }
+ if (lineNvisible) {
+ if (_widget->tagN != EVE_NOTAG) {
+ eve_cmd_dl(TAG(_widget->tagN));
+ eve_touch_set_opt(_widget->tagN, TEXTW_TOUCH_OPT);
+ _widget->tagN++;
+ }
+ draw_line(widget, lineN, 0, 0, 0, _widget->g.w, 0);
+ }
+ } else {
+ widget->line0 = 0;
+ _widget->tag0 = EVE_NOTAG;
+ _widget->tagN = EVE_NOTAG;
+ }
+
+ return _widget->tagN;
+}
+
+int eve_textw_touch(EVEWidget *_widget, EVETouch *touch, uint16_t evt) {
+ EVEPage *page = _widget->page;
+ EVETextWidget *widget = (EVETextWidget *)_widget;
+ EVETextCursor *t_cursor = NULL;
+ short dx, dl;
+ int ret = 0;
+
+ if (evt & (EVE_TOUCH_ETYPE_LPRESS | EVE_TOUCH_ETYPE_TRACK_START)) {
+ if (widget->cursor2.on) {
+ t_cursor = cursor_prox(widget, &widget->cursor2, touch, &dx, &dl);
+ }
+ if ((t_cursor == NULL) && widget->cursor1.on) {
+ t_cursor = cursor_prox(widget, &widget->cursor1, touch, &dx, &dl);
+ }
+ if (t_cursor && (evt & EVE_TOUCH_ETYPE_TRACK_START)) {
+ widget->track.cursor = t_cursor;
+ widget->track.dx = dx;
+ widget->track.dl = dl;
+ }
+ }
+
+ if (widget->track.cursor) {
+ if (evt & EVE_TOUCH_ETYPE_TRACK) eve_textw_cursor_set(widget, widget->track.cursor, touch->tag + widget->track.dl, eve_page_x(page, touch->x) + widget->track.dx);
+ ret = 1;
+ } else {
+ if (evt & EVE_TOUCH_ETYPE_LPRESS) {
+ if (widget->cursor2.on) {
+ // copy
+ } else if (widget->cursor1.on) {
+ if (t_cursor && (dl == 0)) {
+ // paste
+ } else {
+ eve_textw_cursor_set(widget, &widget->cursor2, touch->tag, eve_page_x(page, touch->x));
+ }
+ } else {
+ // select
+ }
+ ret = 1;
+ }
+ if ((evt & EVE_TOUCH_ETYPE_POINT_UP) && !(touch->eevt & (EVE_TOUCH_EETYPE_TRACK_XY | EVE_TOUCH_EETYPE_ABORT | EVE_TOUCH_EETYPE_LPRESS))) {
+ eve_textw_cursor_set(widget, &widget->cursor1, touch->tag_up, eve_page_x(page, touch->x0));
+ if (widget->cursor2.on) eve_textw_cursor_clear(widget, &widget->cursor2);
+ set_focus(widget, &widget->cursor1);
+ ret = 1;
+ }
+ }
+
+ if (evt & EVE_TOUCH_ETYPE_TRACK_STOP) {
+ widget->track.cursor = NULL;
+ widget->track.dx = 0;
+ widget->track.dl = 0;
+ }
+
+ return ret;
+}
+
+void eve_textw_putc(void *w, int c) {
+ EVETextWidget *widget = (EVETextWidget *)w;
+ EVEWidget *_widget = &widget->w;
+ EVETextCursor *cursor1 = &widget->cursor1;
+ EVETextCursor *cursor2 = &widget->cursor2;
+ utf8_t *text;
+ utf8_t *clipb = NULL;
+ int i, r;
+ int ins_c = 0, del_c = 0;
+ int ch_w = 0;
+
+ if (c == EVE_PAGE_KBDCH_CLOSE) {
+ if (cursor1->on) eve_textw_cursor_clear(widget, cursor1);
+ if (cursor2->on) eve_textw_cursor_clear(widget, cursor2);
+ return;
+ }
+
+ if (!cursor1->on) return;
+
+ if (!cursor2->on && ((c == CH_BS) || (c == CH_DEL))) {
+ utf32_t uc;
+
+ text = widget->text + cursor1->ch;
+ switch (c) {
+ case CH_BS:
+ if (cursor1->ch > 0) {
+ del_c = -utf8_seek(text, -1, &uc);
+ ch_w = eve_font_ch_w(widget->font, uc);
+ memmove(text - del_c, text, widget->text_len - cursor1->ch + 1);
+ cursor1->ch -= del_c;
+ }
+ break;
+
+ case CH_DEL:
+ if (cursor1->ch < widget->text_len) {
+ del_c = utf8_dec(text, &uc);
+ ch_w = eve_font_ch_w(widget->font, uc);
+ memmove(text, text + del_c, widget->text_len - cursor1->ch - del_c + 1);
+ }
+ break;
+ }
+ } else {
+ EVETextCursor *c1 = cursor1;
+ EVETextCursor *c2 = cursor1;
+ utf8_t utf8_buf[4];
+
+ if (cursor2->on) {
+ if (cursor1->ch <= cursor2->ch) {
+ c2 = cursor2;
+ } else {
+ c1 = cursor2;
+ }
+ del_c = c2->ch - c1->ch;
+ if ((c == CH_CTRLX) || (c == CH_CTRLC)) {
+ eve_clipb_push(text, del_c);
+ if (c == CH_CTRLC) return;
+ }
+ }
+
+ text = widget->text + c1->ch;
+ if (CHAR_VALID_INPUT(c)) {
+ ins_c = utf8_enc(c, utf8_buf);
+ ch_w = eve_font_ch_w(widget->font, c);
+ } else if (c == CH_CTRLV) {
+ int rv, clipb_len = 0;
+
+ clipb = eve_clipb_get();
+ if (clipb) {
+ rv = utf8_verify(clipb, EVE_CLIPB_SIZE_BUF, &clipb_len);
+ if (rv != UTF_OK) {
+ clipb = NULL;
+ clipb_len = 0;
+ }
+ }
+ ins_c = clipb_len;
+ ch_w = eve_font_str_w(widget->font, clipb);
+ }
+ if (widget->text_len + ins_c >= widget->text_size + del_c) {
+ ins_c = 0;
+ ch_w = 0;
+ }
+ if (ins_c != del_c) memmove(text + ins_c, text + del_c, widget->text_len - c2->ch + 1);
+ if (ins_c) {
+ if (c == CH_CTRLV) {
+ memcpy(text, clipb, ins_c);
+ } else if (ins_c > 1) {
+ memcpy(text, utf8_buf, ins_c);
+ } else {
+ *text = utf8_buf[0];
+ }
+ c1->ch += ins_c;
+ }
+ if (c1 == cursor2) widget->cursor1 = widget->cursor2;
+ if (cursor2->on) eve_textw_cursor_clear(widget, cursor2);
+ }
+
+ if ((ins_c == 0) && (del_c == 0)) return;
+
+ widget->text_len += ins_c - del_c;
+ for (i=cursor1->line; i<widget->line_len; i++) {
+ widget->line[i] += ins_c - del_c;
+ }
+
+ r = cursor1->line;
+ if (cursor1->line) r = eve_textw_text_update(widget, cursor1->line - 1, 1);
+ if ((cursor1->line == 0) || (r == cursor1->line - 1)) r = eve_textw_text_update(widget, cursor1->line, 1);
+
+ if (cursor1->line && (cursor1->ch < LINE_START(widget, cursor1->line))) {
+ cursor1->line--;
+ eve_textw_cursor_update(widget, cursor1);
+ set_focus(widget, cursor1);
+ } else if (cursor1->ch > LINE_END(widget, cursor1->line)) {
+ while (cursor1->ch > LINE_END(widget, cursor1->line)) cursor1->line++;
+ eve_textw_cursor_update(widget, cursor1);
+ set_focus(widget, cursor1);
+ } else {
+ cursor1->x += ch_w;
+ }
+}
+
+uint16_t eve_textw_text_update(EVETextWidget *widget, uint16_t line, int uievt) {
+ int i;
+ utf32_t ch;
+ uint8_t ch_w;
+ uint8_t ch_l;
+ uint16_t word_w, line_w, line_b;
+ uint16_t new_h;
+ EVEWidget *_widget = &widget->w;
+ EVEPage *page = _widget->page;
+
+ word_w = 0;
+ line_w = 0;
+ line_b = LINE_EMPTY;
+
+ i = LINE_START(widget, line);
+ while (i < widget->text_size) {
+ ch_l = utf8_dec(widget->text + i, &ch);
+ if (!CHAR_VALID_INPUT(ch) && ch) {
+ ch = 0;
+ widget->text[i] = '\0';
+ widget->text_len = i;
+ widget->line[line] = LINE_EMPTY;
+ }
+
+ ch_w = eve_font_ch_w(widget->font, ch);
+ if (ch <= 0x20) {
+ if ((ch == '\n') || (ch == '\0')) {
+ if (widget->line[line] == i) return line;
+ widget->line[line] = i;
+ line++;
+ if ((ch == '\0') || (line == widget->line_size)) break;
+ word_w = 0;
+ line_w = 0;
+ line_b = LINE_EMPTY;
+ } else if (ch == ' ') {
+ word_w = 0;
+ line_w += ch_w;
+ line_b = i;
+ }
+ } else {
+ word_w += ch_w;
+ line_w += ch_w;
+ }
+ if ((line_w > _widget->g.w) && (line_b != LINE_EMPTY)) {
+ if (widget->line[line] == line_b) return line;
+ widget->line[line] = line_b;
+ line++;
+ if (line == widget->line_size) {
+ i = line_b;
+ break;
+ }
+ line_w = word_w;
+ line_b = LINE_EMPTY;
+ }
+ i += ch_l;
+ }
+
+ for (i=line; i<widget->line_size; i++) {
+ widget->line[i] = LINE_EMPTY;
+ }
+
+ if (uievt && (widget->line_len != line)) {
+ eve_view_uievt_push(&page->v, EVE_UIEVT_WIDGET_UPDATE_G, _widget);
+ }
+ widget->line_len = line;
+ _widget->g.h = (widget->line_len + 1) * widget->font->h;
+
+ return line;
+}
+
+void eve_textw_cursor_update(EVETextWidget *widget, EVETextCursor *cursor) {
+ int i = LINE_START(widget, cursor->line);
+ uint16_t x = 0;
+ utf32_t ch;
+ uint8_t ch_l;
+ EVEWidget *_widget = &widget->w;
+
+ while ((i < cursor->ch) && (i < LINE_END(widget, cursor->line))) {
+ ch_l = utf8_dec(widget->text + i, &ch);
+ x += eve_font_ch_w(widget->font, ch);
+ i += ch_l;
+ }
+ cursor->x = x;
+}
+
+void eve_textw_cursor_set(EVETextWidget *widget, EVETextCursor *cursor, uint8_t tag, int16_t x) {
+ int i;
+ int16_t _x, _d;
+ uint16_t c_line = LINE_EMPTY;
+ utf32_t ch;
+ uint8_t ch_w;
+ uint8_t ch_l;
+ EVEWidget *_widget = &widget->w;
+
+ if ((tag >= _widget->tag0) && ((_widget->tagN == EVE_NOTAG) || (tag < _widget->tagN))) c_line = tag - _widget->tag0 + widget->line0;
+ if (c_line < widget->line_len) {
+ cursor->line = c_line;
+ } else if (c_line == widget->line_len) {
+ cursor->line = c_line - 1;
+ } else if (!cursor->on) {
+ return;
+ }
+
+ x -= _widget->g.x;
+
+ _x = 0;
+ _d = x;
+ i = LINE_START(widget, cursor->line);
+ while (i < LINE_END(widget, cursor->line)) {
+ ch_l = utf8_dec(widget->text + i, &ch);
+ ch_w = eve_font_ch_w(widget->font, ch);
+ _x += ch_w;
+ i += ch_l;
+ if (_x >= x) {
+ if (_x - x > _d) {
+ _x -= ch_w;
+ i -= ch_l;
+ }
+ break;
+ } else {
+ _d = x - _x;
+ }
+ }
+ cursor->x = _x;
+ cursor->ch = i;
+ cursor->on = 1;
+}
+
+void eve_textw_cursor_clear(EVETextWidget *widget, EVETextCursor *cursor) {
+ cursor->on = 0;
+}
diff --git a/fw/fe310/eos/eve/widget/textw.h b/fw/fe310/eos/eve/widget/textw.h
new file mode 100644
index 0000000..570bba8
--- /dev/null
+++ b/fw/fe310/eos/eve/widget/textw.h
@@ -0,0 +1,46 @@
+#include <stdint.h>
+
+typedef struct EVETextCursor {
+ char on;
+ uint16_t x;
+ uint16_t line;
+ uint16_t ch;
+} EVETextCursor;
+
+typedef struct EVETextWidget {
+ EVEWidget w;
+ EVEFont *font;
+ utf8_t *text;
+ uint16_t text_size;
+ uint16_t text_len;
+ uint16_t *line;
+ uint16_t line_size;
+ uint16_t line_len;
+ EVETextCursor cursor1;
+ EVETextCursor cursor2;
+ uint16_t line0;
+ struct {
+ EVETextCursor *cursor;
+ short dx;
+ short dl;
+ } track;
+} EVETextWidget;
+
+typedef struct EVETextSpec {
+ EVEFont *font;
+ uint16_t text_size;
+ uint16_t line_size;
+} EVETextSpec;
+
+int eve_textw_create(EVETextWidget *widget, EVERect *g, EVEPage *page, EVETextSpec *spec);
+void eve_textw_init(EVETextWidget *widget, EVERect *g, EVEPage *page, EVEFont *font, utf8_t *text, uint16_t text_size, uint16_t *line, uint16_t line_size);
+void eve_textw_destroy(EVETextWidget *widget);
+
+uint8_t eve_textw_draw(EVEWidget *_widget, uint8_t tag0);
+int eve_textw_touch(EVEWidget *_widget, EVETouch *touch, uint16_t evt);
+void eve_textw_putc(void *_w, int c);
+
+uint16_t eve_textw_text_update(EVETextWidget *widget, uint16_t line, int uievt);
+void eve_textw_cursor_update(EVETextWidget *widget, EVETextCursor *cursor);
+void eve_textw_cursor_set(EVETextWidget *widget, EVETextCursor *cursor, uint8_t tag, int16_t x);
+void eve_textw_cursor_clear(EVETextWidget *widget, EVETextCursor *cursor);
diff --git a/fw/fe310/eos/eve/widget/widget.c b/fw/fe310/eos/eve/widget/widget.c
new file mode 100644
index 0000000..96d2ddf
--- /dev/null
+++ b/fw/fe310/eos/eve/widget/widget.c
@@ -0,0 +1,77 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include "eve.h"
+#include "eve_kbd.h"
+#include "eve_font.h"
+
+#include "screen/window.h"
+#include "screen/page.h"
+
+#include "widgets.h"
+
+static const size_t _widget_size[] = {
+ 0,
+ sizeof(EVEFreeWidget),
+ sizeof(EVESpacerWidget),
+ sizeof(EVEPageWidget),
+ sizeof(EVEStrWidget),
+ sizeof(EVETextWidget),
+ sizeof(EVESelectWidget),
+};
+
+static const eve_widget_create_t _widget_create[] = {
+ NULL,
+ (eve_widget_create_t)eve_freew_create,
+ (eve_widget_create_t)eve_spacerw_create,
+ (eve_widget_create_t)eve_pagew_create,
+ (eve_widget_create_t)eve_strw_create,
+ (eve_widget_create_t)eve_textw_create,
+ (eve_widget_create_t)eve_selectw_create,
+};
+
+static const eve_widget_destroy_t _widget_destroy[] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ (eve_widget_destroy_t)eve_strw_destroy,
+ (eve_widget_destroy_t)eve_textw_destroy,
+ (eve_widget_destroy_t)eve_selectw_destroy,
+};
+
+void eve_widget_init(EVEWidget *widget, uint8_t type, EVERect *g, EVEPage *page, eve_widget_draw_t draw, eve_widget_touch_t touch, eve_kbd_input_handler_t putc) {
+ if (g) widget->g = *g;
+ widget->page = page;
+ widget->draw = draw;
+ widget->touch = touch;
+ widget->putc = putc;
+ widget->type = type;
+}
+
+size_t eve_widget_size(uint8_t type) {
+ return _widget_size[type];
+}
+
+void eve_widget_set_label(EVEWidget *widget, EVELabel *label) {
+ widget->label = label;
+}
+
+EVEWidget *eve_widget_next(EVEWidget *widget) {
+ char *_w = (char *)widget;
+ return (EVEWidget *)(_w + _widget_size[widget->type]);
+}
+
+int eve_widget_create(EVEWidget *widget, uint8_t type, EVERect *g, EVEPage *page, EVEWidgetSpecT *spec) {
+ return _widget_create[type](widget, g, page, spec);
+}
+
+void eve_widget_destroy(EVEWidget *widget) {
+ if (_widget_destroy[widget->type]) _widget_destroy[widget->type](widget);
+}
+
+void eve_widget_focus(EVEWidget *widget, EVERect *rect) {
+ EVEPage *page = widget->page;
+
+ eve_page_focus_widget(page, widget, rect);
+}
diff --git a/fw/fe310/eos/eve/widget/widget.h b/fw/fe310/eos/eve/widget/widget.h
new file mode 100644
index 0000000..f081b4c
--- /dev/null
+++ b/fw/fe310/eos/eve/widget/widget.h
@@ -0,0 +1,31 @@
+#include <stdint.h>
+
+#define EVE_WIDGET_TYPE_FREE 1
+#define EVE_WIDGET_TYPE_SPACER 2
+#define EVE_WIDGET_TYPE_PAGE 3
+#define EVE_WIDGET_TYPE_STR 4
+#define EVE_WIDGET_TYPE_TEXT 5
+#define EVE_WIDGET_TYPE_SELECT 6
+
+struct EVEWidget;
+
+typedef uint8_t (*eve_widget_draw_t) (struct EVEWidget *, uint8_t);
+typedef int (*eve_widget_touch_t) (struct EVEWidget *, EVETouch *, uint16_t);
+
+typedef struct EVEWidget {
+ EVERect g;
+ EVEPage *page;
+ eve_widget_draw_t draw;
+ eve_widget_touch_t touch;
+ eve_kbd_input_handler_t putc;
+ EVELabel *label;
+ uint8_t type;
+ uint8_t tag0;
+ uint8_t tagN;
+} EVEWidget;
+
+void eve_widget_init(EVEWidget *widget, uint8_t type, EVERect *g, EVEPage *page, eve_widget_draw_t draw, eve_widget_touch_t touch, eve_kbd_input_handler_t putc);
+size_t eve_widget_size(uint8_t type);
+void eve_widget_set_label(EVEWidget *widget, EVELabel *label);
+EVEWidget *eve_widget_next(EVEWidget *widget);
+void eve_widget_focus(EVEWidget *widget, EVERect *rect); \ No newline at end of file
diff --git a/fw/fe310/eos/eve/widget/widgets.h b/fw/fe310/eos/eve/widget/widgets.h
new file mode 100644
index 0000000..2f8d3ca
--- /dev/null
+++ b/fw/fe310/eos/eve/widget/widgets.h
@@ -0,0 +1,39 @@
+#include "label.h"
+#include "widget.h"
+
+#include "freew.h"
+#include "spacerw.h"
+#include "pagew.h"
+#include "strw.h"
+#include "textw.h"
+#include "selectw.h"
+
+typedef union EVEWidgetSpecT {
+ EVEFreeSpec free;
+ EVESpacerSpec spacer;
+ EVEPageSpec page;
+ EVEStrSpec str;
+ EVETextSpec text;
+ EVESelectSpec select;
+} EVEWidgetSpecT;
+
+typedef struct EVELabelSpec {
+ EVERect g;
+ EVEFont *font;
+ char *title;
+} APPLabelSpec;
+
+typedef struct EVEWidgetSpec {
+ APPLabelSpec label;
+ struct {
+ EVERect g;
+ EVEWidgetSpecT spec;
+ uint8_t type;
+ } widget;
+} EVEWidgetSpec;
+
+typedef int (*eve_widget_create_t) (EVEWidget *, EVERect *, EVEPage *, EVEWidgetSpecT *);
+typedef void (*eve_widget_destroy_t) (EVEWidget *);
+
+int eve_widget_create(EVEWidget *widget, uint8_t type, EVERect *g, EVEPage *page, EVEWidgetSpecT *spec);
+void eve_widget_destroy(EVEWidget *widget);