URUSHI@TSUKUBA / Mbed 2 deprecated AnimatedLED9

Dependencies:   mbed-rtos mbed

TouchSense.h

Committer:
BuntarouShizuki
Date:
2015-01-22
Revision:
0:fefcd43a3608

File content as of revision 0:fefcd43a3608:

#include "mbed.h"
#include "rtos.h"

//#define DEBUG

// for profiling
#define PRSIZE 500
#define START_THREAD 1

class FrameRate {
    float rate;
    int counter;
    Timer timer;

public:    
    FrameRate() {
        rate = 0;
        counter = 0;
        timer.start();
    }
    
    void update() {
        counter++;
        if (counter == 10) {
            rate = 1000*10.0/timer.read_ms();
            counter = 0;
            timer.reset();
        }
    }
    
    float getRate() {
        return rate;
    }
};

class TouchSense
{
    float V0;
    float V1;
    float C1;

    DigitalOut &dout;
    AnalogIn &ain;

    static const int BUFSIZE = 3;
    int buf[BUFSIZE];
    int bufindex;

    int state;

    FrameRate rater;
    
    static void threadStarter(void const *p);
    Thread _thread;
public:
    TouchSense(DigitalOut &dout, AnalogIn &ain): V0(0.0), V1(0.5), C1(20), dout(dout), ain(ain),
     _thread(&TouchSense::threadStarter, this, osPriorityNormal, 10240) {
        // XXX: 0.5 must be defined automatically
        state = 0;
        calibrate();

        _thread.signal_set(START_THREAD);
    }

    int touched() {
        return state;
    }

private:
    void calibrate() {
        printf("TouchSense.calibrate\r\n");
        dout.write(0);
        Thread::wait(1000);

        // initialize V0
        float s = 0.0;
        for (int i = 0; i < 10; i++) {
            float level = ain.read();
            printf("TouchSense.calibrate: level=%f\r\n", level);
            if (s < level)
                s = level;
            Thread::wait(100);
        }
        V0 = s;
        printf("TouchSense.calibrate: V0=%f\r\n", V0);

        // initialize buf, bufindex, and C1
        for (int i = 0; i < BUFSIZE; i++) {
            buf[i] = sense();
            printf("TouchSense.calibrate: sense=%d\r\n", buf[i]);
        }
        int sum = 0;
        for (int i = 0; i < BUFSIZE; i++)
            sum += buf[i];
        C1 = sum*3.0/BUFSIZE;   // XXX: 3 is a magic number
        bufindex = 0;
        printf("TouchSense.calibrate: C1=%f\r\n", C1);
    }

    void loop() {
        _thread.signal_wait(START_THREAD);
        printf("TouchSense.loop: start\r\n");
        for (;;) {
            int r = sense();
            if (r == -1)
                buf[bufindex] = C1+1;
            else
                buf[bufindex] = r;
            bufindex = (bufindex+1)%BUFSIZE;

            int sum = 0;
            for (int i = 0; i < BUFSIZE; i++)
                sum += buf[i];
            float avg = (float)sum/BUFSIZE;

            if (avg > C1)       // touhced for 0.001*BUFSIZE sec
                state = 1;  // touched
            else
                state = 0;  // untouched

            rater.update();
            Thread::wait(5);
        }
    }

    int sense() {
        DigitalIn prswitch(p5);
        prswitch.mode(PullUp);

        // step 1
        int xxx = 0;
        dout.write(0);
#ifdef DEBUG
        printf("touched: ain=%f\n\r", ain.read());
#endif
        while (ain.read() > V0) {
            xxx++;
            if (xxx > 100) {           // 0.1 sec
                printf("touched: warning ain=%f\n\r", ain.read());
                return -1;
            }
            Thread::wait(1);
        }

        // step 2
        dout.write(1);

        // step 3
        int count = 0;

        if (prswitch) {
            // mode: normal
            for  (;;) {
                if (count > C1)
                    break;
                if (ain.read() > V1)
                    break;
                count++;
            }
#ifdef DEBUG
            printf("touched: count=%d\r\n", count);
#endif
        } else {    
            // mode: profiling
            printf("rate = %f\r\n", rater.getRate());

            float prdata[PRSIZE];
            float prtime[PRSIZE];
            Timer timer;

            timer.start();
            for (;;) {
                prdata[count] = ain.read();
                prtime[count] = timer.read();
                if (prdata[count] > V1)
                    break;
                count++;
                if (count == PRSIZE) {
                    printf("touched: warning[count==PRSIZE]\r\n");
                    count--;
                    break;
                }
            }
            printf("# n=%d V0=%f V1=%f\r\n", count+1, V0, V1);
            for (int i = 0; i <= count; i++)
                printf("%f %f\r\n", prtime[i], prdata[i]);
            printf("\r\n");
        }

        // step 4
        dout.write(0);

        return count;
    }
};