Library for MAX30101 SpO2 and heart rate sensor

Dependents:   HeartRate HeartRate proj final_project_ee119 ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MAX30101.cpp Source File

MAX30101.cpp

00001 /*******************************************************************************
00002  * Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
00003  *
00004  * Permission is hereby granted, free of charge, to any person obtaining a
00005  * copy of this software and associated documentation files (the "Software"),
00006  * to deal in the Software without restriction, including without limitation
00007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00008  * and/or sell copies of the Software, and to permit persons to whom the
00009  * Software is furnished to do so, subject to the following conditions:
00010  *
00011  * The above copyright notice and this permission notice shall be included
00012  * in all copies or substantial portions of the Software.
00013  *
00014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00015  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00016  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
00017  * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
00018  * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
00019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
00020  * OTHER DEALINGS IN THE SOFTWARE.
00021  *
00022  * Except as contained in this notice, the name of Maxim Integrated
00023  * Products, Inc. shall not be used except as stated in the Maxim Integrated
00024  * Products, Inc. Branding Policy.
00025  *
00026  * The mere transfer of this software does not imply any licenses
00027  * of trade secrets, proprietary technology, copyrights, patents,
00028  * trademarks, maskwork rights, or any other form of intellectual
00029  * property whatsoever. Maxim Integrated Products, Inc. retains all
00030  * ownership rights.
00031  *******************************************************************************
00032  */
00033  
00034  
00035 #include "MAX30101.h"
00036 
00037 
00038 //*****************************************************************************
00039 MAX30101::MAX30101(I2C &i2c):
00040 m_i2cBus(i2c)
00041 {
00042     //empty block
00043 }
00044 
00045 
00046 //*****************************************************************************
00047 MAX30101::~MAX30101()
00048 {
00049     //empty block
00050 }
00051 
00052 
00053 //*****************************************************************************
00054 int32_t MAX30101::enableInterrupts(const InterruptBitField_u data)
00055 {
00056     char cmdData[3];
00057     cmdData[0] = InterruptEnable1;
00058     cmdData[1] = (data.all & 0xF0);
00059     cmdData[2] = (data.all & 0x02);
00060 
00061     return m_i2cBus.write(I2C_W_ADRS, cmdData, 3);
00062 }
00063 
00064 
00065 //*****************************************************************************
00066 int32_t MAX30101::getInterruptStatus(InterruptBitField_u &data)
00067 {
00068     char local_data[3];
00069     local_data[0] = InterruptStatus1;
00070     
00071     int32_t result = m_i2cBus.write(I2C_W_ADRS, local_data, 1);
00072     if(result == 0)
00073     {
00074         result = m_i2cBus.read(I2C_R_ADRS, (local_data + 1), 2);
00075         if(result == 0)
00076         {
00077             data.all = local_data[1] + local_data[2];
00078         }
00079     }
00080     
00081     return result;
00082 }
00083 
00084 
00085 //*****************************************************************************
00086 int32_t MAX30101::setFIFOConfiguration(const FIFO_Configuration_u config)
00087 {
00088     return writeRegister(FIFO_Configuration, config.all);
00089 }
00090     
00091 
00092 //*****************************************************************************
00093 int32_t MAX30101::getFIFOConfiguration(FIFO_Configuration_u &config)
00094 {
00095     return readRegister(FIFO_Configuration, config.all);
00096 }
00097     
00098     
00099 //*****************************************************************************
00100 int32_t MAX30101::setModeConfiguration(const ModeConfiguration_u config)
00101 {
00102     return writeRegister(ModeConfiguration, (config.all & 0xC7));
00103 }
00104     
00105 
00106 //*****************************************************************************    
00107 int32_t MAX30101::getModeConfiguration(ModeConfiguration_u &config)
00108 {
00109     return readRegister(ModeConfiguration, config.all);
00110 }   
00111     
00112 
00113 //*****************************************************************************    
00114 int32_t MAX30101::setSpO2Configuration(const SpO2Configuration_u config)
00115 {
00116     return writeRegister(SpO2Configuration, (config.all & 0x7F));
00117 }   
00118 
00119 
00120 //*****************************************************************************    
00121 int32_t MAX30101::getSpO2Configuration(SpO2Configuration_u &config)
00122 {
00123     return readRegister(SpO2Configuration, config.all);
00124 }
00125 
00126 
00127 //*****************************************************************************  
00128 int32_t MAX30101::setLEDPulseAmplitude(Registers_e reg, const uint8_t amp)
00129 {
00130     return writeRegister(reg, amp);
00131 }
00132 
00133 
00134 //*****************************************************************************  
00135 int32_t MAX30101::getLEDPulseAmplitude(Registers_e reg, uint8_t &amp)
00136 {
00137     return readRegister(reg, amp);
00138 }
00139 
00140 
00141 //*****************************************************************************  
00142 int32_t MAX30101::setMultiLEDModeControl(Registers_e reg, const ModeControlReg_u data)
00143 {
00144     return writeRegister(reg, data.all);
00145 }
00146  
00147     
00148 //*****************************************************************************  
00149 int32_t MAX30101::getMultiLEDModeControl(Registers_e reg, ModeControlReg_u &data)
00150 {
00151     return readRegister(reg, data.all);
00152 }
00153 
00154     
00155 //*****************************************************************************  
00156 int32_t MAX30101::getDieTemperature(uint16_t &data)
00157 {
00158     int32_t result = -1;
00159     
00160     //Die temp conversion time is 30ms
00161     //ATTEMPTS > than 30ms at 100KHz SCL for getInterruptStatus call
00162     const uint32_t ATTEMPTS = 100; 
00163     uint32_t num_reads = 0;
00164     
00165     //local i2c transaction buffer
00166     char local_data[2];
00167     local_data[0] = DieTempConfig;
00168     local_data[1] = 1;
00169     
00170     //initiate die temp conversion
00171     result = m_i2cBus.write(I2C_W_ADRS, local_data, 2, true);
00172     if(result == 0)
00173     {
00174         //object for holding status registers data
00175         InterruptBitField_u status;
00176         status.all = 0;
00177         
00178         //poll status registers until temp ready, or read fails
00179         do
00180         {
00181             result = getInterruptStatus(status);
00182             num_reads++;
00183         }
00184         while(!status.bits.die_temp && (result == 0) && (num_reads < ATTEMPTS));
00185         
00186         if(status.bits.die_temp)
00187         {
00188             //set pointer to temperature integer register
00189             local_data[0] = DieTempInt;
00190             result = m_i2cBus.write(I2C_W_ADRS, local_data, 1, true);
00191             if(result == 0)
00192             {
00193                 //read two bytes
00194                 result = m_i2cBus.read(I2C_R_ADRS, local_data, 2);
00195                 if(result == 0)
00196                 {
00197                     //stuff data
00198                     data = ( (local_data[0] << 8) | (local_data[1] << 4) );
00199                     data = (data >> 4);
00200                 }
00201             }
00202         }
00203         else
00204         {
00205             //if result equals 0 because num_reads exceeded ATTEMPTS,
00206             //change result to -1.  Otherwise keep result's error code.
00207             result = (result == 0) ? -1 : result;
00208         }
00209     }
00210     return result;
00211 }
00212 
00213     
00214 //*****************************************************************************  
00215 int32_t MAX30101::getDieTemperatureC(float &data)
00216 {
00217     uint16_t raw_temp;
00218     
00219     int32_t result = getDieTemperature(raw_temp);
00220     if(result == 0)
00221     {
00222         if(raw_temp & 0x0800)
00223         {
00224             data = ((0xFFFFF000 | raw_temp)/16.0F);
00225         }
00226         else
00227         {
00228             data = (raw_temp/16.0F);
00229         }
00230     }
00231     
00232     return result;
00233 }
00234 
00235 
00236 //*****************************************************************************  
00237 float MAX30101::celsius2fahrenheit(float c) 
00238 {
00239     return ((1.8F * c) + 32.0F);
00240 }
00241     
00242 
00243 //*****************************************************************************     
00244 int32_t MAX30101::setProxIntThreshold(const uint8_t data)
00245 {
00246     return writeRegister(ProxIntThreshold, data);
00247 }
00248     
00249 
00250 //*****************************************************************************     
00251 int32_t MAX30101::getProxIntThreshold(uint8_t &data)
00252 {
00253     return readRegister(ProxIntThreshold, data);
00254 }
00255 
00256 
00257 //*****************************************************************************     
00258 int32_t MAX30101::readFIFO(LedChannels_e numLeds, uint8_t *data, uint16_t &readBytes)
00259 {
00260     int32_t result = -1;
00261     
00262     readBytes = 0;
00263     
00264     //Get write pointer
00265     result = readRegister(FIFO_WritePointer, m_fifoWritePtr);
00266     if(result == 0)
00267     {
00268         //Get read pointer
00269         result = readRegister(FIFO_ReadPointer, m_fifoReadPtr);
00270         if(result == 0)
00271         {
00272             //Calculate num bytes to read
00273             if(m_fifoWritePtr > m_fifoReadPtr)
00274             {
00275                 m_fifoNumBytes = ((m_fifoWritePtr - m_fifoReadPtr) * 
00276                                   (BYTES_PER_CH * numLeds));
00277             }
00278             else
00279             {
00280                 m_fifoNumBytes = (((32 - m_fifoReadPtr) + m_fifoWritePtr) * 
00281                                    (BYTES_PER_CH * numLeds));
00282             }
00283             
00284             //temporary buffer for data
00285             char local_data[MAX30101::MAX_FIFO_BYTES];
00286             local_data[0] = FIFO_DataRegister;
00287             
00288             //Set fifo data ptr
00289             result = m_i2cBus.write(I2C_W_ADRS, local_data, 1, true);
00290             if(result == 0)
00291             {
00292                 //read fifo
00293                 result = m_i2cBus.read(I2C_R_ADRS, local_data,  m_fifoNumBytes);
00294                 if(result == 0)
00295                 {
00296                     //move data to user buffer
00297                     memcpy(data, local_data, m_fifoNumBytes);
00298                     readBytes = m_fifoNumBytes;
00299                 }
00300             }
00301         }
00302     }
00303     
00304     return result;
00305 }
00306 
00307 
00308 //*****************************************************************************
00309 int32_t MAX30101::writeRegister(Registers_e reg, uint8_t value)
00310 {
00311     char local_data[2] = {reg, value};
00312 
00313     return m_i2cBus.write(I2C_W_ADRS, local_data, 2);
00314 }
00315 
00316 
00317 //*****************************************************************************
00318 int32_t MAX30101::readRegister(Registers_e reg, uint8_t &value)
00319 {
00320     int32_t result;
00321     
00322     char local_data[2];
00323     local_data[0] = reg;
00324 
00325     result = m_i2cBus.write(I2C_W_ADRS, local_data, 1);
00326     if(result == 0) 
00327     {
00328         result = m_i2cBus.read(I2C_R_ADRS, (local_data + 1), 1);
00329         if (result == 0) 
00330         {
00331             value = local_data[1];
00332         }
00333     }
00334 
00335     return result;
00336 }
00337