MAX30100 pulse rate sensor

Dependencies:   PulseRate

Dependents:   PulseRate

MAX30100.h

Committer:
kohlerba
Date:
2017-11-26
Revision:
3:fa37b0c705b3
Parent:
2:d329886938f1
Child:
4:008e40a7d035

File content as of revision 3:fa37b0c705b3:

#ifndef MAX30100_H
#define MAX30100_H

#include "mbed.h"

//definitions
#define MAX30100_ADDRESS 0xAE

// Registers
#define MAX30100_INT_STATUS     0x00  // Which interrupts are tripped
#define MAX30100_INT_ENABLE     0x01  // Which interrupts are active
#define MAX30100_FIFO_WR_PTR    0x02  // Where data is being written
#define MAX30100_OVRFLOW_CTR    0x03  // Number of lost samples
#define MAX30100_FIFO_RD_PTR    0x04  // Where to read from
#define MAX30100_FIFO_DATA      0x05  // Ouput data buffer
#define MAX30100_MODE_CONFIG    0x06  // Control register
#define MAX30100_SPO2_CONFIG    0x07  // Oximetry settings
#define MAX30100_LED_CONFIG     0x09  // Pulse width and power of LEDs
#define MAX30100_TEMP_INTG      0x16  // Temperature value, whole number
#define MAX30100_TEMP_FRAC      0x17  // Temperature value, fraction
#define MAX30100_REV_ID         0xFE  // Part revision
#define MAX30100_PART_ID        0xFF  // Part ID, normally 0x11

#define POR_PART_ID             0x11

typedef enum{ // This is the same for both LEDs
  pw200,    // 200us pulse
  pw400,    // 400us pulse
  pw800,    // 800us pulse
  pw1600    // 1600us pulse
}pulseWidth;

typedef enum{
  sr50,    // 50 samples per second
  sr100,   // 100 samples per second
  sr167,   // 167 samples per second
  sr200,   // 200 samples per second
  sr400,   // 400 samples per second
  sr600,   // 600 samples per second
  sr800,   // 800 samples per second
  sr1000   // 1000 samples per second
}sampleRate;

typedef enum{
  i0,    // No current
  i4,    // 4.4mA
  i8,    // 7.6mA
  i11,   // 11.0mA
  i14,   // 14.2mA
  i17,   // 17.4mA
  i21,   // 20.8mA
  i27,   // 27.1mA
  i31,   // 30.6mA
  i34,   // 33.8mA
  i37,   // 37.0mA
  i40,   // 40.2mA
  i44,   // 43.6mA
  i47,   // 46.8mA
  i50    // 50.0mA
}ledCurrent;

//Set up I2C, (SDA,SCL)
static I2C i2c(I2C_SDA, I2C_SCL);
static Serial pc(USBTX, USBRX); // tx, rx

uint16_t IR = 0;      // Last IR reflectance datapoint
uint16_t RED = 0;     // Last Red reflectance datapoint

class MAX30100 {
 
    protected:
 
    public:
    
