EEP fORK

Dependencies:   BLE_API mbed nRF51822

Fork of MCS_LRF by Farshad N

laser.cpp

Committer:
Farshad
Date:
2017-03-01
Revision:
16:dc9956bac1a3
Parent:
15:bc4f8c597c26

File content as of revision 16:dc9956bac1a3:


#include "laser.h"

#define LASER_BAUD_RATE 115200

extern DigitalOut disableLRF;
extern DigitalOut nReset;

uint32_t base = 0x40002000;
uint32_t rxOffset = 0x514;
uint32_t txOffset = 0x50c;

uint32_t rx = base + rxOffset;
uint32_t tx = base + txOffset;

uint32_t* prx = (uint32_t*)rx;
uint32_t* ptx = (uint32_t*)tx;

int bufIdx = 0;
bool discard = true;

Laser::Laser(Serial& serial, int n) : timerRunning(false), idx(0), serial(serial), powerOffState (true), busy(false), nSamples(n)
{
   // serial.attach(this, &Laser::processResponse);  // this causes a crash?? do the assignment from the caller
}

void Laser::discardResponse()
{
    discard = true;
}

void Laser::triggerDistanceMeasurement()
{
    if(!busy){
        const int bufSize = 30;
        char cmd[bufSize];
        snprintf(&cmd[0], bufSize, "0 -1 %d doMeasDistExt\n", nSamples);
        //char cmd[] = "0 -1 10 doMeasDistExt\n";   // single reading averaged over 10 measurements
        //char cmd[] = "0 -1 100 doMeasDistExt\n";   // single reading averaged over 100 measurements
        //char cmd[] = "0 -1 -1 doMeasDistExt\n";     // single reading auto choice of number of averages - This could make the laser to lock up and may need reseting
    
        busy = true;
        discard = false;
        sendCommand(cmd);
    }
}

bool Laser::sendCommand(char cmd[])
{
    // start timer before the first of the command is sent to the laser
    timer.reset();
    timer.start();
    timerRunning = true;

    for(int i = 0; i < strlen(cmd); i++) {
        serial.putc(cmd[i]);
    }

    return true;
}

void Laser::processRx()
{
    char c = serial.getc();

    if(!discard) {
        if(timerRunning) {
            timer.stop();
            timerRunning = false;
        }

        buf[bufIdx++] =c;

        // TODO sort our timeout
        if(bufIdx == bufSize) {
            // need to reset the LRF module before talking to it again, otherwise it may lock up
            nReset = 0;
            wait_ms(100);
            nReset = 1;
            wait_ms(1000);
            enableMeasurement(true);
            busy = false;
            bufIdx = 0;
        }

        if(c == '\n') {
            buf[bufIdx-1] = 0;        // replace '\n' with string null ternimator
            processResponse();
            discard = false;
             busy = false;
            bufIdx = 0;
        }
    }
}

void Laser::processResponse()
{
    if(!busy) return;

    float distance = -5;
    vector<char*> v;

    split(buf, ' ', v);

    if (v.size() != 6 || atoi(v[1]) != 0 || strcmp(v[5], "Reply") != 0) {
        // there is an error
        distanceCallback(-1.0, 0.0);
    } else {
        float elapsed =  (float)(timer.read_us()/1000.0);      // elapsed in ms
        distance = atoi(v[2]) / 1000000.0; // distance in m
        distanceCallback(distance, elapsed);
    }
}

void Laser::enableMeasurement(bool enable)
{
    if (enable) {
        sendCommand(";\n");
        discardResponse();

    } else {
        sendCommand("switchMeasOff\n");
        discardResponse();
    }
}

void Laser::setRedDot(bool on)
{
    if(on) {
        //char cmd[] = "0 -1 5 doMeasDistExt\n";     // doing a measurement turns the redDot on
        char cmd[] = "0 3 0 -1 3 doLaserCmd;\n";
        sendCommand(cmd);
        wait_ms(120);       // take a while for a response for to measurement command
        discardResponse();
//       triggerDistanceMeasurement();
    } else {
        sendCommand("switchMeasOff\n");
        discardResponse();
    }
}

void Laser::split(char str[], char c, std::vector<char*>& v)
{
    char * pch;
    char limiter[] = {c};
    pch = strtok (str, limiter);
    while (pch != NULL) {
        v.push_back(pch);
        pch = strtok (NULL, limiter);
    }
}

