static int variance_read(struct tslib_module_info *info, struct ts_sample *samp, int nr) { struct tslib_variance *var = (struct tslib_variance *)info; struct ts_sample cur; int count = 0, dist;
while (count < nr) { 如果采样数据被标记为“提交噪音”状态,将当前采样数据相关结构体赋予噪音状态,将清除标志位。 if (var->flags & VAR_SUBMITNOISE) { cur = var->noise; var->flags &= ~VAR_SUBMITNOISE; } else { 如果如果采样数据没有被标记为“提交噪音”,继续采样数据。 if (info->next->ops->read(info->next, &cur, 1) < 1) return count; } 如果当前没有压力值,处于没有笔触摸或者笔释放状态,但是却收到笔按下消息,表明为收到噪音干扰, 所有当笔一释放就立即清除队列,否则之前的层将捕抓到笔起来的消息,但是已经太晚,如果 info->next->ops->read()出现堵塞,将出现这种情况。 if (cur.pressure == 0) { /* Flush the queue immediately when the pen is just * released, otherwise the previous layer will * get the pen up notification too late. This * will happen if info->next->ops->read() blocks. */ if (var->flags & VAR_PENDOWN) { var->flags |= VAR_SUBMITNOISE; var->noise = cur; } /* Reset the state machine on pen up events. */ 复位笔起来事件状态标记位 var->flags &= ~(VAR_PENDOWN | VAR_NOISEVALID | VAR_LASTVALID); goto acceptsample;通知接受采样数据 } else var->flags |= VAR_PENDOWN;通知笔按下 如果标记位与“VAR_LASTVALID"状态不同,进行下一个采样。 if (!(var->flags & VAR_LASTVALID)) { var->last = cur; var->flags |= VAR_LASTVALID; continue; } 如果为笔按下事件 if (var->flags & VAR_PEN DOWN) { /* Compute the distance between last sample and current */ 计算上一次的采样数据与当前采样数据的距离 dist = sqr (cur.x - var->last.x) + sqr (cur.y - var->last.y);
if (dist > var->delta) {如果误差大于默认值,比如30。
视之前的采样为噪音?可疑? /* Do we suspect the previous sample was a noise? */ if (var->flags & VAR_NOISEVALID) { 但是如果之前的采样已经是可疑状态,视为快速的笔移动触发动作。 /* Two "noises": it's just a quick pen movement */ samp [count++] = var->last = var->noise; var->flags = (var->flags & ~VAR_NOISEVALID) | VAR_SUBMITNOISE; } else 如果之前的采样并不是可疑状态,视为可疑状态. var->flags |= VAR_NOISEVALID; /* The pen jumped too far, maybe it's a noise ... */ var->noise = cur; continue; } else var->flags &= ~VAR_NOISEVALID;采样的数据属于正常数据. }
重要算法分析: 为了让事情简单(避免误差),我们确保SUM(重量)=2次方。同时当我们有不到默认采样数量的时候,我们必须知道怎么去近似测试。 static const unsigned char weight [NR_SAMPHISTLEN - 1][NR_SAMPHISTLEN + 1] = { /* The last element is pow2(SUM(0..3)) */ { 5, 3, 0, 0, 3 }, /* When we have 2 samples ... */ { 8, 5, 3, 0, 4 }, /* When we have 3 samples ... */ { 6, 4, 3, 3, 4 }, /* When we have 4 samples ... */ };
static void average (struct tslib_dejitter *djt, struct ts_sample *samp) { const unsigned char *w; int sn = djt->head; int i, x = 0, y = 0; unsigned int p = 0;
for (i = 0; i < djt->nr; i++) { x += djt->hist [sn].x * w [i]; y += djt->hist [sn].y * w [i]; p += djt->hist [sn].p * w [i]; sn = (sn - 1) & (NR_SAMPHISTLEN - 1);记录每一次采样的序号 }
samp->x = x >> w [NR_SAMPHISTLEN];求出平均值 samp->y = y >> w [NR_SAMPHISTLEN]; samp->pressure = p >> w [NR_SAMPHISTLEN]; #ifdef DEBUG fprintf(stderr,"DEJITTER----------------> %d %d %d/n", samp->x, samp->y, samp->pressure); #endif }
static int dejitter_read(struct tslib_module_info *info, struct ts_sample *samp, int nr) { struct tslib_dejitter *djt = (struct tslib_dejitter *)info; struct ts_sample *s; int count = 0, ret;
ret = info->next->ops->read(info->next, samp, nr); for (s = samp; ret > 0; s++, ret--) { if (s->pressure == 0) { /* * Pen was released. Reset the state and 如果笔释放,复位状态标准,同时丢弃所有历史事件。 * forget all history events. */ djt->nr = 0; samp [count++] = *s; continue; }
/* If the pen moves too fast, reset the backlog. */ 如果笔移动太快,复位积压 if (djt->nr) { int prev = (djt->head - 1) & (NR_SAMPHISTLEN - 1); if (sqr (s->x - djt->hist [prev].x) + sqr (s->y - djt->hist [prev].y) > djt->delta) { 如果之前的x的平方距离值与之前的y的平方距离值加入门槛值,提示超过门槛值,丢弃,复位。 #ifdef DEBUG fprintf (stderr, "DEJITTER: pen movement exceeds threshold/n"); #endif djt->nr = 0; } }
/* We'll pass through the very first sample since * we can't average it (no history yet). */ if (djt->nr == 1) 如果这是第一次采样,没有历史或者旧采样数据,直接赋值。 samp [count] = *s; else { 如果不是第一次采样,就执行平均函数,求得经过平均后的采样值。 average (djt, samp + count); samp [count].tv = s->tv; } count++;