maxrefdes117

Revision:
0:78a2573ad768
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MAX30105/MAX30105.cpp	Tue Aug 06 12:19:46 2019 +0000
@@ -0,0 +1,781 @@
+
+#include "mbed.h"
+#include "MAX30105.h"
+#include "millis.h"
+
+
+//******************************************************************************
+
+MAX30105::MAX30105(I2C &i2c): _i2c(i2c)
+{
+}
+
+//******************************************************************************
+
+int MAX30105::writeRegValue(uint8_t reg,  char value)
+{
+    char cmdData[2] = { (char)reg, value };
+ 
+    if (_i2c.write(MAX30105_ADDRESS, cmdData, sizeof(cmdData)) != 0) {
+        return MAX30105_ERROR;
+    }
+ 
+    return MAX30105_NO_ERROR;
+}
+ 
+//******************************************************************************
+
+int MAX30105::writeReg(uint8_t reg )
+{
+    char cmdData[1] = { (char)reg };
+ 
+    if (_i2c.write(MAX30105_ADDRESS, cmdData, sizeof(cmdData)) != 0) {
+        return MAX30105_ERROR;
+    }
+ 
+    return MAX30105_NO_ERROR;
+}
+
+
+//******************************************************************************
+
+int MAX30105::readReg(uint8_t reg, char *value)
+{
+    char cmdData[1] = { (char)reg };
+ 
+    if (_i2c.write(MAX30105_ADDRESS, cmdData, sizeof(cmdData)) != 0) {
+        return MAX30105_ERROR;
+    }
+ 
+    if (_i2c.read(MAX30105_ADDRESS, value, 1) != 0) {
+        return MAX30105_ERROR;
+    }
+ 
+    return MAX30105_NO_ERROR;
+}
+
+
+//******************************************************************************
+
+uint8_t MAX30105::readRegister8(uint8_t address, uint8_t reg){
+    _i2c.write(reg);
+    char *data = new char[5];
+    _i2c.read(address,data,5);
+    return (uint8_t)data; 
+    
+}
+
+
+//******************************************************************************
+void MAX30105::writeRegister8(uint8_t address, uint8_t reg, uint8_t value){
+
+     writeRegValue(reg, value);
+    
+}
+
+
+//******************************************************************************
+
+bool MAX30105::safeCheck(uint8_t maxTimeToCheck)
+{
+  uint32_t markTime = millis();
+  
+  while(1)
+  {
+    if(millis() - markTime > maxTimeToCheck) return(false);
+
+    if(check() == true) //We found new data!
+      return(true);
+
+    wait(1);
+  }
+}
+
+
+//******************************************************************************
+
+// NOTE: Amplitude values: 0x00 = 0mA, 0x7F = 25.4mA, 0xFF = 50mA (typical)
+// See datasheet, page 21
+void MAX30105::setPulseAmplitudeRed(uint8_t amplitude) {
+  writeRegister8(_i2caddr, MAX30105_LED1_PULSEAMP, amplitude);
+}
+
+
+//******************************************************************************
+
+void MAX30105::setPulseAmplitudeIR(uint8_t amplitude) {
+  writeRegister8(_i2caddr, MAX30105_LED2_PULSEAMP, amplitude);
+}
+
+
+//******************************************************************************
+
+void MAX30105::setPulseAmplitudeGreen(uint8_t amplitude) {
+  writeRegister8(_i2caddr, MAX30105_LED3_PULSEAMP, amplitude);
+  
+  
+}
+//******************************************************************************
+
+void MAX30105::setPulseAmplitudeProximity(uint8_t amplitude) {
+  writeRegister8(_i2caddr, MAX30105_LED_PROX_AMP, amplitude);
+}
+//Begin Interrupt configuration
+
+
+//******************************************************************************
+
+uint8_t MAX30105::getINT1(void) {
+  return (readRegister8(_i2caddr, MAX30105_INTSTAT1));
+}
+
+//******************************************************************************
+
+uint8_t MAX30105::getINT2(void) {
+  return (readRegister8(_i2caddr, MAX30105_INTSTAT2));
+}
+
+
+//******************************************************************************
+
+void MAX30105::enableAFULL(void) {
+  bitMask(MAX30105_INTENABLE1, MAX30105_INT_A_FULL_MASK, MAX30105_INT_A_FULL_ENABLE);
+}
+
+
+//******************************************************************************
+
+void MAX30105::disableAFULL(void) {
+  bitMask(MAX30105_INTENABLE1, MAX30105_INT_A_FULL_MASK, MAX30105_INT_A_FULL_DISABLE);
+}
+
+
+//******************************************************************************
+
+void MAX30105::enableDATARDY(void) {
+  bitMask(MAX30105_INTENABLE1, MAX30105_INT_DATA_RDY_MASK, MAX30105_INT_DATA_RDY_ENABLE);
+}
+
+//******************************************************************************
+
+void MAX30105::disableDATARDY(void) {
+  bitMask(MAX30105_INTENABLE1, MAX30105_INT_DATA_RDY_MASK, MAX30105_INT_DATA_RDY_DISABLE);
+}
+
+
+//******************************************************************************
+
+void MAX30105::enableALCOVF(void) {
+  bitMask(MAX30105_INTENABLE1, MAX30105_INT_ALC_OVF_MASK, MAX30105_INT_ALC_OVF_ENABLE);
+}
+
+//******************************************************************************
+
+void MAX30105::disableALCOVF(void) {
+  bitMask(MAX30105_INTENABLE1, MAX30105_INT_ALC_OVF_MASK, MAX30105_INT_ALC_OVF_DISABLE);
+}
+
+
+//******************************************************************************
+
+void MAX30105::enablePROXINT(void) {
+  bitMask(MAX30105_INTENABLE1, MAX30105_INT_PROX_INT_MASK, MAX30105_INT_PROX_INT_ENABLE);
+}
+
+//******************************************************************************
+
+void MAX30105::disablePROXINT(void) {
+  bitMask(MAX30105_INTENABLE1, MAX30105_INT_PROX_INT_MASK, MAX30105_INT_PROX_INT_DISABLE);
+}
+
+
+//******************************************************************************
+
+void MAX30105::enableDIETEMPRDY(void) {
+  bitMask(MAX30105_INTENABLE2, MAX30105_INT_DIE_TEMP_RDY_MASK, MAX30105_INT_DIE_TEMP_RDY_ENABLE);
+}
+
+//******************************************************************************
+
+void MAX30105::disableDIETEMPRDY(void) {
+  bitMask(MAX30105_INTENABLE2, MAX30105_INT_DIE_TEMP_RDY_MASK, MAX30105_INT_DIE_TEMP_RDY_DISABLE);
+}
+
+//End Interrupt configuration
+//******************************************************************************
+
+void MAX30105::softReset(void) {
+  bitMask(MAX30105_MODECONFIG, MAX30105_RESET_MASK, MAX30105_RESET);
+
+  // Poll for bit to clear, reset is then complete
+  // Timeout after 100ms
+  unsigned long startTime = millis();
+  while (millis() - startTime < 100)
+  {
+    uint8_t response = readRegister8(_i2caddr, MAX30105_MODECONFIG);
+    if ((response & MAX30105_RESET) == 0) break; //We're done!
+    wait(1); //Let's not over burden the I2C bus
+  }
+}
+
+//******************************************************************************
+
+void MAX30105::shutDown(void) {
+  // Put IC into low power mode (datasheet pg. 19)
+  // During shutdown the IC will continue to respond to I2C commands but will
+  // not update with or take new readings (such as temperature)
+  bitMask(MAX30105_MODECONFIG, MAX30105_SHUTDOWN_MASK, MAX30105_SHUTDOWN);
+}
+
+
+//******************************************************************************
+
+void MAX30105::wakeUp(void) {
+  // Pull IC out of low power mode (datasheet pg. 19)
+  bitMask(MAX30105_MODECONFIG, MAX30105_SHUTDOWN_MASK, MAX30105_WAKEUP);
+}
+
+
+//******************************************************************************
+
+void MAX30105::setLEDMode(uint8_t mode) {
+  // Set which LEDs are used for sampling -- Red only, RED+IR only, or custom.
+  // See datasheet, page 19
+  bitMask(MAX30105_MODECONFIG, MAX30105_MODE_MASK, mode);
+}
+
+
+//******************************************************************************
+
+void MAX30105::setADCRange(uint8_t adcRange) {
+  // adcRange: one of MAX30105_ADCRANGE_2048, _4096, _8192, _16384
+  bitMask(MAX30105_PARTICLECONFIG, MAX30105_ADCRANGE_MASK, adcRange);
+}
+
+
+//******************************************************************************
+
+void MAX30105::setSampleRate(uint8_t sampleRate) {
+  // sampleRate: one of MAX30105_SAMPLERATE_50, _100, _200, _400, _800, _1000, _1600, _3200
+  bitMask(MAX30105_PARTICLECONFIG, MAX30105_SAMPLERATE_MASK, sampleRate);
+}
+
+
+//******************************************************************************
+
+void MAX30105::setPulseWidth(uint8_t pulseWidth) {
+  // pulseWidth: one of MAX30105_PULSEWIDTH_69, _188, _215, _411
+  bitMask(MAX30105_PARTICLECONFIG, MAX30105_PULSEWIDTH_MASK, pulseWidth);
+}
+
+
+//******************************************************************************
+
+void MAX30105::enableSlot(uint8_t slotNumber, uint8_t device) {
+
+  uint8_t originalContents;
+
+  switch (slotNumber) {
+    case (1):
+      bitMask(MAX30105_MULTILEDCONFIG1, MAX30105_SLOT1_MASK, device);
+      break;
+    case (2):
+      bitMask(MAX30105_MULTILEDCONFIG1, MAX30105_SLOT2_MASK, device << 4);
+      break;
+    case (3):
+      bitMask(MAX30105_MULTILEDCONFIG2, MAX30105_SLOT3_MASK, device);
+      break;
+    case (4):
+      bitMask(MAX30105_MULTILEDCONFIG2, MAX30105_SLOT4_MASK, device << 4);
+      break;
+    default:
+      //Shouldn't be here!
+      break;
+  }
+}
+
+
+//******************************************************************************
+
+void MAX30105::disableSlots(void) {
+  writeRegister8(_i2caddr, MAX30105_MULTILEDCONFIG1, 0);
+  writeRegister8(_i2caddr, MAX30105_MULTILEDCONFIG2, 0);
+}
+
+//
+// FIFO Configuration
+//
+
+
+//******************************************************************************
+
+//Set sample average (Table 3, Page 18)
+void MAX30105::setFIFOAverage(uint8_t numberOfSamples) {
+  bitMask(MAX30105_FIFOCONFIG, MAX30105_SAMPLEAVG_MASK, numberOfSamples);
+}
+
+//Resets all points to start in a known state
+//Page 15 recommends clearing FIFO before beginning a read
+void MAX30105::clearFIFO(void) {
+  writeRegister8(_i2caddr, MAX30105_FIFOWRITEPTR, 0);
+  writeRegister8(_i2caddr, MAX30105_FIFOOVERFLOW, 0);
+  writeRegister8(_i2caddr, MAX30105_FIFOREADPTR, 0);
+}
+
+
+//******************************************************************************
+
+//Enable roll over if FIFO over flows
+void MAX30105::enableFIFORollover(void) {
+  bitMask(MAX30105_FIFOCONFIG, MAX30105_ROLLOVER_MASK, MAX30105_ROLLOVER_ENABLE);
+}
+
+
+//******************************************************************************
+
+//Disable roll over if FIFO over flows
+void MAX30105::disableFIFORollover(void) {
+  bitMask(MAX30105_FIFOCONFIG, MAX30105_ROLLOVER_MASK, MAX30105_ROLLOVER_DISABLE);
+}
+
+//******************************************************************************
+
+//Set number of samples to trigger the almost full interrupt (Page 18)
+//Power on default is 32 samples
+//Note it is reverse: 0x00 is 32 samples, 0x0F is 17 samples
+void MAX30105::setFIFOAlmostFull(uint8_t numberOfSamples) {
+  bitMask(MAX30105_FIFOCONFIG, MAX30105_A_FULL_MASK, numberOfSamples);
+}
+
+//******************************************************************************
+
+//Read the FIFO Write Pointer
+uint8_t MAX30105::getWritePointer(void) {
+  return (readRegister8(_i2caddr, MAX30105_FIFOWRITEPTR));
+}
+
+
+//******************************************************************************
+
+//Read the FIFO Read Pointer
+uint8_t MAX30105::getReadPointer(void) {
+  return (readRegister8(_i2caddr, MAX30105_FIFOREADPTR));
+}
+
+//******************************************************************************
+
+float MAX30105::readTemperature() {
+    
+  //DIE_TEMP_RDY interrupt must be enabled
+  //See issue 19: https://github.com/sparkfun/SparkFun_MAX3010x_Sensor_Library/issues/19
+  
+  // Step 1: Config die temperature register to take 1 temperature sample
+  writeRegister8(_i2caddr, MAX30105_DIETEMPCONFIG, 0x01);
+
+  // Poll for bit to clear, reading is then complete
+  // Timeout after 100ms
+  unsigned long startTime = millis();
+  while (millis() - startTime < 100)
+  {
+    //uint8_t response = readRegister8(_i2caddr, MAX30105_DIETEMPCONFIG); //Original way
+    //if ((response & 0x01) == 0) break; //We're done!
+    
+    //Check to see if DIE_TEMP_RDY interrupt is set
+    uint8_t response = readRegister8(_i2caddr, MAX30105_INTSTAT2);
+    if ((response & MAX30105_INT_DIE_TEMP_RDY_ENABLE) > 0) break; //We're done!
+    wait(1); //Let's not over burden the I2C bus
+  }
+  //TODO How do we want to fail? With what type of error?
+  //? if(millis() - startTime >= 100) return(-999.0);
+
+  // Step 2: Read die temperature register (integer)
+  int8_t tempInt = readRegister8(_i2caddr, MAX30105_DIETEMPINT);
+  uint8_t tempFrac = readRegister8(_i2caddr, MAX30105_DIETEMPFRAC); //Causes the clearing of the DIE_TEMP_RDY interrupt
+
+  // Step 3: Calculate temperature (datasheet pg. 23)
+  return (float)tempInt + ((float)tempFrac * 0.0625);
+}
+
+
+//******************************************************************************
+
+
+// Returns die temp in F
+float MAX30105::readTemperatureF() {
+  float temp = readTemperature();
+
+  if (temp != -999.0) temp = temp * 1.8 + 32.0;
+
+  return (temp);
+}
+
+
+//******************************************************************************
+
+
+// Set the PROX_INT_THRESHold
+void MAX30105::setPROXINTTHRESH(uint8_t val) {
+  writeRegister8(_i2caddr, MAX30105_PROXINTTHRESH, val);
+}
+
+
+//******************************************************************************
+
+
+//
+// Device ID and Revision
+//
+uint8_t MAX30105::readPartID() {
+  return readRegister8(_i2caddr, MAX30105_PARTID);
+}
+
+
+//******************************************************************************
+ 
+
+void MAX30105::readRevisionID() {
+  revisionID = readRegister8(_i2caddr, MAX30105_REVISIONID);
+}
+
+//******************************************************************************
+
+
+uint8_t MAX30105::getRevisionID() {
+  return revisionID;
+}
+
+//******************************************************************************
+
+
+
+//Setup the sensor
+//The MAX30105 has many settings. By default we select:
+// Sample Average = 4
+// Mode = MultiLED
+// ADC Range = 16384 (62.5pA per LSB)
+// Sample rate = 50
+//Use the default setup if you are just getting started with the MAX30105 sensor
+void MAX30105::setup(uint8_t powerLevel, uint8_t sampleAverage, uint8_t ledMode, int sampleRate, int pulseWidth, int adcRange) {
+  softReset(); //Reset all configuration, threshold, and data registers to POR values
+
+  //FIFO Configuration
+  //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+  //The chip will average multiple samples of same type together if you wish
+  if (sampleAverage == 1) setFIFOAverage(MAX30105_SAMPLEAVG_1); //No averaging per FIFO record
+  else if (sampleAverage == 2) setFIFOAverage(MAX30105_SAMPLEAVG_2);
+  else if (sampleAverage == 4) setFIFOAverage(MAX30105_SAMPLEAVG_4);
+  else if (sampleAverage == 8) setFIFOAverage(MAX30105_SAMPLEAVG_8);
+  else if (sampleAverage == 16) setFIFOAverage(MAX30105_SAMPLEAVG_16);
+  else if (sampleAverage == 32) setFIFOAverage(MAX30105_SAMPLEAVG_32);
+  else setFIFOAverage(MAX30105_SAMPLEAVG_4);
+
+  //setFIFOAlmostFull(2); //Set to 30 samples to trigger an 'Almost Full' interrupt
+  enableFIFORollover(); //Allow FIFO to wrap/roll over
+  //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+  //Mode Configuration
+  //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+  if (ledMode == 3) setLEDMode(MAX30105_MODE_MULTILED); //Watch all three LED channels
+  else if (ledMode == 2) setLEDMode(MAX30105_MODE_REDIRONLY); //Red and IR
+  else setLEDMode(MAX30105_MODE_REDONLY); //Red only
+  activeLEDs = ledMode; //Used to control how many uint8_ts to read from FIFO buffer
+  //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+  //Particle Sensing Configuration
+  //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+  if(adcRange < 4096) setADCRange(MAX30105_ADCRANGE_2048); //7.81pA per LSB
+  else if(adcRange < 8192) setADCRange(MAX30105_ADCRANGE_4096); //15.63pA per LSB
+  else if(adcRange < 16384) setADCRange(MAX30105_ADCRANGE_8192); //31.25pA per LSB
+  else if(adcRange == 16384) setADCRange(MAX30105_ADCRANGE_16384); //62.5pA per LSB
+  else setADCRange(MAX30105_ADCRANGE_2048);
+
+  if (sampleRate < 100) setSampleRate(MAX30105_SAMPLERATE_50); //Take 50 samples per second
+  else if (sampleRate < 200) setSampleRate(MAX30105_SAMPLERATE_100);
+  else if (sampleRate < 400) setSampleRate(MAX30105_SAMPLERATE_200);
+  else if (sampleRate < 800) setSampleRate(MAX30105_SAMPLERATE_400);
+  else if (sampleRate < 1000) setSampleRate(MAX30105_SAMPLERATE_800);
+  else if (sampleRate < 1600) setSampleRate(MAX30105_SAMPLERATE_1000);
+  else if (sampleRate < 3200) setSampleRate(MAX30105_SAMPLERATE_1600);
+  else if (sampleRate == 3200) setSampleRate(MAX30105_SAMPLERATE_3200);
+  else setSampleRate(MAX30105_SAMPLERATE_50);
+
+  //The longer the pulse width the longer range of detection you'll have
+  //At 69us and 0.4mA it's about 2 inches
+  //At 411us and 0.4mA it's about 6 inches
+  if (pulseWidth < 118) setPulseWidth(MAX30105_PULSEWIDTH_69); //Page 26, Gets us 15 bit resolution
+  else if (pulseWidth < 215) setPulseWidth(MAX30105_PULSEWIDTH_118); //16 bit resolution
+  else if (pulseWidth < 411) setPulseWidth(MAX30105_PULSEWIDTH_215); //17 bit resolution
+  else if (pulseWidth == 411) setPulseWidth(MAX30105_PULSEWIDTH_411); //18 bit resolution
+  else setPulseWidth(MAX30105_PULSEWIDTH_69);
+  //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+  //LED Pulse Amplitude Configuration
+  //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+  //Default is 0x1F which gets us 6.4mA
+  //powerLevel = 0x02, 0.4mA - Presence detection of ~4 inch
+  //powerLevel = 0x1F, 6.4mA - Presence detection of ~8 inch
+  //powerLevel = 0x7F, 25.4mA - Presence detection of ~8 inch
+  //powerLevel = 0xFF, 50.0mA - Presence detection of ~12 inch
+
+  setPulseAmplitudeRed(powerLevel);
+  setPulseAmplitudeIR(powerLevel);
+  setPulseAmplitudeGreen(powerLevel);
+  setPulseAmplitudeProximity(powerLevel);
+  //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+  //Multi-LED Mode Configuration, Enable the reading of the three LEDs
+  //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+  enableSlot(1, SLOT_RED_LED);
+  if (ledMode > 1) enableSlot(2, SLOT_IR_LED);
+  if (ledMode > 2) enableSlot(3, SLOT_GREEN_LED);
+  //enableSlot(1, SLOT_RED_PILOT);
+  //enableSlot(2, SLOT_IR_PILOT);
+  //enableSlot(3, SLOT_GREEN_PILOT);
+  //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+  clearFIFO(); //Reset the FIFO before we begin checking the sensor
+}
+
+//
+// Data Collection
+//
+
+//Tell caller how many samples are available
+uint8_t MAX30105::available(void)
+{
+  int8_t numberOfSamples = sense.head - sense.tail;
+  if (numberOfSamples < 0) numberOfSamples += STORAGE_SIZE;
+
+  return (numberOfSamples);
+}
+
+//******************************************************************************
+
+
+//Report the most recent red value
+uint32_t MAX30105::getRed(void)
+{
+  //Check the sensor for new data for 250ms
+  if(safeCheck(250))
+    return (sense.red[sense.head]);
+  else
+    return(0); //Sensor failed to find new data
+}
+
+
+//******************************************************************************
+
+
+//Report the most recent IR value
+uint32_t MAX30105::getIR(void)
+{
+  //Check the sensor for new data for 250ms
+  if(safeCheck(250))
+    return (sense.IR[sense.head]);
+  else
+    return(0); //Sensor failed to find new data
+}
+
+//******************************************************************************
+
+
+//Report the most recent Green value
+uint32_t MAX30105::getGreen(void)
+{
+  //Check the sensor for new data for 250ms
+  if(safeCheck(250))
+    return (sense.green[sense.head]);
+  else
+    return(0); //Sensor failed to find new data
+}
+
+//******************************************************************************
+
+
+//Report the next Red value in the FIFO
+uint32_t MAX30105::getFIFORed(void)
+{
+  return (sense.red[sense.tail]);
+}
+
+
+//******************************************************************************
+
+//Report the next IR value in the FIFO
+uint32_t MAX30105::getFIFOIR(void)
+{
+  return (sense.IR[sense.tail]);
+}
+
+//******************************************************************************
+
+
+//Report the next Green value in the FIFO
+uint32_t MAX30105::getFIFOGreen(void)
+{
+  return (sense.green[sense.tail]);
+}
+
+//******************************************************************************
+
+
+//Advance the tail
+void MAX30105::nextSample(void)
+{
+  if(available()) //Only advance the tail if new data is available
+  {
+    sense.tail++;
+    sense.tail %= STORAGE_SIZE; //Wrap condition
+  }
+}
+
+//******************************************************************************
+
+
+//Polls the sensor for new data
+//Call regularly
+//If new data is available, it updates the head and tail in the main struct
+//Returns number of new samples obtained
+
+uint16_t MAX30105::check(void)
+{
+  /*
+  //Read register FIDO_DATA in (3-uint8_t * number of active LED) chunks
+  //Until FIFO_RD_PTR = FIFO_WR_PTR
+
+  uint8_t readPointer = getReadPointer();
+  uint8_t writePointer = getWritePointer();
+
+  int numberOfSamples = 0;
+
+  //Do we have new data?
+  if (readPointer != writePointer)
+  {
+    //Calculate the number of readings we need to get from sensor
+    numberOfSamples = writePointer - readPointer;
+    if (numberOfSamples < 0) numberOfSamples += 32; //Wrap condition
+
+    //We now have the number of readings, now calc uint8_ts to read
+    //For this example we are just doing Red and IR (3 uint8_ts each)
+    int uint8_tsLeftToRead = numberOfSamples * activeLEDs * 3;
+
+    //Get ready to read a burst of data from the FIFO register
+    //buraya bak
+    _i2c.writeReg(MAX30105_FIFODATA);
+    
+
+    //We may need to read as many as 288 uint8_ts so we read in blocks no larger than I2C_BUFFER_LENGTH
+    //I2C_BUFFER_LENGTH changes based on the platform. 64 uint8_ts for SAMD21, 32 uint8_ts for Uno.
+    //Wire.requestFrom() is limited to BUFFER_LENGTH which is 32 on the Uno
+    while (uint8_tsLeftToRead > 0)
+    {
+      int toGet = uint8_tsLeftToRead;
+      if (toGet > I2C_BUFFER_LENGTH)
+      {
+        //If toGet is 32 this is bad because we read 6 uint8_ts (Red+IR * 3 = 6) at a time
+        //32 % 6 = 2 left over. We don't want to request 32 uint8_ts, we want to request 30.
+        //32 % 9 (Red+IR+GREEN) = 5 left over. We want to request 27.
+
+        toGet = I2C_BUFFER_LENGTH - (I2C_BUFFER_LENGTH % (activeLEDs * 3)); //Trim toGet to be a multiple of the samples we need to read
+      }
+
+      uint8_tsLeftToRead -= toGet;
+
+      //Request toGet number of uint8_ts from sensor
+      
+      //buraya bak
+      _i2c.requestFrom(MAX30105_ADDRESS, toGet);
+      
+      while (toGet > 0)
+      {
+        sense.head++; //Advance the head of the storage struct
+        sense.head %= STORAGE_SIZE; //Wrap condition
+
+        uint8_t temp[sizeof(uint32_t)]; //Array of 4 uint8_ts that we will convert into long
+        uint32_t tempLong;
+
+        //Burst read three uint8_ts - RED
+        
+        //buraya bak
+        
+        temp[3] = 0;
+        temp[2] = _i2cPort->read();
+        temp[1] = _i2cPort->read();
+        temp[0] = _i2cPort->read();
+
+        //Convert array to long
+        memcpy(&tempLong, temp, sizeof(tempLong));
+        
+        tempLong &= 0x3FFFF; //Zero out all but 18 bits
+
+        sense.red[sense.head] = tempLong; //Store this reading into the sense array
+
+        if (activeLEDs > 1)
+        {
+          
+          //Burst read three more uint8_ts - IR
+          temp[3] = 0;
+          temp[2] = _i2cPort->read();
+          temp[1] = _i2cPort->read();
+          temp[0] = _i2cPort->read();
+          
+          //Convert array to long
+          memcpy(&tempLong, temp, sizeof(tempLong));
+
+          tempLong &= 0x3FFFF; //Zero out all but 18 bits
+          
+          sense.IR[sense.head] = tempLong;
+        }
+
+        if (activeLEDs > 2)
+        {
+          //Burst read three more uint8_ts - Green
+          
+          
+          temp[3] = 0;
+          temp[2] = _i2cPort->read();
+          temp[1] = _i2cPort->read();
+          temp[0] = _i2cPort->read();
+            
+          //Convert array to long
+          memcpy(&tempLong, temp, sizeof(tempLong));
+
+          tempLong &= 0x3FFFF; //Zero out all but 18 bits
+
+          sense.green[sense.head] = tempLong;
+        }
+
+        toGet -= activeLEDs * 3;
+      }
+
+    } //End while (uint8_tsLeftToRead > 0)
+
+  } //End readPtr != writePtr
+
+  return (numberOfSamples);  //Let the world know how much new data we found
+  
+  */
+}
+
+
+//******************************************************************************
+
+
+//Check for new data but give up after a certain amount of time
+//Returns true if new data was found
+//Returns false if new data was not found
+
+
+//Given a register, read it, mask it, and then set the thing
+void MAX30105::bitMask(uint8_t reg, uint8_t mask, uint8_t thing)
+{
+  // Grab current register context
+  uint8_t originalContents = readRegister8(_i2caddr, reg);
+
+  // Zero-out the portions of the register we're interested in
+  originalContents = originalContents & mask;
+
+  // Change contents
+  writeRegister8(_i2caddr, reg, originalContents | thing);
+}
+