void Laser::setDistaceCallback(void (*callback)(float, float))
{
    distanceCallback = callback;
}

void Laser::setDebugCallback(void (*callback)(char*))
{
    debugCallback = callback;
}

void Laser::turnLaserPowerOn()
{
    if(powerOffState == true) {
        powerOffState = false;

        connectPower();

        enableMeasurement(true);
        setRedDot(1);
    }
}

void Laser::turnLaserPowerOff()
{
    if(powerOffState == false) {
        powerOffState = true;
        setRedDot(0);   // this disables measurements

        removePower();
    }
}

// when connceting power to the laser module ensure that tx and rx pins are
// reassigned to the serial port
void Laser::connectPower()
{
    disableLRF = 0;
    nReset = 1;
    *ptx = 27;  // p27 for tx
    *prx = 26;  // p26 for rx
    wait_ms(1000);
}

// when removing power from the laser module ensure that rx and tx pins are not
// driving voltage into the laser module to avoid hardware damage
void Laser::removePower()
{
    *ptx = 0xffffffff;      // no pin for tx
    *prx = 0xffffffff;      // no pin for rx
    DigitalOut rx(p26);
    DigitalOut tx(p27);
    rx = 0;
    tx = 0;
    nReset = 0;
    disableLRF = 1;
}

Laser::~Laser()
{
    enableMeasurement(false);
}




//void Laser::processRxData(char c)
//{
//    if(c != '\n') {
//        buf[idx++] = c;
//        if(idx == bufSize) idx = 0;      // avoid overflow
//    } else {
//        buf[idx] = 0;       // null terminate the string
//        processBuffer();
//        idx = 0;
//    }
//}

//float Laser::getDistance()
//{
//    float distance = -4.0;
//    const int bufSize = 50;
//    char data[bufSize];
//    int i = 0;
//    //char cmd[] = ";\n";
//    char cmd[] = "0 -1 10 doMeasDistExt\n";   // single reading averaged over 10 measurements
//    //char cmd[] = "0 -1 -1 doMeasDistExt\n";     // single reading of single measurement
//
//    if (sendCommand(cmd) == true) {
//        // Note: Need to actually read from the serial to clear the RX interrupt
//        char c = 0;
//        uint16_t count = 0;
//        do {
//            if(serial.readable()) {
//                c = serial.getc();
//                data[i++] = c;
//            } else {
//                wait_us(100);
//            }
//        } while (c != '\n' && i < bufSize && count++ < 5000);  // timeout after about 500ms and ensure no overflow
//
//        if (count >= 5000 || i >= bufSize) return -2.0;  // timeout or overflow
//
//        // now that we have the reply parse it
//        data[i - 1] = 0;        // null terminate the string
//
//        //reply is in this form '2 0 1844364 324 Reply'. 2nd number is error code, 3rd number is distance in um, 4th number is measurement signal
//        vector<char*> v;
//        split(data, ' ', v);
//
//        if (v.size() != 6 || atoi(v[1]) != 0 || strcmp(v[5], "Reply") != 0) {
//            // there is an error
//            distance = -3.0;
//        } else {
//            distance = atoi(v[2]) / 1000000.0; // distance in m
//        }
//    }
//
//    return distance;
//}

//void Laser::processBuffer()
//{
//    //float distance;
////    vector<char*> v;
////   // debugCallback(buf);
////
////    split(buf, ' ', v);
////
////    if (v.size() != 6 || atoi(v[1]) != 0 || strcmp(v[5], "Reply") != 0) {
////        // there is an error
////        distanceCallback(-1.0);
////    } else
////    {
////        distance = atoi(v[2]) / 1000000.0; // distance in m
////        distanceCallback(distance);
////    }
//
//
//    float distance = -5;
//    vector<char*> v;
//
//    split(buf, ' ', v);
//
//    if (v.size() != 6 || atoi(v[1]) != 0 || strcmp(v[5], "Reply") != 0) {
//        // there is an error
//        distanceCallback(-1.0, 0.0);
//    } else {
//        float elapsed =  (float)(timer.read_us()/1000.0);      // elapsed in ms
//        distance = atoi(v[2]) / 1000000.0; // distance in m
//        distanceCallback(distance, elapsed);
//    }
//}