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