Hexiwear Heart rate sensor driver

Dependents:   Hexi_MAX30101 Hexiwear HexiwearFinal HexiwearFinal1

Fork of FXOS8700 by Aswin Sivakumar

Files at this revision

API Documentation at this revision

Comitter:
DimiterK
Date:
Tue Aug 30 22:13:28 2016 +0000
Parent:
2:98ea52282575
Child:
4:3be008e67345
Commit message:
First commit

Changed in this revision

FXOS8700.cpp Show diff for this revision Revisions of this file
FXOS8700.h Show diff for this revision Revisions of this file
MAX30101.cpp Show annotated file Show diff for this revision Revisions of this file
MAX30101.h Show annotated file Show diff for this revision Revisions of this file
--- a/FXOS8700.cpp	Tue Dec 22 00:22:57 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-  /* Copyright (c) 2015 NXP Semiconductors. MIT License
-*
-* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
-* and associated documentation files (the "Software"), to deal in the Software without
-* restriction, including without limitation the rights to use, copy, modify, merge, publish,
-* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
-* Software is furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included in all copies or
-* substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
-* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/
-
-#include "FXOS8700.h"
- #include "mbed.h"
-
-FXOS8700::FXOS8700(PinName sda, PinName scl) : accelmagi2c(sda,scl)
- {
-       
- }
-    
- void FXOS8700::accel_config(void)
- {
-   char d[2]; 
-   d[0] = FXOS8700_CTRL_REG1;                     //Puts device in Standby mode
-   d[1] = 0x00; 
-   accelmagi2c.write(FXOS8700_I2C_ADDRESS, d,2);   
-          
-   
-   d[0] = FXOS8700_CTRL_REG1;                     //Puts device in Active mode
-   d[1] = 0x01;
-   accelmagi2c.write(FXOS8700_I2C_ADDRESS, d, 2);   
-      
- }
- 
-  void FXOS8700::mag_config(void)
- {
-   char d[2];
-   d[0] = FXOS8700_CTRL_REG1;                     //Puts device in Standby mode
-   d[1] = 0x00;
-   accelmagi2c.write(FXOS8700_I2C_ADDRESS, d,2);   
-          
-   
-   d[0] = FXOS8700_M_CTRL_REG1;                   //Puts device in hybrid mode (both accel and mag are active)
-   d[1] = 0x03;
-   accelmagi2c.write(FXOS8700_I2C_ADDRESS, d, 2);   
-   
-
-   d[0] = FXOS8700_CTRL_REG1;                     //Puts device in Active mode
-   d[1] = 0x01;
-   accelmagi2c.write(FXOS8700_I2C_ADDRESS, d,2);  
-   
- }
- 
- void FXOS8700::acquire_accel_data_g(float * a_data)
- {
-  
-   char data_bytes[7];
-   char d[1];
-   d[0]=FXOS8700_STATUS;
-   accelmagi2c.write(FXOS8700_I2C_ADDRESS,d,1,true);  // Read the 6 data bytes - LSB and MSB for X, Y and Z Axes.
-   accelmagi2c.read(FXOS8700_I2C_ADDRESS,data_bytes,7);
-   
-   a_data[0] =  ((float)((int16_t)(((data_bytes[1]*256) + (data_bytes[2])))>> 2) * 0.000244);
-   a_data[1] =  ((float)((int16_t)(((data_bytes[3]*256) + (data_bytes[4])))>> 2) * 0.000244);
-   a_data[2] =  ((float)((int16_t)(((data_bytes[5]*256) + (data_bytes[6])))>> 2) * 0.000244);
-   
- }
-
- void FXOS8700::acquire_mag_data_uT(float * m_data)
- {
-  
-   char data_bytes[7];
-   char d[1];
-   d[0]=FXOS8700_MDR_STATUS;
-   accelmagi2c.write(FXOS8700_I2C_ADDRESS,d,1,true);  // Read the 6 data bytes - LSB and MSB for X, Y and Z Axes.
-   accelmagi2c.read(FXOS8700_I2C_ADDRESS,data_bytes,7);
-   
-   m_data[0] =  (float)((int16_t)((data_bytes[1]*256) + (data_bytes[2]))) * 0.1;
-   m_data[1] =  (float)((int16_t)((data_bytes[3]*256) + (data_bytes[4]))) * 0.1;
-   m_data[2] =  (float)((int16_t)((data_bytes[5]*256) + (data_bytes[6]))) * 0.1;
-   
- }
-     
-     
\ No newline at end of file
--- a/FXOS8700.h	Tue Dec 22 00:22:57 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
- /* Copyright (c) 2015 NXP Semiconductors. MIT License
-*
-* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
-* and associated documentation files (the "Software"), to deal in the Software without
-* restriction, including without limitation the rights to use, copy, modify, merge, publish,
-* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
-* Software is furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included in all copies or
-* substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
-* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/
-
-#ifndef FXOS8700_H
-#define FXOS8700_H
-#include "mbed.h"
-
-#define FXOS8700_I2C_ADDRESS (0x1E<<1) //pins SA0,SA1=0
-
-#define FXOS8700_STATUS 0x00
-#define FXOS8700_MDR_STATUS 0x32
-#define FXOS8700_WHO_AM_I 0x0D
-#define FXOS8700_CTRL_REG1 0x2A
-#define FXOS8700_M_CTRL_REG1 0x5B
-#define FXOS8700_WHO_AM_I_VALUE 0xC7
-
-class FXOS8700
-{
-    public:
-    
-    FXOS8700(PinName sda, PinName scl);
-      
-    void accel_config(void);
-    
-    void mag_config(void);
-        
-    void acquire_accel_data_g(float * da);
-    
-    void acquire_mag_data_uT(float * dm);
-    
-    private:
-    I2C accelmagi2c;
-    
-};
-
-#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MAX30101.cpp	Tue Aug 30 22:13:28 2016 +0000
@@ -0,0 +1,230 @@
+#include "MAX30101.h"
+ #include "mbed.h"
+
+
+MAX30101::MAX30101(PinName sda, PinName scl ,int addr) : m_i2c(sda, scl), m_addr(addr) {
+   // mode (HR, SpO2, or multi-led)
+   mode = modeMultiLED;
+
+   // LED currents
+   LEDCurrentRed = 0;
+   LEDCurrentIR = 0;
+   LEDCurrentGreen = 0;
+
+   // timings
+   sampleRate = sampleRate_50;
+   pulseWidth = ledPower_411;
+   // ADC range
+   range = adcRange8192;
+   // averaging
+   oversample = ovsNone;
+  
+//   writeRegister(MAX30101_LED1RedPulseAmplitude,   0xFF );
+//   writeRegister(MAX30101_LED2IrPulseAmplitude,    0x33 );
+//   writeRegister(MAX30101_LED3GreenPulseAmplitude, 0xFF );
+//   writeRegister(MAX30101_ProximityModePulseAmplitude,  0x19 );
+//
+//   writeRegister( MAX30101_MultiLEDModeControlTime2Time1, 0x03 );
+//   writeRegister( MAX30101_MultiLEDModeControlTime4Time3, 0x00 );
+//
+//   writeRegister( MAX30101_FIFOConfiguration , 0x06 );
+//   writeRegister( MAX30101_SPO2Configuration , 0x43 );
+//
+//   writeRegister(MAX30101_ProximityInterruptThreshold , 0x14 );
+//
+//   /** clear FIFO pointers */
+//   writeRegister(MAX30101_FIFO_WR_PTR , 0 );
+//   writeRegister(MAX30101_FIFO_RD_PTR , 0 );
+//   writeRegister(MAX30101_FIFO_OV_PTR , 0 );
+
+}
+ 
+MAX30101::~MAX30101() { }
+
+    
+ void MAX30101::enable(void)
+ {
+   
+   writeRegister( MAX30101_InterruptEnable1 , 0x10 );
+   writeRegister( MAX30101_ModeConfiguration , 0x07 ); 
+      
+ }
+    
+ void MAX30101::shutdown(void)
+ {
+   writeRegister(MAX30101_ModeConfiguration,SHDN);
+      
+ }
+ 
+  max30101_status_t MAX30101::reset(void)
+ {
+    writeRegister(MAX30101_ModeConfiguration,RESET);
+    
+    while (1)
+    {
+    uint8_t status = readRegister( MAX30101_ModeConfiguration );
+
+      if ( 0 == ( status & RESET ) )
+      {
+        return STATUS_MAXIM_SUCCESS;
+      }
+    }
+   
+ }
+ 
+ void MAX30101::setMode(max30101_mode_t sensorMode)
+ {
+     
+ }
+ 
+ void MAX30101::setSPO2_ADC_range(void)
+ {
+
+   
+ }
+
+ 
+ void MAX30101::set_SPO2_sampleRange(void)
+ {
+
+ }
+    
+ void MAX30101::set_LED_PulseWidth(uint8_t pw)
+ {
+    
+ }
+ 
+ max30101_status_t MAX30101::readRawData(uint8_t* dataBuff, uint8_t* sampleNum )
+ {
+     // temporary buffer to read samples from the FIFO buffer
+    uint8_t  tmpBuf[ MAXIM_FIFO_DEPTH * MAXIM_BYTES_PER_ADC_VALUE ];
+
+    uint8_t  numAvailSam;
+
+    // read FIFO pointers
+    uint8_t fifoWrPtr = readRegister( MAX30101_FIFO_WR_PTR );
+    uint8_t fifoRdPtr = readRegister( MAX30101_FIFO_RD_PTR );
+    uint8_t fifoOvPtr = readRegister( MAX30101_FIFO_OV_PTR );
+    
+    // overflow happened
+    if ( fifoOvPtr > 0 )
+    {
+      uint8_t      cmd = MAX30101_FIFO_DATA ;
+      readRegs(cmd,tmpBuf,100);
+      numAvailSam = 0xFF;
+    }
+
+    else
+    {
+        if ( fifoWrPtr > fifoRdPtr )
+        {
+            /**
+            * NUM_AVAILABLE_SAMPLES = FIFO_WR_PTR – FIFO_RD_PTR
+            * NUM_SAMPLES_TO_READ   = < less than or equal to NUM_AVAILABLE_SAMPLES >
+            */
+            numAvailSam = fifoWrPtr - fifoRdPtr;
+        }
+
+        // note: pointer wrap around should be taken into account
+        else if ( fifoWrPtr < fifoRdPtr )
+        {
+            numAvailSam = fifoWrPtr + MAXIM_FIFO_DEPTH - fifoRdPtr;
+        }
+
+        // no new samples available
+        else
+        {
+            numAvailSam = 0;
+        }
+
+        if ( numAvailSam > 0 )
+        {
+            uint8_t cmd = MAX30101_FIFO_DATA ;
+
+            /**
+             * read all the available samples,
+             * FIFO RD pointer is implicitly incremented after each successful sample read
+             */
+            readRegs(cmd,tmpBuf,100);
+
+            if ( NULL != dataBuff )
+            {
+                memcpy  (
+                            (void*)dataBuff,
+                            (const void*)tmpBuf,
+                            numAvailSam * MAXIM_BYTES_PER_ADC_VALUE
+                        );
+            }
+        }
+    }
+
+    /** save data */
+
+    if ( NULL != sampleNum )
+    {
+        *sampleNum = numAvailSam;
+    }
+
+    
+    return STATUS_MAXIM_SUCCESS;
+ }
+    
+ float  MAX30101::getTemp(void)
+ {
+    float temp = 0;
+    
+    return temp;
+ }
+    
+ float  MAX30101::getDieTemp(void)
+ {
+    float dieTemp = 0;
+    
+    
+    return dieTemp;
+
+ }
+
+ uint8_t  MAX30101::getRevisionID(void)
+ {
+     uint8_t chipid = 0;
+     
+     readRegs(MAX30101_DeviceID, &chipid, 1);
+     return chipid;
+ }
+  
+ uint8_t  MAX30101::getChipID(void)
+ {
+     uint8_t chipid = 0;
+     
+     readRegs(MAX30101_DeviceID, &chipid, 1);
+     return chipid;
+ }
+     
+void MAX30101::readRegs(int addr, uint8_t * data, int len) 
+{
+    char t[1] = {addr};
+    m_i2c.write(m_addr, t, 1, true);
+    m_i2c.read(m_addr, (char *)data, len);
+}
+ 
+void MAX30101::writeRegs(uint8_t * data, int len) 
+{
+    m_i2c.write(m_addr, (char *)data, len);
+}
+     
+
+uint8_t MAX30101::readRegister( uint8_t regaddr)
+{
+    uint8_t data = 0;
+    readRegs(regaddr, &data,1);
+    return data;
+}
+
+void MAX30101::writeRegister(uint8_t regaddr, uint8_t data)
+{
+    uint8_t i2data[2]= {regaddr, data};
+    
+    writeRegs(i2data, 2);
+}
+     
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MAX30101.h	Tue Aug 30 22:13:28 2016 +0000
@@ -0,0 +1,228 @@
+#ifndef MAX30101_H
+#define MAX30101_H
+#include "mbed.h"
+
+#define MAX30101_I2C_ADDRESS (0xAE<<1) //pins SA0,SA1=0
+
+#define MAXIM_BYTES_PER_ADC_VALUE ( 3 )
+#define MAXIM_FIFO_DEPTH          ( 32 )
+
+#define MAX30101_InterruptStatus1                       0x00
+#define MAX30101_InterruptStatus2                       0x01
+#define MAX30101_InterruptEnable1                       0x02
+#define MAX30101_InterruptEnable2                       0x03
+
+#define MAX30101_FIFO_WR_PTR                            0x04
+#define MAX30101_FIFO_OV_PTR                            0x05
+#define MAX30101_FIFO_RD_PTR                            0x06
+#define MAX30101_FIFO_DATA                              0x07
+#define MAX30101_FIFOConfiguration                      0x08
+#define MAX30101_ModeConfiguration                      0x09
+#define MAX30101_SPO2Configuration                      0x0A
+#define MAX30101_LED1RedPulseAmplitude                  0x0C
+#define MAX30101_LED2IrPulseAmplitude                   0x0D
+#define MAX30101_LED3GreenPulseAmplitude                0x0E
+#define MAX30101_ProximityModePulseAmplitude            0x10
+#define MAX30101_MultiLEDModeControlTime2Time1          0x11
+#define MAX30101_MultiLEDModeControlTime4Time3          0x12
+#define MAX30101_DieTemperatureInteger                  0x1F
+#define MAX30101_DieTemperatureFraction                 0x20
+#define MAX30101_DieTemperatureConfig                   0x21
+#define MAX30101_ProximityInterruptThreshold            0x30
+#define MAX30101_RevisionID                             0xFE
+#define MAX30101_DeviceID                               0xFF
+
+/******************************************************************************/
+#define A_FULL          0x80
+#define PPG_RD          0x40
+#define ALC_OVF         0x20
+#define PROX_IN         0x10
+#define PWR_RDY         0x01
+
+#define DIE_TEMP_RDY    0x02
+
+#define A_FULL_EN       0x80
+#define PPG_RDY_EN      0x40
+#define ALC_OVF_EN1     0x20
+#define ALC_OVF_EN0     0x10
+
+#define DIE_TEMP_RDY_EN 0x02
+
+#define SHDN            0x80
+#define RESET           0x40
+#define MODE1           0x02
+#define MODE0           0x01
+
+#define SPO2_ADC_RGE1   0x40 
+#define SPO2_ADC_RGE0   0x20
+#define SPO2_SR2        0x10
+#define SPO2_SR1        0x08
+#define SPO2_SR0        0x04
+#define LED_PW1         0x02
+#define LED_PW0         0x01
+
+#define TEMP_EN         0x01
+
+/******************************************************************************/
+
+#define MAXIM_SLOT_NUM  2
+
+typedef enum
+{
+  modeHR        = 0x2,
+  modeSPO2      = 0x3,
+  modeMultiLED  = 0x7
+
+} max30101_mode_t;
+
+typedef enum
+{
+  ledPower_69  = 0x0, // ADC -> 15 bit
+  ledPower_118 = 0x1, // ADC -> 16 bit
+  ledPower_215 = 0x2, // ADC -> 17 bit
+  ledPower_411 = 0x3  // ADC -> 18 bit
+
+} max30101_ledpwr_t;
+
+
+/** HR global status enum */
+typedef enum
+{
+    HEART_RATE_STATUS_SUCCESS,
+    HEART_RATE_STATUS_ERROR
+
+} heartRate_status_t;
+
+typedef enum
+{
+  sampleRate_50   = 0x0,
+  sampleRate_100  = 0x1,
+  sampleRate_200  = 0x2,
+  sampleRate_400  = 0x3,
+  sampleRate_800  = 0x4,
+  sampleRate_1000 = 0x5,
+  sampleRate_1600 = 0x6,
+  sampleRate_3200 = 0x7
+
+} max30101_sampleRate_t;
+
+typedef enum
+{
+  LEDSlotNone  =  0x0,
+  LEDSlotRed   =  0x1,
+  LEDSlotIR    =  0x2,
+  LEDSlotGreen =  0x3
+
+} max30101_LEDSlot_t;
+
+typedef enum
+{
+  STATUS_MAXIM_SUCCESS,        // success
+  STATUS_MAXIM_ERROR,          // fail
+  STATUS_MAXIM_PROTOCOL_ERROR, // protocol failure
+  STATUS_MAXIM_INIT_ERROR,     // initialization error
+  STATUS_MAXIM_PARAM_ERROR,    // invalid parameter is given
+  STATUS_MAXIM_OVF_ERROR,      // sensor data overflow
+  STATUS_MAXIM_TIMEOUT         // timeout occured
+
+} max30101_status_t;
+
+typedef enum
+{
+  adcRange2048  = 0x0,
+  adcRange4096  = 0x1,
+  adcRange8192  = 0x2,
+  adcRange16384 = 0x3
+
+} max30101_adcRange_t;
+
+typedef enum
+{
+  ovsNone = 0x0, // no averaging
+  ovs2    = 0x1, // average 2 samples
+  ovs4    = 0x2, // average 4 samples
+  ovs8    = 0x3, // average 8 samples
+  ovs16   = 0x4, // average 16 samples
+  ovs32   = 0x5  // average 32 samples
+
+} max30101_ovs_t;
+
+#define HR_SAMPLE_RATE ( 50 ) /** sample rate for MAXIM 30101 sensor */
+
+
+class MAX30101
+{
+public:
+  /**
+  * MAX30101 constructor
+  *
+  * @param sda SDA pin
+  * @param sdl SCL pin
+  * @param addr addr of the I2C peripheral
+  */
+  MAX30101(PinName sda, PinName scl,  int addr);
+ 
+  /**
+  * MAX30101 destructor
+  */
+  ~MAX30101();
+
+    void enable(void);
+     
+    void shutdown(void);
+    
+    max30101_status_t reset(void);
+        
+    void setMode(max30101_mode_t sensorMode);
+    
+    void setSPO2_ADC_range(void);
+    
+    void set_SPO2_sampleRange(void);
+    
+    void set_LED_PulseWidth(uint8_t pw);
+    
+    max30101_status_t readRawData(uint8_t* dataBuff, uint8_t* sampleNum );
+    float getTemp(void);
+    
+    float getDieTemp(void);
+    
+    uint8_t  getRevisionID(void);
+
+    uint8_t getChipID(void);
+ 
+private:
+  I2C m_i2c;
+  int m_addr;
+  void readRegs(int addr, uint8_t * data, int len);
+  void writeRegs(uint8_t * data, int len);
+  
+  uint8_t readRegister( uint8_t regaddr);
+  void writeRegister(uint8_t regaddr, uint8_t data);
+  
+  // mode (HR, SpO2, or multi-led)
+  max30101_mode_t mode;
+
+  // multiLED slots
+  max30101_LEDSlot_t LEDSlot[ MAXIM_SLOT_NUM ];
+  uint8_t activeSlots;
+
+  // LED currents
+  uint8_t LEDCurrentRed;
+  uint8_t LEDCurrentIR;
+  uint8_t LEDCurrentGreen;
+
+  // timings
+  max30101_sampleRate_t sampleRate;
+  max30101_ledpwr_t pulseWidth;
+  // ADC range
+  max30101_adcRange_t range;
+  // averaging
+  max30101_ovs_t oversample;
+ 
+};
+ 
+#endif
+
+
+
+