From d05eefaf7f10769ddae3840890af6a1e52440238 Mon Sep 17 00:00:00 2001
From: Uros Majstorovic <majstor@majstor.org>
Date: Thu, 11 Mar 2021 02:56:59 +0100
Subject: vitrual tracking fixed

---
 fw/fe310/eos/eve/Makefile      |   2 +-
 fw/fe310/eos/eve/eve.c         |   1 -
 fw/fe310/eos/eve/eve.h         |   2 +-
 fw/fe310/eos/eve/eve_touch.c   | 176 ++++++++++++++++++-----------------------
 fw/fe310/eos/eve/eve_touch.h   |  30 +++----
 fw/fe310/eos/eve/eve_track.c   |  77 ------------------
 fw/fe310/eos/eve/eve_track.h   |  22 ------
 fw/fe310/eos/eve/eve_vtrack.c  | 132 +++++++++++++++++++++++++++++++
 fw/fe310/eos/eve/eve_vtrack.h  |  51 ++++++++++++
 fw/fe310/eos/eve/screen/form.c |  10 +--
 10 files changed, 278 insertions(+), 225 deletions(-)
 delete mode 100644 fw/fe310/eos/eve/eve_track.c
 delete mode 100644 fw/fe310/eos/eve/eve_track.h
 create mode 100644 fw/fe310/eos/eve/eve_vtrack.c
 create mode 100644 fw/fe310/eos/eve/eve_vtrack.h

(limited to 'fw/fe310/eos/eve')

diff --git a/fw/fe310/eos/eve/Makefile b/fw/fe310/eos/eve/Makefile
index 8183c31..43470d8 100644
--- a/fw/fe310/eos/eve/Makefile
+++ b/fw/fe310/eos/eve/Makefile
@@ -2,7 +2,7 @@ include ../../common.mk
 
 CFLAGS += -I.. -I../../bsp/include
 
-obj = eve.o eve_platform.o eve_touch.o eve_track.o eve_kbd.o eve_text.o eve_font.o clipb.o
+obj = eve.o eve_platform.o eve_touch.o eve_vtrack.o eve_kbd.o eve_text.o eve_font.o clipb.o
 
 
 %.o: %.c %.h
diff --git a/fw/fe310/eos/eve/eve.c b/fw/fe310/eos/eve/eve.c
index f35ccf7..efbd02b 100644
--- a/fw/fe310/eos/eve/eve.c
+++ b/fw/fe310/eos/eve/eve.c
@@ -429,7 +429,6 @@ int eve_init(int pwr_on) {
     }
 
     eve_touch_init();
-    eve_track_init();
     eve_platform_init();
 
     return EVE_OK;
diff --git a/fw/fe310/eos/eve/eve.h b/fw/fe310/eos/eve/eve.h
index e0583f0..4056dd3 100644
--- a/fw/fe310/eos/eve/eve.h
+++ b/fw/fe310/eos/eve/eve.h
@@ -2,7 +2,7 @@
 
 #include "eve_def.h"
 #include "eve_touch.h"
-#include "eve_track.h"
+#include "eve_vtrack.h"
 #include "eve_platform.h"
 
 #define EVE_OK              0
diff --git a/fw/fe310/eos/eve/eve_touch.c b/fw/fe310/eos/eve/eve_touch.c
index fff1eec..334dfa3 100644
--- a/fw/fe310/eos/eve/eve_touch.c
+++ b/fw/fe310/eos/eve/eve_touch.c
@@ -1,12 +1,11 @@
 #include <stdlib.h>
 #include <string.h>
+#include <math.h>
 
 #include "eve.h"
 
 #define EVE_THRESHOLD_X         5
 #define EVE_THRESHOLD_Y         5
-#define EVE_TIMEOUT_TAP         1000
-#define EVE_TIMEOUT_TRACK       20
 #define EVE_TRAVG               3
 
 #define EVE_NOTOUCH             0x80000000
@@ -19,7 +18,6 @@ static uint8_t _tag0;
 
 static EVETouch _touch[EVE_MAX_TOUCH];
 static EVETouchTimer _touch_timer;
-static EVEExtTracker _ext_tracker;
 
 static eve_touch_handler_t _touch_handler;
 static void *_touch_handler_param;
@@ -48,26 +46,10 @@ static const uint32_t _reg_track[] = {
     REG_TRACKER_4
 };
 
