A library for the RFD77402 ToF distance-sensor. It's a port form the sparkfun-arduino-library.

RFD77402 ToF-sensor

I just ported the sourcecode provided by sparkfun (available on https://github.com/sparkfun/SparkFun_RFD77402_Arduino_Library) to the mbed-environment. So if you like it, please support them by e.g. buying a sparkfun-board, because in fact they did all the work :)

If you found any errors, please report them, I'm no professinal coder, so maybe there are some things I dindn't consider while porting the library.

The datasheet of the sensor is available at https://media.digikey.com/pdf/Data%20Sheets/RF%20Digital%20PDFs/RFD77402.pdf

The easiest way to use the sensor is e.g.:

RFD77402 MyDistance;                            //create an object-instance
MyDistance.begin(i2c);                          //initialize the sensor

MyDistance.takeMeasurement();                   //tell sensor to take a measurement

uint16_t distance = MyDistance.getDistance();   //get the last measurement result
Revision:
0:661414c07859
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RFD77402.cpp	Tue Nov 21 21:29:58 2017 +0000
@@ -0,0 +1,412 @@
+/*
+  This is a library written for the RFD77402 Time of Flight sensor.
+  SparkFun sells these at its website: www.sparkfun.com
+  Written by Nathan Seidle @ SparkFun Electronics, June 9th, 2017
+  The VCSEL (vertical-cavity surface-emitting laser) Time of Flight sensor 
+  can accurately measure from 10cm to 200cm (2m) with milimeter precision.
+  This library handles the initialization of the RFD77402 and bringing in of
+  various readings.
+  https://github.com/sparkfun/SparkFun_RFD77402_Arduino_Library
+  Do you like this library? Help support SparkFun. Buy a board!
+  Development environment specifics:
+  Arduino IDE 1.8.1
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+  GNU General Public License for more details.
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  
+  I just ported the sourcecode provided by sparkfun 
+  (on https://github.com/sparkfun/SparkFun_RFD77402_Arduino_Library) to the 
+  mbed-environment. So if you like it, please support them by e.g. buying a
+  sparkfun-board :)
+*/
+
+#include "mbed.h"
+#include "RFD77402.h"
+
+//Sets up the sensor for constant read
+//Returns false if sensor does not respond
+bool RFD77402::begin(I2C &i2cPort)
+{
+  //Bring in the user's choices
+  _i2cPort = &i2cPort; //Grab which port the user wants us to use
+
+
+  if (getChipID() < 0xAD00) return (false); //Chip ID failed. Should be 0xAD01 or 0xAD02
+
+  //Put chip into standby
+  if (goToStandbyMode() == false) return (false); //Chip timed out before going to standby
+
+  //Drive INT_PAD high
+  uint8_t setting = readRegister(RFD77402_ICSR);
+  setting |= (1 << 2); //Set the bit
+  writeRegister(RFD77402_ICSR, setting);
+
+  //Configure I2C Interface
+  writeRegister(RFD77402_CONFIGURE_I2C, 0x65); //0b.0110.0101 = Address increment, auto increment, host debug, MCPU debug
+
+  //Set initialization - Magic from datasheet. Write 0x05 to 0x15 location.
+  writeRegister16(RFD77402_CONFIGURE_PMU, 0x0500); //0b.0000.0101.0000.0000 //Patch_code_id_en, Patch_mem_en
+
+  if (goToOffMode() == false) return (false); //MCPU never turned off
+
+  //Read Module ID
+  //Skipped
+
+  //Read Firmware ID
+  //Skipped
+
+  //Set initialization - Magic from datasheet. Write 0x06 to 0x15 location.
+  writeRegister16(RFD77402_CONFIGURE_PMU, 0x0600); //MCPU_Init_state, Patch_mem_en
+
+  if (goToOnMode() == false) return (false); //MCPU never turned on
+
+  //ToF Configuration
+  //writeRegister16(RFD77402_CONFIGURE_A, 0xE100); //0b.1110.0001 = Peak is 0x0E, Threshold is 1.
+  setPeak(0x0E); //Suggested values from page 20
+  setThreshold(0x01);
+
+  writeRegister16(RFD77402_CONFIGURE_B, 0x10FF); //Set valid pixel. Set MSP430 default config.
+  writeRegister16(RFD77402_CONFIGURE_HW_0, 0x07D0); //Set saturation threshold = 2,000.
+  writeRegister16(RFD77402_CONFIGURE_HW_1, 0x5008); //Frequecy = 5. Low level threshold = 8.
+  writeRegister16(RFD77402_CONFIGURE_HW_2, 0xA041); //Integration time = 10 * (6500-20)/15)+20 = 4.340ms. Plus reserved magic.
+  writeRegister16(RFD77402_CONFIGURE_HW_3, 0x45D4); //Enable harmonic cancellation. Enable auto adjust of integration time. Plus reserved magic.
+
+  if (goToStandbyMode() == false) return (false); //Error - MCPU never went to standby
+
+  //Whew! We made it through power on configuration
+
+  //Get the calibration data via the 0x0006 mailbox command
+  //getCalibrationData(); //Skipped
+  
+  //Put device into Standby mode
+  if (goToStandbyMode() == false) return (false); //Error - MCPU never went to standby
+
+  //Now assume user will want sensor in measurement mode
+
+  //Set initialization - Magic from datasheet. Write 0x05 to 0x15 location.
+  writeRegister16(RFD77402_CONFIGURE_PMU, 0x0500); //Patch_code_id_en, Patch_mem_en
+
+  if (goToOffMode() == false) return (false); //Error - MCPU never turned off
+
+  //Write calibration data
+  //Skipped
+
+  //Set initialization - Magic from datasheet. Write 0x06 to 0x15 location.
+  writeRegister16(RFD77402_CONFIGURE_PMU, 0x0600); //MCPU_Init_state, Patch_mem_en
+
+  if (goToOnMode() == false) return (false); //Error - MCPU never turned on
+
+  return (true); //Success! Sensor is ready for measurements
+}
+
+//Takes a single measurement and sets the global variables with new data
+//Returns zero if reading is good, otherwise return the errorCode from the result register.
+uint8_t RFD77402::takeMeasurement(void)
+{
+  if (goToMeasurementMode() == false) return (CODE_FAILED_TIMEOUT); //Error - Timeout
+  //New data is now available!
+
+  //Read result
+  uint16_t resultRegister = readRegister16(RFD77402_RESULT);
+
+  if (resultRegister & 0x7FFF) //Reading is valid
+  {
+    uint8_t errorCode = (resultRegister >> 13) & 0x03;
+
+    if (errorCode == 0)
+    {
+      distance = (resultRegister >> 2) & 0x07FF; //Distance is good. Read it.
+      //Serial.println("Distance field valid");
+
+      //Read confidence register
+      uint16_t confidenceRegister = readRegister16(RFD77402_RESULT_CONFIDENCE);
+      validPixels = confidenceRegister & 0x0F;
+      confidenceValue = (confidenceRegister >> 4) & 0x07FF;
+    }
+
+    return (errorCode);
+
+  }
+  else
+  {
+    //Reading is not vald
+    return (CODE_FAILED_NOT_NEW); //Error code for reading is not new
+  }
+
+}
+
+//Returns the local variable to the caller
+uint16_t RFD77402::getDistance()
+{
+  return (distance);
+}
+
+//Returns the number of valid pixels found when taking measurement
+uint8_t RFD77402::getValidPixels()
+{
+  return (validPixels);
+}
+
+//Returns the qualitative value representing how confident the sensor is about its reported distance
+uint16_t RFD77402::getConfidenceValue()
+{
+  return (confidenceValue);
+}
+
+//Read the command opcode and covert to mode
+uint8_t RFD77402::getMode()
+{
+  return (readRegister(RFD77402_COMMAND) & 0x3F);
+}
+
+//Tell MCPU to go to standby mode
+//Return true if successful
+bool RFD77402::goToStandbyMode()
+{
+  //Set Low Power Standby
+  writeRegister(RFD77402_COMMAND, 0x90); //0b.1001.0000 = Go to standby mode. Set valid command.
+
+  //Check MCPU_ON Status
+  for (uint8_t x = 0 ; x < 10 ; x++)
+  {
+    if ( (readRegister16(RFD77402_DEVICE_STATUS) & 0x001F) == 0x0000) return (true); //MCPU is now in standby
+    wait_ms(10); //Suggested timeout for status checks from datasheet
+  }
+
+  return (false); //Error - MCPU never went to standby
+}
+
+//Tell MCPU to go to off state
+//Return true if successful
+bool RFD77402::goToOffMode()
+{
+  //Set MCPU_OFF
+  writeRegister(RFD77402_COMMAND, 0x91); //0b.1001.0001 = Go MCPU off state. Set valid command.
+
+  //Check MCPU_OFF Status
+  for (uint8_t x = 0 ; x < 10 ; x++)
+  {
+    if ( (readRegister16(RFD77402_DEVICE_STATUS) & 0x001F) == 0x0010) return (true); //MCPU is now off
+    wait_ms(10); //Suggested timeout for status checks from datasheet
+  }
+
+  return (false); //Error - MCPU never turned off
+}
+
+//Tell MCPU to go to on state
+//Return true if successful
+bool RFD77402::goToOnMode()
+{
+  //Set MCPU_ON
+  writeRegister(RFD77402_COMMAND, 0x92); //0b.1001.0010 = Wake up MCPU to ON mode. Set valid command.
+
+  //Check MCPU_ON Status
+  for (uint8_t x = 0 ; x < 10 ; x++)
+  {
+    if ( (readRegister16(RFD77402_DEVICE_STATUS) & 0x001F) == 0x0018) return (true); //MCPU is now on
+    wait_ms(10); //Suggested timeout for status checks from datasheet
+  }
+
+  return (false); //Error - MCPU never turned on
+}
+
+//Tell MCPU to go to measurement mode
+//Takes a measurement. If measurement data is ready, return true
+bool RFD77402::goToMeasurementMode()
+{
+  //Single measure command
+  writeRegister(RFD77402_COMMAND, 0x81); //0b.1000.0001 = Single measurement. Set valid command.
+
+  //Read ICSR Register - Check to see if measurement data is ready
+  for (uint8_t x = 0 ; x < 10 ; x++)
+  {
+    if ( (readRegister(RFD77402_ICSR) & (1 << 4)) != 0) return (true); //Data is ready!
+    wait_ms(10); //Suggested timeout for status checks from datasheet
+  }
+
+  return (false); //Error - Timeout
+}
+
+//Returns the VCSEL peak 4-bit value
+uint8_t RFD77402::getPeak(void)
+{
+  uint16_t configValue = readRegister16(RFD77402_CONFIGURE_A);
+  return ((configValue >> 12) & 0x0F);
+}
+
+//Sets the VCSEL peak 4-bit value
+void RFD77402::setPeak(uint8_t peakValue)
+{
+  uint16_t configValue = readRegister16(RFD77402_CONFIGURE_A); //Read
+  configValue &= ~0xF000;// Zero out the peak configuration bits
+  configValue |= (uint16_t)peakValue << 12; //Mask in user's settings
+  writeRegister16(RFD77402_CONFIGURE_A, configValue); //Write in this new value
+}
+
+//Returns the VCSEL Threshold 4-bit value
+uint8_t RFD77402::getThreshold(void)
+{
+  uint16_t configValue = readRegister16(RFD77402_CONFIGURE_A);
+  return ((configValue >> 8) & 0x0F);
+}
+
+//Sets the VCSEL Threshold 4-bit value
+void RFD77402::setThreshold(uint8_t thresholdValue)
+{
+  uint16_t configValue = readRegister16(RFD77402_CONFIGURE_A); //Read
+  configValue &= ~0x0F00;// Zero out the threshold configuration bits
+  configValue |= thresholdValue << 8; //Mask in user's settings
+  writeRegister16(RFD77402_CONFIGURE_A, configValue); //Write in this new value
+}
+
+//Returns the VCSEL Frequency 4-bit value
+uint8_t RFD77402::getFrequency(void)
+{
+  uint16_t configValue = readRegister16(RFD77402_CONFIGURE_HW_1);
+  return ((configValue >> 12) & 0x0F);
+}
+
+//Sets the VCSEL Frequency 4-bit value
+void RFD77402::setFrequency(uint8_t thresholdValue)
+{
+  uint16_t configValue = readRegister16(RFD77402_CONFIGURE_HW_1); //Read
+  configValue &= ~0xF000;// Zero out the threshold configuration bits
+  configValue |= thresholdValue << 12; //Mask in user's settings
+  writeRegister16(RFD77402_CONFIGURE_HW_1, configValue); //Write in this new value
+}
+
+//Gets whatever is in the 'MCPU to Host' mailbox
+//Check ICSR bit 5 before reading
+uint16_t RFD77402::getMailbox(void)
+{
+  return (readRegister16(RFD77402_MCPU_TO_HOST_MAILBOX));
+}
+
+//Software reset the device
+void RFD77402::reset(void)
+{
+  writeRegister(RFD77402_COMMAND, 1<<6);
+  wait_ms(100);
+}
+
+//Returns the chip ID
+//Should be 0xAD01 or higher
+uint16_t RFD77402::getChipID()
+{
+  return(readRegister16(RFD77402_MOD_CHIP_ID));
+}
+
+//Retreive 2*27 bytes from MCPU for computation of calibration parameters
+//This is 9.2.2 from datasheet
+//Reads 54 bytes into the calibration[] array
+//Returns true if new cal data is loaded
+bool RFD77402::getCalibrationData(void)
+{
+  if (goToOnMode() == false) return (false); //Error - sensor timed out before getting to On Mode
+
+  //Check ICSR Register and read Mailbox until it is empty
+  uint8_t messages = 0;
+  while (1)
+  {
+    if ( (readRegister(RFD77402_ICSR) & (1 << 5)) == 0) break; //Mailbox interrupt is cleared
+
+    //Mailbox interrupt (Bit 5) is set so read the M2H mailbox register
+    getMailbox(); //Throw it out. Just read to clear the register.
+
+    if (messages++ > 27) return (false); //Error - Too many messages
+
+    wait_ms(10); //Suggested timeout for status checks from datasheet
+  }
+
+  //Issue mailbox command
+  writeRegister16(RFD77402_HOST_TO_MCPU_MAILBOX, 0x0006); //Send 0x0006 mailbox command
+
+  //Check to see if Mailbox can be read
+  //Read 54 bytes of payload into the calibration[54] array
+  for (uint8_t message = 0 ; message < 27 ; message++)
+  {
+    //Wait for bit to be set
+    uint8_t x = 0;
+    while (1)
+    {
+      uint8_t icsr = readRegister(RFD77402_ICSR);
+      if ( (icsr & (1 << 5)) != 0) break; //New message in available
+
+      if (x++ > 10) return (false); //Error - Timeout
+
+      wait_ms(10); //Suggested timeout for status checks from datasheet
+    }
+
+    uint16_t incoming = getMailbox(); //Get 16-bit message
+
+    //Put message into larger calibrationData array
+    calibrationData[message * 2] = incoming >> 8;
+    calibrationData[message * 2 + 1] = incoming & 0xFF;
+  }
+
+  /*Serial.println("Calibration data:");
+    for (int x = 0 ; x < 54 ; x++)
+    {
+    Serial.print("[");
+    Serial.print(x);
+    Serial.print("]=0x");
+    if (calibrationData[x] < 0x10) Serial.print("0"); //Pretty print
+    Serial.println(calibrationData[x], HEX);
+    }*/
+}
+
+
+
+//Reads two bytes from a given location from the RFD77402
+uint16_t RFD77402::readRegister16(char addr)
+{
+  char cmd[2] = { 0 };
+  cmd[0] = addr;
+  
+  _i2cPort->write(RFD77402_ADDR, cmd, 1);
+  _i2cPort->read(RFD77402_ADDR, cmd, 2);
+
+  //if (_i2cPort->available() != 2) return (0xFFFF); //Error
+
+  //uint8_t lower = _i2cPort->read();
+  //uint8_t higher = _i2cPort->read();
+
+  return ((uint16_t)cmd[1] << 8 | cmd[0]);
+}
+
+//Reads from a given location from the RFD77402
+uint8_t RFD77402::readRegister(char addr)
+{
+  char cmd[1] = { 0 };
+  cmd[0] = addr;
+  
+  _i2cPort->write(RFD77402_ADDR, cmd, 1);
+  _i2cPort->read(RFD77402_ADDR, cmd, 1);
+  return cmd[0];
+
+  //return (0xFF); //Error
+}
+
+//Write a 16 bit value to a spot in the RFD77402
+void RFD77402::writeRegister16(char addr, uint16_t val)
+{
+  char cmd[3] = { 0 };
+  cmd[0] = addr;
+
+  cmd[1] = (val & 0xFF); //Lower byte
+  cmd[2] = (val >> 8); //Uper byte
+  _i2cPort->write(RFD77402_ADDR, cmd, 3);
+}
+
+//Write a value to a spot in the RFD77402
+void RFD77402::writeRegister(char addr, char val)
+{
+  char cmd[2] = { 0 };
+  cmd[0] = addr;
+
+  cmd[1] = val; //Lower byte
+  _i2cPort->write(RFD77402_ADDR, cmd, 2);
+}
\ No newline at end of file