Bradley Kohler / Mbed OS PulseRate

Dependencies:   PulseRate

Dependents:   PulseRate

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MAX30100.h Source File

MAX30100.h

00001 #ifndef MAX30100_H
00002 #define MAX30100_H
00003 
00004 #include "mbed.h"
00005 
00006 //definitions
00007 #define MAX30100_ADDRESS 0xAE
00008 
00009 // Registers
00010 #define MAX30100_INT_STATUS     0x00  // Which interrupts are tripped
00011 #define MAX30100_INT_ENABLE     0x01  // Which interrupts are active
00012 #define MAX30100_FIFO_WR_PTR    0x02  // Where data is being written
00013 #define MAX30100_OVRFLOW_CTR    0x03  // Number of lost samples
00014 #define MAX30100_FIFO_RD_PTR    0x04  // Where to read from
00015 #define MAX30100_FIFO_DATA      0x05  // Ouput data buffer
00016 #define MAX30100_MODE_CONFIG    0x06  // Control register
00017 #define MAX30100_SPO2_CONFIG    0x07  // Oximetry settings
00018 #define MAX30100_LED_CONFIG     0x09  // Pulse width and power of LEDs
00019 #define MAX30100_TEMP_INTG      0x16  // Temperature value, whole number
00020 #define MAX30100_TEMP_FRAC      0x17  // Temperature value, fraction
00021 #define MAX30100_REV_ID         0xFE  // Part revision
00022 #define MAX30100_PART_ID        0xFF  // Part ID, normally 0x11
00023 
00024 #define POR_PART_ID             0x11
00025 
00026 //Mode Configuration register
00027 #define MAX30100_MC_TEMP_EN                     (1 << 3)
00028 #define MAX30100_MC_RESET                       (1 << 6)
00029 #define MAX30100_MC_SHDN                        (1 << 7)
00030 
00031 typedef enum Mode {
00032     MAX30100_MODE_HRONLY    = 0x02,
00033     MAX30100_MODE_SPO2_HR   = 0x03
00034 } Mode;
00035 
00036 // SpO2 Configuration register
00037 // Check tables 8 and 9, p19 of the MAX30100 datasheet to see the permissible
00038 // combinations of sampling rates and pulse widths
00039 #define MAX30100_SPC_SPO2_HI_RES_EN             (1 << 6)
00040 typedef enum SamplingRate {
00041     MAX30100_SAMPRATE_50HZ      = 0x00,
00042     MAX30100_SAMPRATE_100HZ     = 0x01,
00043     MAX30100_SAMPRATE_167HZ     = 0x02,
00044     MAX30100_SAMPRATE_200HZ     = 0x03,
00045     MAX30100_SAMPRATE_400HZ     = 0x04,
00046     MAX30100_SAMPRATE_600HZ     = 0x05,
00047     MAX30100_SAMPRATE_800HZ     = 0x06,
00048     MAX30100_SAMPRATE_1000HZ    = 0x07
00049 } SamplingRate;
00050 
00051 typedef enum LEDPulseWidth {
00052     MAX30100_SPC_PW_200US_13BITS    = 0x00,
00053     MAX30100_SPC_PW_400US_14BITS    = 0x01,
00054     MAX30100_SPC_PW_800US_15BITS    = 0x02,
00055     MAX30100_SPC_PW_1600US_16BITS   = 0x03
00056 } LEDPulseWidth;
00057 
00058 // LED Configuration register
00059 typedef enum LEDCurrent {
00060     MAX30100_LED_CURR_0MA      = 0x00,
00061     MAX30100_LED_CURR_4_4MA    = 0x01,
00062     MAX30100_LED_CURR_7_6MA    = 0x02,
00063     MAX30100_LED_CURR_11MA     = 0x03,
00064     MAX30100_LED_CURR_14_2MA   = 0x04,
00065     MAX30100_LED_CURR_17_4MA   = 0x05,
00066     MAX30100_LED_CURR_20_8MA   = 0x06,
00067     MAX30100_LED_CURR_24MA     = 0x07,
00068     MAX30100_LED_CURR_27_1MA   = 0x08,
00069     MAX30100_LED_CURR_30_6MA   = 0x09,
00070     MAX30100_LED_CURR_33_8MA   = 0x0a,
00071     MAX30100_LED_CURR_37MA     = 0x0b,
00072     MAX30100_LED_CURR_40_2MA   = 0x0c,
00073     MAX30100_LED_CURR_43_6MA   = 0x0d,
00074     MAX30100_LED_CURR_46_8MA   = 0x0e,
00075     MAX30100_LED_CURR_50MA     = 0x0f
00076 } LEDCurrent;
00077 
00078 #define DEFAULT_MODE                MAX30100_MODE_HRONLY
00079 #define DEFAULT_SAMPLING_RATE       MAX30100_SAMPRATE_100HZ
00080 #define DEFAULT_PULSE_WIDTH         MAX30100_SPC_PW_1600US_16BITS
00081 #define DEFAULT_RED_LED_CURRENT     MAX30100_LED_CURR_50MA
00082 #define DEFAULT_IR_LED_CURRENT      MAX30100_LED_CURR_50MA
00083 #define EXPECTED_PART_ID            0x11
00084 
00085 //Set up I2C, (SDA,SCL)
00086 static I2C i2c(I2C_SDA, I2C_SCL);
00087 static Serial pc(USBTX, USBRX); // tx, rx
00088 
00089 class MAX30100 {
00090  
00091     protected:
00092  
00093     public:
00094     
00095     //Variables
00096     uint16_t rawIRValue;
00097     uint16_t rawRedValue;
00098     
00099     //Wire read and write protocols
00100 static int i2c_write (uint8_t i2c_addr, uint8_t register_addr, char* buffer, uint8_t Nbyte )
00101 {
00102     int ret;
00103     char *tmp_buffer;
00104 
00105     tmp_buffer = (char*)malloc(sizeof(char)*(Nbyte+1));
00106 
00107     /* First, send device address. Then, send data and STOP condition */
00108     tmp_buffer[0] = register_addr;
00109     memcpy(tmp_buffer+1, buffer, Nbyte);
00110 
00111     ret = i2c.write(i2c_addr, tmp_buffer, Nbyte+1, false);
00112 
00113     return ret;
00114 }
00115 
00116 static int i2c_read (uint8_t i2c_addr, uint8_t register_addr, char* buffer, uint8_t Nbyte )
00117 {
00118     int ret;
00119 
00120     /* Send device address, with no STOP condition */
00121     ret = i2c.write(i2c_addr, (const char*)&register_addr, 1, true);
00122     if(!ret) {
00123         /* Read data, with STOP condition  */
00124         ret = i2c.read((i2c_addr|0x01), buffer, Nbyte, false);
00125     }
00126 
00127     return ret;
00128 }
00129     //
00130 
00131 uint8_t getRevID(void){
00132   char buffer[1];
00133   i2c_read(MAX30100_ADDRESS, MAX30100_REV_ID, &buffer[0], 1);
00134   return buffer[0];
00135 }
00136 
00137 uint8_t getPartID(void){
00138   char buffer[1];
00139   i2c_read(MAX30100_ADDRESS, MAX30100_PART_ID, &buffer[0], 1);
00140   return buffer[0];
00141 }
00142 
00143 void shutdown(void){
00144     char reg[1];
00145     i2c_read(MAX30100_ADDRESS, MAX30100_MODE_CONFIG, &reg[0], 1);
00146     reg[0] = reg[0] | MAX30100_MC_SHDN;
00147     i2c_write(MAX30100_ADDRESS, MAX30100_MODE_CONFIG, &reg[0], 1);
00148 }
00149 
00150 void resume(void){
00151     char reg[1];
00152     i2c_read(MAX30100_ADDRESS, MAX30100_MODE_CONFIG, &reg[0], 1);
00153     reg[0] = reg[0] & ~MAX30100_MC_SHDN;
00154     i2c_write(MAX30100_ADDRESS, MAX30100_MODE_CONFIG, &reg[0], 1);
00155 }
00156 
00157 void update(void){
00158     readFifoData();
00159 }
00160 
00161 void printRegisters(void){
00162     char reg[1];
00163     i2c_read(MAX30100_ADDRESS, MAX30100_INT_STATUS, &reg[0], 1);
00164     pc.printf("MAX30100_INT_STATUS: %d\r\n",reg[0]);
00165     i2c_read(MAX30100_ADDRESS, MAX30100_INT_ENABLE, &reg[0], 1);
00166     pc.printf("MAX30100_INT_ENABLE: %d\r\n",reg[0]);
00167     i2c_read(MAX30100_ADDRESS, MAX30100_FIFO_WR_PTR, &reg[0], 1);
00168     pc.printf("MAX30100_FIFO_WR_PTR: %d\r\n",reg[0]);
00169     i2c_read(MAX30100_ADDRESS, MAX30100_OVRFLOW_CTR, &reg[0], 1);
00170     pc.printf("MAX30100_OVRFLOW_CTR: %d\r\n",reg[0]);
00171     i2c_read(MAX30100_ADDRESS, MAX30100_FIFO_RD_PTR, &reg[0], 1);
00172     pc.printf("MAX30100_FIFO_RD_PTR: %d\r\n",reg[0]);
00173     i2c_read(MAX30100_ADDRESS, MAX30100_FIFO_DATA, &reg[0], 1);
00174     pc.printf("MAX30100_FIFO_DATA: %d\r\n",reg[0]);
00175     i2c_read(MAX30100_ADDRESS, MAX30100_MODE_CONFIG, &reg[0], 1);
00176     pc.printf("MAX30100_MODE_CONFIG: %d\r\n",reg[0]);
00177     i2c_read(MAX30100_ADDRESS, MAX30100_SPO2_CONFIG, &reg[0], 1);
00178     pc.printf("MAX30100_SPO2_CONFIG: %d\r\n",reg[0]);
00179     i2c_read(MAX30100_ADDRESS, MAX30100_LED_CONFIG, &reg[0], 1);
00180     pc.printf("MAX30100_LED_CONFIG: %d\r\n",reg[0]);
00181     i2c_read(MAX30100_ADDRESS, MAX30100_TEMP_INTG, &reg[0], 1);
00182     pc.printf("MAX30100_TEMP_INTG: %d\r\n",reg[0]);
00183     i2c_read(MAX30100_ADDRESS, MAX30100_TEMP_FRAC, &reg[0], 1);
00184     pc.printf("MAX30100_TEMP_FRAC: %d\r\n",reg[0]);
00185     i2c_read(MAX30100_ADDRESS, MAX30100_REV_ID, &reg[0], 1);
00186     pc.printf("MAX30100_REV_ID: %d\r\n",reg[0]);
00187     i2c_read(MAX30100_ADDRESS, MAX30100_PART_ID, &reg[0], 1);
00188     pc.printf("MAX30100_PART_ID: %d\r\n",reg[0]);
00189 }
00190 
00191 bool begin(){
00192     if(getPartID() != POR_PART_ID){
00193         return false;
00194     }
00195     setMode(DEFAULT_MODE);
00196     setLedsPulseWidth(DEFAULT_PULSE_WIDTH);
00197     setSamplingRate(DEFAULT_SAMPLING_RATE);
00198     setLedsCurrent(DEFAULT_IR_LED_CURRENT, DEFAULT_RED_LED_CURRENT);
00199     setHighresModeEnabled(true);
00200     
00201     return true;
00202 }
00203 
00204 void setMode(Mode mode){
00205     char reg[1];
00206     reg[0] = mode;
00207     i2c_write(MAX30100_ADDRESS, MAX30100_MODE_CONFIG, &reg[0], 1);
00208 }
00209 
00210 void setLedsPulseWidth(LEDPulseWidth ledPulseWidth){
00211     char reg[1];
00212     i2c_read(MAX30100_ADDRESS, MAX30100_SPO2_CONFIG, &reg[0], 1);
00213     reg[0] = (reg[0] & 0xfc) | ledPulseWidth;
00214     i2c_write(MAX30100_ADDRESS, MAX30100_SPO2_CONFIG, &reg[0], 1);
00215 }
00216 
00217 void setSamplingRate(SamplingRate samplingRate){
00218     char reg[1];
00219     i2c_read(MAX30100_ADDRESS, MAX30100_SPO2_CONFIG, &reg[0], 1);
00220     reg[0] = (reg[0] & 0xe3) | (samplingRate << 2);
00221     i2c_write(MAX30100_ADDRESS, MAX30100_SPO2_CONFIG, &reg[0], 1);
00222 }
00223 
00224 void setLedsCurrent(LEDCurrent irLedCurrent, LEDCurrent redLedCurrent){
00225     char reg[1];
00226     reg[0] = (redLedCurrent << 4) | irLedCurrent;
00227     i2c_write(MAX30100_ADDRESS, MAX30100_LED_CONFIG, &reg[0], 1);
00228 }
00229 
00230 void setHighresModeEnabled(bool enabled){
00231     char reg[1];
00232     i2c_read(MAX30100_ADDRESS, MAX30100_SPO2_CONFIG, &reg[0], 1);
00233     if(enabled){
00234         reg[0] = reg[0] | MAX30100_SPC_SPO2_HI_RES_EN;
00235     }
00236     else{
00237         reg[0] = reg[0] & ~MAX30100_SPC_SPO2_HI_RES_EN;
00238     }
00239     i2c_write(MAX30100_ADDRESS, MAX30100_SPO2_CONFIG, &reg[0], 1);
00240 }
00241 
00242 void readFifoData(void){
00243     char reg[4];
00244     i2c_read(MAX30100_ADDRESS, MAX30100_FIFO_DATA, &reg[0], 4);
00245     rawIRValue = (reg[0] << 8) | reg[1];
00246     rawRedValue = (reg[2] << 8) | reg[3];
00247 }
00248 
00249 void startTemperatureSampling(void){
00250     char reg[1];
00251     i2c_read(MAX30100_ADDRESS, MAX30100_MODE_CONFIG, &reg[0], 1);
00252     reg[0] = reg[0] | MAX30100_MC_TEMP_EN;
00253     i2c_write(MAX30100_ADDRESS, MAX30100_MODE_CONFIG, &reg[0], 1);
00254 }
00255 
00256 bool isTemperatureReady(void){
00257     char reg[1];
00258     bool ret;
00259     ret = i2c_read(MAX30100_ADDRESS, MAX30100_MODE_CONFIG, &reg[0], 1);
00260     ret = ret & MAX30100_MC_TEMP_EN;
00261     return !ret;
00262 }
00263 
00264 float retrieveTemperature(void){
00265     char reg[2];
00266     i2c_read(MAX30100_ADDRESS, MAX30100_TEMP_INTG, &reg[0], 1);
00267     i2c_read(MAX30100_ADDRESS, MAX30100_TEMP_FRAC, &reg[1], 1);
00268     return reg[0] + (reg[1] * 0.0625);
00269 }
00270 
00271 };
00272 #endif