For coursework of group 3 in SOFT564Z

Dependencies:   Motordriver ros_lib_kinetic

VL6180.cpp

Committer:
Jonathan738
Date:
2019-12-19
Revision:
11:0b9098ec11c7
Parent:
10:c752a8d76ee2
Child:
12:82b8fe254222

File content as of revision 11:0b9098ec11c7:

#include "mbed.h"
#include "General.hpp"
#include "rtos.h"
#include "Pins.h"
#include "VL6180.hpp"
#include <vector>

//#define DEBUG_TOF
#ifdef DEBUG_TOF
Serial debug_term(SERIAL_TX, SERIAL_RX);
#endif


#define ROS_TOF
int Global_TOF_Ranges[num_VL6180];
bool TOF_Range_Flag;
Mutex Global_TOF_Range_Mutex;

/*------------------------------------------------------------------------------
//  Main Program loop
------------------------------------------------------------------------------*/
int TOF_Thread()
{
    /* Pins are (PC_9, PC_11, PD_2, PG_3) */
    I2C i2c_bus(I2C_SDA, I2C_SCL); // Set up I²C on the STM32 NUCLEO-401RE

    //Dynamically create VL6180 objects for the TOF sensors
    PinName SHDN_Pins[num_VL6180] = SHDN_Pins_Cell;
    char Addresses[num_VL6180] = Shifted_TOF_Addresses;
    TOFsPtr * TOF = new TOFsPtr[num_VL6180];
    for (int idx = 0; idx < num_VL6180; ++idx) {
        TOF[idx] = new VL6180(i2c_bus, SHDN_Pins[idx], Addresses[idx]);
    }

    // Initialise all TOF sensors
    Init_All_TOFs(TOF);

    //Create range variable to stored read TOF values
    int Range[num_VL6180] = {};

    //note that sensor 1 can be left at the default address, since other sensors
    //are already allocated. Adding more I2C devices would require it to be
    //reassigned to a different address, however.
    while (1) {
        for(int IDX = 0; IDX < num_VL6180; IDX++) {
            TOF[IDX]->Start_Range();
            TOF[IDX]->Poll_Range();
            Range[IDX] = TOF[IDX]->Read_Range();
            TOF[IDX]->Clear_Interrupts();

            wait_ms(10);
        }
        
#ifdef ROS_TOF
    Global_TOF_Range_Mutex.lock();
    for(int IDX = 0; IDX < num_VL6180; IDX++) {
        Global_TOF_Ranges[IDX] = Range[IDX];
    }
    if(TOF_Range_Flag == false)
    {
        TOF_Range_Flag = true;
    }
    Global_TOF_Range_Mutex.unlock();
#endif

#ifdef DEBUG_TOF
        debug_term.printf("|--------------------------------\n\r"
                          "|Ranges:                         \n\r"
                          "| %d\n\r",Range[0]);
                          
                          /*
                          "| %d\n\r"
                          "| %d\n\r"
                          "| %d\n\r",Range[0], Range[1], Range[2], Range[3]);
                          */
#endif

        wait_ms(100);

    }
}


/*------------------------------------------------------------------------------
    Function turns TOF sensor ON or OFF
------------------------------------------------------------------------------*/
bool VL6180::TOF_PWR(bool State)
{
    this->shutdown = State;
    return State;   
}

/*------------------------------------------------------------------------------
    Split 16-bit register address into two bytes and write
    the address + data via I²C
------------------------------------------------------------------------------*/
void VL6180::WriteByte(wchar_t reg, char data)
{
    char data_write[3];
    data_write[0] = (reg >> 8) & 0xFF;;
    // MSB of register address
    data_write[1] = reg  & 0xFF;
    // LSB of register address
    data_write[2] = data & 0xFF;
    this->i2c.write(addr, data_write, 3);
}
void VL6180::WriteByte_Uninitialized(wchar_t reg, char data, char Uninitialized_Address) {    
    char data_write[3];
    data_write[0] = (reg >> 8) & 0xFF;;
    // MSB of register address
    data_write[1] = reg  & 0xFF;
    // LSB of register address
    data_write[2] = data & 0xFF;
    this->i2c.write(Uninitialized_Address, data_write, 3);
}

/*------------------------------------------------------------------------------
    Split 16-bit register address into two bytes and write
    required register address to VL6180 and read the data back
------------------------------------------------------------------------------*/
char VL6180::ReadByte(wchar_t reg)
{
    char data_write[2];
    char data_read[1];

    data_write[0] = (reg >> 8) & 0xFF; // MSB of register address
    data_write[1] = reg  & 0xFF; // LSB of register address

    this->i2c.write(addr, data_write, 2);
    this->i2c.read(addr, data_read, 1);
    return data_read[0];
}
char VL6180::ReadByte_Uninitialized(wchar_t reg, char Uninitialized_Address) {
    char data_write[2];
    char data_read[1];
   
    data_write[0] = (reg >> 8) & 0xFF; // MSB of register address
    data_write[1] = reg  & 0xFF; // LSB of register address
   
    this->i2c.write(Uninitialized_Address, data_write, 2);
    this->i2c.read(Uninitialized_Address, data_read, 1);
    return data_read[0];
}

