Maxim Integrated / Mbed OS MAX30101WING_HR_SPO2

Dependencies:   MAX30101 max32630fthr

Fork of MAX30101_HR_SPO2 by John Greene

main.cpp

Committer:
johnGreeneMaxim
Date:
2017-10-15
Revision:
9:affd4e6372a0
Parent:
8:a1538e8a3fd9
Child:
10:fcfa9adc99a9

File content as of revision 9:affd4e6372a0:

/*******************************************************************************
 * Copyright (C) 2017 Maxim Integrated Products, Inc., All Rights Reserved.
 *
 * 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 MAXIM INTEGRATED 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.
 *
 * Except as contained in this notice, the name of Maxim Integrated
 * Products, Inc. shall not be used except as stated in the Maxim Integrated
 * Products, Inc. Branding Policy.
 *
 * The mere transfer of this software does not imply any licenses
 * of trade secrets, proprietary technology, copyrights, patents,
 * trademarks, maskwork rights, or any other form of intellectual
 * property whatsoever. Maxim Integrated Products, Inc. retains all
 * ownership rights.
 *******************************************************************************
 */
 

#include "mbed.h"
#include "max32630fthr.h"
#include "MAX30101.h"
#include "algorithm.h"

//equals 3*number of LEDS used
#define DIV_SAMPLE 6 
//sets the number of samples sent to the heart rate and SPO2 calculation 
#define CALC_SAMPLE 500

MAX32630FTHR pegasus(MAX32630FTHR::VIO_3V3);

bool op_sensor_config(MAX30101 &op_sensor);
void pmic_config(I2C & i2c_bus, DigitalOut & pmic_en);

/* Op Sensor FIFO nearly full callback */
volatile bool op_sensorIntFlag = 0;                  
void op_sensor_callback()
{
    op_sensorIntFlag = 1;
}

int main()
{
    Serial pc(USBTX, USBRX);            // Use USB debug probe for serial link
    pc.baud(115200);                    // Baud rate = 115200
    
    DigitalOut rLed(LED1, LED_OFF);     // Debug LEDs
    DigitalOut gLed(LED2, LED_OFF);
    DigitalOut bLed(LED3, LED_OFF);
    
    InterruptIn op_sensor_int(P3_2);            // Config P3_2 as int. in for
    op_sensor_int.fall(&op_sensor_callback);    // FIFO ready interrupt
    
    I2C i2cBus(I2C1_SDA, I2C1_SCL);         // I2C bus, P3_4 = SDA, P3_5 = SCL 

    DigitalOut VLED_EN(P3_3,0);                //Enable for VLEDs
    pmic_config(i2cBus, VLED_EN);
    
    MAX30101 op_sensor(i2cBus);             // Create new MAX30101 on i2cBus
    int rc = op_sensor_config(op_sensor);   // Config sensor, return 0 on success
    
    MAX30101::InterruptBitField_u ints;         // Read interrupt status to clear
    rc = op_sensor.getInterruptStatus(ints);    // power on interrupt 
    
    uint8_t fifoData[MAX30101::MAX_FIFO_BYTES];
    uint16_t idx, readBytes;
    int32_t opSample;
    uint32_t sample;
    uint32_t redData[500];//set array to max fifo size 
    uint32_t irData[500];//set array to max fifo size 
    int r=0; //counter for redData position 
    int ir=0; //counter for irData position
    int c=0; //counter to print values
    int i =0; //second counter 
    int32_t spo2 =0;
    int8_t spo2Valid = 0;
    int32_t heartRate = 0;
    int8_t heartRateValid = 0;
    int32_t numSamples = 0;
    uint32_t fifoIR[MAX30101::MAX_FIFO_BYTES];
    uint32_t fifoRED[MAX30101::MAX_FIFO_BYTES];
    
    
    while(1) 
    {
       
        
        if( rc == 0 ) 
        {
            
            // Check if op_sensor interrupt asserted
            if(op_sensorIntFlag) 
            {
                pc.printf("Entered op_sensorIntFlag check\r\n");
                op_sensorIntFlag = 0;                       // Lower interrupt flag
                rc = op_sensor.getInterruptStatus(ints);    // Read interrupt status 
                
                // Check if FIFO almost full interrupt asserted
                if((rc == 0) && (ints.bits.a_full)) 
                {
                    pc.printf("about to read fifo\r\n");
                    // Read FIFO 
                    rc = op_sensor.readFIFO(MAX30101::TwoLedChannels, fifoData, readBytes);     
                    
                    numSamples = readBytes/DIV_SAMPLE; //calcualtes number of smaples read 
                    
                    if(rc == 0) 
                    {
                        
                        // Convert read bytes into samples
                        for(idx = 0, c=0, i=0; idx < readBytes; idx+=3) 
                        {
                            //pc.printf("In sample adjustment \r\n");
                            sample = (fifoData[idx]<<16) | (fifoData[idx+1]<<8) | (fifoData[idx+2]);
                            opSample = sample << 14;           // Sign extends sample 
                            opSample = opSample >> 14;
                            if(idx%2==0)
                            {
                                //pc.printf("end red allocation\r\n");
                                redData[r] = opSample;//saves to buff for calculations 
                                fifoRED[i] = opSample;//saves to buff to print values just obtained 
                                r++;
                                i++;
                                
                            }
                            else
                            {
                                //pc.printf("end ir allocation\r\n");
                                irData[ir] = opSample; //saves to buff for calculations 
                                fifoIR[c] = opSample;//saves to buff to print values just obtained 
                                ir++;
                                c++;
                                
                            }
                            pc.printf("Red count = %i\r\n IR count = %i\r\n",r,ir);
                            //pc.printf("idx = %i and readbytes = %i\r\n", idx,readBytes);
                            
                        }
                        
                        if(r>=200 & ir>=200)//checks to make sure there are 200 samples in data buffers 
                        {
                            pc.printf("In Calculation Function\r\n");
                            //calculate heart rate and spo2
                            maxim_heart_rate_and_oxygen_saturation( irData, CALC_SAMPLE, 
                            redData, &spo2, &spo2Valid, &heartRate, &heartRateValid);
                            
                             for(c=100;c<200;c++)//dump first hundred samples after calculations 
                            {
                                redData[c-100]=redData[c];
                                irData[c-100]=irData[c];

                            }
                            r=50;
                            ir=50;
                            
                            
                        }

                        
                        
                        pc.printf("Read Samples %i\r\n",numSamples);
                        //prints the Red LED data 
                        pc.printf("RED LED DATA\r\n");
                        for(c=0; c<numSamples; c++)
                        {
                            pc.printf("%i\r\n",fifoRED[c]);  
                        }
                        
                        //prints the IR LED data 
                        pc.printf("IR LED DATA\r\n");
                        for(c=0; c<numSamples; c++)
                        {
                            pc.printf("%i\r\n",fifoIR[c]);  
                        }
                        
                        if(spo2Valid==1)
                        {
                            pc.printf("SPO2 = %i\r\n",spo2);
                            spo2Valid=0;
                        }
                        else
                        {
                           pc.printf("SPO2 calculation waiting for enough samples\r\n");
                        }
                        if(heartRateValid==1)
                        {
                            pc.printf("Heart Rate = %i\r\n",heartRate);
                            heartRateValid=0;
                        }else
                        {
                            pc.printf("Heart rate calculation waiting for enough samples\r\n");
                        }
                        
                        
                    }
                }
            }
        
        // If rc != 0, a communication error has occurred 
        } else {        
            
            pc.printf("Something went wrong, "
                      "check the I2C bus or power connections... \r\n");
            bLed = LED_OFF;
            gLed = LED_OFF;
            
            while(1)
            {
                rLed = !rLed;
                wait(0.5);   
            } 
        }  
        
    } 
}


