Dependencies:   MODSERIAL mbed-rtos mbed

main.cpp

Committer:
rkk
Date:
2015-03-21
Revision:
1:f213d3a65eb4
Parent:
0:5e236dc97961
Child:
2:5914e8cbf992

File content as of revision 1:f213d3a65eb4:

#include "mbed.h"
#include "rtos.h"
#include "MODSERIAL.h"
#include "math.h"

#define BT_BAUD 9600
#define NUM_LRAS 8
#define DEBUGGING true

// bluetooth serial
// p9 - tx, p10 - rx
MODSERIAL bt(p9, p10); //only receiving pin is actually needed

//DigitalOut led[4] = {
//    DigitalOut(LED1), DigitalOut(LED2), DigitalOut(LED3), DigitalOut(LED4)
//};

PwmOut lra[NUM_LRAS] = {
    PwmOut(p5), PwmOut(p6), PwmOut(p14), PwmOut(p20), 
    PwmOut(p25), PwmOut(p26), PwmOut(p34), PwmOut(p36)
};

DigitalOut lra_en[NUM_LRAS] = {
    DigitalOut(p7), DigitalOut(p8), DigitalOut(p11), DigitalOut(p12),
    DigitalOut(p13), DigitalOut(p29), DigitalOut(p30), DigitalOut(p35)
};

int lraOn_ms[NUM_LRAS];
int lraPeriod_ms[NUM_LRAS];
float lraIntensity[NUM_LRAS];

Thread* lra_thread[NUM_LRAS];
Thread* commThread;
RtosTimer* timer[NUM_LRAS];
int counter[NUM_LRAS] = {0};

void timer_cb(void const *n)
{
    counter[(int)n]++;
}

void lra_fun(void const *n)
{
    int leftToWait_ms;

    while (true) {
        // Turn On LRA:     
        //if((int)n < 4) {
        //    led[(int)n] = 1; 
        //}
        lra_en[(int)n] = 1;
        lra[(int)n] = ceil(lraIntensity[(int)n]); //set initial intensity
        counter[(int)n] = 0; //reset counter to 0

        leftToWait_ms = lraOn_ms[(int)n] - counter[(int)n];
        while( leftToWait_ms > 0) {
            //printf("time: %d\n",leftToWait_ms);
            Thread::signal_wait(0x1,(uint32_t) leftToWait_ms); //signal number, wait time
            leftToWait_ms = lraOn_ms[(int)n] - counter[(int)n];
            lra[(int)n] = ceil(lraIntensity[(int)n]); //adjust intensity according to current value
        }


        //if((int)n < 4) {
        //    led[(int)n] = 0; 
        //}
        //Set LRA PWM to 0.5
        lra[(int)n] = 0.5f;
        //Turn LRA Off
        lra_en[(int)n] = 0;

        //set rest time to sleep while the lra is off
        leftToWait_ms = lraPeriod_ms[(int)n]-counter[(int)n];
        while( leftToWait_ms > 0) {
            //printf("time: %d\n",leftToWait_ms);
            Thread::signal_wait(0x2,(uint32_t) leftToWait_ms); //signal number, wait time
            //it woke up!
            leftToWait_ms = lraPeriod_ms[(int)n] - counter[(int)n];
        }
    }
}

// Called everytime a new character goes into
// the RX buffer. Test that character for \n
// Note, rxGetLastChar() gets the last char that
// we received but it does NOT remove it from
// the RX buffer.
void rx_cb(MODSERIAL_IRQ_INFO *q)
{
    MODSERIAL *serial = q->serial;
    if ( serial->rxGetLastChar() == '\0') {
        commThread->signal_set(0x3); //signal 3
    }
}

void commThread_cb(void const *n)
{
    int index = 0;
    int which = 0;
    char input = 0;
    float newIntensity;
    int newOnTime;
    int newTotalTime;
    
    while (true) {
        // Wait here until we detect the \0 going into the buffer.
        //new data in the buffer, read it out
        while(bt.readable()) {
            input = bt.getc();
            switch ( index ) {
                case 0:
                    which = input-'0';
                    index = (which < 0)? 4 : index;
                    index = (which > (NUM_LRAS-1))? 4 : index;
                    break;
                case 1:
                    // Intensity
                    input = (input < 1)? 1 : input;
                    input = (input > 255)? 255 : input;
                    // scale intensity between 0.5f to 1.0f
                    newIntensity = (float) (input+253)/508.0;
                    lraIntensity[which] = newIntensity;
                    break;
                case 2:
                    // Period Length Start
                    input = (input < 1)? 1 : input;
                    input = (input > 255)? 255 : input;
                    // scale start length between 50 to 300 - see matlab script "range_calculations.m" in git repo
                    newOnTime = (int) floor( ((input+49.8)/1.016) + 0.5); //floor(...+0.5) = round()
                    if(newOnTime!=lraOn_ms[which]) {
                        lraOn_ms[which] = newOnTime;
                        lra_thread[which]->signal_set(0x1); //signal 1
                    }
                case 3:
                    // Total Period Length
                    input = (input < 1)? 1 : input;
                    input = (input > 255)? 255 : input;
                    // scale total period length between 301 to 4000 - see matlab script "range_calculations.m" in git repo
                    newTotalTime = (int) floor( ((input+19.5946)/0.0686) +0.5); //floor(...+0.5) = round()
                    if(newTotalTime!=lraPeriod_ms[which]) {
                        lraPeriod_ms[which] = newTotalTime;
                        lra_thread[which]->signal_set(0x2); //signal 2
                    }
                    break;
                default:
                    // do nothing
                    break;
            }
            index++;
        }
        index = 0; //reset index
        Thread::signal_wait(0x3); //signal 3
    }
}
int main (void)
{
    //Init communication
    bt.baud(BT_BAUD); //set baud rate of bluetooth connection
    bt.attach(&rx_cb, MODSERIAL::RxIrq); // attach callback to get '\0' command

    commThread = new Thread(commThread_cb);
    
    //initialize and start everything
    for(int i = 0; i < NUM_LRAS; i++) {
        
        //set pwm frequency
        lra[i].period_us(20);
        
        //set starting vibration
        lraOn_ms[i] = 100;
        lraPeriod_ms[i] = 1000;
        lraIntensity[i] = 0.5f;
        //start timers
        timer[i]= new RtosTimer(timer_cb,osTimerPeriodic, (void *) i);
        timer[i]->start(1); //run timer every millisecond
        //Set up lra threads
        lra_thread[i] = new Thread(lra_fun, (void *)i);
    }
}