Library for MAX30101 SpO2 and heart rate sensor

Dependents:   HeartRate HeartRate proj final_project_ee119 ... more

Committer:
j3
Date:
Sat Sep 02 11:57:40 2017 -0700
Revision:
10:85513b7480f5
Parent:
8:cc2dae00ce63
Fixed [Warning] MAX30101.cpp@56,52: narrowing conversion of '(((int)data.MAX30101::InterruptBitField_u::all) & 240)' from 'int' to 'char' inside { } is ill-formed in C++11 [-Wnarrowing]

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 10:85513b7480f5 56 char cmdData[3];
j3 10:85513b7480f5 57 cmdData[0] = InterruptEnable1;
j3 10:85513b7480f5 58 cmdData[1] = (data.all & 0xF0);
j3 10:85513b7480f5 59 cmdData[2] = (data.all & 0x02);
j3 10:85513b7480f5 60
j3 0:2d0c91de9279 61 return m_i2cBus.write(I2C_W_ADRS, cmdData, 3);
j3 0:2d0c91de9279 62 }
j3 0:2d0c91de9279 63
j3 0:2d0c91de9279 64
j3 0:2d0c91de9279 65 //*****************************************************************************
j3 0:2d0c91de9279 66 int32_t MAX30101::getInterruptStatus(InterruptBitField_u &data)
j3 0:2d0c91de9279 67 {
j3 0:2d0c91de9279 68 char local_data[3];
j3 0:2d0c91de9279 69 local_data[0] = InterruptStatus1;
j3 0:2d0c91de9279 70
j3 0:2d0c91de9279 71 int32_t result = m_i2cBus.write(I2C_W_ADRS, local_data, 1);
j3 0:2d0c91de9279 72 if(result == 0)
j3 0:2d0c91de9279 73 {
j3 0:2d0c91de9279 74 result = m_i2cBus.read(I2C_R_ADRS, (local_data + 1), 2);
j3 0:2d0c91de9279 75 if(result == 0)
j3 0:2d0c91de9279 76 {
j3 0:2d0c91de9279 77 data.all = local_data[1] + local_data[2];
j3 0:2d0c91de9279 78 }
j3 0:2d0c91de9279 79 }
j3 0:2d0c91de9279 80
j3 0:2d0c91de9279 81 return result;
j3 0:2d0c91de9279 82 }
j3 0:2d0c91de9279 83
j3 0:2d0c91de9279 84
j3 0:2d0c91de9279 85 //*****************************************************************************
j3 1:9e2a3b4a24c7 86 int32_t MAX30101::setFIFOConfiguration(const FIFO_Configuration_u config)
j3 1:9e2a3b4a24c7 87 {
j3 2:0db1f3bec727 88 return writeRegister(FIFO_Configuration, config.all);
j3 1:9e2a3b4a24c7 89 }
j3 1:9e2a3b4a24c7 90
j3 1:9e2a3b4a24c7 91
j3 1:9e2a3b4a24c7 92 //*****************************************************************************
j3 1:9e2a3b4a24c7 93 int32_t MAX30101::getFIFOConfiguration(FIFO_Configuration_u &config)
j3 1:9e2a3b4a24c7 94 {
j3 2:0db1f3bec727 95 return readRegister(FIFO_Configuration, config.all);
j3 1:9e2a3b4a24c7 96 }
j3 1:9e2a3b4a24c7 97
j3 1:9e2a3b4a24c7 98
j3 1:9e2a3b4a24c7 99 //*****************************************************************************
j3 1:9e2a3b4a24c7 100 int32_t MAX30101::setModeConfiguration(const ModeConfiguration_u config)
j3 1:9e2a3b4a24c7 101 {
j3 2:0db1f3bec727 102 return writeRegister(ModeConfiguration, (config.all & 0xC7));
j3 1:9e2a3b4a24c7 103 }
j3 1:9e2a3b4a24c7 104
j3 1:9e2a3b4a24c7 105
j3 1:9e2a3b4a24c7 106 //*****************************************************************************
j3 1:9e2a3b4a24c7 107 int32_t MAX30101::getModeConfiguration(ModeConfiguration_u &config)
j3 1:9e2a3b4a24c7 108 {
j3 2:0db1f3bec727 109 return readRegister(ModeConfiguration, config.all);
j3 1:9e2a3b4a24c7 110 }
j3 1:9e2a3b4a24c7 111
j3 1:9e2a3b4a24c7 112
j3 1:9e2a3b4a24c7 113 //*****************************************************************************
j3 1:9e2a3b4a24c7 114 int32_t MAX30101::setSpO2Configuration(const SpO2Configuration_u config)
j3 1:9e2a3b4a24c7 115 {
j3 2:0db1f3bec727 116 return writeRegister(SpO2Configuration, (config.all & 0x7F));
j3 1:9e2a3b4a24c7 117 }
j3 1:9e2a3b4a24c7 118
j3 1:9e2a3b4a24c7 119
j3 1:9e2a3b4a24c7 120 //*****************************************************************************
j3 1:9e2a3b4a24c7 121 int32_t MAX30101::getSpO2Configuration(SpO2Configuration_u &config)
j3 1:9e2a3b4a24c7 122 {
j3 2:0db1f3bec727 123 return readRegister(SpO2Configuration, config.all);
j3 1:9e2a3b4a24c7 124 }
j3 1:9e2a3b4a24c7 125
j3 1:9e2a3b4a24c7 126
j3 1:9e2a3b4a24c7 127 //*****************************************************************************
j3 1:9e2a3b4a24c7 128 int32_t MAX30101::setLEDPulseAmplitude(Registers_e reg, const uint8_t amp)
j3 1:9e2a3b4a24c7 129 {
j3 2:0db1f3bec727 130 return writeRegister(reg, amp);
j3 1:9e2a3b4a24c7 131 }
j3 1:9e2a3b4a24c7 132
j3 1:9e2a3b4a24c7 133
j3 1:9e2a3b4a24c7 134 //*****************************************************************************
j3 1:9e2a3b4a24c7 135 int32_t MAX30101::getLEDPulseAmplitude(Registers_e reg, uint8_t &amp)
j3 1:9e2a3b4a24c7 136 {
j3 2:0db1f3bec727 137 return readRegister(reg, amp);
j3 1:9e2a3b4a24c7 138 }
j3 1:9e2a3b4a24c7 139
j3 1:9e2a3b4a24c7 140
j3 1:9e2a3b4a24c7 141 //*****************************************************************************
j3 1:9e2a3b4a24c7 142 int32_t MAX30101::setMultiLEDModeControl(Registers_e reg, const ModeControlReg_u data)
j3 1:9e2a3b4a24c7 143 {
j3 2:0db1f3bec727 144 return writeRegister(reg, data.all);
j3 1:9e2a3b4a24c7 145 }
j3 1:9e2a3b4a24c7 146
j3 1:9e2a3b4a24c7 147
j3 1:9e2a3b4a24c7 148 //*****************************************************************************
j3 1:9e2a3b4a24c7 149 int32_t MAX30101::getMultiLEDModeControl(Registers_e reg, ModeControlReg_u &data)
j3 1:9e2a3b4a24c7 150 {
j3 2:0db1f3bec727 151 return readRegister(reg, data.all);
j3 1:9e2a3b4a24c7 152 }
j3 1:9e2a3b4a24c7 153
j3 1:9e2a3b4a24c7 154
j3 1:9e2a3b4a24c7 155 //*****************************************************************************
j3 1:9e2a3b4a24c7 156 int32_t MAX30101::getDieTemperature(uint16_t &data)
j3 1:9e2a3b4a24c7 157 {
j3 2:0db1f3bec727 158 int32_t result = -1;
j3 2:0db1f3bec727 159
j3 2:0db1f3bec727 160 //Die temp conversion time is 30ms
j3 2:0db1f3bec727 161 //ATTEMPTS > than 30ms at 100KHz SCL for getInterruptStatus call
j3 2:0db1f3bec727 162 const uint32_t ATTEMPTS = 100;
j3 2:0db1f3bec727 163 uint32_t num_reads = 0;
j3 2:0db1f3bec727 164
j3 2:0db1f3bec727 165 //local i2c transaction buffer
j3 2:0db1f3bec727 166 char local_data[2];
j3 2:0db1f3bec727 167 local_data[0] = DieTempConfig;
j3 2:0db1f3bec727 168 local_data[1] = 1;
j3 2:0db1f3bec727 169
j3 2:0db1f3bec727 170 //initiate die temp conversion
j3 2:0db1f3bec727 171 result = m_i2cBus.write(I2C_W_ADRS, local_data, 2, true);
j3 2:0db1f3bec727 172 if(result == 0)
j3 2:0db1f3bec727 173 {
j3 2:0db1f3bec727 174 //object for holding status registers data
j3 2:0db1f3bec727 175 InterruptBitField_u status;
j3 2:0db1f3bec727 176 status.all = 0;
j3 2:0db1f3bec727 177
j3 2:0db1f3bec727 178 //poll status registers until temp ready, or read fails
j3 2:0db1f3bec727 179 do
j3 2:0db1f3bec727 180 {
j3 2:0db1f3bec727 181 result = getInterruptStatus(status);
j3 2:0db1f3bec727 182 num_reads++;
j3 2:0db1f3bec727 183 }
j3 2:0db1f3bec727 184 while(!status.bits.die_temp && (result == 0) && (num_reads < ATTEMPTS));
j3 2:0db1f3bec727 185
j3 2:0db1f3bec727 186 if(status.bits.die_temp)
j3 2:0db1f3bec727 187 {
j3 2:0db1f3bec727 188 //set pointer to temperature integer register
j3 2:0db1f3bec727 189 local_data[0] = DieTempInt;
j3 2:0db1f3bec727 190 result = m_i2cBus.write(I2C_W_ADRS, local_data, 1, true);
j3 2:0db1f3bec727 191 if(result == 0)
j3 2:0db1f3bec727 192 {
j3 2:0db1f3bec727 193 //read two bytes
j3 2:0db1f3bec727 194 result = m_i2cBus.read(I2C_R_ADRS, local_data, 2);
j3 2:0db1f3bec727 195 if(result == 0)
j3 2:0db1f3bec727 196 {
j3 2:0db1f3bec727 197 //stuff data
j3 2:0db1f3bec727 198 data = ( (local_data[0] << 8) | (local_data[1] << 4) );
j3 2:0db1f3bec727 199 data = (data >> 4);
j3 2:0db1f3bec727 200 }
j3 2:0db1f3bec727 201 }
j3 2:0db1f3bec727 202 }
j3 2:0db1f3bec727 203 else
j3 2:0db1f3bec727 204 {
j3 2:0db1f3bec727 205 //if result equals 0 because num_reads exceeded ATTEMPTS,
j3 2:0db1f3bec727 206 //change result to -1. Otherwise keep result's error code.
j3 2:0db1f3bec727 207 result = (result == 0) ? -1 : result;
j3 2:0db1f3bec727 208 }
j3 2:0db1f3bec727 209 }
j3 2:0db1f3bec727 210 return result;
j3 1:9e2a3b4a24c7 211 }
j3 1:9e2a3b4a24c7 212
j3 1:9e2a3b4a24c7 213
j3 1:9e2a3b4a24c7 214 //*****************************************************************************
j3 1:9e2a3b4a24c7 215 int32_t MAX30101::getDieTemperatureC(float &data)
j3 1:9e2a3b4a24c7 216 {
j3 2:0db1f3bec727 217 uint16_t raw_temp;
j3 2:0db1f3bec727 218
j3 2:0db1f3bec727 219 int32_t result = getDieTemperature(raw_temp);
j3 2:0db1f3bec727 220 if(result == 0)
j3 2:0db1f3bec727 221 {
j3 2:0db1f3bec727 222 if(raw_temp & 0x0800)
j3 2:0db1f3bec727 223 {
j3 2:0db1f3bec727 224 data = ((0xFFFFF000 | raw_temp)/16.0F);
j3 2:0db1f3bec727 225 }
j3 2:0db1f3bec727 226 else
j3 2:0db1f3bec727 227 {
j3 2:0db1f3bec727 228 data = (raw_temp/16.0F);
j3 2:0db1f3bec727 229 }
j3 2:0db1f3bec727 230 }
j3 2:0db1f3bec727 231
j3 2:0db1f3bec727 232 return result;
j3 1:9e2a3b4a24c7 233 }
j3 1:9e2a3b4a24c7 234
j3 1:9e2a3b4a24c7 235
j3 1:9e2a3b4a24c7 236 //*****************************************************************************
j3 1:9e2a3b4a24c7 237 float MAX30101::celsius2fahrenheit(float c)
j3 1:9e2a3b4a24c7 238 {
j3 2:0db1f3bec727 239 return ((1.8F * c) + 32.0F);
j3 1:9e2a3b4a24c7 240 }
j3 1:9e2a3b4a24c7 241
j3 1:9e2a3b4a24c7 242
j3 1:9e2a3b4a24c7 243 //*****************************************************************************
j3 1:9e2a3b4a24c7 244 int32_t MAX30101::setProxIntThreshold(const uint8_t data)
j3 1:9e2a3b4a24c7 245 {
j3 2:0db1f3bec727 246 return writeRegister(ProxIntThreshold, data);
j3 1:9e2a3b4a24c7 247 }
j3 1:9e2a3b4a24c7 248
j3 1:9e2a3b4a24c7 249
j3 1:9e2a3b4a24c7 250 //*****************************************************************************
j3 1:9e2a3b4a24c7 251 int32_t MAX30101::getProxIntThreshold(uint8_t &data)
j3 1:9e2a3b4a24c7 252 {
j3 2:0db1f3bec727 253 return readRegister(ProxIntThreshold, data);
j3 1:9e2a3b4a24c7 254 }
j3 1:9e2a3b4a24c7 255
j3 1:9e2a3b4a24c7 256
j3 3:a2effad05c99 257 //*****************************************************************************
j3 5:be1dde31fe49 258 int32_t MAX30101::readFIFO(LedChannels_e numLeds, uint8_t *data, uint16_t &readBytes)
j3 3:a2effad05c99 259 {
j3 3:a2effad05c99 260 int32_t result = -1;
j3 3:a2effad05c99 261
j3 3:a2effad05c99 262 readBytes = 0;
j3 3:a2effad05c99 263
j3 5:be1dde31fe49 264 //Get write pointer
j3 5:be1dde31fe49 265 result = readRegister(FIFO_WritePointer, m_fifoWritePtr);
j3 5:be1dde31fe49 266 if(result == 0)
j3 3:a2effad05c99 267 {
j3 5:be1dde31fe49 268 //Get read pointer
j3 5:be1dde31fe49 269 result = readRegister(FIFO_ReadPointer, m_fifoReadPtr);
j3 3:a2effad05c99 270 if(result == 0)
j3 3:a2effad05c99 271 {
j3 5:be1dde31fe49 272 //Calculate num bytes to read
j3 5:be1dde31fe49 273 if(m_fifoWritePtr > m_fifoReadPtr)
j3 5:be1dde31fe49 274 {
j3 5:be1dde31fe49 275 m_fifoNumBytes = ((m_fifoWritePtr - m_fifoReadPtr) *
j3 5:be1dde31fe49 276 (BYTES_PER_CH * numLeds));
j3 5:be1dde31fe49 277 }
j3 5:be1dde31fe49 278 else
j3 5:be1dde31fe49 279 {
j3 5:be1dde31fe49 280 m_fifoNumBytes = (((32 - m_fifoReadPtr) + m_fifoWritePtr) *
j3 5:be1dde31fe49 281 (BYTES_PER_CH * numLeds));
j3 5:be1dde31fe49 282 }
j3 5:be1dde31fe49 283
j3 5:be1dde31fe49 284 //temporary buffer for data
j3 8:cc2dae00ce63 285 char local_data[MAX30101::MAX_FIFO_BYTES];
j3 5:be1dde31fe49 286 local_data[0] = FIFO_DataRegister;
j3 5:be1dde31fe49 287
j3 5:be1dde31fe49 288 //Set fifo data ptr
j3 5:be1dde31fe49 289 result = m_i2cBus.write(I2C_W_ADRS, local_data, 1, true);
j3 3:a2effad05c99 290 if(result == 0)
j3 3:a2effad05c99 291 {
j3 5:be1dde31fe49 292 //read fifo
j3 5:be1dde31fe49 293 result = m_i2cBus.read(I2C_R_ADRS, local_data, m_fifoNumBytes);
j3 3:a2effad05c99 294 if(result == 0)
j3 3:a2effad05c99 295 {
j3 5:be1dde31fe49 296 //move data to user buffer
j3 5:be1dde31fe49 297 memcpy(data, local_data, m_fifoNumBytes);
j3 5:be1dde31fe49 298 readBytes = m_fifoNumBytes;
j3 3:a2effad05c99 299 }
j3 3:a2effad05c99 300 }
j3 3:a2effad05c99 301 }
j3 3:a2effad05c99 302 }
j3 3:a2effad05c99 303
j3 3:a2effad05c99 304 return result;
j3 3:a2effad05c99 305 }
j3 3:a2effad05c99 306
j3 3:a2effad05c99 307
j3 1:9e2a3b4a24c7 308 //*****************************************************************************
j3 0:2d0c91de9279 309 int32_t MAX30101::writeRegister(Registers_e reg, uint8_t value)
j3 0:2d0c91de9279 310 {
j3 0:2d0c91de9279 311 char local_data[2] = {reg, value};
j3 0:2d0c91de9279 312
j3 0:2d0c91de9279 313 return m_i2cBus.write(I2C_W_ADRS, local_data, 2);
j3 0:2d0c91de9279 314 }
j3 0:2d0c91de9279 315
j3 0:2d0c91de9279 316
j3 0:2d0c91de9279 317 //*****************************************************************************
j3 0:2d0c91de9279 318 int32_t MAX30101::readRegister(Registers_e reg, uint8_t &value)
j3 0:2d0c91de9279 319 {
j3 0:2d0c91de9279 320 int32_t result;
j3 0:2d0c91de9279 321
j3 0:2d0c91de9279 322 char local_data[2];
j3 0:2d0c91de9279 323 local_data[0] = reg;
j3 0:2d0c91de9279 324
j3 0:2d0c91de9279 325 result = m_i2cBus.write(I2C_W_ADRS, local_data, 1);
j3 0:2d0c91de9279 326 if(result == 0)
j3 0:2d0c91de9279 327 {
j3 0:2d0c91de9279 328 result = m_i2cBus.read(I2C_R_ADRS, (local_data + 1), 1);
j3 0:2d0c91de9279 329 if (result == 0)
j3 0:2d0c91de9279 330 {
j3 0:2d0c91de9279 331 value = local_data[1];
j3 0:2d0c91de9279 332 }
j3 0:2d0c91de9279 333 }
j3 0:2d0c91de9279 334
j3 0:2d0c91de9279 335 return result;
j3 0:2d0c91de9279 336 }
j3 0:2d0c91de9279 337