Greg Toth / Mbed OS MAX30101WING_HR_SPO2

Dependencies:   MAX30101 MAX32620FTHR

main.cpp

Committer:
johnGreeneMaxim
Date:
2017-11-20
Revision:
10:fcfa9adc99a9
Parent:
9:affd4e6372a0
Child:
11:976c80cc99d5

File content as of revision 10:fcfa9adc99a9:

/*******************************************************************************
 * 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"



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;
}

//declare large variables outside of main 
uint32_t redData[500];//set array to max fifo size 
uint32_t irData[500];//set array to max fifo size 
    
    
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;
 
    int r=0; //counter for redData position 
    int ir=0; //counter for irData position
    int c=0; //counter to print values
    int32_t spo2 =0;
    int8_t spo2Valid = 0;
    int32_t heartRate = 0;
    int8_t heartRateValid = 0;

    
    pc.printf("Starting Program...Please wait a few seconds while data is being collected.\r\n");
    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)) 
                {
                    // Read FIFO 
                    rc = op_sensor.readFIFO(MAX30101::TwoLedChannels, fifoData, readBytes);     
                
                    if(rc == 0) 
                    {
                        
                        // Convert read bytes into samples
                        for(idx = 0, c=0; idx < readBytes; idx+=3) 
                        {

                            sample = (fifoData[idx]<<16) | (fifoData[idx+1]<<8) | (fifoData[idx+2]);
                            opSample = sample;
                            opSample&=0x03FFFF;  //Mask MSB [23:18]
                            
                            if(idx%2==0)
                            {
                                redData[r] = opSample;//saves to buff for calculations 
                                r++;
                                
                            }
                            else
                            {
                               
                                irData[ir] = opSample; //saves to buff for calculations 
                                ir++;
                                
                            }
                            
                        }
                        
                        if(r>=450 & ir>=450)//checks to make sure there are 450 
                                            //samples in data buffers 
                        {
                            
                            //calculate heart rate and spo2
                            maxim_heart_rate_and_oxygen_saturation( irData, ir, 
                            redData, &spo2, &spo2Valid, &heartRate, &heartRateValid);
                            pc.printf("SPO2 = %i\r\n",spo2);
                            //heart rate is typically twice what it should be, thus divide by 2
                            pc.printf("Heart Rate = %i\r\n",heartRate/2); 
                            
                             for(c=100;c<450;c++)//dump first hundred samples 
                                                 //after calculations 
                            {
                                redData[c-100]=redData[c];
                                irData[c-100]=irData[c];

                            }
                            r=350;
                            ir=350;    
                        }  
                    }
                }
            }
        
        // 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                                               
}