touchscreen sampling

Dale Schumacher dale.schumacher at gmail.com
Fri Jun 20 05:43:50 CEST 2008

```Here's a proof-of-concept showing a 5-point median feeding a weighted moving
average.

----smoothing.c----
/*
* sample smoothing proof-of-concept
*/
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>

#define    W            5        /* smoothing window */

struct smooth {
int        data[W];        /* data samples */
int        sort[W];        /* sorted data */
int        pos;            /* circular data buffer position */
int        avg;            /* 2x moving average */
};

void
init_smooth(struct smooth* p)
{
int i;

for (i = 0; i < W; ++i) {
p->data[i] = 0;
p->sort[i] = 0;
}
p->pos = 0;
p->avg = 0;
}

#define    get_smooth(p)        (((p)->avg) >> 1)
#define    get_median(p)        ((p)->sort[W/2])

void
put_smooth(struct smooth* p, int value)
{
p->data[p->pos] = value;
if (p->pos <= 0) {
p->pos = W;
}
--p->pos;
}

void
sort_smooth(struct smooth* p)
{
int i;
int j;
int k;
int n;

i = p->pos;
for (k = 0; k < W; ++k) {
/* get sample from ring buffer */
if (i <= 0) {
i = W;
}
--i;
n = p->data[i];
/* insert into sorted list */
for (j = 0; j < k; ++j) {
if (p->sort[j] >= n) {
int m = k;
while (j < m) {
p->sort[m] = p->sort[m - 1];
m -= 1;
}
break;
}
}
p->sort[j] = n;
}
/* done sorting, pick median & add to average */
p->avg = get_median(p) + get_smooth(p);
}

void
dump_smooth(struct smooth* p)
{
int i;

printf("data=[");
i = p->pos;
while(1) {
++i;
if (i >= W) {
i = 0;
}
printf("%d", p->data[i]);
if (i == p->pos) {
printf("] ");
break;
}
printf(",");
}
printf("sort=[");
for (i = 0; i < W; ++i) {
printf("%s%d", (i ? "," : ""), p->sort[i]);
}
printf("] ");
printf("median=%d smooth=%d ", get_median(p), get_smooth(p));
printf("avg(x2)=%d\n", p->avg);
}

/**
SAMPLE DATA

1213744740.484058:    511    589      1
1213744740.489078:    513    588      1
1213744740.494059:    511    588      1
1213744740.499058:    509    588      1
1213744740.504078:    485    591      1  <===
1213744740.509058:    509    591      1
1213744740.514079:    506    586      1
1213744740.519078:    511    589      1
1213744740.524078:    507    587      1
1213744740.529079:    511    586      1
1213744740.534059:    511    590      1
1213744740.539058:    509    590      1
1213744740.544078:    420    589      1  <===
1213744740.549079:    509    591      1
1213744740.554078:    501    589      1
1213744740.559078:    511    588      1
1213744740.564079:    490    589      1  <===
1213744740.569058:    511    589      1
1213744740.574078:    512    588      1
1213744740.579078:    511    589      1
1213744740.584078:    513    588      1
1213744740.589078:    512    583      1
1213744740.594079:    510    589      1
1213744740.599098:    514    589      1
1213744740.604078:    510    588      1
1213744740.609058:    509    588      1
1213744740.614058:    514    588      1
1213744740.619078:    511    589      1
1213744740.624059:    517    589      1
1213744740.629057:    505    589      1
1213744740.634058:    511    589      1
1213744740.639089:    523    589      1  <===
1213744740.644116:    508    590      1
**/

static int sample_data[] = {
100,
101,
102,
103,
104,
105,
511, /* start */
513,
511,
509,
485, /* <=== */
509,
506,
511,
507,
511,
511,
509,
420, /* <=== */
509,
501,
511,
490, /* <=== */
511,
512,
511,
513,
512,
510,
514,
510,
509,
514,
511,
517,
505,
511,
523, /* <=== */
508
};

void
test_smoothing()
{
int i;
int n;
struct smooth s;
struct smooth* p = &s;

assert(p != NULL);
init_smooth(p);
assert(get_smooth(p) == 0);
dump_smooth(p);

n = sizeof(sample_data) / sizeof(int);
for (i = 0; i < n; ++i) {
put_smooth(p, sample_data[i]);
sort_smooth(p);
dump_smooth(p);
}
}

int
main(int argc, char** argv)
{
test_smoothing();
return (exit(EXIT_SUCCESS), 0);
}

On Thu, Jun 19, 2008 at 3:13 AM, Andy Green <andy at openmoko.com> wrote:

> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> Somebody in the thread at some point said:
> | On 19.06.2008 01:14, Andy Green wrote:
> |> Somebody in the thread at some point said:
> |> | On 18.06.2008 22:46, Dale Schumacher wrote:
> |> |> The averaging scheme seems overly complicated.  Using a "median"
> |> |> a "mean" (average) would automatically reject outliers and would also
> |> track
> |> |> the mid-point of a moving signal.  There should also be less math
> |> involved
> |> |> since you would only be sorting 2 sets of 32 values.
> |>
> |> | Exactly what I suggested as well. I don't understand why people
> |> | absolutely want to use averages and throw away outliers based on
> average
> |> | calculations. Maybe because the concept of "mean" is easier to grasp
> |> | than the concept of "median". A median solves all these problems of
> data
> |> | having outliers with less math and better accuracy.
> |>
> |> It's not a bad idea at all.  You're quite right it "automatically
> |> rejects outliers".  But, it's going to get a bit slow as the number of
> |> samples held in whatever the sorting structure is increases,
> |
> | The secret is to keep the number of samples exactly at 5. You remove the
>
> There's also a question about how noisy one of the axes is, the hardware
> may not play ball with this nice idea -- it is a nice idea -- of magic
> number 5.  Oldstyle averaging has good performance for "averaging
> noise", jitter in the result can still come with this method if generic
> noise is present and skews one set of 5 one way, and another the other.
> ~ Maybe some combination of mean and median gets the best result.  I
> don't think what ails the bad axis is quite as simple as perfect results
> disturbed occasionally by an excursion, the raw samples seem to be all
> over the shop anyway (hidden a bit by mean averaging) and occasionally
> really crazy.
>
> |> but if someone wants to send patches I'll be happy to be wrong.
> |
> | As I indicated before, I won't have time in the next 3 weeks, but if
> | there is something to be done afterwards, why not? I lack the hardware
> | to test, though, so I can only send untested patches.
>
> I'm going to leave mine in until then, pending any complaints about
> performance or a better implementation turning up.
>
> - -Andy
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.4.9 (GNU/Linux)
> Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org
>
> iEYEARECAAYFAkhaFRkACgkQOjLpvpq7dMrkagCfaxPcDCH2+g26ZElYw3E5yND8
> H9wAnRW/eOQE3wQKIGZnlwh+tNZfFEI4
> =TYbf
> -----END PGP SIGNATURE-----
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.openmoko.org/pipermail/openmoko-kernel/attachments/20080619/7b286c57/attachment.htm
```