/*------------------------------------------------------------------------------
    Start a range measurement in single shot mode
------------------------------------------------------------------------------*/
int VL6180::Start_Range(void)
{
    this->WriteByte(0x018,0x03);
    return 0;
}

/*------------------------------------------------------------------------------
    poll for new sample ready ready
------------------------------------------------------------------------------*/
int VL6180::Poll_Range(void)
{
    char status;
    char range_status;

    // check the status
    status = this->ReadByte(0x04f);
    range_status = status & 0x07;

    // wait for new measurement ready status
    while (range_status !=  0x00) {
        status = this->ReadByte(0x04f);
        range_status = status & 0x07;
        //wait_ms(50); // (can be removed)
    }

    return 0;
}


/*------------------------------------------------------------------------------
    Read range result (mm)
------------------------------------------------------------------------------*/
int VL6180::Read_Range(void)
{
    int range;
    range = this->ReadByte(0x062);
    return range;
}

/*------------------------------------------------------------------------------
    clear interrupts
------------------------------------------------------------------------------*/

int VL6180::Clear_Interrupts(void)
{
    this->WriteByte(0x015,0x07);
    return 0;
}

/*------------------------------------------------------------------------------
    load settings
------------------------------------------------------------------------------*/
bool VL6180::Init(void)
{
    // check to see has if the TOF sensor has been Initialised already
    char reset = this->ReadByte_Uninitialized(0x016, 0x82);    
    if (reset==1)
    {            
        // Mandatory : private registers
        this->WriteByte_Uninitialized(0x0207, 0x01, 0x82);
        this->WriteByte_Uninitialized(0x0208, 0x01, 0x82);
        this->WriteByte_Uninitialized(0x0096, 0x00, 0x82);
        this->WriteByte_Uninitialized(0x0097, 0xfd, 0x82);
        this->WriteByte_Uninitialized(0x00e3, 0x01, 0x82);
        this->WriteByte_Uninitialized(0x00e4, 0x03, 0x82);
        this->WriteByte_Uninitialized(0x00e5, 0x02, 0x82);
        this->WriteByte_Uninitialized(0x00e6, 0x01, 0x82);
        this->WriteByte_Uninitialized(0x00e7, 0x03, 0x82);
        this->WriteByte_Uninitialized(0x00f5, 0x02, 0x82);
        this->WriteByte_Uninitialized(0x00d9, 0x05, 0x82);
        this->WriteByte_Uninitialized(0x00db, 0xce, 0x82);
        this->WriteByte_Uninitialized(0x00dc, 0x03, 0x82);
        this->WriteByte_Uninitialized(0x00dd, 0xf8, 0x82);
        this->WriteByte_Uninitialized(0x009f, 0x00, 0x82);
        this->WriteByte_Uninitialized(0x00a3, 0x3c, 0x82);
        this->WriteByte_Uninitialized(0x00b7, 0x00, 0x82);
        this->WriteByte_Uninitialized(0x00bb, 0x3c, 0x82);
        this->WriteByte_Uninitialized(0x00b2, 0x09, 0x82);
        this->WriteByte_Uninitialized(0x00ca, 0x09, 0x82);
        this->WriteByte_Uninitialized(0x0198, 0x01, 0x82);
        this->WriteByte_Uninitialized(0x01b0, 0x17, 0x82);
        this->WriteByte_Uninitialized(0x01ad, 0x00, 0x82);
        this->WriteByte_Uninitialized(0x00ff, 0x05, 0x82);
        this->WriteByte_Uninitialized(0x0100, 0x05, 0x82);
        this->WriteByte_Uninitialized(0x0199, 0x05, 0x82);
        this->WriteByte_Uninitialized(0x01a6, 0x1b, 0x82);
        this->WriteByte_Uninitialized(0x01ac, 0x3e, 0x82);
        this->WriteByte_Uninitialized(0x01a7, 0x1f, 0x82);
        this->WriteByte_Uninitialized(0x0030, 0x00, 0x82);
        this->WriteByte_Uninitialized(0x016, 0x00, 0x82); //change fresh out of set status to 0 
    } else {
        return true;
    }
    return false;
}


/*------------------------------------------------------------------------------
    Function to Initialise all TOF sensors
------------------------------------------------------------------------------*/
bool Init_All_TOFs(TOFsPtr *tof)
{
    bool Err_Flag = false;
    
    char Non_Shifted_Addresses[num_VL6180] = TOF_Addresses;
    
    for(int IDX = 0; IDX < num_VL6180; IDX++)
    {
        tof[IDX]->TOF_PWR(false);
    }
    
    wait_ms(0.5);

    if(num_VL6180 > 1)
    {
        for(int IDX = 1; IDX < num_VL6180; IDX++)
        {
            tof[IDX]->TOF_PWR(true);
            
            if(tof[IDX]->Init() == true)
            {
                Err_Flag = true;    
            }
            tof[IDX]->WriteByte(0x212, Non_Shifted_Addresses[IDX]);

        }
    }
    
    tof[0]->TOF_PWR(true);         
    tof[0]->Init();
    tof[0]->WriteByte(0x212, Non_Shifted_Addresses[0]); 

    return Err_Flag;
}