bool op_sensor_config(MAX30101 &op_sensor) {
    
    //Reset Device
    MAX30101::ModeConfiguration_u modeConfig;
    modeConfig.all = 0;
    modeConfig.bits.reset = 1;
    int32_t rc = op_sensor.setModeConfiguration(modeConfig);
    
        
    //enable MAX30101 interrupts
    MAX30101::InterruptBitField_u ints;
    if(rc == 0)
    {
        ints.all = 0;
        ints.bits.die_temp = 1;     // Enable internal die temp. interrupt
        ints.bits.a_full = 1;       // Enable FIFO almost full interrupt
        rc = op_sensor.enableInterrupts(ints);
    }
    
    //configure FIFO
    MAX30101::FIFO_Configuration_u fifoConfig;
    if(rc == 0)
    {
        fifoConfig.all = 0;
        fifoConfig.bits.fifo_a_full = 15;                               // Max level of 15 samples  
        fifoConfig.bits.sample_average = MAX30101::AveragedSamples_8;   // Average 8 samples
        rc = op_sensor.setFIFOConfiguration(fifoConfig);
    }
    
    MAX30101::SpO2Configuration_u spo2Config;
    if(rc == 0)
    {
        spo2Config.all = 0;                                 // sets smallest LSB size 
        spo2Config.bits.spo2_sr = MAX30101::SR_3200_Hz;     // SpO2 SR = 3200Hz
        spo2Config.bits.led_pw = MAX30101::PW_3;            // 18-bit ADC resolution
        rc = op_sensor.setSpO2Configuration(spo2Config);
    }
    
    //Set LED drive currents
    if(rc == 0)
    {
        // Heart Rate only, 1 LED channel, Pulse amp. = 0x1F
        rc = op_sensor.setLEDPulseAmplitude(MAX30101::LED1_PA, 0x1F);
        //To include SPO2, 2 LED channel, Pulse amp. 0x1F
        if(rc==0)
        {
            rc = op_sensor.setLEDPulseAmplitude(MAX30101::LED2_PA, 0x1F);
        }
    }
       
    //Set operating mode
    modeConfig.all = 0;
    if(rc == 0)
    {
        modeConfig.bits.mode = MAX30101::SpO2Mode;     // Sets SPO2 Mode 
        rc = op_sensor.setModeConfiguration(modeConfig);
    }    
    
    
    return rc;
}

void pmic_config(I2C & i2c_bus, DigitalOut & pmic_en)
{
    
    const uint8_t PMIC_ADRS = 0x54;
    const uint8_t BBB_EXTRA_ADRS = 0x1C;
    const uint8_t BOOST_VOLTAGE = 0x05;
    
    char data_buff[] = {BBB_EXTRA_ADRS, 0x40};    //BBBExtra register address 
                                                  //and data to enable passive 
                                                  //pull down. 
    i2c_bus.write(PMIC_ADRS, data_buff,2);        //write to BBBExtra register
    
    data_buff[0] = BOOST_VOLTAGE;
    data_buff[1] = 0x14;                          //Boost voltage configuration 
                                                  //register followed by data 
                                                  //to set voltage to 4.5V 
    pmic_en = 0;                                  //disables VLED 
    i2c_bus.write(PMIC_ADRS, data_buff,2);        //write to BBBExtra register
    pmic_en = 1;                                  //enables VLED                                               
}