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"
> |> instead of
> |> |> 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
More information about the openmoko-kernel
mailing list