Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
MAX30105.cpp
00001 /** \file max30105.cpp ****************************************************** 00002 * 00003 * Project: MAXREFDES117# 00004 * Filename: max30105.cpp 00005 * Description: This module is an embedded controller driver for the MAX30105 00006 * 00007 * ------------------------------------------------------------------------- */ 00008 /******************************************************************************* 00009 * Copyright (C) 2016 Maxim Integrated Products, Inc., All Rights Reserved. 00010 * 00011 * Permission is hereby granted, free of charge, to any person obtaining a 00012 * copy of this software and associated documentation files (the "Software"), 00013 * to deal in the Software without restriction, including without limitation 00014 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 00015 * and/or sell copies of the Software, and to permit persons to whom the 00016 * Software is furnished to do so, subject to the following conditions: 00017 * 00018 * The above copyright notice and this permission notice shall be included 00019 * in all copies or substantial portions of the Software. 00020 * 00021 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 00022 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 00023 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 00024 * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES 00025 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 00026 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 00027 * OTHER DEALINGS IN THE SOFTWARE. 00028 * 00029 * Except as contained in this notice, the name of Maxim Integrated 00030 * Products, Inc. shall not be used except as stated in the Maxim Integrated 00031 * Products, Inc. Branding Policy. 00032 * 00033 * The mere transfer of this software does not imply any licenses 00034 * of trade secrets, proprietary technology, copyrights, patents, 00035 * trademarks, maskwork rights, or any other form of intellectual 00036 * property whatsoever. Maxim Integrated Products, Inc. retains all 00037 * ownership rights. 00038 ******************************************************************************* 00039 */ 00040 #include "mbed.h" 00041 #include "MAX30105.h" 00042 00043 //****************************************************************************** 00044 MAX30105::MAX30105(I2C &i2c): _i2c(i2c) 00045 { 00046 } 00047 00048 //****************************************************************************** 00049 MAX30105::~MAX30105() 00050 { 00051 } 00052 00053 //****************************************************************************** 00054 int MAX30105::writeReg(registers_t reg, char value) 00055 { 00056 char cmdData[2] = { (char)reg, value }; 00057 00058 if (_i2c.write(MAX30105_I2C_ADDR, cmdData, sizeof(cmdData)) != 0) { 00059 return MAX30105_ERROR; 00060 } 00061 00062 return MAX30105_NO_ERROR; 00063 } 00064 00065 //****************************************************************************** 00066 int MAX30105::readReg(registers_t reg, char *value) 00067 { 00068 char cmdData[1] = { (char)reg }; 00069 00070 if (_i2c.write(MAX30105_I2C_ADDR, cmdData, sizeof(cmdData)) != 0) { 00071 return MAX30105_ERROR; 00072 } 00073 00074 if (_i2c.read(MAX30105_I2C_ADDR, value, 1) != 0) { 00075 return MAX30105_ERROR; 00076 } 00077 00078 return MAX30105_NO_ERROR; 00079 } 00080 00081 //****************************************************************************** 00082 int MAX30105::setSingleLED(smp_ave_t smpAve, 00083 bool fifoRollOver, 00084 fifo_a_full_t fifoAFull, 00085 adc_rge_t adcRange, 00086 smp_rt_t smpRate, 00087 led_pw_t ledPW, 00088 char led1PA) { 00089 char dataBuf[4]; 00090 _fifoConfiguration = (smpAve & MASK_SMP_AVE) | (fifoAFull & MASK_FIFO_A_FULL); 00091 if(fifoRollOver) _fifoConfiguration |= MASK_FIFO_ROLLOVER_EN; 00092 _modeConfiguration = (_modeConfiguration & MASK_SHDN) | MODE_1LED; 00093 _spo2Configuration = (adcRange & MASK_ADC_RGE) | (smpRate & MASK_SMP_RT) | (ledPW & MASK_LED_PW); 00094 _led1PulseAmplitude = led1PA; 00095 dataBuf[0] = REG_LED1_PA; 00096 dataBuf[1] = _led1PulseAmplitude; 00097 if (_i2c.write(MAX30105_I2C_ADDR, dataBuf, 2) != 0) return MAX30105_ERROR; 00098 dataBuf[0] = REG_FIFO_CONFIG; 00099 dataBuf[1] = _fifoConfiguration; 00100 dataBuf[2] = _modeConfiguration; 00101 dataBuf[3] = _spo2Configuration; 00102 if (_i2c.write(MAX30105_I2C_ADDR, dataBuf, 4) != 0) return MAX30105_ERROR; 00103 00104 return MAX30105_NO_ERROR; 00105 } 00106 00107 //****************************************************************************** 00108 int MAX30105::setDualLED(smp_ave_t smpAve, 00109 bool fifoRollOver, 00110 fifo_a_full_t fifoAFull, 00111 adc_rge_t adcRange, 00112 smp_rt_t smpRate, 00113 led_pw_t ledPW, 00114 char led1PA, 00115 char led2PA) { 00116 char dataBuf[4]; 00117 _fifoConfiguration = (smpAve & MASK_SMP_AVE) | (fifoAFull & MASK_FIFO_A_FULL); 00118 if(fifoRollOver) _fifoConfiguration |= MASK_FIFO_ROLLOVER_EN; 00119 _modeConfiguration = (_modeConfiguration & MASK_SHDN) | MODE_2LED; 00120 _spo2Configuration = (adcRange & MASK_ADC_RGE) | (smpRate & MASK_SMP_RT) | (ledPW & MASK_LED_PW); 00121 _led1PulseAmplitude = led1PA; 00122 _led2PulseAmplitude = led2PA; 00123 dataBuf[0] = REG_LED1_PA; 00124 dataBuf[1] = _led1PulseAmplitude; 00125 dataBuf[2] = _led2PulseAmplitude; 00126 if (_i2c.write(MAX30105_I2C_ADDR, dataBuf, 3) != 0) return MAX30105_ERROR; 00127 dataBuf[0] = REG_FIFO_CONFIG; 00128 dataBuf[1] = _fifoConfiguration; 00129 dataBuf[2] = _modeConfiguration; 00130 dataBuf[3] = _spo2Configuration; 00131 if (_i2c.write(MAX30105_I2C_ADDR, dataBuf, 4) != 0) return MAX30105_ERROR; 00132 00133 return MAX30105_NO_ERROR; 00134 } 00135 00136 //****************************************************************************** 00137 int MAX30105::setMultiLED(smp_ave_t smpAve, 00138 bool fifoRollOver, 00139 fifo_a_full_t fifoAFull, 00140 adc_rge_t adcRange, 00141 smp_rt_t smpRate, 00142 led_pw_t ledPW, 00143 char led1PA, 00144 char led2PA, 00145 char led3PA, 00146 char pilotPA, 00147 slot_t slot1, 00148 slot_t slot2, 00149 slot_t slot3, 00150 slot_t slot4) { 00151 char dataBuf[4]; 00152 _fifoConfiguration = (smpAve & MASK_SMP_AVE) | (fifoAFull & MASK_FIFO_A_FULL); 00153 if(fifoRollOver) _fifoConfiguration |= MASK_FIFO_ROLLOVER_EN; 00154 _modeConfiguration = (_modeConfiguration & MASK_SHDN) | MODE_MULTI; 00155 _spo2Configuration = (adcRange & MASK_ADC_RGE) | (smpRate & MASK_SMP_RT) | (ledPW & MASK_LED_PW); 00156 _led1PulseAmplitude = led1PA; 00157 _led2PulseAmplitude = led2PA; 00158 _led3PulseAmplitude = led3PA; 00159 _pilotPulseAmplitude = pilotPA; 00160 _multiLedControl1 = (slot2 << 4) | slot1; 00161 _multiLedControl2 = (slot4 << 4) | slot3; 00162 dataBuf[0] = REG_PILOT_PA; 00163 dataBuf[1] = _pilotPulseAmplitude; 00164 dataBuf[2] = _multiLedControl1; 00165 dataBuf[3] = _multiLedControl2; 00166 if (_i2c.write(MAX30105_I2C_ADDR, dataBuf, 4) != 0) return MAX30105_ERROR; 00167 dataBuf[0] = REG_LED1_PA; 00168 dataBuf[1] = _led1PulseAmplitude; 00169 dataBuf[2] = _led2PulseAmplitude; 00170 dataBuf[3] = _led3PulseAmplitude; 00171 if (_i2c.write(MAX30105_I2C_ADDR, dataBuf, 4) != 0) return MAX30105_ERROR; 00172 dataBuf[0] = REG_FIFO_CONFIG; 00173 dataBuf[1] = _fifoConfiguration; 00174 dataBuf[2] = _modeConfiguration; 00175 dataBuf[3] = _spo2Configuration; 00176 if (_i2c.write(MAX30105_I2C_ADDR, dataBuf, 4) != 0) return MAX30105_ERROR; 00177 00178 return MAX30105_NO_ERROR; 00179 } 00180 00181 //****************************************************************************** 00182 int MAX30105::init() 00183 { 00184 if(writeReg(REG_INTR_ENABLE_1,0xc0) != MAX30105_NO_ERROR) // INTR setting 00185 return MAX30105_ERROR; 00186 if(writeReg(REG_INTR_ENABLE_2,0x00) != MAX30105_NO_ERROR) 00187 return MAX30105_ERROR; 00188 if(writeReg(REG_FIFO_WR_PTR,0x00) != MAX30105_NO_ERROR) //FIFO_WR_PTR[4:0] 00189 return MAX30105_ERROR; 00190 if(writeReg(REG_OVF_COUNTER,0x00) != MAX30105_NO_ERROR) //OVF_COUNTER[4:0] 00191 return MAX30105_ERROR; 00192 if(writeReg(REG_FIFO_RD_PTR,0x00) != MAX30105_NO_ERROR) //FIFO_RD_PTR[4:0] 00193 return MAX30105_ERROR; 00194 if(writeReg(REG_FIFO_CONFIG,0x0f) != MAX30105_NO_ERROR) //sample avg = 1, fifo rollover=false, fifo almost full = 17 00195 return MAX30105_ERROR; 00196 if(writeReg(REG_MODE_CONFIG,0x03) != MAX30105_NO_ERROR) //0x02 for Red only, 0x03 for SpO2 mode 0x07 multimode LED 00197 return MAX30105_ERROR; 00198 if(writeReg(REG_SPO2_CONFIG,0x27) != MAX30105_NO_ERROR) // SPO2_ADC range = 4096nA, SPO2 sample rate (100 Hz), LED pulseWidth (400uS) 00199 return MAX30105_ERROR; 00200 if(writeReg(REG_LED1_PA,0x24) != MAX30105_NO_ERROR) //Choose value for ~ 7mA for LED1 00201 return MAX30105_ERROR; 00202 if(writeReg(REG_LED2_PA,0x24) != MAX30105_NO_ERROR) // Choose value for ~ 7mA for LED2 00203 return MAX30105_ERROR; 00204 if(writeReg(REG_PILOT_PA,0x7f) != MAX30105_NO_ERROR) // Choose value for ~ 25mA for Pilot LED 00205 return MAX30105_ERROR; 00206 return MAX30105_NO_ERROR; 00207 } 00208 00209 int MAX30105::readFIFO(uint32_t *redLED, uint32_t *irLED) 00210 { 00211 uint32_t un_temp; 00212 // char uch_temp; 00213 *redLED=0; 00214 *irLED=0; 00215 char ach_i2c_data[6]; 00216 00217 //read and clear status register 00218 //readReg(REG_INTR_STATUS_1, &uch_temp); 00219 //readReg(REG_INTR_STATUS_2, &uch_temp); 00220 00221 ach_i2c_data[0]=REG_FIFO_DATA; 00222 if(_i2c.write(MAX30105_I2C_ADDR, ach_i2c_data, 1, true)!=0) 00223 return MAX30105_ERROR; 00224 if(_i2c.read(MAX30105_I2C_ADDR, ach_i2c_data, 6, false)!=0) { 00225 return MAX30105_ERROR; 00226 } 00227 un_temp=(unsigned char) ach_i2c_data[0]; 00228 un_temp<<=16; 00229 *redLED+=un_temp; 00230 un_temp=(unsigned char) ach_i2c_data[1]; 00231 un_temp<<=8; 00232 *redLED+=un_temp; 00233 un_temp=(unsigned char) ach_i2c_data[2]; 00234 *redLED+=un_temp; 00235 00236 un_temp=(unsigned char) ach_i2c_data[3]; 00237 un_temp<<=16; 00238 *irLED+=un_temp; 00239 un_temp=(unsigned char) ach_i2c_data[4]; 00240 un_temp<<=8; 00241 *irLED+=un_temp; 00242 un_temp=(unsigned char) ach_i2c_data[5]; 00243 *irLED+=un_temp; 00244 *redLED&=0x03FFFF; //Mask MSB [23:18] 00245 *irLED&=0x03FFFF; //Mask MSB [23:18] 00246 00247 00248 return MAX30105_NO_ERROR; 00249 } 00250 00251 00252 //****************************************************************************** 00253 int MAX30105::getIntr1() 00254 { 00255 char * intStatus; 00256 if(readReg(REG_INTR_STATUS_1, intStatus) != MAX30105_NO_ERROR) return MAX30105_TEMP_ERROR; 00257 return (int)*intStatus; 00258 } 00259 00260 //****************************************************************************** 00261 int MAX30105::getIntr2() 00262 { 00263 char * intStatus; 00264 if(readReg(REG_INTR_STATUS_2, intStatus) != MAX30105_NO_ERROR) return MAX30105_TEMP_ERROR; 00265 return (int)*intStatus; 00266 } 00267 00268 //****************************************************************************** 00269 int MAX30105::enableIntr(char intrBits) 00270 { 00271 char intr1 = intrBits & (INTR_A_FULL|INTR_DATA_RDY|INTR_ALC_OVF|INTR_PROX); 00272 char intr2 = intrBits & INTR_TEMP_RDY; 00273 _interruptEnable1 |= intr1; 00274 if(writeReg(REG_INTR_ENABLE_1, _interruptEnable1) != MAX30105_NO_ERROR) return MAX30105_TEMP_ERROR; 00275 _interruptEnable2 |= intr2; 00276 if(writeReg(REG_INTR_ENABLE_2, _interruptEnable2) != MAX30105_NO_ERROR) return MAX30105_TEMP_ERROR; 00277 return MAX30105_NO_ERROR; 00278 } 00279 00280 //****************************************************************************** 00281 int MAX30105::disableIntr(char intrBits) 00282 { 00283 char intr1 = intrBits & (INTR_A_FULL|INTR_DATA_RDY|INTR_ALC_OVF|INTR_PROX); 00284 char intr2 = intrBits & INTR_TEMP_RDY; 00285 _interruptEnable1 &= ~intr1; 00286 if(writeReg(REG_INTR_ENABLE_1, _interruptEnable1) != MAX30105_NO_ERROR) return MAX30105_TEMP_ERROR; 00287 _interruptEnable2 &= ~intr2; 00288 if(writeReg(REG_INTR_ENABLE_2, _interruptEnable2) != MAX30105_NO_ERROR) return MAX30105_TEMP_ERROR; 00289 return MAX30105_NO_ERROR; 00290 } 00291 00292 //****************************************************************************** 00293 int MAX30105::setProx(char proxAmp, char proxThresh) 00294 { 00295 if(writeReg(REG_PILOT_PA, proxAmp) != MAX30105_NO_ERROR) return MAX30105_ERROR; 00296 if(writeReg(REG_PROX_INTR_THRESH, proxThresh) != MAX30105_NO_ERROR) return MAX30105_ERROR; 00297 return MAX30105_NO_ERROR; 00298 } 00299 00300 00301 //****************************************************************************** 00302 float MAX30105::readTemperature() 00303 { 00304 char dataBuf[2]; 00305 int8_t * dataSigned = reinterpret_cast<int8_t *>(dataBuf); 00306 00307 if(writeReg(REG_TEMP_CONFIG, 0x01) != MAX30105_NO_ERROR) return MAX30105_TEMP_ERROR; 00308 wait_ms(30); 00309 if(readReg(REG_TEMP_CONFIG, dataBuf) != MAX30105_NO_ERROR) return MAX30105_TEMP_ERROR; 00310 while (dataBuf[0]) { 00311 // Thread::wait(1); 00312 wait_ms(1); 00313 if(readReg(REG_TEMP_CONFIG, dataBuf) != MAX30105_NO_ERROR) return MAX30105_TEMP_ERROR; 00314 } 00315 dataBuf[0] = REG_TEMP_INT; 00316 if (_i2c.write(MAX30105_I2C_ADDR, dataBuf, 1) != 0) return MAX30105_TEMP_ERROR; 00317 if (_i2c.read(MAX30105_I2C_ADDR, dataBuf, 2) != 0) return MAX30105_TEMP_ERROR; 00318 return ((float)dataSigned[0] + ((float)dataSigned[1] * 0.0625)); 00319 } 00320 00321 //****************************************************************************** 00322 int MAX30105::shutDown() 00323 { 00324 _modeConfiguration |= MASK_SHDN; 00325 if(writeReg(REG_MODE_CONFIG, _modeConfiguration) != MAX30105_NO_ERROR) return MAX30105_ERROR; 00326 return MAX30105_NO_ERROR; 00327 } 00328 00329 //****************************************************************************** 00330 int MAX30105::wakeUp() 00331 { 00332 _modeConfiguration &= ~MASK_SHDN; 00333 if(writeReg(REG_MODE_CONFIG, _modeConfiguration) != MAX30105_NO_ERROR) return MAX30105_ERROR; 00334 return MAX30105_NO_ERROR; 00335 } 00336 00337 //****************************************************************************** 00338 int MAX30105::softReset() 00339 { 00340 if(writeReg(REG_MODE_CONFIG, MASK_RESET) != MAX30105_NO_ERROR) return MAX30105_ERROR; 00341 _interruptEnable1 = 0x00; 00342 _interruptEnable2 = 0x00; 00343 _fifoConfiguration = 0x00; 00344 _modeConfiguration = 0x00; 00345 _spo2Configuration = 0x00; 00346 _led1PulseAmplitude = 0x00; 00347 _led2PulseAmplitude = 0x00; 00348 _led3PulseAmplitude = 0x00; 00349 _pilotPulseAmplitude = 0x00; 00350 _multiLedControl1 = 0x00; 00351 _multiLedControl2 = 0x00; 00352 _proxIntThreshold = 0x00; 00353 return MAX30105_NO_ERROR; 00354 }
Generated on Wed Jul 13 2022 16:12:09 by
1.7.2