-static void _touch_timer_set(uint8_t tag, uint8_t idx, uint16_t evt, int x0, int y0, uint32_t to) {
-    _touch_timer.tag = tag;
-    _touch_timer.idx = idx;
-    _touch_timer.evt = evt;
-    _touch_timer.x0 = x0;
-    _touch_timer.y0 = y0;
-    eve_timer_set(to);
-}
-
-static void _touch_timer_clear(void) {
-    eve_timer_clear();
-    _touch_timer.tag = 0;
-    _touch_timer.evt = 0;
-}
-
 void eve_handle_touch(void) {
     int i;
     char touch_ex = 0;
     char int_ccomplete = 0;
-    uint8_t tag0 = _tag0;
     uint8_t touch_last = 0;
     uint8_t flags;
 
@@ -91,9 +73,12 @@ void eve_handle_touch(void) {
             if (touch->x == EVE_NOTOUCH) {
                 uint16_t _evt = 0;
                 uint16_t _eevt = 0;
+                uint16_t _ttevt = eve_touch_timer_evt(i);
+
+                if (_ttevt) {
+                    EVEVTrack *vtrack = eve_vtrack_get();
 
-                if (!_tag0 && _touch_timer.tag) {
-                    if (_touch_timer.evt & EVE_TOUCH_ETYPE_TAP1) {
+                    if (_ttevt & EVE_TOUCH_ETYPE_TAP1) {
                         int dx = touch_x - touch->x0;
                         int dy = touch_y - touch->y0;
                         dx = dx < 0 ? -dx : dx;
@@ -104,15 +89,14 @@ void eve_handle_touch(void) {
                             _evt |= EVE_TOUCH_ETYPE_TAP2;
                             _eevt |= EVE_TOUCH_EETYPE_TAP2;
                         }
-                    }
-                    if (_touch_timer.evt & EVE_TOUCH_ETYPE_TRACK) {
-                        touch->evt |= EVE_TOUCH_ETYPE_TRACK_STOP;
-                        if (_ext_tracker.stop) _ext_tracker.stop(&_touch_timer, touch);
+                    } else {
+                        touch->evt |= _ttevt;
+                        if (vtrack->stop) vtrack->stop(touch, vtrack->param);
                     }
                     if (_touch_handler && touch->evt) {
-                        _touch_handler(_touch_handler_param, _touch_timer.tag, i);
+                        _touch_handler(_touch_handler_param, _touch_timer.tag0, i);
                     }
-                    _touch_timer_clear();
+                    eve_touch_timer_clear();
                 }
                 touch->evt = EVE_TOUCH_ETYPE_POINT | _evt;
                 touch->eevt = _eevt;
@@ -147,17 +131,19 @@ void eve_handle_touch(void) {
             touch_tag = 0;
             if (touch->x != EVE_NOTOUCH) {
                 touch->evt |= EVE_TOUCH_ETYPE_POINT_UP;
-                if (_touch_timer.tag && (i == 0)) {
+                if (eve_touch_timer_evt(i)) {
                     _touch_timer.evt &= ~EVE_TOUCH_ETYPE_LPRESS;
-                    if (!_touch_timer.evt) _touch_timer_clear();
+                    if (!_touch_timer.evt) eve_touch_timer_clear();
                 }
                 if (touch->tracker.tag && touch->tracker.track) {
                     uint8_t opt = _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 (!_touch_timer.tag && track_ext) {
-                        _touch_timer_set(touch->tracker.tag, i, EVE_TOUCH_ETYPE_TRACK, touch->x, touch->y, EVE_TIMEOUT_TRACK);
-                        if (_ext_tracker.init) _ext_tracker.init(&_touch_timer, touch);
+                    if (!_touch_timer.evt && track_ext) {
+                        EVEVTrack *vtrack = eve_vtrack_get();
+
+                        eve_touch_timer_set(_tag0, i, EVE_TOUCH_ETYPE_TRACK, EVE_TOUCH_TIMEOUT_TRACK);
+                        if (vtrack->start) vtrack->start(touch, vtrack->param);
                     } else {
                         touch->evt |= EVE_TOUCH_ETYPE_TRACK_STOP;
                     }
@@ -168,6 +154,7 @@ void eve_handle_touch(void) {
         }
         if (touch_tag != touch->tag) {
             if (touch_tag) {
+                if (!_tag0) _tag0 = touch_tag;
                 if (!touch->tag0) {
                     touch->tag0 = touch_tag;
                     if (_tag_opt[touch_tag] & EVE_TOUCH_OPT_TRACK_MASK) {
@@ -178,15 +165,14 @@ void eve_handle_touch(void) {
                         touch->evt |= EVE_TOUCH_ETYPE_TRACK_START;
                         touch->t = now;
                     }
-                    if (!_tag0 && (_tag_opt[touch_tag] & EVE_TOUCH_OPT_TIMER_MASK)) {
+                    if (!_touch_timer.evt && (_tag_opt[touch_tag] & EVE_TOUCH_OPT_TIMER_MASK)) {
                         uint16_t _evt = 0;
 
                         if (_tag_opt[touch_tag] & EVE_TOUCH_OPT_LPRESS) _evt |= EVE_TOUCH_ETYPE_LPRESS;
                         if (_tag_opt[touch_tag] & EVE_TOUCH_OPT_DTAP) _evt |= EVE_TOUCH_ETYPE_TAP1;
-                        _touch_timer_set(touch_tag, 0, _evt, 0, 0, EVE_TIMEOUT_TAP);
+                        eve_touch_timer_set(_tag0, i, _evt, EVE_TOUCH_TIMEOUT_TAP);
                     }
                 }
-                if (!_tag0) _tag0 = tag0 = touch_tag;
             }
             touch->tag_up = touch->tag;
             if (touch->tag_up) touch->evt |= EVE_TOUCH_ETYPE_TAG_UP;
@@ -194,8 +180,8 @@ void eve_handle_touch(void) {
             if (touch->tag) touch->evt |= EVE_TOUCH_ETYPE_TAG;
         }
         if (touch_xy != 0x80008000) {
-            char _track = touch->tracker.tag && !touch->tracker.track;
-            char _timer = _touch_timer.tag && (_touch_timer.evt & EVE_TOUCH_ETYPE_TIMER_MASK) && (i == 0);
+            int _track = touch->tracker.tag && !touch->tracker.track;
+            int _timer = eve_touch_timer_evt(i) & EVE_TOUCH_ETYPE_TIMER_MASK;
             if (_track || _timer) {
                 int dx = touch->x - touch->x0;
                 int dy = touch->y - touch->y0;
@@ -221,8 +207,9 @@ void eve_handle_touch(void) {
                     }
                 }
                 if (_timer && ((dx > EVE_THRESHOLD_X) || (dy > EVE_THRESHOLD_Y))) {
+                    _timer = 0;
                     _touch_timer.evt &= ~EVE_TOUCH_ETYPE_TIMER_MASK;
-                    if (!_touch_timer.evt) _touch_timer_clear();
+                    if (!_touch_timer.evt) eve_touch_timer_clear();
                 }
             }
             if (touch->tracker.tag && touch->tracker.track) {
@@ -236,12 +223,19 @@ void eve_handle_touch(void) {
                     touch->evt &= ~EVE_TOUCH_ETYPE_TRACK_REG;
                 }
             }
-            if (touch->tracker.tag || _touch_timer.tag) int_ccomplete = 1;
+            if (touch->tracker.tag || _timer) int_ccomplete = 1;
         }
         if (touch->evt) touch_last = i + 1;
         if (!_multitouch) break;
     }
 
+    for (i=0; i<touch_last; i++) {
+        EVETouch *touch = &_touch[i];
+        if (_touch_handler && touch->evt) {
+            _touch_handler(_touch_handler_param, _tag0, i);
+        }
+    }
+
     if (!touch_ex) {
         _tag0 = 0;
         _multitouch = 0;
@@ -258,58 +252,52 @@ void eve_handle_touch(void) {
         eve_write8(REG_INT_MASK, _intr_mask);
     }
 
-    for (i=0; i<touch_last; i++) {
-        EVETouch *touch = &_touch[i];
-        if (_touch_handler && touch->evt) {
-            _touch_handler(_touch_handler_param, tag0, i);
-        }
-    }
-
     eve_spi_stop();
 }
 
 void eve_handle_time(void) {
-    eve_spi_start();
+    EVETouch *touch = &_touch[_touch_timer.idx];
 
-    if (_touch_handler && _touch_timer.tag) {
-        EVETouch *touch = &_touch[_touch_timer.idx];
+    if ((_touch_timer.evt & EVE_TOUCH_ETYPE_TAP1) && (touch->x != EVE_NOTOUCH)) _touch_timer.evt &= ~EVE_TOUCH_ETYPE_TAP1;
 
-        if ((_touch_timer.evt & EVE_TOUCH_ETYPE_TAP1) && (touch->x != EVE_NOTOUCH)) _touch_timer.evt &= ~EVE_TOUCH_ETYPE_TAP1;
+    if (_touch_timer.evt) {
+        int more = 0;
+        int _x = touch->x;
+        int _y = touch->y;
+        EVEVTrack *vtrack = eve_vtrack_get();
 
-        if (_touch_timer.evt) {
-            int more = 0;
-            int _x = touch->x;
-            int _y = touch->y;
+        eve_spi_start();
 
-            touch->evt = _touch_timer.evt;
-            if (touch->evt & EVE_TOUCH_ETYPE_TRACK) {
-                if (_ext_tracker.tick) more = _ext_tracker.tick(&_touch_timer, touch);
-                if (more) {
-                    eve_timer_set(EVE_TIMEOUT_TRACK);
-                } else {
-                    touch->evt |= EVE_TOUCH_ETYPE_TRACK_STOP;
-                    if (_ext_tracker.stop) _ext_tracker.stop(&_touch_timer, touch);
-                }
-            } else if (touch->evt & EVE_TOUCH_ETYPE_LPRESS) {
-                touch->eevt |= EVE_TOUCH_EETYPE_LPRESS;
+        touch->evt = _touch_timer.evt;
+        if (touch->evt & EVE_TOUCH_ETYPE_LPRESS) {
+            touch->eevt |= EVE_TOUCH_EETYPE_LPRESS;
+        } else {
+            if (vtrack->tick) more = vtrack->tick(touch, vtrack->param);
+            if (more) {
+                eve_timer_set(EVE_TOUCH_TIMEOUT_TRACK);
+            } else if (vtrack->stop) {
+                vtrack->stop(touch, vtrack->param);
             }
+        }
 
-            _touch_handler(_touch_handler_param, _touch_timer.tag, _touch_timer.idx);
+        if (_touch_handler) _touch_handler(_touch_handler_param, _touch_timer.tag0, _touch_timer.idx);
 
-            if (!more) _touch_timer_clear();
-            touch->x = _x;
-            touch->y = _y;
-        } else {
-            _touch_timer_clear();
-        }
+        eve_spi_stop();
+
+        if (!more) eve_touch_timer_clear();
+        touch->x = _x;
+        touch->y = _y;
+    } else {
+        eve_touch_timer_clear();
     }
 
-    eve_spi_stop();
 }
 
 void eve_touch_init(void) {
     int i;
 
+    eve_vtrack_init();
+
     for (i=0; i<EVE_MAX_TOUCH; i++) {
         EVETouch *touch = &_touch[i];
         touch->x = EVE_NOTOUCH;
@@ -325,6 +313,10 @@ void eve_touch_set_handler(eve_touch_handler_t handler, void *param) {
     _touch_handler_param = param;
 }
 
+EVETouch *eve_touch_get(int i) {
+    return &_touch[i];
+}
+
 EVETouch *eve_touch_evt(uint8_t tag0, int touch_idx, uint8_t tag_min, uint8_t tag_n, uint16_t *evt) {
     int tag_max;
     uint8_t _tag;
@@ -351,16 +343,12 @@ EVETouch *eve_touch_evt(uint8_t tag0, int touch_idx, uint8_t tag_min, uint8_t ta
         _tag = ret->tag_up;
         if ((_tag >= tag_min) && (_tag < tag_max)) *evt |= EVE_TOUCH_ETYPE_TAG_UP;
     }
-    if (_evt & EVE_TOUCH_ETYPE_TRACK_REG) {
-        _tag = ret->tracker.tag;
-        if ((_tag >= tag_min) && (_tag < tag_max)) *evt |= EVE_TOUCH_ETYPE_TRACK_REG;
-    }
     if (_evt & EVE_TOUCH_ETYPE_TRACK_MASK) {
         _tag = ret->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_timer.tag;
+        _tag = ret->tag0;
         if ((_tag >= tag_min) && (_tag < tag_max)) *evt |= _evt & (EVE_TOUCH_ETYPE_LPRESS | EVE_TOUCH_ETYPE_TAP1 | EVE_TOUCH_ETYPE_TAP2);
     }
 
@@ -379,30 +367,22 @@ void eve_touch_clear_opt(void) {
     memset(_tag_opt, 0, sizeof(_tag_opt));
 }
 
-EVETouchTimer *eve_touch_get_timer(void) {
-    return &_touch_timer;
+void eve_touch_timer_set(uint8_t tag0, int i, uint16_t evt, uint32_t to) {
+    _touch_timer.tag0 = tag0;
+    _touch_timer.idx = i;
+    _touch_timer.evt = evt;
+    eve_timer_set(to);
 }
 
-void eve_etrack_set(eve_etrack_init_t init, eve_etrack_tick_t tick, eve_etrack_stop_t stop, void *param) {
-    _ext_tracker.init = init;
-    _ext_tracker.tick = tick;
-    _ext_tracker.stop = stop;
-    _touch_timer.p = param;
+void eve_touch_timer_clear(void) {
+    eve_timer_clear();
+    _touch_timer.evt = 0;
 }
 
-void eve_etrack_start(int i) {
-    EVETouch *touch = &_touch[i];
-
-    _touch_timer_set(touch->tracker.tag, i, EVE_TOUCH_ETYPE_TRACK, touch->x, touch->y, EVE_TIMEOUT_TRACK);
-    if (_ext_tracker.init) _ext_tracker.init(&_touch_timer, touch);
+uint16_t eve_touch_timer_evt(int i) {
+    return (i ==  _touch_timer.idx) ? _touch_timer.evt : 0;
 }
 
-void eve_etrack_stop(void) {
-    if (_ext_tracker.stop) {
-        EVETouch *touch = &_touch[_touch_timer.idx];
-
-        touch->evt = EVE_TOUCH_ETYPE_TRACK_STOP;
-        _ext_tracker.stop(&_touch_timer, touch);
-    }
-    _touch_timer_clear();
+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
index 454dcc7..80d7f61 100644
--- a/fw/fe310/eos/eve/eve_touch.h
+++ b/fw/fe310/eos/eve/eve_touch.h
@@ -1,5 +1,8 @@
 #include <stdint.h>
 
+#define EVE_TOUCH_TIMEOUT_TAP           1000
+#define EVE_TOUCH_TIMEOUT_TRACK         20
+
 /* events */
 #define EVE_TOUCH_ETYPE_TRACK           0x0001
 #define EVE_TOUCH_ETYPE_TRACK_REG       0x0002
@@ -15,7 +18,7 @@
 
 #define EVE_TOUCH_ETYPE_TAG_MASK        (EVE_TOUCH_ETYPE_TAG    | EVE_TOUCH_ETYPE_TAG_UP)
 #define EVE_TOUCH_ETYPE_TAP_MASK        (EVE_TOUCH_ETYPE_TAP1   | EVE_TOUCH_ETYPE_TAP2)
-#define EVE_TOUCH_ETYPE_TRACK_MASK      (EVE_TOUCH_ETYPE_TRACK  | EVE_TOUCH_ETYPE_TRACK_START   | EVE_TOUCH_ETYPE_TRACK_STOP)
+#define EVE_TOUCH_ETYPE_TRACK_MASK      (EVE_TOUCH_ETYPE_TRACK  | EVE_TOUCH_ETYPE_TRACK_START | EVE_TOUCH_ETYPE_TRACK_STOP | EVE_TOUCH_ETYPE_TRACK_REG)
 #define EVE_TOUCH_ETYPE_POINT_MASK      (EVE_TOUCH_ETYPE_POINT  | EVE_TOUCH_ETYPE_POINT_UP)
 #define EVE_TOUCH_ETYPE_TIMER_MASK      (EVE_TOUCH_OPT_LPRESS   | EVE_TOUCH_OPT_DTAP)
 
@@ -70,12 +73,9 @@ typedef struct EVETouch {
 } EVETouch;
 
 typedef struct EVETouchTimer {
-    uint8_t tag;
+    uint8_t tag0;
     uint8_t idx;
     uint16_t evt;
-    int x0;
-    int y0;
-    void *p;
 } EVETouchTimer;
 
 void eve_handle_touch(void);
@@ -83,22 +83,14 @@ 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);
 EVETouch *eve_touch_evt(uint8_t tag0, int touch_idx, uint8_t tag_min, uint8_t tag_n, uint16_t *evt);
+
 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);
-EVETouchTimer *eve_touch_get_timer(void);
-
-typedef void (*eve_etrack_init_t) (EVETouchTimer *, EVETouch *);
-typedef int  (*eve_etrack_tick_t) (EVETouchTimer *, EVETouch *);
-typedef void (*eve_etrack_stop_t) (EVETouchTimer *, EVETouch *);
-
-typedef struct EVEExtTracker {
-    eve_etrack_init_t init;
-    eve_etrack_tick_t tick;
-    eve_etrack_stop_t stop;
-} EVEExtTracker;
 
-void eve_etrack_set(eve_etrack_init_t init, eve_etrack_tick_t tick, eve_etrack_stop_t stop, void *param);
-void eve_etrack_start(int i);
-void eve_etrack_stop(void);
+void eve_touch_timer_set(uint8_t tag0, int i, uint16_t evt, uint32_t to);
+void eve_touch_timer_clear(void);
+uint16_t eve_touch_timer_evt(int i);
+EVETouchTimer *eve_touch_timer_get(void);
diff --git a/fw/fe310/eos/eve/eve_track.c b/fw/fe310/eos/eve/eve_track.c
deleted file mode 100644
index 97ef72b..0000000
--- a/fw/fe310/eos/eve/eve_track.c
+++ /dev/null
@@ -1,77 +0,0 @@
-#include <stdlib.h>
-#include <math.h>
-
-#include "eve.h"
-
-void eve_track_init(void) {
-    eve_etrack_set(eve_track_inert_init, eve_track_inert_tick, NULL, NULL);
-}
-
-void eve_track_set(uint8_t type, void *param) {
-    switch (type) {
-        case EVE_TRACK_TYPE_INERT:
-            eve_etrack_set(eve_track_inert_init, eve_track_inert_tick, NULL, NULL);
-            break;
-        case EVE_TRACK_TYPE_OSC:
-            eve_etrack_set(NULL, eve_track_osc_tick, NULL, param);
-            break;
-        default:
-            break;
-    }
-}
-
-void eve_track_inert_init(EVETouchTimer *timer, EVETouch *touch) {
-    double d = sqrt(touch->vx * touch->vx + touch->vy * touch->vy);
-    int fc = (double)(EVE_RTC_FREQ) * d / EVE_TRACK_FRICTION;
-
-    timer->p = (void *)fc;
-}
-
-int eve_track_inert_tick(EVETouchTimer *timer, EVETouch *touch) {
-    int dt = eve_time_get_tick() - touch->t;
-    int fc = (int)timer->p;
-    int more = 1;
-
-    if (dt >= fc / 2) {
-        dt = fc / 2;
-        more = 0;
-    }
-    touch->x = timer->x0 + (touch->vx * dt - touch->vx * dt / fc * dt) / (int)(EVE_RTC_FREQ);
-    touch->y = timer->y0 + (touch->vy * dt - touch->vy * dt / fc * dt) / (int)(EVE_RTC_FREQ);
-    return more;
-}
-
-void eve_track_osc_init(EVETrackOsc *p, 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;
-    p->x = x;
-    p->y = y;
-    p->f = d ? f0 * sqrt(1 - d * d) : f0;
-    p->d = d;
-    p->a = -d * f0;
-    p->t_max = t_max;
-}
-
-int eve_track_osc_tick(EVETouchTimer *timer, EVETouch *touch) {
-    EVETrackOsc *p = (EVETrackOsc *)timer->p;
-    int dt = eve_time_get_tick() - touch->t;
-    int ax = timer->x0 - p->x;
-    int ay = timer->y0 - p->y;
-    int more = 1;
-
-    if (p->t_max && (dt >= p->t_max)) {
-        dt = p->t_max;
-        more = 0;
-    }
-    if (p->d) {
-        double e = exp(p->a * dt);
-        ax = ax * e;
-        ay = ay * e;
-        if ((ax == 0) && (ay == 0)) more = 0;
-    }
-    touch->x = p->x + ax * cos(p->f * dt);
-    touch->y = p->y + ay * cos(p->f * dt);
-    return more;
-}
diff --git a/fw/fe310/eos/eve/eve_track.h b/fw/fe310/eos/eve/eve_track.h
deleted file mode 100644
index a5fd113..0000000
--- a/fw/fe310/eos/eve/eve_track.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#include <stdint.h>
-
-#define EVE_TRACK_TYPE_INERT            1
-#define EVE_TRACK_TYPE_OSC              2
-#define EVE_TRACK_FRICTION              500
-
-typedef struct EVETrackOsc {
-    int x;
-    int y;
-    double f;
-    double d;
-    double a;
-    uint32_t t_max;
-} EVETrackOsc;
-
-void eve_track_init(void);
-void eve_track_set(uint8_t type, void *param);
-
-void eve_track_inert_init(EVETouchTimer *timer, EVETouch *touch);
-int eve_track_inert_tick(EVETouchTimer *timer, EVETouch *touch);
-void eve_track_osc_init(EVETrackOsc *p, int x, int y, uint32_t T, double d, uint32_t t_max);
-int eve_track_osc_tick(EVETouchTimer *timer, EVETouch *touch);
diff --git a/fw/fe310/eos/eve/eve_vtrack.c b/fw/fe310/eos/eve/eve_vtrack.c
new file mode 100644
index 0000000..bf65ec8
--- /dev/null
+++ b/fw/fe310/eos/eve/eve_vtrack.c
@@ -0,0 +1,132 @@
+#include <stdlib.h>
+#include <math.h>
+
+#include "eve.h"
+
+static EVEVTrack _vtrack;
+static EVEVTrackInert _vtrack_inert;
+
+void eve_vtrack_init(void) {
+    eve_vtrack_inert_init(&_vtrack_inert, EVE_VTRACK_FRICTION);
+    eve_vtrack_set(eve_vtrack_inert_start, eve_vtrack_inert_tick, eve_vtrack_inert_stop, &_vtrack_inert);
+}
+
+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_inert_start, eve_vtrack_inert_tick, eve_vtrack_inert_stop, &_vtrack_inert);
+}
+
+void eve_vtrack_start(uint8_t tag0, int i) {
+    EVETouch *touch = eve_touch_get(i);
+
+    eve_touch_timer_set(tag0, i, EVE_TOUCH_ETYPE_TRACK, EVE_TOUCH_TIMEOUT_TRACK);
+    if (_vtrack.start) _vtrack.start(touch, _vtrack.param);
+}
+
+void eve_vtrack_stop(void) {
+    eve_touch_timer_clear();
+    eve_vtrack_reset();
+}
+
+
+EVEVTrackInert *eve_vtrack_inert_get_param(void) {
+    return &_vtrack_inert;
+}
+
+void eve_vtrack_inert_init(EVEVTrackInert *param, int fc) {
+    param->fc = fc;
+}
+
+void eve_vtrack_inert_start(EVETouch *touch, void *p) {
+    EVEVTrackInert *param = (EVEVTrackInert *)p;
+    double d = sqrt(touch->vx * touch->vx + touch->vy * touch->vy);
+
+    param->x0 = touch->x;
+    param->y0 = touch->y;
+    param->f = (double)(EVE_RTC_FREQ) * d / param->fc;
+}
+
+int eve_vtrack_inert_tick(EVETouch *touch, void *p) {
+    EVEVTrackInert *param = (EVEVTrackInert *)p;
+    int dt = eve_time_get_tick() - touch->t;
+    int f = param->f;
+    int more = 1;
+
+    if (dt >= f / 2) {
+        dt = f / 2;
+        more = 0;
+    }
+    touch->x = param->x0 + (touch->vx * dt - touch->vx * dt / f * dt) / (int)(EVE_RTC_FREQ);
+    touch->y = param->y0 + (touch->vy * dt - touch->vy * dt / f * dt) / (int)(EVE_RTC_FREQ);
+
+    return more;
+}
+
+void eve_vtrack_inert_stop(EVETouch *touch, void *p) {
+    touch->evt |= EVE_TOUCH_ETYPE_TRACK_STOP;
+}
+
+
+static EVEVTrackOsc _vtrack_osc;
+
+EVEVTrackOsc *eve_vtrack_osc_get_param(void) {
+    return &_vtrack_osc;
+}
+
+void eve_vtrack_osc_init(EVEVTrackOsc *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 = d ? f0 * sqrt(1 - d * d) : f0;
+    param->d = d;
+    param->a = -d * f0;
+    param->t_max = t_max;
+}
+
+void eve_vtrack_osc_start(EVETouch *touch, void *p) {
+    EVEVTrackOsc *param = (EVEVTrackOsc *)p;
+
+    param->x0 = touch->x;
+    param->y0 = touch->y;
+}
+
+int eve_vtrack_osc_tick(EVETouch *touch, void *p) {
+    EVEVTrackOsc *param = (EVEVTrackOsc *)p;
+    int dt = eve_time_get_tick() - touch->t;
+    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->d) {
+        double e = exp(param->a * dt);
+        ax = ax * e;
+        ay = ay * e;
+        if ((ax == 0) && (ay == 0)) more = 0;
+    }
+    touch->x = param->x + ax * cos(param->f * dt);
+    touch->y = param->y + ay * cos(param->f * dt);
+
+    return more;
+}
+
+void eve_vtrack_osc_stop(EVETouch *touch, void *p) {
+    touch->evt |= EVE_TOUCH_ETYPE_TRACK_STOP;
+    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..6bf8fa5
--- /dev/null
+++ b/fw/fe310/eos/eve/eve_vtrack.h
@@ -0,0 +1,51 @@
+#include <stdint.h>
+
+#define EVE_VTRACK_FRICTION             500
+
+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(uint8_t tag0, int i);
+void eve_vtrack_stop(void);
+
+typedef struct EVEVTrackInert {
+    int fc;
+    int f;
+    int x0;
+    int y0;
+} EVEVTrackInert;
+
+EVEVTrackInert *eve_vtrack_inert_get_param(void);
+void eve_vtrack_inert_init(EVEVTrackInert *param, int fc);
+void eve_vtrack_inert_start(EVETouch *touch, void *p);
+int eve_vtrack_inert_tick(EVETouch *touch, void *p);
+void eve_vtrack_inert_stop(EVETouch *touch, void *p);
+
+typedef struct EVEVTrackOsc {
+    int x;
+    int y;
+    double f;
+    double d;
+    double a;
+    uint32_t t_max;
+    int x0;
+    int y0;
+} EVEVTrackOsc;
+
+EVEVTrackOsc *eve_vtrack_osc_get_param(void);
+void eve_vtrack_osc_init(EVEVTrackOsc *param, int x, int y, uint32_t T, double d, uint32_t t_max);
+void eve_vtrack_osc_start(EVETouch *touch, void *p);
+int eve_vtrack_osc_tick(EVETouch *touch, void *p);
+void eve_vtrack_osc_stop(EVETouch *touch, void *p);
diff --git a/fw/fe310/eos/eve/screen/form.c b/fw/fe310/eos/eve/screen/form.c
index c8a8bba..32227c9 100644
--- a/fw/fe310/eos/eve/screen/form.c
+++ b/fw/fe310/eos/eve/screen/form.c
@@ -56,10 +56,12 @@ static int form_handle_evt(EVEForm *form, EVEWidget *widget, EVETouch *touch, ui
         form->evt_lock = 1;
     }
     if (evt & EVE_TOUCH_ETYPE_TRACK_STOP) {
-        form->win_x0 = 0;
-        form->win_y0 = 0;
         form->evt_lock = 0;
     }
+    if ((evt & EVE_TOUCH_ETYPE_TRACK) && (touch->eevt & EVE_TOUCH_EETYPE_TRACK_Y)) {
+        form->p.win_y = form->win_y0 + touch->y0 - touch->y;
+        return 1;
+    }
     if (evt & EVE_TOUCH_ETYPE_POINT_UP) {
         if ((touch->eevt & EVE_TOUCH_EETYPE_TRACK_XY) == 0) {
             if (form->p.widget_f) eve_page_set_focus(&form->p, NULL, NULL);
@@ -74,10 +76,6 @@ static int form_handle_evt(EVEForm *form, EVEWidget *widget, EVETouch *touch, ui
             return 1;
         }
     }
-    if ((evt & EVE_TOUCH_ETYPE_TRACK) && (touch->eevt & EVE_TOUCH_EETYPE_TRACK_Y)) {
-        form->p.win_y = form->win_y0 + touch->y0 - touch->y;
-        return 1;
-    }
 
     return 0;
 }
-- 
cgit v1.2.3