Hexiwear Heart rate sensor driver
Dependents: Hexi_MAX30101 Hexiwear HexiwearFinal HexiwearFinal1
Fork of FXOS8700 by
Revision 3:4bfb42d6c70c, committed 2016-08-30
- 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
--- 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 + + + +