Library for MAX30101 SpO2 and heart rate sensor

Dependents:   HeartRate HeartRate proj final_project_ee119 ... more

Committer:
j3
Date:
Sat Sep 02 11:00:44 2017 -0700
Revision:
8:cc2dae00ce63
Parent:
7:ce122c27358e
Child:
10:85513b7480f5
fixed [Warning] MAX30101.cpp@282,43: variable length array 'local_data' is used [-Wvla]

Who changed what in which revision?

UserRevisionLine numberNew contents of line
j3 0:2d0c91de9279 1 /*******************************************************************************
j3 0:2d0c91de9279 2 * Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
j3 0:2d0c91de9279 3 *
j3 0:2d0c91de9279 4 * Permission is hereby granted, free of charge, to any person obtaining a
j3 0:2d0c91de9279 5 * copy of this software and associated documentation files (the "Software"),
j3 0:2d0c91de9279 6 * to deal in the Software without restriction, including without limitation
j3 0:2d0c91de9279 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
j3 0:2d0c91de9279 8 * and/or sell copies of the Software, and to permit persons to whom the
j3 0:2d0c91de9279 9 * Software is furnished to do so, subject to the following conditions:
j3 0:2d0c91de9279 10 *
j3 0:2d0c91de9279 11 * The above copyright notice and this permission notice shall be included
j3 0:2d0c91de9279 12 * in all copies or substantial portions of the Software.
j3 0:2d0c91de9279 13 *
j3 0:2d0c91de9279 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
j3 0:2d0c91de9279 15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
j3 0:2d0c91de9279 16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
j3 0:2d0c91de9279 17 * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
j3 0:2d0c91de9279 18 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
j3 0:2d0c91de9279 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
j3 0:2d0c91de9279 20 * OTHER DEALINGS IN THE SOFTWARE.
j3 0:2d0c91de9279 21 *
j3 0:2d0c91de9279 22 * Except as contained in this notice, the name of Maxim Integrated
j3 0:2d0c91de9279 23 * Products, Inc. shall not be used except as stated in the Maxim Integrated
j3 0:2d0c91de9279 24 * Products, Inc. Branding Policy.
j3 0:2d0c91de9279 25 *
j3 0:2d0c91de9279 26 * The mere transfer of this software does not imply any licenses
j3 0:2d0c91de9279 27 * of trade secrets, proprietary technology, copyrights, patents,
j3 0:2d0c91de9279 28 * trademarks, maskwork rights, or any other form of intellectual
j3 0:2d0c91de9279 29 * property whatsoever. Maxim Integrated Products, Inc. retains all
j3 0:2d0c91de9279 30 * ownership rights.
j3 0:2d0c91de9279 31 *******************************************************************************
j3 0:2d0c91de9279 32 */
j3 0:2d0c91de9279 33
j3 0:2d0c91de9279 34
j3 0:2d0c91de9279 35 #include "MAX30101.h"
j3 0:2d0c91de9279 36
j3 0:2d0c91de9279 37
j3 0:2d0c91de9279 38 //*****************************************************************************
j3 0:2d0c91de9279 39 MAX30101::MAX30101(I2C &i2c):
j3 0:2d0c91de9279 40 m_i2cBus(i2c)
j3 0:2d0c91de9279 41 {
j3 0:2d0c91de9279 42 //empty block
j3 0:2d0c91de9279 43 }
j3 0:2d0c91de9279 44
j3 0:2d0c91de9279 45
j3 0:2d0c91de9279 46 //*****************************************************************************
j3 0:2d0c91de9279 47 MAX30101::~MAX30101()
j3 0:2d0c91de9279 48 {
j3 0:2d0c91de9279 49 //empty block
j3 0:2d0c91de9279 50 }
j3 0:2d0c91de9279 51
j3 0:2d0c91de9279 52
j3 0:2d0c91de9279 53 //*****************************************************************************
j3 0:2d0c91de9279 54 int32_t MAX30101::enableInterrupts(const InterruptBitField_u data)
j3 0:2d0c91de9279 55 {
j3 0:2d0c91de9279 56 char cmdData[3] = {InterruptEnable1, (data.all & 0xF0), (data.all & 0x02)};
j3 0:2d0c91de9279 57
j3 0:2d0c91de9279 58 return m_i2cBus.write(I2C_W_ADRS, cmdData, 3);
j3 0:2d0c91de9279 59 }
j3 0:2d0c91de9279 60
j3 0:2d0c91de9279 61
j3 0:2d0c91de9279 62 //*****************************************************************************
j3 0:2d0c91de9279 63 int32_t MAX30101::getInterruptStatus(InterruptBitField_u &data)
j3 0:2d0c91de9279 64 {
j3 0:2d0c91de9279 65 char local_data[3];
j3 0:2d0c91de9279 66 local_data[0] = InterruptStatus1;
j3 0:2d0c91de9279 67
j3 0:2d0c91de9279 68 int32_t result = m_i2cBus.write(I2C_W_ADRS, local_data, 1);
j3 0:2d0c91de9279 69 if(result == 0)
j3 0:2d0c91de9279 70 {
j3 0:2d0c91de9279 71 result = m_i2cBus.read(I2C_R_ADRS, (local_data + 1), 2);
j3 0:2d0c91de9279 72 if(result == 0)
j3 0:2d0c91de9279 73 {
j3 0:2d0c91de9279 74 data.all = local_data[1] + local_data[2];
j3 0:2d0c91de9279 75 }
j3 0:2d0c91de9279 76 }
j3 0:2d0c91de9279 77
j3 0:2d0c91de9279 78 return result;
j3 0:2d0c91de9279 79 }
j3 0:2d0c91de9279 80
j3 0:2d0c91de9279 81
j3 0:2d0c91de9279 82 //*****************************************************************************
j3 1:9e2a3b4a24c7 83 int32_t MAX30101::setFIFOConfiguration(const FIFO_Configuration_u config)
j3 1:9e2a3b4a24c7 84 {
j3 2:0db1f3bec727 85 return writeRegister(FIFO_Configuration, config.all);
j3 1:9e2a3b4a24c7 86 }
j3 1:9e2a3b4a24c7 87
j3 1:9e2a3b4a24c7 88
j3 1:9e2a3b4a24c7 89 //*****************************************************************************
j3 1:9e2a3b4a24c7 90 int32_t MAX30101::getFIFOConfiguration(FIFO_Configuration_u &config)
j3 1:9e2a3b4a24c7 91 {
j3 2:0db1f3bec727 92 return readRegister(FIFO_Configuration, config.all);
j3 1:9e2a3b4a24c7 93 }
j3 1:9e2a3b4a24c7 94
j3 1:9e2a3b4a24c7 95
j3 1:9e2a3b4a24c7 96 //*****************************************************************************
j3 1:9e2a3b4a24c7 97 int32_t MAX30101::setModeConfiguration(const ModeConfiguration_u config)
j3 1:9e2a3b4a24c7 98 {
j3 2:0db1f3bec727 99 return writeRegister(ModeConfiguration, (config.all & 0xC7));
j3 1:9e2a3b4a24c7 100 }
j3 1:9e2a3b4a24c7 101
j3 1:9e2a3b4a24c7 102
j3 1:9e2a3b4a24c7 103 //*****************************************************************************
j3 1:9e2a3b4a24c7 104 int32_t MAX30101::getModeConfiguration(ModeConfiguration_u &config)
j3 1:9e2a3b4a24c7 105 {
j3 2:0db1f3bec727 106 return readRegister(ModeConfiguration, config.all);
j3 1:9e2a3b4a24c7 107 }
j3 1:9e2a3b4a24c7 108
j3 1:9e2a3b4a24c7 109
j3 1:9e2a3b4a24c7 110 //*****************************************************************************
j3 1:9e2a3b4a24c7 111 int32_t MAX30101::setSpO2Configuration(const SpO2Configuration_u config)
j3 1:9e2a3b4a24c7 112 {
j3 2:0db1f3bec727 113 return writeRegister(SpO2Configuration, (config.all & 0x7F));
j3 1:9e2a3b4a24c7 114 }
j3 1:9e2a3b4a24c7 115
j3 1:9e2a3b4a24c7 116
j3 1:9e2a3b4a24c7 117 //*****************************************************************************
j3 1:9e2a3b4a24c7 118 int32_t MAX30101::getSpO2Configuration(SpO2Configuration_u &config)
j3 1:9e2a3b4a24c7 119 {
j3 2:0db1f3bec727 120 return readRegister(SpO2Configuration, config.all);
j3 1:9e2a3b4a24c7 121 }
j3 1:9e2a3b4a24c7 122
j3 1:9e2a3b4a24c7 123
j3 1:9e2a3b4a24c7 124 //*****************************************************************************
j3 1:9e2a3b4a24c7 125 int32_t MAX30101::setLEDPulseAmplitude(Registers_e reg, const uint8_t amp)
j3 1:9e2a3b4a24c7 126 {
j3 2:0db1f3bec727 127 return writeRegister(reg, amp);
j3 1:9e2a3b4a24c7 128 }
j3 1:9e2a3b4a24c7 129
j3 1:9e2a3b4a24c7 130
j3 1:9e2a3b4a24c7 131 //*****************************************************************************
j3 1:9e2a3b4a24c7 132 int32_t MAX30101::getLEDPulseAmplitude(Registers_e reg, uint8_t &amp)
j3 1:9e2a3b4a24c7 133 {
j3 2:0db1f3bec727 134 return readRegister(reg, amp);
j3 1:9e2a3b4a24c7 135 }
j3 1:9e2a3b4a24c7 136
j3 1:9e2a3b4a24c7 137
j3 1:9e2a3b4a24c7 138 //*****************************************************************************
j3 1:9e2a3b4a24c7 139 int32_t MAX30101::setMultiLEDModeControl(Registers_e reg, const ModeControlReg_u data)
j3 1:9e2a3b4a24c7 140 {
j3 2:0db1f3bec727 141 return writeRegister(reg, data.all);
j3 1:9e2a3b4a24c7 142 }
j3 1:9e2a3b4a24c7 143
j3 1:9e2a3b4a24c7 144
j3 1:9e2a3b4a24c7 145 //*****************************************************************************
j3 1:9e2a3b4a24c7 146 int32_t MAX30101::getMultiLEDModeControl(Registers_e reg, ModeControlReg_u &data)
j3 1:9e2a3b4a24c7 147 {
j3 2:0db1f3bec727 148 return readRegister(reg, data.all);
j3 1:9e2a3b4a24c7 149 }
j3 1:9e2a3b4a24c7 150
j3 1:9e2a3b4a24c7 151
j3 1:9e2a3b4a24c7 152 //*****************************************************************************
j3 1:9e2a3b4a24c7 153 int32_t MAX30101::getDieTemperature(uint16_t &data)
j3 1:9e2a3b4a24c7 154 {
j3 2:0db1f3bec727 155 int32_t result = -1;
j3 2:0db1f3bec727 156
j3 2:0db1f3bec727 157 //Die temp conversion time is 30ms
j3 2:0db1f3bec727 158 //ATTEMPTS > than 30ms at 100KHz SCL for getInterruptStatus call
j3 2:0db1f3bec727 159 const uint32_t ATTEMPTS = 100;
j3 2:0db1f3bec727 160 uint32_t num_reads = 0;
j3 2:0db1f3bec727 161
j3 2:0db1f3bec727 162 //local i2c transaction buffer
j3 2:0db1f3bec727 163 char local_data[2];
j3 2:0db1f3bec727 164 local_data[0] = DieTempConfig;
j3 2:0db1f3bec727 165 local_data[1] = 1;
j3 2:0db1f3bec727 166
j3 2:0db1f3bec727 167 //initiate die temp conversion
j3 2:0db1f3bec727 168 result = m_i2cBus.write(I2C_W_ADRS, local_data, 2, true);
j3 2:0db1f3bec727 169 if(result == 0)
j3 2:0db1f3bec727 170 {
j3 2:0db1f3bec727 171 //object for holding status registers data
j3 2:0db1f3bec727 172 InterruptBitField_u status;
j3 2:0db1f3bec727 173 status.all = 0;
j3 2:0db1f3bec727 174
j3 2:0db1f3bec727 175 //poll status registers until temp ready, or read fails
j3 2:0db1f3bec727 176 do
j3 2:0db1f3bec727 177 {
j3 2:0db1f3bec727 178 result = getInterruptStatus(status);
j3 2:0db1f3bec727 179 num_reads++;
j3 2:0db1f3bec727 180 }
j3 2:0db1f3bec727 181 while(!status.bits.die_temp && (result == 0) && (num_reads < ATTEMPTS));
j3 2:0db1f3bec727 182
j3 2:0db1f3bec727 183 if(status.bits.die_temp)
j3 2:0db1f3bec727 184 {
j3 2:0db1f3bec727 185 //set pointer to temperature integer register
j3 2:0db1f3bec727 186 local_data[0] = DieTempInt;
j3 2:0db1f3bec727 187 result = m_i2cBus.write(I2C_W_ADRS, local_data, 1, true);
j3 2:0db1f3bec727 188 if(result == 0)
j3 2:0db1f3bec727 189 {
j3 2:0db1f3bec727 190 //read two bytes
j3 2:0db1f3bec727 191 result = m_i2cBus.read(I2C_R_ADRS, local_data, 2);
j3 2:0db1f3bec727 192 if(result == 0)
j3 2:0db1f3bec727 193 {
j3 2:0db1f3bec727 194 //stuff data
j3 2:0db1f3bec727 195 data = ( (local_data[0] << 8) | (local_data[1] << 4) );
j3 2:0db1f3bec727 196 data = (data >> 4);
j3 2:0db1f3bec727 197 }
j3 2:0db1f3bec727 198 }
j3 2:0db1f3bec727 199 }
j3 2:0db1f3bec727 200 else
j3 2:0db1f3bec727 201 {
j3 2:0db1f3bec727 202 //if result equals 0 because num_reads exceeded ATTEMPTS,
j3 2:0db1f3bec727 203 //change result to -1. Otherwise keep result's error code.
j3 2:0db1f3bec727 204 result = (result == 0) ? -1 : result;
j3 2:0db1f3bec727 205 }
j3 2:0db1f3bec727 206 }
j3 2:0db1f3bec727 207 return result;
j3 1:9e2a3b4a24c7 208 }
j3 1:9e2a3b4a24c7 209
j3 1:9e2a3b4a24c7 210
j3 1:9e2a3b4a24c7 211 //*****************************************************************************
j3 1:9e2a3b4a24c7 212 int32_t MAX30101::getDieTemperatureC(float &data)
j3 1:9e2a3b4a24c7 213 {
j3 2:0db1f3bec727 214 uint16_t raw_temp;
j3 2:0db1f3bec727 215
j3 2:0db1f3bec727 216 int32_t result = getDieTemperature(raw_temp);
j3 2:0db1f3bec727 217 if(result == 0)
j3 2:0db1f3bec727 218 {
j3 2:0db1f3bec727 219 if(raw_temp & 0x0800)
j3 2:0db1f3bec727 220 {
j3 2:0db1f3bec727 221 data = ((0xFFFFF000 | raw_temp)/16.0F);
j3 2:0db1f3bec727 222 }
j3 2:0db1f3bec727 223 else
j3 2:0db1f3bec727 224 {
j3 2:0db1f3bec727 225 data = (raw_temp/16.0F);
j3 2:0db1f3bec727 226 }
j3 2:0db1f3bec727 227 }
j3 2:0db1f3bec727 228
j3 2:0db1f3bec727 229 return result;
j3 1:9e2a3b4a24c7 230 }
j3 1:9e2a3b4a24c7 231
j3 1:9e2a3b4a24c7 232
j3 1:9e2a3b4a24c7 233 //*****************************************************************************
j3 1:9e2a3b4a24c7 234 float MAX30101::celsius2fahrenheit(float c)
j3 1:9e2a3b4a24c7 235 {
j3 2:0db1f3bec727 236 return ((1.8F * c) + 32.0F);
j3 1:9e2a3b4a24c7 237 }
j3 1:9e2a3b4a24c7 238
j3 1:9e2a3b4a24c7 239
j3 1:9e2a3b4a24c7 240 //*****************************************************************************
j3 1:9e2a3b4a24c7 241 int32_t MAX30101::setProxIntThreshold(const uint8_t data)
j3 1:9e2a3b4a24c7 242 {
j3 2:0db1f3bec727 243 return writeRegister(ProxIntThreshold, data);
j3 1:9e2a3b4a24c7 244 }
j3 1:9e2a3b4a24c7 245
j3 1:9e2a3b4a24c7 246
j3 1:9e2a3b4a24c7 247 //*****************************************************************************
j3 1:9e2a3b4a24c7 248 int32_t MAX30101::getProxIntThreshold(uint8_t &data)
j3 1:9e2a3b4a24c7 249 {
j3 2:0db1f3bec727 250 return readRegister(ProxIntThreshold, data);
j3 1:9e2a3b4a24c7 251 }
j3 1:9e2a3b4a24c7 252
j3 1:9e2a3b4a24c7 253
j3 3:a2effad05c99 254 //*****************************************************************************
j3 5:be1dde31fe49 255 int32_t MAX30101::readFIFO(LedChannels_e numLeds, uint8_t *data, uint16_t &readBytes)
j3 3:a2effad05c99 256 {
j3 3:a2effad05c99 257 int32_t result = -1;
j3 3:a2effad05c99 258
j3 3:a2effad05c99 259 readBytes = 0;
j3 3:a2effad05c99 260
j3 5:be1dde31fe49 261 //Get write pointer
j3 5:be1dde31fe49 262 result = readRegister(FIFO_WritePointer, m_fifoWritePtr);
j3 5:be1dde31fe49 263 if(result == 0)
j3 3:a2effad05c99 264 {
j3 5:be1dde31fe49 265 //Get read pointer
j3 5:be1dde31fe49 266 result = readRegister(FIFO_ReadPointer, m_fifoReadPtr);
j3 3:a2effad05c99 267 if(result == 0)
j3 3:a2effad05c99 268 {
j3 5:be1dde31fe49 269 //Calculate num bytes to read
j3 5:be1dde31fe49 270 if(m_fifoWritePtr > m_fifoReadPtr)
j3 5:be1dde31fe49 271 {
j3 5:be1dde31fe49 272 m_fifoNumBytes = ((m_fifoWritePtr - m_fifoReadPtr) *
j3 5:be1dde31fe49 273 (BYTES_PER_CH * numLeds));
j3 5:be1dde31fe49 274 }
j3 5:be1dde31fe49 275 else
j3 5:be1dde31fe49 276 {
j3 5:be1dde31fe49 277 m_fifoNumBytes = (((32 - m_fifoReadPtr) + m_fifoWritePtr) *
j3 5:be1dde31fe49 278 (BYTES_PER_CH * numLeds));
j3 5:be1dde31fe49 279 }
j3 5:be1dde31fe49 280
j3 5:be1dde31fe49 281 //temporary buffer for data
j3 8:cc2dae00ce63 282 char local_data[MAX30101::MAX_FIFO_BYTES];
j3 5:be1dde31fe49 283 local_data[0] = FIFO_DataRegister;
j3 5:be1dde31fe49 284
j3 5:be1dde31fe49 285 //Set fifo data ptr
j3 5:be1dde31fe49 286 result = m_i2cBus.write(I2C_W_ADRS, local_data, 1, true);
j3 3:a2effad05c99 287 if(result == 0)
j3 3:a2effad05c99 288 {
j3 5:be1dde31fe49 289 //read fifo
j3 5:be1dde31fe49 290 result = m_i2cBus.read(I2C_R_ADRS, local_data, m_fifoNumBytes);
j3 3:a2effad05c99 291 if(result == 0)
j3 3:a2effad05c99 292 {
j3 5:be1dde31fe49 293 //move data to user buffer
j3 5:be1dde31fe49 294 memcpy(data, local_data, m_fifoNumBytes);
j3 5:be1dde31fe49 295 readBytes = m_fifoNumBytes;
j3 3:a2effad05c99 296 }
j3 3:a2effad05c99 297 }
j3 3:a2effad05c99 298 }
j3 3:a2effad05c99 299 }
j3 3:a2effad05c99 300
j3 3:a2effad05c99 301 return result;
j3 3:a2effad05c99 302 }
j3 3:a2effad05c99 303
j3 3:a2effad05c99 304
j3 1:9e2a3b4a24c7 305 //*****************************************************************************
j3 0:2d0c91de9279 306 int32_t MAX30101::writeRegister(Registers_e reg, uint8_t value)
j3 0:2d0c91de9279 307 {
j3 0:2d0c91de9279 308 char local_data[2] = {reg, value};
j3 0:2d0c91de9279 309
j3 0:2d0c91de9279 310 return m_i2cBus.write(I2C_W_ADRS, local_data, 2);
j3 0:2d0c91de9279 311 }
j3 0:2d0c91de9279 312
j3 0:2d0c91de9279 313
j3 0:2d0c91de9279 314 //*****************************************************************************
j3 0:2d0c91de9279 315 int32_t MAX30101::readRegister(Registers_e reg, uint8_t &value)
j3 0:2d0c91de9279 316 {
j3 0:2d0c91de9279 317 int32_t result;
j3 0:2d0c91de9279 318
j3 0:2d0c91de9279 319 char local_data[2];
j3 0:2d0c91de9279 320 local_data[0] = reg;
j3 0:2d0c91de9279 321
j3 0:2d0c91de9279 322 result = m_i2cBus.write(I2C_W_ADRS, local_data, 1);
j3 0:2d0c91de9279 323 if(result == 0)
j3 0:2d0c91de9279 324 {
j3 0:2d0c91de9279 325 result = m_i2cBus.read(I2C_R_ADRS, (local_data + 1), 1);
j3 0:2d0c91de9279 326 if (result == 0)
j3 0:2d0c91de9279 327 {
j3 0:2d0c91de9279 328 value = local_data[1];
j3 0:2d0c91de9279 329 }
j3 0:2d0c91de9279 330 }
j3 0:2d0c91de9279 331
j3 0:2d0c91de9279 332 return result;
j3 0:2d0c91de9279 333 }
j3 0:2d0c91de9279 334