    //Wire read and write protocols
static int i2c_write (uint8_t i2c_addr, uint8_t register_addr, char* buffer, uint8_t Nbyte )
{
    int ret;
    char *tmp_buffer;

    tmp_buffer = (char*)malloc(sizeof(char)*(Nbyte+1));

    /* First, send device address. Then, send data and STOP condition */
    tmp_buffer[0] = register_addr;
    memcpy(tmp_buffer+1, buffer, Nbyte);

    ret = i2c.write(i2c_addr, tmp_buffer, Nbyte+1, false);

    return ret;
}

static int i2c_read (uint8_t i2c_addr, uint8_t register_addr, char* buffer, uint8_t Nbyte )
{
    int ret;

    /* Send device address, with no STOP condition */
    ret = i2c.write(i2c_addr, (const char*)&register_addr, 1, true);
    if(!ret) {
        /* Read data, with STOP condition  */
        ret = i2c.read((i2c_addr|0x01), buffer, Nbyte, false);
    }

    return ret;
}
    //
   
void setLEDs(pulseWidth pw, ledCurrent red, ledCurrent ir){
  char reg[1];
  i2c_read(MAX30100_ADDRESS, MAX30100_SPO2_CONFIG, &reg[0], 1);
  reg[0] = reg[0] & 0xFC; // Set LED_PW to 00
  reg[0] = reg[0] | pw;
  i2c_write(MAX30100_ADDRESS, MAX30100_SPO2_CONFIG, &reg[0], 1);     // Mask LED_PW
  reg[0] = (red<<4) | ir;
  i2c_write(MAX30100_ADDRESS, MAX30100_LED_CONFIG, &reg[0], 1); // write LED configs
}

void setSPO2(sampleRate sr){
  char reg[1];
  i2c_read(MAX30100_ADDRESS, MAX30100_SPO2_CONFIG, &reg[0], 1);
  reg[0] = reg[0] & 0xE3; // Set SPO2_SR to 000
  reg[0] = reg[0] | (sr<<2);
  i2c_write(MAX30100_ADDRESS, MAX30100_SPO2_CONFIG, &reg[0], 1); // Mask SPO2_SR
  i2c_read(MAX30100_ADDRESS, MAX30100_MODE_CONFIG, &reg[0], 1);
  reg[0] = reg[0] & 0xf8; // Set Mode to 000
  reg[0] = reg[0] | 0x03;
  i2c_write(MAX30100_ADDRESS, MAX30100_SPO2_CONFIG, &reg[0], 1); // Mask MODE
}

int getNumSamp(void){
    char wrPtr[1];
    char rdPtr[1];
    i2c_read(MAX30100_ADDRESS, MAX30100_FIFO_WR_PTR, &wrPtr[0], 1);
    i2c_read(MAX30100_ADDRESS, MAX30100_FIFO_RD_PTR, &rdPtr[0], 1);
    return (abs( 16 + wrPtr[0] - rdPtr[0] ) % 16);
}

void readSensor(void){
  char temp[4] = {0};  // Temporary buffer for read values
  i2c_read(MAX30100_ADDRESS, MAX30100_FIFO_DATA, &temp[0], 4);  // Read four times from the FIFO
  IR = (temp[0]<<8) | temp[1];    // Combine values to get the actual number
  RED = (temp[2]<<8) | temp[3];   // Combine values to get the actual number
}

void shutdown(void){
  char reg[1];
  i2c_read(MAX30100_ADDRESS, MAX30100_MODE_CONFIG, &reg[0], 1);  // Get the current register
  reg[0] = reg[0] | 0x80;
  i2c_write(MAX30100_ADDRESS, MAX30100_MODE_CONFIG, &reg[0], 1);   // mask the SHDN bit
}

void reset(void){
  char reg[1];
  i2c_read(MAX30100_ADDRESS, MAX30100_MODE_CONFIG, &reg[0], 1);  // Get the current register
  reg[0] = reg[0] | 0x40;
  i2c_write(MAX30100_ADDRESS, MAX30100_MODE_CONFIG, &reg[0], 1);   // mask the RESET bit
}

void startup(void){
  char reg[1];
  i2c_read(MAX30100_ADDRESS, MAX30100_MODE_CONFIG, &reg[0], 1);  // Get the current register
  reg[0] = reg[0] & 0x7F;
  i2c_write(MAX30100_ADDRESS, MAX30100_MODE_CONFIG, &reg[0], 1);   // mask the SHDN bit
}

uint8_t getRevID(void){
  char buffer[1];
  i2c_read(MAX30100_ADDRESS, MAX30100_REV_ID, &buffer[0], 1);
  return buffer[0];
}

uint8_t getPartID(void){
  char buffer[1];
  i2c_read(MAX30100_ADDRESS, MAX30100_PART_ID, &buffer[0], 1);
  return buffer[0];
}

void begin(pulseWidth pw, ledCurrent ir, sampleRate sr){
  char buffer[1];
  buffer[0] = 0x02;
  i2c_write(MAX30100_ADDRESS, MAX30100_MODE_CONFIG, &buffer[0], 1); // Heart rate only
  buffer[0] = ir;
  i2c_write(MAX30100_ADDRESS, MAX30100_LED_CONFIG, &buffer[0], 1);
  buffer[0] = (sr<<2)|pw;
  i2c_write(MAX30100_ADDRESS, MAX30100_SPO2_CONFIG, &buffer[0], 1);
}

void printRegisters(){
    char reg[1];
    i2c_read(MAX30100_ADDRESS, MAX30100_INT_STATUS, &reg[0], 1);
    pc.printf("MAX30100_INT_STATUS: %d\r\n",reg[0]);
    i2c_read(MAX30100_ADDRESS, MAX30100_INT_ENABLE, &reg[0], 1);
    pc.printf("MAX30100_INT_ENABLE: %d\r\n",reg[0]);
    i2c_read(MAX30100_ADDRESS, MAX30100_FIFO_WR_PTR, &reg[0], 1);
    pc.printf("MAX30100_FIFO_WR_PTR: %d\r\n",reg[0]);
    i2c_read(MAX30100_ADDRESS, MAX30100_OVRFLOW_CTR, &reg[0], 1);
    pc.printf("MAX30100_OVRFLOW_CTR: %d\r\n",reg[0]);
    i2c_read(MAX30100_ADDRESS, MAX30100_FIFO_RD_PTR, &reg[0], 1);
    pc.printf("MAX30100_FIFO_RD_PTR: %d\r\n",reg[0]);
    i2c_read(MAX30100_ADDRESS, MAX30100_FIFO_DATA, &reg[0], 1);
    pc.printf("MAX30100_FIFO_DATA: %d\r\n",reg[0]);
    i2c_read(MAX30100_ADDRESS, MAX30100_MODE_CONFIG, &reg[0], 1);
    pc.printf("MAX30100_MODE_CONFIG: %d\r\n",reg[0]);
    i2c_read(MAX30100_ADDRESS, MAX30100_SPO2_CONFIG, &reg[0], 1);
    pc.printf("MAX30100_SPO2_CONFIG: %d\r\n",reg[0]);
    i2c_read(MAX30100_ADDRESS, MAX30100_LED_CONFIG, &reg[0], 1);
    pc.printf("MAX30100_LED_CONFIG: %d\r\n",reg[0]);
    i2c_read(MAX30100_ADDRESS, MAX30100_TEMP_INTG, &reg[0], 1);
    pc.printf("MAX30100_TEMP_INTG: %d\r\n",reg[0]);
    i2c_read(MAX30100_ADDRESS, MAX30100_TEMP_FRAC, &reg[0], 1);
    pc.printf("MAX30100_TEMP_FRAC: %d\r\n",reg[0]);
    i2c_read(MAX30100_ADDRESS, MAX30100_REV_ID, &reg[0], 1);
    pc.printf("MAX30100_REV_ID: %d\r\n",reg[0]);
    i2c_read(MAX30100_ADDRESS, MAX30100_PART_ID, &reg[0], 1);
    pc.printf("MAX30100_PART_ID: %d\r\n",reg[0]);
}

};
#endif