This program for MAX32620HSP board's ECG to recieve raw data on serial. You can delete everything in main() everything happens on StreamPacketUint32_ex

Dependencies:   mbed MAX14720 USBDevice

Dependents:   HSP_ECG_LeadOFF_Detection

Files at this revision

API Documentation at this revision

Comitter:
douqan93
Date:
Thu Mar 28 08:10:23 2019 +0000
Commit message:
MAX32620HSP raw ECG data on serial

Changed in this revision

MAX14720.lib Show annotated file Show diff for this revision Revisions of this file
MAX30001/MAX30001/MAX30001.cpp Show annotated file Show diff for this revision Revisions of this file
MAX30001/MAX30001/MAX30001.h Show annotated file Show diff for this revision Revisions of this file
MAX30101/MAX30101/MAX30101.cpp Show annotated file Show diff for this revision Revisions of this file
MAX30101/MAX30101/MAX30101.h Show annotated file Show diff for this revision Revisions of this file
System/System.cpp Show annotated file Show diff for this revision Revisions of this file
System/System.h Show annotated file Show diff for this revision Revisions of this file
USBDevice.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MAX14720.lib	Thu Mar 28 08:10:23 2019 +0000
@@ -0,0 +1,1 @@
+https://developer.mbed.org/teams/MaximIntegrated/code/MAX14720/#2c3f2da51c5d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MAX30001/MAX30001/MAX30001.cpp	Thu Mar 28 08:10:23 2019 +0000
@@ -0,0 +1,1317 @@
+
+/*******************************************************************************
+ * Copyright (C) 2016 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 "MAX30001.h"
+
+MAX30001 *MAX30001::instance = NULL;
+
+//******************************************************************************
+MAX30001::MAX30001(PinName mosi, PinName miso, PinName sclk, PinName cs) {
+  spi = new SPI(mosi, miso, sclk, cs);
+  spi->frequency(3000000);
+  spi_owner = true;
+  functionpointer.attach(&spiHandler);
+  onDataAvailableCallback = NULL;
+  instance = this;
+}
+
+//******************************************************************************
+MAX30001::MAX30001(SPI *_spi) {
+  spi = _spi;
+  spi->frequency(3000000);
+  spi_owner = false;
+  functionpointer.attach(&spiHandler);
+  onDataAvailableCallback = NULL;
+  instance = this;
+}
+
+//******************************************************************************
+MAX30001::~MAX30001(void) {
+  if (spi_owner) {
+    delete spi;
+  }
+}
+
+//******************************************************************************
+int MAX30001::max30001_Rbias_FMSTR_Init(uint8_t En_rbias, uint8_t Rbiasv,
+                                        uint8_t Rbiasp, uint8_t Rbiasn,
+                                        uint8_t Fmstr) {
+  if (max30001_reg_read(CNFG_GEN, &max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  max30001_cnfg_gen.bit.en_rbias = En_rbias;
+  max30001_cnfg_gen.bit.rbiasv   = Rbiasv;
+  max30001_cnfg_gen.bit.rbiasp   = Rbiasp;
+  max30001_cnfg_gen.bit.rbiasn   = Rbiasn;
+  max30001_cnfg_gen.bit.fmstr    = Fmstr;
+
+  if (max30001_reg_write(CNFG_GEN, max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+  return 0;
+}
+
+//******************************************************************************
+int MAX30001::max30001_CAL_InitStart(uint8_t En_Vcal, uint8_t Vmode,
+                                     uint8_t Vmag, uint8_t Fcal, uint16_t Thigh,
+                                     uint8_t Fifty) {
+  // CNFG_CAL
+  if (max30001_reg_read(CNFG_CAL, &max30001_cnfg_cal.all) == -1) {
+    return -1;
+  }
+
+  max30001_cnfg_cal.bit.vmode = Vmode;
+  max30001_cnfg_cal.bit.vmag  = Vmag;
+  max30001_cnfg_cal.bit.fcal  = Fcal;
+  max30001_cnfg_cal.bit.thigh = Thigh;
+  max30001_cnfg_cal.bit.fifty = Fifty;
+
+  if (max30001_reg_write(CNFG_CAL, max30001_cnfg_cal.all) == -1) {
+    return -1;
+  }
+
+  // RTOS uses a 32768HZ clock.  32768ticks represents 1secs.  1sec/10 =
+  // 100msecs.
+  wait(1.0 / 10.0);
+
+  if (max30001_reg_read(CNFG_CAL, &max30001_cnfg_cal.all) == -1) {
+    return -1;
+  }
+
+  max30001_cnfg_cal.bit.en_vcal = En_Vcal;
+
+  if (max30001_reg_write(CNFG_CAL, max30001_cnfg_cal.all) == -1) {
+    return -1;
+  }
+
+  // RTOS uses a 32768HZ clock.  32768ticks represents 1secs.  1sec/10 =
+  // 100msecs.
+  wait(1.0 / 10.0);
+
+  return 0;
+}
+
+//******************************************************************************
+int MAX30001::max30001_CAL_Stop(void) {
+
+  if (max30001_reg_read(CNFG_CAL, &max30001_cnfg_cal.all) == -1) {
+    return -1;
+  }
+
+  max30001_cnfg_cal.bit.en_vcal = 0; // Disable VCAL, all other settings are left unaffected
+
+  if (max30001_reg_write(CNFG_CAL, max30001_cnfg_cal.all) == -1) {
+    return -1;
+  }
+
+  return 0;
+}
+//******************************************************************************
+//******************************************************************************
+int MAX30001::max30001_INT_assignment(max30001_intrpt_Location_t en_enint_loc,     max30001_intrpt_Location_t en_eovf_loc,  max30001_intrpt_Location_t en_fstint_loc,
+		                      max30001_intrpt_Location_t en_dcloffint_loc, max30001_intrpt_Location_t en_bint_loc,  max30001_intrpt_Location_t en_bovf_loc,
+		                      max30001_intrpt_Location_t en_bover_loc,     max30001_intrpt_Location_t en_bundr_loc, max30001_intrpt_Location_t en_bcgmon_loc,
+		                      max30001_intrpt_Location_t en_pint_loc,      max30001_intrpt_Location_t en_povf_loc,  max30001_intrpt_Location_t en_pedge_loc,
+		                      max30001_intrpt_Location_t en_lonint_loc,    max30001_intrpt_Location_t en_rrint_loc, max30001_intrpt_Location_t en_samp_loc,
+		                      max30001_intrpt_type_t  intb_Type,           max30001_intrpt_type_t int2b_Type)
+
+
+{
+  // INT1
+
+  if (max30001_reg_read(EN_INT, &max30001_en_int.all) == -1) {
+    return -1;
+  }
+
+  // max30001_en_int2.bit.en_pint       = 0b1;  // Keep this off...
+
+  max30001_en_int.bit.en_eint = 0b1 & en_enint_loc;
+  max30001_en_int.bit.en_eovf = 0b1 & en_eovf_loc;
+  max30001_en_int.bit.en_fstint = 0b1 & en_fstint_loc;
+
+  max30001_en_int.bit.en_dcloffint = 0b1 & en_dcloffint_loc;
+  max30001_en_int.bit.en_bint = 0b1 & en_bint_loc;
+  max30001_en_int.bit.en_bovf = 0b1 & en_bovf_loc;
+
+  max30001_en_int.bit.en_bover = 0b1 & en_bover_loc;
+  max30001_en_int.bit.en_bundr = 0b1 & en_bundr_loc;
+  max30001_en_int.bit.en_bcgmon = 0b1 & en_bcgmon_loc;
+
+  max30001_en_int.bit.en_pint = 0b1 & en_pint_loc;
+  max30001_en_int.bit.en_povf = 0b1 & en_povf_loc;
+  max30001_en_int.bit.en_pedge = 0b1 & en_pedge_loc;
+
+  max30001_en_int.bit.en_lonint = 0b1 & en_lonint_loc;
+  max30001_en_int.bit.en_rrint = 0b1 & en_rrint_loc;
+  max30001_en_int.bit.en_samp = 0b1 & en_samp_loc;
+
+  max30001_en_int.bit.intb_type = int2b_Type;
+
+  if (max30001_reg_write(EN_INT, max30001_en_int.all) == -1) {
+    return -1;
+  }
+
+  // INT2
+
+  if (max30001_reg_read(EN_INT2, &max30001_en_int2.all) == -1) {
+    return -1;
+  }
+
+  max30001_en_int2.bit.en_eint   = 0b1 & (en_enint_loc >> 1);
+  max30001_en_int2.bit.en_eovf   = 0b1 & (en_eovf_loc >> 1);
+  max30001_en_int2.bit.en_fstint = 0b1 & (en_fstint_loc >> 1);
+
+  max30001_en_int2.bit.en_dcloffint = 0b1 & (en_dcloffint_loc >> 1);
+  max30001_en_int2.bit.en_bint      = 0b1 & (en_bint_loc >> 1);
+  max30001_en_int2.bit.en_bovf      = 0b1 & (en_bovf_loc >> 1);
+
+  max30001_en_int2.bit.en_bover  = 0b1 & (en_bover_loc >> 1);
+  max30001_en_int2.bit.en_bundr  = 0b1 & (en_bundr_loc >> 1);
+  max30001_en_int2.bit.en_bcgmon = 0b1 & (en_bcgmon_loc >> 1);
+
+  max30001_en_int2.bit.en_pint  = 0b1 & (en_pint_loc >> 1);
+  max30001_en_int2.bit.en_povf  = 0b1 & (en_povf_loc >> 1);
+  max30001_en_int2.bit.en_pedge = 0b1 & (en_pedge_loc >> 1);
+
+  max30001_en_int2.bit.en_lonint = 0b1 & (en_lonint_loc >> 1);
+  max30001_en_int2.bit.en_rrint  = 0b1 & (en_rrint_loc >> 1);
+  max30001_en_int2.bit.en_samp   = 0b1 & (en_samp_loc >> 1);
+
+  max30001_en_int2.bit.intb_type = intb_Type;
+
+  if (max30001_reg_write(EN_INT2, max30001_en_int2.all) == -1) {
+    return -1;
+  }
+
+  return 0;
+}
+
+//******************************************************************************
+int MAX30001::max30001_ECG_InitStart(uint8_t En_ecg, uint8_t Openp,
+                                     uint8_t Openn, uint8_t Pol,
+                                     uint8_t Calp_sel, uint8_t Caln_sel,
+                                     uint8_t E_fit, uint8_t Rate, uint8_t Gain,
+                                     uint8_t Dhpf, uint8_t Dlpf) {
+
+  // CNFG_EMUX
+
+  if (max30001_reg_read(CNFG_EMUX, &max30001_cnfg_emux.all) == -1) {
+    return -1;
+  }
+
+  max30001_cnfg_emux.bit.openp    = Openp;
+  max30001_cnfg_emux.bit.openn    = Openn;
+  max30001_cnfg_emux.bit.pol      = Pol;
+  max30001_cnfg_emux.bit.calp_sel = Calp_sel;
+  max30001_cnfg_emux.bit.caln_sel = Caln_sel;
+
+  if (max30001_reg_write(CNFG_EMUX, max30001_cnfg_emux.all) == -1) {
+    return -1;
+  }
+
+  /**** ENABLE CHANNELS ****/
+  // CNFG_GEN
+
+  if (max30001_reg_read(CNFG_GEN, &max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  max30001_cnfg_gen.bit.en_ecg = En_ecg; // 0b1
+
+  // fmstr is default
+
+  if (max30001_reg_write(CNFG_GEN, max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  /**** Wait for PLL Lock & References to settle down ****/
+
+  max30001_timeout = 0;
+
+  do {
+    if (max30001_reg_read(STATUS, &max30001_status.all) == -1) // Wait and spin for PLL to lock...
+    {
+      return -1;
+    }
+  } while (max30001_status.bit.pllint == 1 && max30001_timeout++ <= 1000);
+
+  // MNGR_INT
+
+  if (max30001_reg_read(MNGR_INT, &max30001_mngr_int.all) == -1) {
+    return -1;
+  }
+
+  max30001_mngr_int.bit.e_fit = E_fit; // 31
+
+  if (max30001_reg_write(MNGR_INT, max30001_mngr_int.all) == -1) {
+    return -1;
+  }
+
+  // CNFG_ECG
+
+  if (max30001_reg_read(CNFG_ECG, &max30001_cnfg_ecg.all) == -1) {
+    return -1;
+  }
+
+  max30001_cnfg_ecg.bit.rate = Rate; 
+  max30001_cnfg_ecg.bit.gain = Gain;
+  max30001_cnfg_ecg.bit.dhpf = Dhpf;
+  max30001_cnfg_ecg.bit.dlpf = Dlpf;
+
+  if (max30001_reg_write(CNFG_ECG, max30001_cnfg_ecg.all) == -1) {
+    return -1;
+  }
+
+  return 0;
+}
+
+//******************************************************************************
+int MAX30001::max30001_ECGFast_Init(uint8_t Clr_Fast, uint8_t Fast, uint8_t Fast_Th) {
+  if (max30001_reg_read(MNGR_INT, &max30001_mngr_int.all) == -1) {
+    return -1;
+  }
+
+  max30001_mngr_int.bit.clr_fast = Clr_Fast;
+
+  if (max30001_reg_write(MNGR_INT, max30001_mngr_int.all) == -1) {
+    return -1;
+  }
+
+  if (max30001_reg_read(MNGR_DYN, &max30001_mngr_dyn.all) == -1) {
+    return -1;
+  }
+
+  max30001_mngr_dyn.bit.fast = Fast;
+  max30001_mngr_dyn.bit.fast_th = Fast_Th;
+
+  if (max30001_reg_write(MNGR_INT, max30001_mngr_int.all) == -1) {
+    return -1;
+  }
+
+  return 0;
+}
+
+//******************************************************************************
+int MAX30001::max30001_Stop_ECG(void) {
+
+  if (max30001_reg_read(CNFG_GEN, &max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  max30001_cnfg_gen.bit.en_ecg = 0; // Stop ECG
+
+  // fmstr is default
+
+  if (max30001_reg_write(CNFG_GEN, max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  return 0;
+}
+
+//******************************************************************************
+int MAX30001::max30001_PACE_InitStart(uint8_t En_pace, uint8_t Clr_pedge,
+                                      uint8_t Pol, uint8_t Gn_diff_off,
+                                      uint8_t Gain, uint8_t Aout_lbw,
+                                      uint8_t Aout, uint8_t Dacp,
+                                      uint8_t Dacn) {
+
+  /**** SET MASTER FREQUENCY, ENABLE CHANNELS ****/
+
+  // CNFG_GEN
+
+  if (max30001_reg_read(CNFG_GEN, &max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  max30001_cnfg_gen.bit.en_pace = En_pace; // 0b1;
+
+  if (max30001_reg_write(CNFG_GEN, max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  /**** Wait for PLL Lock & References to settle down ****/
+  max30001_timeout = 0;
+
+  do {
+    if (max30001_reg_read(STATUS, &max30001_status.all) ==
+        -1) // Wait and spin for PLL to lock...
+    {
+      return -1;
+    }
+
+  } while (max30001_status.bit.pllint == 1 && max30001_timeout++ <= 1000);
+
+  // MNGR_INT
+
+  if (max30001_reg_read(MNGR_INT, &max30001_mngr_int.all) == -1) {
+    return -1;
+  }
+
+  max30001_mngr_int.bit.clr_pedge = Clr_pedge; // 0b0;
+
+  if (max30001_reg_write(MNGR_INT, max30001_mngr_int.all) == -1) {
+    return -1;
+  }
+
+  /* Put: CNFG_PACE */
+
+  max30001_reg_read(CNFG_PACE, &max30001_cnfg_pace.all);
+
+  max30001_cnfg_pace.bit.pol         = Pol;         
+  max30001_cnfg_pace.bit.gn_diff_off = Gn_diff_off;
+  max30001_cnfg_pace.bit.gain        = Gain;
+  max30001_cnfg_pace.bit.aout_lbw    = Aout_lbw;
+  max30001_cnfg_pace.bit.aout        = Aout;
+  max30001_cnfg_pace.bit.dacp        = Dacp;
+  max30001_cnfg_pace.bit.dacn        = Dacn;
+
+  max30001_reg_write(CNFG_PACE, max30001_cnfg_pace.all);
+
+  return 0;
+}
+//******************************************************************************
+int MAX30001::max30001_Stop_PACE(void) {
+
+  if (max30001_reg_read(CNFG_GEN, &max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  max30001_cnfg_gen.bit.en_pace = 0; // Stop PACE
+
+  if (max30001_reg_write(CNFG_GEN, max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  return 0;
+}
+
+//******************************************************************************
+int MAX30001::max30001_BIOZ_InitStart(
+    uint8_t En_bioz, uint8_t Openp, uint8_t Openn, uint8_t Calp_sel,
+    uint8_t Caln_sel, uint8_t CG_mode, uint8_t B_fit, uint8_t Rate,
+    uint8_t Ahpf, uint8_t Ext_rbias, uint8_t Gain, uint8_t Dhpf, uint8_t Dlpf,
+    uint8_t Fcgen, uint8_t Cgmon, uint8_t Cgmag, uint8_t Phoff) {
+
+  // CNFG_BMUX
+
+  if (max30001_reg_read(CNFG_BMUX, &max30001_cnfg_bmux.all) == -1) {
+    return -1;
+  }
+
+  max30001_cnfg_bmux.bit.openp    = Openp;       // 0b1;
+  max30001_cnfg_bmux.bit.openn    = Openn;       // 0b1;
+  max30001_cnfg_bmux.bit.calp_sel = Calp_sel; // 0b10;
+  max30001_cnfg_bmux.bit.caln_sel = Caln_sel; // 0b11;
+  max30001_cnfg_bmux.bit.cg_mode  = CG_mode;   // 0b00;
+
+  if (max30001_reg_write(CNFG_BMUX, max30001_cnfg_bmux.all) == -1) {
+    return -1;
+  }
+
+  /**** SET MASTER FREQUENCY, ENABLE CHANNELS ****/
+
+  // CNFG_GEN
+
+  if (max30001_reg_read(CNFG_GEN, &max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  max30001_cnfg_gen.bit.en_bioz = En_bioz;
+
+  // fmstr is default
+
+  if (max30001_reg_write(CNFG_GEN, max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  /**** Wait for PLL Lock & References to settle down ****/
+
+  max30001_timeout = 0;
+
+  do {
+    if (max30001_reg_read(STATUS, &max30001_status.all) ==
+        -1) // Wait and spin for PLL to lock...
+    {
+      return -1;
+    }
+
+  } while (max30001_status.bit.pllint == 1 && max30001_timeout++ <= 1000);
+
+  /**** Start of CNFG_BIOZ ****/
+
+  // MNGR_INT
+
+  if (max30001_reg_read(MNGR_INT, &max30001_mngr_int.all) == -1) {
+    return -1;
+  }
+
+  max30001_mngr_int.bit.b_fit = B_fit; //;
+
+  if (max30001_reg_write(MNGR_INT, max30001_mngr_int.all) == -1) {
+    return -1;
+  }
+
+  // CNFG_BIOZ
+
+  if (max30001_reg_read(CNFG_BIOZ, &max30001_cnfg_bioz.all) == -1) {
+    return -1;
+  }
+
+  max30001_cnfg_bioz.bit.rate      = Rate;
+  max30001_cnfg_bioz.bit.ahpf      = Ahpf;
+  max30001_cnfg_bioz.bit.ext_rbias = Ext_rbias;
+  max30001_cnfg_bioz.bit.gain      = Gain;
+  max30001_cnfg_bioz.bit.dhpf      = Dhpf;
+  max30001_cnfg_bioz.bit.dlpf      = Dlpf;
+  max30001_cnfg_bioz.bit.fcgen     = Fcgen;
+  max30001_cnfg_bioz.bit.cgmon     = Cgmon;
+  max30001_cnfg_bioz.bit.cgmag     = Cgmag;
+  max30001_cnfg_bioz.bit.phoff     = Phoff;
+
+  if (max30001_reg_write(CNFG_BIOZ, max30001_cnfg_bioz.all) == -1) {
+    return -1;
+  }
+
+  return 0;
+}
+
+//******************************************************************************
+int MAX30001::max30001_Stop_BIOZ(void) {
+
+  if (max30001_reg_read(CNFG_GEN, &max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  max30001_cnfg_gen.bit.en_bioz = 0; // Stop BIOZ
+
+  if (max30001_reg_write(CNFG_GEN, max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  return 0;
+}
+
+//******************************************************************************
+int MAX30001::max30001_BIOZ_InitBist(uint8_t En_bist, uint8_t Rnom,
+                                     uint8_t Rmod, uint8_t Fbist) {
+
+  // CNFG_BMUX
+
+  if (max30001_reg_read(CNFG_BMUX, &max30001_cnfg_bmux.all) == -1) {
+    return -1;
+  }
+
+  max30001_cnfg_bmux.bit.en_bist = En_bist;
+  max30001_cnfg_bmux.bit.rnom = Rnom;
+  max30001_cnfg_bmux.bit.rmod = Rmod;
+  max30001_cnfg_bmux.bit.fbist = Fbist;
+
+  if (max30001_reg_write(CNFG_BMUX, max30001_cnfg_bmux.all) == -1) {
+    return -1;
+  }
+
+  return 0;
+}
+//******************************************************************************
+int MAX30001::max30001_RtoR_InitStart(uint8_t En_rtor, uint8_t Wndw,
+                                      uint8_t Gain, uint8_t Pavg, uint8_t Ptsf,
+                                      uint8_t Hoff, uint8_t Ravg, uint8_t Rhsf,
+                                      uint8_t Clr_rrint) {
+
+  // MNGR_INT
+
+  if (max30001_reg_read(MNGR_INT, &max30001_mngr_int.all) == -1) {
+    return -1;
+  }
+
+  max30001_mngr_int.bit.clr_rrint =
+      Clr_rrint; // 0b01 & 0b00 are for interrupt mode...
+  // 0b10 is for monitoring mode... it just overwrites the data...
+
+  if (max30001_reg_write(MNGR_INT, max30001_mngr_int.all) == -1) {
+    return -1;
+  }
+
+  // RTOR1
+  if (max30001_reg_read(CNFG_RTOR1, &max30001_cnfg_rtor1.all) == -1) {
+    return -1;
+  }
+
+  max30001_cnfg_rtor1.bit.wndw = Wndw;
+  max30001_cnfg_rtor1.bit.gain = Gain;
+  max30001_cnfg_rtor1.bit.en_rtor = En_rtor;
+  max30001_cnfg_rtor1.bit.pavg = Pavg;
+  max30001_cnfg_rtor1.bit.ptsf = Ptsf;
+
+  if (max30001_reg_write(CNFG_RTOR1, max30001_cnfg_rtor1.all) == -1) {
+    return -1;
+  }
+  // RTOR2
+
+  if (max30001_reg_read(CNFG_RTOR2, &max30001_cnfg_rtor2.all) == -1) {
+    return -1;
+  }
+  max30001_cnfg_rtor2.bit.hoff = Hoff;
+  max30001_cnfg_rtor2.bit.ravg = Ravg;
+  max30001_cnfg_rtor2.bit.rhsf = Rhsf;
+
+  if (max30001_reg_write(CNFG_RTOR2, max30001_cnfg_rtor2.all) == -1) {
+    return -1;
+  }
+
+  return 0;
+}
+
+//******************************************************************************
+int MAX30001::max30001_Stop_RtoR(void) {
+
+  if (max30001_reg_read(CNFG_RTOR1, &max30001_cnfg_rtor1.all) == -1) {
+    return -1;
+  }
+
+  max30001_cnfg_rtor1.bit.en_rtor = 0; // Stop RtoR
+
+  if (max30001_reg_write(CNFG_RTOR1, max30001_cnfg_rtor1.all) == -1) {
+    return -1;
+  }
+
+  return 0;
+}
+
+//******************************************************************************
+int MAX30001::max30001_PLL_lock(void) {
+  // Spin to see PLLint become zero to indicate a lock.
+
+  max30001_timeout = 0;
+
+  do {
+    if (max30001_reg_read(STATUS, &max30001_status.all) ==
+        -1) // Wait and spin for PLL to lock...
+    {
+      return -1;
+    }
+
+  } while (max30001_status.bit.pllint == 1 && max30001_timeout++ <= 1000);
+
+  return 0;
+}
+
+//******************************************************************************
+int MAX30001::max30001_sw_rst(void) {
+  // SW reset for the MAX30001 chip
+
+  if (max30001_reg_write(SW_RST, 0x000000) == -1) {
+    return -1;
+  }
+
+  return 0;
+}
+
+//******************************************************************************
+int MAX30001::max30001_synch(void) { // For synchronization
+  if (max30001_reg_write(SYNCH, 0x000000) == -1) {
+    return -1;
+  }
+  return 0;
+}
+
+//******************************************************************************
+int MAX30001::max300001_fifo_rst(void) { // Resets the FIFO
+  if (max30001_reg_write(FIFO_RST, 0x000000) == -1) {
+    return -1;
+  }
+  return 0;
+}
+
+//******************************************************************************
+// int MAX30001::max30001_reg_write(uint8_t addr, uint32_t data)
+int MAX30001::max30001_reg_write(MAX30001_REG_map_t addr, uint32_t data) {
+
+  uint8_t result[4];
+  uint8_t data_array[4];
+  int32_t success = 0;
+
+  data_array[0] = (addr << 1) & 0xff;
+
+  data_array[3] = data & 0xff;
+  data_array[2] = (data >> 8) & 0xff;
+  data_array[1] = (data >> 16) & 0xff;
+
+  success = SPI_Transmit(&data_array[0], 4, &result[0], 4);
+
+  if (success != 0) {
+    return -1;
+  } else {
+    return 0;
+  }
+}
+
+//******************************************************************************
+// int MAX30001::max30001_reg_read(uint8_t addr, uint32_t *return_data)
+int MAX30001::max30001_reg_read(MAX30001_REG_map_t addr,
+                                uint32_t *return_data) {
+  uint8_t result[4];
+  uint8_t data_array[1];
+  int32_t success = 0;
+
+  data_array[0] = ((addr << 1) & 0xff) | 1; // For Read, Or with 1
+  success = SPI_Transmit(&data_array[0], 1, &result[0], 4);
+  *return_data = /*result[0] + */ (uint32_t)(result[1] << 16) +
+                 (result[2] << 8) + result[3];
+  if (success != 0) {
+    return -1;
+  } else {
+    return 0;
+  }
+}
+
+//******************************************************************************
+int MAX30001::max30001_Enable_DcLeadOFF_Init(int8_t En_dcloff, int8_t Ipol,
+                                             int8_t Imag, int8_t Vth) {
+  //  the leads are not touching the body
+
+  // CNFG_EMUX, Set ECGP and ECGN for external hook up...
+
+  if (max30001_reg_read(CNFG_GEN, &max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  max30001_cnfg_gen.bit.en_dcloff = En_dcloff;
+  max30001_cnfg_gen.bit.ipol = Ipol;
+  max30001_cnfg_gen.bit.imag = Imag;
+  max30001_cnfg_gen.bit.vth = Vth;
+
+  if (max30001_reg_write(CNFG_GEN, max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  return 0;
+}
+
+//******************************************************************************
+int MAX30001::max30001_Disable_DcLeadOFF(void) {
+  if (max30001_reg_read(CNFG_GEN, &max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  max30001_cnfg_gen.bit.en_dcloff = 0; // Turned off the dc lead off.
+
+  if (max30001_reg_write(CNFG_GEN, max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  return 0;
+}
+
+//******************************************************************************
+int MAX30001::max30001_BIOZ_Enable_ACLeadOFF_Init(uint8_t En_bloff,
+                                                  uint8_t Bloff_hi_it,
+                                                  uint8_t Bloff_lo_it) {
+
+  // CNFG_GEN
+  if (max30001_reg_read(CNFG_GEN, &max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  max30001_cnfg_gen.bit.en_bloff = En_bloff;
+
+  if (max30001_reg_write(CNFG_GEN, max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  // MNGR_DYN
+  if (max30001_reg_read(MNGR_DYN, &max30001_mngr_dyn.all) == -1) {
+    return -1;
+  }
+
+  max30001_mngr_dyn.bit.bloff_hi_it = Bloff_hi_it;
+  max30001_mngr_dyn.bit.bloff_lo_it = Bloff_lo_it;
+
+  if (max30001_reg_write(MNGR_DYN, max30001_mngr_dyn.all) == -1) {
+    return -1;
+  }
+
+  return 0;
+}
+
+//******************************************************************************
+int MAX30001::max30001_BIOZ_Disable_ACleadOFF(void) {
+  // CNFG_GEN
+  if (max30001_reg_read(CNFG_GEN, &max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  max30001_cnfg_gen.bit.en_bloff = 0b0; // Turns of the BIOZ AC Lead OFF feature
+
+  if (max30001_reg_write(CNFG_GEN, max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  return 0;
+}
+
+//******************************************************************************
+int MAX30001::max30001_BIOZ_Enable_BCGMON(void) {
+  // CNFG_BIOZ
+  if (max30001_reg_read(CNFG_BIOZ, &max30001_cnfg_bioz.all) == -1) {
+    return -1;
+  }
+
+  max30001_cnfg_bioz.bit.cgmon = 1;
+
+  if (max30001_reg_write(CNFG_BIOZ, max30001_cnfg_bioz.all) == -1) {
+    return -1;
+  }
+
+  max30001_reg_read(CNFG_BIOZ, &max30001_cnfg_bioz.all);
+
+  return 0;
+}
+
+#if 1
+//******************************************************************************
+int MAX30001::max30001_Enable_LeadON(int8_t Channel) // Channel: ECG = 0b01, BIOZ = 0b10, Disable = 0b00
+{
+
+  if (max30001_reg_read(CNFG_GEN, &max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  max30001_cnfg_gen.bit.en_ecg  = 0b0;
+  max30001_cnfg_gen.bit.en_bioz = 0b0;
+  max30001_cnfg_gen.bit.en_pace = 0b0;
+
+  max30001_cnfg_gen.bit.en_ulp_lon = Channel; // BIOZ ULP lead on detection...
+
+  if (max30001_reg_write(CNFG_GEN, max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  max30001_reg_read(CNFG_GEN, &max30001_cnfg_gen.all);
+
+  max30001_reg_read(STATUS, &max30001_status.all);
+
+  return 0;
+}
+//******************************************************************************
+int MAX30001::max30001_Disable_LeadON(void) {
+
+  if (max30001_reg_read(CNFG_GEN, &max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  max30001_cnfg_gen.bit.en_ulp_lon = 0b0;
+
+  if (max30001_reg_write(CNFG_GEN, max30001_cnfg_gen.all) == -1) {
+    return -1;
+  }
+
+  return 0;
+}
+#endif
+//******************************************************************************
+#define LEADOFF_SERVICE_TIME 0x2000 // 0x1000 = 1 second
+#define LEADOFF_NUMSTATES 2
+uint32_t leadoffState = 0;
+uint32_t max30001_LeadOffoldTime = 0;
+void MAX30001::max30001_ServiceLeadoff(uint32_t currentTime) {
+
+  uint32_t delta_Time;
+
+  delta_Time = currentTime - max30001_LeadOffoldTime;
+
+  if (delta_Time > LEADOFF_SERVICE_TIME) {
+    switch (leadoffState) {
+    case 0: /* switch to ECG DC Lead OFF */
+      max30001_Enable_DcLeadOFF_Init(0b01, 0b0, 0b001, 0b00);
+      break;
+
+    case 1: /* switch to BIOZ DC Lead OFF */
+      max30001_Enable_DcLeadOFF_Init(0b10, 0b0, 0b001, 0b00);
+      break;
+    }
+
+    leadoffState++;
+    leadoffState %= LEADOFF_NUMSTATES;
+
+    max30001_LeadOffoldTime = currentTime;
+  }
+}
+//******************************************************************************
+#define LEADON_SERVICE_TIME 0x2000 // 0x1000 = 1 second
+#define LEADON_NUMSTATES 2
+uint32_t leadOnState = 0;
+uint32_t max30001_LeadOnoldTime = 0;
+void MAX30001::max30001_ServiceLeadON(uint32_t currentTime) {
+
+  uint32_t delta_Time;
+
+  delta_Time = currentTime - max30001_LeadOnoldTime;
+
+  if (delta_Time > LEADON_SERVICE_TIME) {
+    switch (leadOnState) {
+    case 0: /* switch to ECG DC Lead ON */
+      max30001_Enable_LeadON(0b01);
+      break;
+
+    case 1: /* switch to BIOZ DC Lead ON */
+      max30001_Enable_LeadON(0b10);
+      break;
+    }
+
+    leadOnState++;
+    leadOnState %= LEADON_NUMSTATES;
+
+    max30001_LeadOnoldTime = currentTime;
+  }
+}
+
+//******************************************************************************
+int MAX30001::max30001_FIFO_LeadONOff_Read(void) {
+
+  uint8_t result[32 * 3]; // 32words - 3bytes each
+
+  uint8_t data_array[4];
+  int32_t success = 0;
+  int i, j;
+
+  uint32_t total_databytes;
+  uint8_t i_index;
+  uint8_t data_chunk;
+  uint8_t loop_logic;
+
+  uint8_t etag, ptag, btag;
+
+  uint8_t adr;
+
+  int8_t ReadAllPaceOnce;
+
+  static uint8_t dcloffint_OneShot = 0;
+  static uint8_t acloffint_OneShot = 0;
+  static uint8_t bcgmon_OneShot = 0;
+  static uint8_t acleadon_OneShot = 0;
+
+  int8_t ret_val;
+
+  if (max30001_status.bit.eint == 1 || max30001_status.bit.pint == 1) {
+    adr = ECG_FIFO_BURST;
+    data_array[0] = ((adr << 1) & 0xff) | 1;
+
+    // The SPI routine only sends out data of 32 bytes in size.  Therefore the
+    // data is being read in
+    // smaller chunks in this routine...
+
+    total_databytes = (max30001_mngr_int.bit.e_fit + 1) * 3;
+
+    i_index = 0;
+    loop_logic = 1;
+
+    while (loop_logic) {
+      if (total_databytes > 30) {
+        data_chunk = 30;
+        total_databytes = total_databytes - 30;
+      } else {
+        data_chunk = total_databytes;
+        loop_logic = 0;
+      }
+
+      /* The extra 1 byte is for the extra byte that comes out of the SPI */
+      success = SPI_Transmit(&data_array[0], 1, &result[i_index], (data_chunk + 1)); // Make a copy of the FIFO over here...
+
+      if (success != 0) {
+        return -1;
+      }
+
+      /* This is important, because every transaction above creates an empty
+       * redundant data at result[0] */
+      for (j = i_index; j < (data_chunk + i_index); j++) /* get rid of the 1 extra byte by moving the whole array up one */
+      {
+        result[j] = result[j + 1];
+      }
+
+      i_index = i_index + 30; /* point to the next array location to put the data in */
+    }
+
+    ReadAllPaceOnce = 0;
+
+    /* Put the content of the FIFO based on the EFIT value, We ignore the
+     * result[0] and start concatenating indexes: 1,2,3 - 4,5,6 - 7,8,9 -  */
+    for (i = 0, j = 0; i < max30001_mngr_int.bit.e_fit + 1; i++, j = j + 3) // index1=23-16 bit, index2=15-8 bit, index3=7-0 bit
+    {
+      max30001_ECG_FIFO_buffer[i] = ((uint32_t)result[j] << 16) + (result[j + 1] << 8) + result[j + 2];
+
+      etag = (0b00111000 & result[j + 2]) >> 3;
+      ptag = 0b00000111 & result[j + 2];
+
+      if (ptag != 0b111 && ReadAllPaceOnce == 0) {
+
+        ReadAllPaceOnce = 1; // This will prevent extra read of PACE, once group
+                             // 0-5 is read ONCE.
+
+        adr = PACE0_FIFO_BURST;
+
+        data_array[0] = ((adr << 1) & 0xff) | 1; // For Read Or with 1
+
+        success = SPI_Transmit(&data_array[0], 1, &result[0], 10);
+
+        max30001_PACE[0] = (uint32_t)(result[1] << 16) + (result[2] << 8) + result[3];
+        max30001_PACE[1] = (uint32_t)(result[4] << 16) + (result[5] << 8) + result[6];
+        max30001_PACE[2] = (uint32_t)(result[7] << 16) + (result[8] << 8) + result[9];
+
+        adr = PACE1_FIFO_BURST;
+
+        data_array[0] = ((adr << 1) & 0xff) | 1; // For Read Or with 1
+
+        success = SPI_Transmit(&data_array[0], 1, &result[0], 10);
+
+        max30001_PACE[3] = (uint32_t)(result[1] << 16) + (result[2] << 8) + result[3];
+        max30001_PACE[4] = (uint32_t)(result[4] << 16) + (result[5] << 8) + result[6];
+        max30001_PACE[5] = (uint32_t)(result[7] << 16) + (result[8] << 8) + result[9];
+
+        adr = PACE2_FIFO_BURST;
+
+        data_array[0] = ((adr << 1) & 0xff) | 1; // For Read Or with 1
+
+        success = SPI_Transmit(&data_array[0], 1, &result[0], 10);
+
+        max30001_PACE[6] = (uint32_t)(result[1] << 16) + (result[2] << 8) + result[3];
+        max30001_PACE[7] = (uint32_t)(result[4] << 16) + (result[5] << 8) + result[6];
+        max30001_PACE[8] = (uint32_t)(result[7] << 16) + (result[8] << 8) + result[9];
+
+        adr = PACE3_FIFO_BURST;
+
+        data_array[0] = ((adr << 1) & 0xff) | 1; // For Read Or with 1
+
+        success = SPI_Transmit(&data_array[0], 1, &result[0], 10);
+
+        max30001_PACE[9]  = (uint32_t)(result[1] << 16) + (result[2] << 8) + result[3];
+        max30001_PACE[10] = (uint32_t)(result[4] << 16) + (result[5] << 8) + result[6];
+        max30001_PACE[11] = (uint32_t)(result[7] << 16) + (result[8] << 8) + result[9];
+
+        adr = PACE4_FIFO_BURST;
+
+        data_array[0] = ((adr << 1) & 0xff) | 1; // For Read Or with 1
+
+        success = SPI_Transmit(&data_array[0], 1, &result[0], 10);
+
+        max30001_PACE[12] = (uint32_t)(result[1] << 16) + (result[2] << 8) + result[3];
+        max30001_PACE[13] = (uint32_t)(result[4] << 16) + (result[5] << 8) + result[6];
+        max30001_PACE[14] = (uint32_t)(result[7] << 16) + (result[8] << 8) + result[9];
+
+        adr = PACE5_FIFO_BURST;
+
+        data_array[0] = ((adr << 1) & 0xff) | 1; // For Read Or with 1
+
+        success = SPI_Transmit(&data_array[0], 1, &result[0], 10);
+
+        max30001_PACE[15] = (uint32_t)(result[1] << 16) + (result[2] << 8) + result[3];
+        max30001_PACE[16] = (uint32_t)(result[4] << 16) + (result[5] << 8) + result[6];
+        max30001_PACE[17] = (uint32_t)(result[7] << 16) + (result[8] << 8) + result[9];
+
+        dataAvailable(MAX30001_DATA_PACE, max30001_PACE, 18); // Send out the Pace data once only
+      }
+    }
+
+    if (etag != 0b110) {
+
+      dataAvailable(MAX30001_DATA_ECG, max30001_ECG_FIFO_buffer, (max30001_mngr_int.bit.e_fit + 1));
+    }
+
+  } /* End of ECG init */
+
+  /* RtoR */
+
+  if (max30001_status.bit.rrint == 1) {
+    if (max30001_reg_read(RTOR, &max30001_RtoR_data) == -1) {
+      return -1;
+    }
+
+    max30001_RtoR_data = (0x00FFFFFF & max30001_RtoR_data) >> 10;
+
+    hspValMax30001.R2R = (uint16_t)max30001_RtoR_data;
+    hspValMax30001.fmstr = (uint16_t)max30001_cnfg_gen.bit.fmstr;
+
+    dataAvailable(MAX30001_DATA_RTOR, &max30001_RtoR_data, 1);
+  }
+
+  // Handling BIOZ data...
+
+  if (max30001_status.bit.bint == 1) {
+    adr = 0x22;
+    data_array[0] = ((adr << 1) & 0xff) | 1;
+
+    /* [(BFIT+1)*3byte]+1extra byte due to the addr */
+
+    if (SPI_Transmit(&data_array[0], 1, &result[0],((max30001_mngr_int.bit.b_fit + 1) * 3) + 1) == -1) // Make a copy of the FIFO over here...
+
+    {
+      return -1;
+    }
+
+    btag = 0b00000111 & result[3];
+
+    /* Put the content of the FIFO based on the BFIT value, We ignore the
+     * result[0] and start concatenating indexes: 1,2,3 - 4,5,6 - 7,8,9 -  */
+    for (i = 0, j = 0; i < max30001_mngr_int.bit.b_fit + 1; i++, j = j + 3) // index1=23-16 bit, index2=15-8 bit, index3=7-0 bit
+    {
+      max30001_BIOZ_FIFO_buffer[i] = ((uint32_t)result[j + 1] << 16) + (result[j + 2] << 8) + result[j + 3];
+    }
+
+    if (btag != 0b110) {
+      dataAvailable(MAX30001_DATA_BIOZ, max30001_BIOZ_FIFO_buffer, 8);
+    }
+  }
+
+  ret_val = 0;
+
+  if (max30001_status.bit.dcloffint == 1) // ECG/BIOZ Lead Off
+  {
+    dcloffint_OneShot = 1;
+    max30001_DCLeadOff = 0;
+    max30001_DCLeadOff = max30001_DCLeadOff | (max30001_cnfg_gen.bit.en_dcloff << 8) | (max30001_status.all & 0x00000F);
+    dataAvailable(MAX30001_DATA_LEADOFF_DC, &max30001_DCLeadOff, 1);
+    // Do a FIFO Reset
+    max30001_reg_write(FIFO_RST, 0x000000);
+
+    ret_val = 0b100;
+
+  } else if (dcloffint_OneShot == 1 && max30001_status.bit.dcloffint == 0) // Just send once when it comes out of dc lead off
+  {
+    max30001_DCLeadOff = 0;
+    max30001_DCLeadOff = max30001_DCLeadOff | (max30001_cnfg_gen.bit.en_dcloff << 8) | (max30001_status.all & 0x00000F);
+    dataAvailable(MAX30001_DATA_LEADOFF_DC, &max30001_DCLeadOff, 1);
+    dcloffint_OneShot = 0;
+  }
+
+  if (max30001_status.bit.bover == 1 || max30001_status.bit.bundr == 1) // BIOZ AC Lead Off
+  {
+    acloffint_OneShot = 1;
+    max30001_ACLeadOff = 0;
+    max30001_ACLeadOff =
+        max30001_ACLeadOff | ((max30001_status.all & 0x030000) >> 16);
+    dataAvailable(MAX30001_DATA_LEADOFF_AC, &max30001_ACLeadOff, 1);
+    // Do a FIFO Reset
+    max30001_reg_write(FIFO_RST, 0x000000);
+
+    ret_val = 0b1000;
+  } else if (acloffint_OneShot == 1 && max30001_status.bit.bover == 0 && max30001_status.bit.bundr == 0) // Just send once when it comes out of ac lead off
+  {
+    max30001_ACLeadOff = 0;
+    max30001_ACLeadOff = max30001_ACLeadOff | ((max30001_status.all & 0x030000) >> 16);
+    dataAvailable(MAX30001_DATA_LEADOFF_AC, &max30001_ACLeadOff, 1);
+    acloffint_OneShot = 0;
+  }
+
+  if (max30001_status.bit.bcgmon == 1) // BIOZ BCGMON check
+  {
+    bcgmon_OneShot = 1;
+    max30001_bcgmon = 0;
+    max30001_bcgmon = max30001_bcgmon | ((max30001_status.all & 0x000030) >> 4);
+    dataAvailable(MAX30001_DATA_BCGMON, &max30001_bcgmon, 1);
+    // Do a FIFO Reset
+    max30001_reg_write(FIFO_RST, 0x000000);
+
+    ret_val = 0b10000;
+  } else if (bcgmon_OneShot == 1 && max30001_status.bit.bcgmon == 0) {
+    max30001_bcgmon = 0;
+    max30001_bcgmon = max30001_bcgmon | ((max30001_status.all & 0x000030) >> 4);
+    bcgmon_OneShot = 0;
+    dataAvailable(MAX30001_DATA_BCGMON, &max30001_bcgmon, 1);
+  }
+
+#if 0
+if(max30001_status.bit.lonint == 1)   // AC LeadON Check
+{
+	max30001_LeadOn = 0;
+	max30001_reg_read(STATUS,&max30001_status.all);        // Reading is important
+	max30001_LeadOn = max30001_LeadOn | (max30001_cnfg_gen.bit.en_ulp_lon << 8) | ((max30001_status.all & 0x000800) >> 11);  // 0b01 will mean ECG Lead On, 0b10 will mean BIOZ Lead On
+    // LEAD ON has been detected... Now take actions
+}
+#endif
+
+  if (max30001_status.bit.lonint == 1 &&
+      acleadon_OneShot == 0) // AC LeadON Check, when lead is on
+  {
+    max30001_LeadOn = 0;
+    max30001_reg_read(STATUS, &max30001_status.all); // Reading is important
+    max30001_LeadOn =
+        max30001_LeadOn | (max30001_cnfg_gen.bit.en_ulp_lon << 8) |
+        ((max30001_status.all & 0x000800) >>
+         11); // 0b01 will mean ECG Lead On, 0b10 will mean BIOZ Lead On
+
+    // LEAD ON has been detected... Now take actions
+    acleadon_OneShot = 1;
+    dataAvailable(MAX30001_DATA_ACLEADON, &max30001_LeadOn, 1); // One shot data will be sent...
+  } else if (max30001_status.bit.lonint == 0 && acleadon_OneShot == 1) {
+    max30001_LeadOn = 0;
+    max30001_reg_read(STATUS, &max30001_status.all);
+    max30001_LeadOn =
+        max30001_LeadOn | (max30001_cnfg_gen.bit.en_ulp_lon << 8) | ((max30001_status.all & 0x000800) >> 11); // 0b01 will mean ECG Lead On, 0b10 will mean BIOZ Lead On
+    dataAvailable(MAX30001_DATA_ACLEADON, &max30001_LeadOn, 1); // One shot data will be sent...
+    acleadon_OneShot = 0;
+  }
+
+  return ret_val;
+}
+
+//******************************************************************************
+
+int MAX30001::max30001_int_handler(void) {
+
+  static uint32_t InitReset = 0;
+
+  int8_t return_value;
+
+  max30001_reg_read(STATUS, &max30001_status.all);
+
+  // Inital Reset and any FIFO over flow invokes a FIFO reset
+  if (InitReset == 0 || max30001_status.bit.eovf == 1 || max30001_status.bit.bovf == 1 || max30001_status.bit.povf == 1) {
+    // Do a FIFO Reset
+    max30001_reg_write(FIFO_RST, 0x000000);
+
+    InitReset++;
+    return 2;
+  }
+
+  return_value = 0;
+
+  // The four data handling goes on over here
+  if (max30001_status.bit.eint == 1 || max30001_status.bit.pint == 1 || max30001_status.bit.bint == 1 || max30001_status.bit.rrint == 1) {
+    return_value = return_value | max30001_FIFO_LeadONOff_Read();
+  }
+
+  // ECG/BIOZ DC Lead Off test
+  if (max30001_status.bit.dcloffint == 1) {
+    return_value = return_value | max30001_FIFO_LeadONOff_Read();
+  }
+
+  // BIOZ AC Lead Off test
+  if (max30001_status.bit.bover == 1 || max30001_status.bit.bundr == 1) {
+    return_value = return_value | max30001_FIFO_LeadONOff_Read();
+  }
+
+  // BIOZ DRVP/N test using BCGMON.
+  if (max30001_status.bit.bcgmon == 1) {
+    return_value = return_value | max30001_FIFO_LeadONOff_Read();
+  }
+
+  if (max30001_status.bit.lonint == 1) // ECG Lead ON test: i.e. the leads are touching the body...
+  {
+
+    max30001_FIFO_LeadONOff_Read();
+  }
+
+  return return_value;
+}
+
+/// function pointer to the async callback
+static event_callback_t functionpointer;
+/// flag used to indicate an async xfer has taken place
+static volatile int xferFlag = 0;
+
+/**
+* @brief Callback handler for SPI async events
+* @param events description of event that occurred
+*/
+static void spiHandler(int events) { xferFlag = 1; }
+
+/**
+* @brief Transmit and recieve QUAD SPI data
+* @param tx_buf pointer to transmit byte buffer
+* @param tx_size number of bytes to transmit
+* @param rx_buf pointer to the recieve buffer
+* @param rx_size number of bytes to recieve
+*/
+int MAX30001::SPI_Transmit(const uint8_t *tx_buf, uint32_t tx_size, uint8_t *rx_buf, uint32_t rx_size) {
+  xferFlag = 0;
+  int i;
+  for (i = 0; i < sizeof(buffer); i++) {
+    if (i < tx_size)
+      buffer[i] = tx_buf[i];
+    else
+      buffer[i] = 0xFF;
+  }
+  spi->transfer<uint8_t>(buffer, (int)rx_size, rx_buf, (int)rx_size, spiHandler /* functionpointer */);
+  while (xferFlag == 0);
+  return 0;
+}
+
+//******************************************************************************
+void MAX30001::max30001_ReadHeartrateData(max30001_t *_hspValMax30001) {
+  _hspValMax30001->R2R = hspValMax30001.R2R;
+  _hspValMax30001->fmstr = hspValMax30001.fmstr;
+}
+
+//******************************************************************************
+void MAX30001::onDataAvailable(PtrFunction _onDataAvailable) {
+  onDataAvailableCallback = _onDataAvailable;
+}
+
+/**
+* @brief Used to notify an external function that interrupt data is available
+* @param id type of data available
+* @param buffer 32-bit buffer that points to the data
+* @param length length of 32-bit elements available
+*/
+void MAX30001::dataAvailable(uint32_t id, uint32_t *buffer, uint32_t length) {
+  if (onDataAvailableCallback != NULL) {
+    (*onDataAvailableCallback)(id, buffer, length);
+  }
+}
+
+/**
+* @brief Callback handler for SPI async events
+* @param events description of event that occurred
+*/
+void MAX30001::spiHandler(int events) { xferFlag = 1; }
+
+//******************************************************************************
+static int allowInterrupts = 0;
+
+void MAX30001Mid_IntB_Handler(void) {
+  if (allowInterrupts == 0) return;
+  MAX30001::instance->max30001_int_handler();
+}
+
+void MAX30001Mid_Int2B_Handler(void) {
+  if (allowInterrupts == 0) return;
+  MAX30001::instance->max30001_int_handler();
+}
+
+void MAX30001_AllowInterrupts(int state) { 
+allowInterrupts = state; 
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MAX30001/MAX30001/MAX30001.h	Thu Mar 28 08:10:23 2019 +0000
@@ -0,0 +1,1076 @@
+/*******************************************************************************
+* Copyright (C) 2015 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.
+*******************************************************************************/
+/*
+ * max30001.h
+ *
+ *  Created on: Oct 9, 2015
+ *      Author: faisal.tariq
+ */
+
+#ifndef MAX30001_H_
+#define MAX30001_H_
+
+#include "mbed.h"
+
+#define mbed_COMPLIANT // Uncomment to Use timer for MAX30001 FCLK (for mbed)
+                       // Comment to use the RTC clock
+
+#define ASYNC_SPI_BUFFER_SIZE (32 * 3) // Maximimum buffer size for async byte transfers
+
+// Defines for data callbacks
+#define MAX30001_DATA_ECG        0x30
+#define MAX30001_DATA_PACE       0x31
+#define MAX30001_DATA_RTOR       0x32
+#define MAX30001_DATA_BIOZ       0x33
+#define MAX30001_DATA_LEADOFF_DC 0x34
+#define MAX30001_DATA_LEADOFF_AC 0x35
+#define MAX30001_DATA_BCGMON     0x36
+#define MAX30001_DATA_ACLEADON   0x37
+
+#define MAX30001_SPI_MASTER_PORT 0
+#define MAX30001_SPI_SS_INDEX    0
+
+#define MAX30001_INT_PORT_B      3
+#define MAX30001_INT_PIN_B       6
+
+#define MAX30001_INT_PORT_2B     4
+#define MAX30001_INT_PIN_2B      5
+
+#define MAX30001_INT_PORT_FCLK   1
+#define MAX30001_INT_PIN_FCLK    7
+
+#define MAX30001_FUNC_SEL_TMR    2 // 0=FW Control, 1= Pulse Train, 2=Timer
+
+#define MAX30001_INDEX    3
+#define MAX30001_POLARITY 0
+#define MAX30001_PERIOD   30518
+#define MAX30001_CYCLE    50
+
+#define MAX30001_IOMUX_IO_ENABLE 1
+
+#define MAX30001_SPI_PORT            0
+#define MAX30001_CS_PIN              0
+#define MAX30001_CS_POLARITY         0
+#define MAX30001_CS_ACTIVITY_DELAY   0
+#define MAX30001_CS_INACTIVITY_DELAY 0
+#define MAX30001_CLK_HI              1
+#define MAX30001_CLK_LOW             1
+#define MAX30001_ALT_CLK             0
+#define MAX30001_CLK_POLARITY        0
+#define MAX30001_CLK_PHASE           0
+#define MAX30001_WRITE               1
+#define MAX30001_READ                0
+
+#define MAX30001_INT_PORT_B  3
+#define MAX30001INT_PIN_B    6
+
+void MAX30001_AllowInterrupts(int state);
+
+/**
+* Maxim Integrated MAX30001 ECG/BIOZ chip
+*/
+class MAX30001 {
+
+public:
+  typedef enum { // MAX30001 Register addresses
+    STATUS     = 0x01,
+    EN_INT     = 0x02,
+    EN_INT2    = 0x03,
+    MNGR_INT   = 0x04,
+    MNGR_DYN   = 0x05,
+    SW_RST     = 0x08,
+    SYNCH      = 0x09,
+    FIFO_RST   = 0x0A,
+    INFO       = 0x0F,
+    CNFG_GEN   = 0x10,
+    CNFG_CAL   = 0x12,
+    CNFG_EMUX  = 0x14,
+    CNFG_ECG   = 0x15,
+    CNFG_BMUX  = 0x17,
+    CNFG_BIOZ  = 0x18,
+    CNFG_PACE  = 0x1A,
+    CNFG_RTOR1 = 0x1D,
+    CNFG_RTOR2 = 0x1E,
+
+    // Data locations
+    ECG_FIFO_BURST = 0x20,
+    ECG_FIFO       = 0x21,
+    FIFO_BURST     = 0x22,
+    BIOZ_FIFO      = 0x23,
+    RTOR           = 0x25,
+
+    PACE0_FIFO_BURST = 0x30,
+    PACE0_A          = 0x31,
+    PACE0_B          = 0x32,
+    PACE0_C          = 0x33,
+
+    PACE1_FIFO_BURST = 0x34,
+    PACE1_A          = 0x35,
+    PACE1_B          = 0x36,
+    PACE1_C          = 0x37,
+
+    PACE2_FIFO_BURST = 0x38,
+    PACE2_A          = 0x39,
+    PACE2_B          = 0x3A,
+    PACE2_C          = 0x3B,
+
+    PACE3_FIFO_BURST = 0x3C,
+    PACE3_A          = 0x3D,
+    PACE3_B          = 0x3E,
+    PACE3_C          = 0x3F,
+
+    PACE4_FIFO_BURST = 0x40,
+    PACE4_A          = 0x41,
+    PACE4_B          = 0x42,
+    PACE4_C          = 0x43,
+
+    PACE5_FIFO_BURST = 0x44,
+    PACE5_A          = 0x45,
+    PACE5_B          = 0x46,
+    PACE5_C          = 0x47,
+
+  } MAX30001_REG_map_t;
+
+  /**
+   * @brief STATUS (0x01) 
+   */
+  union max30001_status_reg {
+    uint32_t all;
+
+    struct {
+      uint32_t loff_nl : 1;
+      uint32_t loff_nh : 1;
+      uint32_t loff_pl : 1;
+      uint32_t loff_ph : 1;
+
+      uint32_t bcgmn     : 1;
+      uint32_t bcgmp     : 1;
+      uint32_t reserved1 : 1;
+      uint32_t reserved2 : 1;
+
+      uint32_t pllint : 1;
+      uint32_t samp   : 1;
+      uint32_t rrint  : 1;
+      uint32_t lonint : 1;
+
+      uint32_t pedge  : 1;
+      uint32_t povf   : 1;
+      uint32_t pint   : 1;
+      uint32_t bcgmon : 1;
+
+      uint32_t bundr : 1;
+      uint32_t bover : 1;
+      uint32_t bovf  : 1;
+      uint32_t bint  : 1;
+
+      uint32_t dcloffint : 1;
+      uint32_t fstint    : 1;
+      uint32_t eovf      : 1;
+      uint32_t eint      : 1;
+
+      uint32_t reserved : 8;
+
+    } bit;
+
+  } max30001_status;
+
+  
+  /**
+   * @brief EN_INT (0x02) 
+   */
+
+  union max30001_en_int_reg {
+    uint32_t all;
+
+    struct {
+      uint32_t intb_type : 2;
+      uint32_t reserved1 : 1;
+      uint32_t reserved2 : 1;
+
+      uint32_t reserved3 : 1;
+      uint32_t reserved4 : 1;
+      uint32_t reserved5 : 1;
+      uint32_t reserved6 : 1;
+
+      uint32_t en_pllint : 1;
+      uint32_t en_samp   : 1;
+      uint32_t en_rrint  : 1;
+      uint32_t en_lonint : 1;
+
+      uint32_t en_pedge  : 1;
+      uint32_t en_povf   : 1;
+      uint32_t en_pint   : 1;
+      uint32_t en_bcgmon : 1;
+
+      uint32_t en_bundr : 1;
+      uint32_t en_bover : 1;
+      uint32_t en_bovf  : 1;
+      uint32_t en_bint  : 1;
+
+      uint32_t en_dcloffint : 1;
+      uint32_t en_fstint    : 1;
+      uint32_t en_eovf      : 1;
+      uint32_t en_eint      : 1;
+
+      uint32_t reserved : 8;
+
+    } bit;
+
+  } max30001_en_int;
+
+  
+  /**
+   * @brief EN_INT2 (0x03) 
+   */  
+  union max30001_en_int2_reg {
+    uint32_t all;
+
+    struct {
+      uint32_t intb_type : 2;
+      uint32_t reserved1 : 1;
+      uint32_t reserved2 : 1;
+
+      uint32_t reserved3 : 1;
+      uint32_t reserved4 : 1;
+      uint32_t reserved5 : 1;
+      uint32_t reserved6 : 1;
+
+      uint32_t en_pllint : 1;
+      uint32_t en_samp   : 1;
+      uint32_t en_rrint  : 1;
+      uint32_t en_lonint : 1;
+
+      uint32_t en_pedge  : 1;
+      uint32_t en_povf   : 1;
+      uint32_t en_pint   : 1;
+      uint32_t en_bcgmon : 1;
+
+      uint32_t en_bundr  : 1;
+      uint32_t en_bover  : 1;
+      uint32_t en_bovf   : 1;
+      uint32_t en_bint   : 1;
+
+      uint32_t en_dcloffint : 1;
+      uint32_t en_fstint    : 1;
+      uint32_t en_eovf      : 1;
+      uint32_t en_eint      : 1;
+
+      uint32_t reserved : 8;
+
+    } bit;
+
+  } max30001_en_int2;
+
+  /**
+   * @brief MNGR_INT (0x04) 
+   */  
+  union max30001_mngr_int_reg {
+    uint32_t all;
+
+    struct {
+      uint32_t samp_it   : 2;
+      uint32_t clr_samp  : 1;
+      uint32_t clr_pedge : 1;
+      uint32_t clr_rrint : 2;
+      uint32_t clr_fast  : 1;
+      uint32_t reserved1 : 1;
+      uint32_t reserved2 : 4;
+      uint32_t reserved3 : 4;
+
+      uint32_t b_fit     : 3;
+      uint32_t e_fit     : 5;
+
+      uint32_t reserved : 8;
+
+    } bit;
+
+  } max30001_mngr_int;
+
+   /**
+   * @brief MNGR_DYN (0x05) 
+   */ 
+  union max30001_mngr_dyn_reg {
+    uint32_t all;
+
+    struct {
+      uint32_t bloff_lo_it : 8;
+      uint32_t bloff_hi_it : 8;
+      uint32_t fast_th     : 6;
+      uint32_t fast        : 2;
+      uint32_t reserved    : 8;
+    } bit;
+
+  } max30001_mngr_dyn;
+
+  // 0x08
+  // uint32_t max30001_sw_rst;
+
+  // 0x09
+  // uint32_t max30001_synch;
+
+  // 0x0A
+  // uint32_t max30001_fifo_rst;
+
+  
+   /**
+   * @brief INFO (0x0F) 
+   */
+  union max30001_info_reg {
+    uint32_t all;
+    struct {
+      uint32_t serial    : 12;
+      uint32_t part_id   : 2;
+      uint32_t sample    : 1;
+      uint32_t reserved1 : 1;
+      uint32_t rev_id    : 4;
+      uint32_t pattern   : 4;
+      uint32_t reserved  : 8;
+    } bit;
+
+  } max30001_info;
+
+   /**
+   * @brief CNFG_GEN (0x10) 
+   */
+  union max30001_cnfg_gen_reg {
+    uint32_t all;
+    struct {
+      uint32_t rbiasn     : 1;
+      uint32_t rbiasp     : 1;
+      uint32_t rbiasv     : 2;
+      uint32_t en_rbias   : 2;
+      uint32_t vth        : 2;
+      uint32_t imag       : 3;
+      uint32_t ipol       : 1;
+      uint32_t en_dcloff  : 2;
+      uint32_t en_bloff   : 2;
+      uint32_t reserved1  : 1;
+      uint32_t en_pace    : 1;
+      uint32_t en_bioz    : 1;
+      uint32_t en_ecg     : 1;
+      uint32_t fmstr      : 2;
+      uint32_t en_ulp_lon : 2;
+      uint32_t reserved : 8;
+    } bit;
+
+  } max30001_cnfg_gen;
+
+  
+   /**
+   * @brief CNFG_CAL (0x12) 
+   */  
+  union max30001_cnfg_cal_reg {
+    uint32_t all;
+    struct {
+      uint32_t thigh     : 11;
+      uint32_t fifty     : 1;
+      uint32_t fcal      : 3;
+      uint32_t reserved1 : 5;
+      uint32_t vmag      : 1;
+      uint32_t vmode     : 1;
+      uint32_t en_vcal   : 1;
+      uint32_t reserved2 : 1;
+      uint32_t reserved  : 8;
+    } bit;
+
+  } max30001_cnfg_cal;
+
+   /**
+   * @brief CNFG_EMUX  (0x14) 
+   */
+  union max30001_cnfg_emux_reg {
+    uint32_t all;
+    struct {
+      uint32_t reserved1 : 16;
+      uint32_t caln_sel  : 2;
+      uint32_t calp_sel  : 2;
+      uint32_t openn     : 1;
+      uint32_t openp     : 1;
+      uint32_t reserved2 : 1;
+      uint32_t pol       : 1;
+      uint32_t reserved : 8;
+    } bit;
+
+  } max30001_cnfg_emux;
+
+  
+   /**
+   * @brief CNFG_ECG   (0x15) 
+   */  
+  union max30001_cnfg_ecg_reg {
+    uint32_t all;
+    struct {
+      uint32_t reserved1 : 12;
+      uint32_t dlpf      : 2;
+      uint32_t dhpf      : 1;
+      uint32_t reserved2 : 1;
+      uint32_t gain      : 2;
+      uint32_t reserved3 : 4;
+      uint32_t rate      : 2;
+
+      uint32_t reserved  : 8;
+    } bit;
+
+  } max30001_cnfg_ecg;
+
+   /**
+   * @brief CNFG_BMUX   (0x17) 
+   */  
+  union max30001_cnfg_bmux_reg {
+    uint32_t all;
+    struct {
+      uint32_t fbist     : 2;
+      uint32_t reserved1 : 2;
+      uint32_t rmod      : 3;
+      uint32_t reserved2 : 1;
+      uint32_t rnom      : 3;
+      uint32_t en_bist   : 1;
+      uint32_t cg_mode   : 2;
+      uint32_t reserved3 : 2;
+      uint32_t caln_sel  : 2;
+      uint32_t calp_sel  : 2;
+      uint32_t openn     : 1;
+      uint32_t openp     : 1;
+      uint32_t reserved4 : 2;
+      uint32_t reserved : 8;
+    } bit;
+
+  } max30001_cnfg_bmux;
+
+   /**
+   * @brief CNFG_BIOZ   (0x18) 
+   */ 
+  union max30001_bioz_reg {
+    uint32_t all;
+    struct {
+      uint32_t phoff     : 4;
+      uint32_t cgmag     : 3;
+      uint32_t cgmon     : 1;
+      uint32_t fcgen     : 4;
+      uint32_t dlpf      : 2;
+      uint32_t dhpf      : 2;
+      uint32_t gain      : 2;
+      uint32_t reserved1 : 1;
+      uint32_t ext_rbias : 1;
+      uint32_t ahpf      : 3;
+      uint32_t rate      : 1;
+      uint32_t reserved : 8;
+    } bit;
+
+  } max30001_cnfg_bioz;
+
+  
+   /**
+   * @brief CNFG_PACE   (0x1A) 
+   */   
+  union max30001_cnfg_pace_reg {
+    uint32_t all;
+
+    struct {
+      uint32_t dacn        : 4;
+      uint32_t dacp        : 4;
+      uint32_t reserved1   : 4;
+      uint32_t aout        : 2;
+      uint32_t aout_lbw    : 1;
+      uint32_t reserved2   : 1;
+      uint32_t gain        : 3;
+      uint32_t gn_diff_off : 1;
+      uint32_t reserved3   : 3;
+      uint32_t pol         : 1;
+      uint32_t reserved    : 8;
+    } bit;
+
+  } max30001_cnfg_pace;
+
+   /**
+   * @brief CNFG_RTOR1   (0x1D) 
+   */   
+  union max30001_cnfg_rtor1_reg {
+    uint32_t all;
+    struct {
+      uint32_t reserved1 : 8;
+      uint32_t ptsf      : 4;
+      uint32_t pavg      : 2;
+      uint32_t reserved2 : 1;
+      uint32_t en_rtor   : 1;
+      uint32_t gain      : 4;
+      uint32_t wndw      : 4;
+      uint32_t reserved : 8;
+    } bit;
+
+  } max30001_cnfg_rtor1;
+
+   /**
+   * @brief CNFG_RTOR2 (0x1E) 
+   */   
+  union max30001_cnfg_rtor2_reg {
+    uint32_t all;
+    struct {
+      uint32_t reserved1 : 8;
+      uint32_t rhsf      : 3;
+      uint32_t reserved2 : 1;
+      uint32_t ravg      : 2;
+      uint32_t reserved3 : 2;
+      uint32_t hoff      : 6;
+      uint32_t reserved4 : 2;
+      uint32_t reserved : 8;
+    } bit;
+
+  } max30001_cnfg_rtor2;
+
+  /*********************************************************************************/
+
+  typedef enum {
+    MAX30001_NO_INT = 0, // No interrupt
+    MAX30001_INT_B  = 1,  // INTB selected for interrupt
+    MAX30001_INT_2B = 2  // INT2B selected for interrupt
+  } max30001_intrpt_Location_t;
+
+  typedef enum {
+    MAX30001_INT_DISABLED = 0b00,
+    MAX30001_INT_CMOS     = 0b01,
+    MAX30001_INT_ODN      = 0b10,
+    MAX30001_INT_ODNR     = 0b11
+  } max30001_intrpt_type_t;
+
+  typedef enum {          // Input Polarity selection
+    MAX30001_NON_INV = 0, // Non-Inverted
+    MAX30001_INV     = 1      // Inverted
+  } max30001_emux_pol;
+
+  typedef enum {              // OPENP and OPENN setting
+    MAX30001_ECG_CON_AFE = 0, // ECGx is connected to AFE channel
+    MAX30001_ECG_ISO_AFE = 1  // ECGx is isolated from AFE channel
+  } max30001_emux_openx;
+
+  typedef enum {                // EMUX_CALP_SEL & EMUX_CALN_SEL
+    MAX30001_NO_CAL_SIG = 0b00, // No calibration signal is applied
+    MAX30001_INPT_VMID  = 0b01,  // Input is connected to VMID
+    MAX30001_INPT_VCALP = 0b10, // Input is connected to VCALP
+    MAX30001_INPT_VCALN = 0b11  // Input is connected to VCALN
+  } max30001_emux_calx_sel;
+
+  typedef enum {                     // EN_ECG, EN_BIOZ, EN_PACE
+    MAX30001_CHANNEL_DISABLED = 0b0, //
+    MAX30001_CHANNEL_ENABLED = 0b1
+  } max30001_en_feature;
+
+  /*********************************************************************************/
+  // Data
+  uint32_t max30001_ECG_FIFO_buffer[32]; // (303 for internal test)
+  uint32_t max30001_BIOZ_FIFO_buffer[8]; // (303 for internal test)
+
+  uint32_t max30001_PACE[18]; // Pace Data 0-5
+
+  uint32_t max30001_RtoR_data; // This holds the RtoR data
+
+  uint32_t max30001_DCLeadOff; // This holds the LeadOff data, Last 4 bits give
+                               // the status, BIT3=LOFF_PH, BIT2=LOFF_PL,
+                               // BIT1=LOFF_NH, BIT0=LOFF_NL
+                               // 8th and 9th bits tell Lead off is due to ECG or BIOZ.  
+                               // 0b01 = ECG Lead Off and 0b10 = BIOZ Lead off
+
+  uint32_t max30001_ACLeadOff; // This gives the state of the BIOZ AC Lead Off
+                               // state.  BIT 1 = BOVER,   BIT 0 = BUNDR
+
+  uint32_t max30001_bcgmon; // This holds the BCGMON data, BIT 1 = BCGMP, BIT0 =
+                            // BCGMN
+
+  uint32_t max30001_LeadOn; // This holds the LeadOn data, BIT1 = BIOZ Lead ON,
+                            // BIT0 = ECG Lead ON, BIT8= Lead On Status Bit
+
+  uint32_t max30001_timeout; // If the PLL does not respond, timeout and get out.
+
+  typedef struct { // Creating a structure for BLE data
+    int16_t R2R;
+    int16_t fmstr;
+  } max30001_t;
+
+  max30001_t hspValMax30001; // R2R, FMSTR
+
+  /**
+  * @brief Constructor that accepts pin names for the SPI interface
+  * @param spi pointer to the mbed SPI object
+  */
+  MAX30001(SPI *spi);
+
+  /**
+  * @brief Constructor that accepts pin names for the SPI interface
+  * @param mosi master out slave in pin name
+  * @param miso master in slave out pin name
+  * @param sclk serial clock pin name
+  * @param cs chip select pin name
+  */
+  MAX30001(PinName mosi, PinName miso, PinName sclk, PinName cs);
+
+  /**
+   * MAX30001 destructor
+   */
+  ~MAX30001(void);
+
+  /**
+   * @brief This function sets up the Resistive Bias mode and also selects the master clock frequency.
+   * @brief Uses Register: CNFG_GEN-0x10
+   * @param En_rbias: Enable and Select Resitive Lead Bias Mode
+   * @param Rbiasv: Resistive Bias Mode Value Selection
+   * @param Rbiasp: Enables Resistive Bias on Positive Input
+   * @param Rbiasn: Enables Resistive Bias on Negative Input
+   * @param Fmstr: Selects Master Clock Frequency
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   *
+  */
+  int max30001_Rbias_FMSTR_Init(uint8_t En_rbias, uint8_t Rbiasv,
+                                uint8_t Rbiasp, uint8_t Rbiasn, uint8_t Fmstr);
+
+  /**
+   * @brief This function uses sets up the calibration signal internally.  If it is desired to use the internal signal, then
+   * @brief this function must be called and the registers set, prior to setting the CALP_SEL and CALN_SEL in the ECG_InitStart
+   * @brief and BIOZ_InitStart functions.
+   * @brief Uses Register: CNFG_CAL-0x12
+   * @param En_Vcal: Calibration Source (VCALP and VCALN) Enable
+   * @param Vmode:   Calibration Source Mode Selection
+   * @param Vmag:    Calibration Source Magnitude Selection (VMAG)
+   * @param Fcal:    Calibration Source Frequency Selection (FCAL)
+   * @param Thigh:   Calibration Source Time High Selection
+   * @param Fifty:   Calibration Source Duty Cycle Mode Selection
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   *
+   */
+  int max30001_CAL_InitStart(uint8_t En_Vcal, uint8_t Vmode, uint8_t Vmag,
+                             uint8_t Fcal, uint16_t Thigh, uint8_t Fifty);
+
+  /**
+   * @brief This function disables the VCAL signal
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   */
+  int max30001_CAL_Stop(void);
+
+  /**
+   * @brief This function handles the assignment of the two interrupt pins (INTB & INT2B) with various
+   * @brief functions/behaviors  of the MAX30001.  Also, each pin can be configured for different drive capability.
+   * @brief Uses Registers: EN_INT-0x02 and EN_INT2-0x03.
+   * @param max30001_intrpt_Locatio_t  <argument>:  All the arguments with the aforementioned enumeration essentially
+   *        can be configured to generate an interrupt on either INTB or INT2B or NONE.
+   * @param max30001_intrpt_type_t  intb_Type:  INTB Port Type (EN_INT Selections).
+   * @param max30001_intrpt_type _t int2b_Type:   INT2B Port Type (EN_INT2 Selections)
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   *
+   */
+     int max30001_INT_assignment(max30001_intrpt_Location_t en_enint_loc,     max30001_intrpt_Location_t en_eovf_loc,  max30001_intrpt_Location_t en_fstint_loc,
+		                 max30001_intrpt_Location_t en_dcloffint_loc, max30001_intrpt_Location_t en_bint_loc,  max30001_intrpt_Location_t en_bovf_loc,
+		                 max30001_intrpt_Location_t en_bover_loc,     max30001_intrpt_Location_t en_bundr_loc, max30001_intrpt_Location_t en_bcgmon_loc,
+		                 max30001_intrpt_Location_t en_pint_loc,      max30001_intrpt_Location_t en_povf_loc,  max30001_intrpt_Location_t en_pedge_loc,
+		                 max30001_intrpt_Location_t en_lonint_loc,    max30001_intrpt_Location_t en_rrint_loc, max30001_intrpt_Location_t en_samp_loc,
+		                 max30001_intrpt_type_t  intb_Type,           max30001_intrpt_type_t int2b_Type);
+
+
+
+  /**
+   * @brief For MAX30001/3 ONLY
+   * @brief This function sets up the MAX30001 for the ECG measurements.
+   * @brief Registers used:  CNFG_EMUX, CNFG_GEN, MNGR_INT, CNFG_ECG.
+   * @param En_ecg: ECG Channel Enable <CNFG_GEN register bits>
+   * @param Openp: Open the ECGN Input Switch (most often used for testing and calibration studies) <CNFG_EMUX register bits>
+   * @param Openn: Open the ECGN Input Switch (most often used for testing and calibration studies) <CNFG_EMUX register bits>
+   * @param Calp_sel: ECGP Calibration Selection <CNFG_EMUX register bits>
+   * @param Caln_sel: ECGN Calibration Selection <CNFG_EMUX register bits>
+   * @param E_fit: ECG FIFO Interrupt Threshold (issues EINT based on number of unread FIFO records) <CNFG_GEN register bits>
+   * @param Clr_rrint: RTOR R Detect Interrupt (RRINT) Clear Behavior <CNFG_GEN register bits>
+   * @param Rate: ECG Data Rate
+   * @param Gain: ECG Channel Gain Setting
+   * @param Dhpf: ECG Channel Digital High Pass Filter Cutoff Frequency
+   * @param Dlpf:  ECG Channel Digital Low Pass Filter Cutoff Frequency
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   *
+   */
+  int max30001_ECG_InitStart(uint8_t En_ecg, uint8_t Openp, uint8_t Openn,
+                             uint8_t Pol, uint8_t Calp_sel, uint8_t Caln_sel,
+                             uint8_t E_fit, uint8_t Rate, uint8_t Gain,
+                             uint8_t Dhpf, uint8_t Dlpf);
+
+  /**
+   * @brief For MAX30001/3 ONLY
+   * @brief This function enables the Fast mode feature of the ECG.
+   * @brief Registers used: MNGR_INT-0x04, MNGR_DYN-0x05
+   * @param Clr_Fast: FAST MODE Interrupt Clear Behavior <MNGR_INT Register>
+   * @param Fast: ECG Channel Fast Recovery Mode Selection (ECG High Pass Filter Bypass) <MNGR_DYN Register>
+   * @param Fast_Th: Automatic Fast Recovery Threshold
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   *
+   */
+  int max30001_ECGFast_Init(uint8_t Clr_Fast, uint8_t Fast, uint8_t Fast_Th);
+
+  /**
+  * @brief For MAX30001/3 ONLY
+  * @brief This function disables the ECG.
+  * @brief Uses Register CNFG_GEN-0x10.
+  * @returns 0-if no error.  A non-zero value indicates an error.
+  *
+  */
+  int max30001_Stop_ECG(void);
+
+  /**
+   *  @brief For MAX30001 ONLY
+   *  @brief This function sets up the MAX30001 for pace signal detection.
+   *  @brief If both PACE and BIOZ are turned ON, then make sure Fcgen is set for 80K or 40K in the
+   *  @brief max30001_BIOZ_InitStart() function.  However, if Only PACE is on but BIOZ off, then Fcgen can be set
+   *  @brief for 80K only, in the max30001_BIOZ_InitStart() function
+   *  @brief Registers used: MNGR_INT-0x04, CNFG_GEN-0x37, CNFG_PACE-0x1A.
+   *  @param En_pace : PACE Channel Enable <CNFG_GEN Register>
+   *  @param Clr_pedge : PACE Edge Detect Interrupt (PEDGE) Clear Behavior <MNGR_INT Register>
+   *  @param Pol: PACE Input Polarity Selection <CNFG_PACE Register>
+   *  @param Gn_diff_off: PACE Differentiator Mode <CNFG_PACE Register>
+   *  @param Gain: PACE Channel Gain Selection <CNFG_PACE Register>
+   *  @param Aout_lbw:  PACE Analog Output Buffer Bandwidth Mode <CNFG_PACE Register>
+   *  @param Aout: PACE Single Ended Analog Output Buffer Signal Monitoring Selection <CNFG_PACE Register>
+   *  @param Dacp (4bits): PACE Detector Positive Comparator Threshold <CNFG_PACE Register>
+   *  @param Dacn(4bits): PACE Detector Negative Comparator Threshold <CNFG_PACE Register>
+   *  @returns 0-if no error.  A non-zero value indicates an error <CNFG_PACE Register>
+   *
+   */
+  int max30001_PACE_InitStart(uint8_t En_pace, uint8_t Clr_pedge, uint8_t Pol,
+                              uint8_t Gn_diff_off, uint8_t Gain,
+                              uint8_t Aout_lbw, uint8_t Aout, uint8_t Dacp,
+                              uint8_t Dacn);
+
+  /**
+   *@brief For MAX30001 ONLY
+   *@param This function disables the PACE.  Uses Register CNFG_GEN-0x10.
+   *@returns 0-if no error.  A non-zero value indicates an error.
+   *
+   */
+  int max30001_Stop_PACE(void);
+
+  /**
+   * @brief For MAX30001/2 ONLY
+   * @brief This function sets up the MAX30001 for BIOZ measurement.
+   * @brief Registers used: MNGR_INT-0x04, CNFG_GEN-0X10, CNFG_BMUX-0x17,CNFG_BIOZ-0x18.
+   * @param En_bioz: BIOZ Channel Enable <CNFG_GEN Register>
+   * @param Openp: Open the BIP Input Switch <CNFG_BMUX Register>
+   * @param Openn: Open the BIN Input Switch <CNFG_BMUX Register>
+   * @param Calp_sel: BIP Calibration Selection <CNFG_BMUX Register>
+   * @param Caln_sel: BIN Calibration Selection <CNFG_BMUX Register>
+   * @param CG_mode:  BIOZ Current Generator Mode Selection <CNFG_BMUX Register>
+   * @param B_fit:  BIOZ FIFO Interrupt Threshold (issues BINT based on number of unread FIFO records) <MNGR_INT Register>
+   * @param Rate: BIOZ Data Rate <CNFG_BIOZ Register>
+   * @param Ahpf: BIOZ/PACE Channel Analog High Pass Filter Cutoff Frequency and Bypass <CNFG_BIOZ Register>
+   * @param Ext_rbias:  External Resistor Bias Enable <CNFG_BIOZ Register>
+   * @param Gain: BIOZ Channel Gain Setting <CNFG_BIOZ Register>
+   * @param Dhpf: BIOZ Channel Digital High Pass Filter Cutoff Frequency <CNFG_BIOZ Register>
+   * @param Dlpf:  BIOZ Channel Digital Low Pass Filter Cutoff Frequency <CNFG_BIOZ Register>
+   * @param Fcgen:  BIOZ Current Generator Modulation Frequency <CNFG_BIOZ Register>
+   * @param Cgmon:  BIOZ Current Generator Monitor <CNFG_BIOZ Register>
+   * @param Cgmag:  BIOZ Current Generator Magnitude <CNFG_BIOZ Register>
+   * @param Phoff: BIOZ Current Generator Modulation Phase Offset <CNFG_BIOZ Register>
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   *
+   */
+  int max30001_BIOZ_InitStart(uint8_t En_bioz, uint8_t Openp, uint8_t Openn,
+                              uint8_t Calp_sel, uint8_t Caln_sel,
+                              uint8_t CG_mode,
+                              /* uint8_t En_bioz,*/ uint8_t B_fit, uint8_t Rate,
+                              uint8_t Ahpf, uint8_t Ext_rbias, uint8_t Gain,
+                              uint8_t Dhpf, uint8_t Dlpf, uint8_t Fcgen,
+                              uint8_t Cgmon, uint8_t Cgmag, uint8_t Phoff);
+
+  /**
+   * @brief For MAX30001/2 ONLY
+   * @brief This function disables the BIOZ.  Uses Register CNFG_GEN-0x10.
+   * @returns 0-if no error.  A non-zero value indicates an error.
+       * @returns 0-if no error.  A non-zero value indicates an error.
+   *
+   */
+  int max30001_Stop_BIOZ(void);
+
+  /**
+   * @brief For MAX30001/2 ONLY
+   * @brief BIOZ modulated Resistance Built-in-Self-Test, Registers used: CNFG_BMUX-0x17
+   * @param En_bist: Enable Modulated Resistance Built-in-Self-test <CNFG_BMUX Register>
+   * @param Rnom: BIOZ RMOD BIST Nominal Resistance Selection <CNFG_BMUX Register>
+   * @param Rmod: BIOZ RMOD BIST Modulated Resistance Selection <CNFG_BMUX Register>
+   * @param Fbist: BIOZ RMOD BIST Frequency Selection <CNFG_BMUX Register>
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   *
+   */
+  int max30001_BIOZ_InitBist(uint8_t En_bist, uint8_t Rnom, uint8_t Rmod,
+                             uint8_t Fbist);
+
+  /**
+   * @brief For MAX30001/3/4 ONLY
+   * @brief Sets up the device for RtoR measurement
+   * @param EN_rtor: ECG RTOR Detection Enable <RTOR1 Register>
+   * @param Wndw: R to R Window Averaging (Window Width = RTOR_WNDW[3:0]*8mS) <RTOR1 Register>
+   * @param Gain: R to R Gain (where Gain = 2^RTOR_GAIN[3:0], plus an auto-scale option) <RTOR1 Register>
+   * @param Pavg: R to R Peak Averaging Weight Factor <RTOR1 Register>
+   * @param Ptsf: R to R Peak Threshold Scaling Factor <RTOR1 Register>
+   * @param Hoff: R to R minimum Hold Off <RTOR2 Register>
+   * @param Ravg: R to R Interval Averaging Weight Factor <RTOR2 Register>
+   * @param Rhsf: R to R Interval Hold Off Scaling Factor <RTOR2 Register>
+   * @param Clr_rrint: RTOR Detect Interrupt Clear behaviour <MNGR_INT Register>
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   *
+   */
+  int max30001_RtoR_InitStart(uint8_t En_rtor, uint8_t Wndw, uint8_t Gain,
+                              uint8_t Pavg, uint8_t Ptsf, uint8_t Hoff,
+                              uint8_t Ravg, uint8_t Rhsf, uint8_t Clr_rrint);
+
+  /**
+   * @brief For MAX30001/3/4 ONLY
+   * @brief This function disables the RtoR.  Uses Register CNFG_RTOR1-0x1D
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   *
+   */
+  int max30001_Stop_RtoR(void);
+
+  /**
+   * @brief This is a function that waits for the PLL to lock; once a lock is achieved it exits out. (For convenience only)
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   *
+   */
+  int max30001_PLL_lock(void);
+
+  /**
+   * @brief This function causes the MAX30001 to reset.  Uses Register SW_RST-0x08
+   * @return 0-if no error.  A non-zero value indicates an error.
+   *
+   */
+  int max30001_sw_rst(void);
+
+  /**
+   * @brief This function provides a SYNCH operation.  Uses Register SYCNH-0x09. Please refer to the data sheet for
+   * @brief the details on how to use this.
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   *
+   */
+  int max30001_synch(void);
+
+  /**
+   * @brief This function performs a FIFO Reset.  Uses Register FIFO_RST-0x0A. Please refer to the data sheet
+   * @brief for the details on how to use this.
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   */
+  int max300001_fifo_rst(void);
+
+  /**
+   *
+   * @brief This is a callback function which collects all the data from the ECG, BIOZ, PACE and RtoR. It also handles
+   * @brief Lead On/Off.  This  function is passed through the argument of max30001_COMMinit().
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   *
+   */
+  int max30001_int_handler(void);
+
+  /**
+   * @brief This is function called from the max30001_int_handler() function and processes all the ECG, BIOZ, PACE
+   * @brief and the RtoR data and sticks them in appropriate arrays and variables each unsigned 32 bits.
+   * @param ECG data will be in the array (input): max30001_ECG_FIFO_buffer[]
+   * @param Pace data will be in the array (input): max30001_PACE[]
+   * @param RtoRdata will be in the variable (input): max30001_RtoR_data
+   * @param BIOZ data will be in the array (input): max30001_BIOZ_FIFO_buffer[]
+   * @param global  max30001_ECG_FIFO_buffer[]
+   * @param global  max30001_PACE[]
+   * @param global  max30001_BIOZ_FIFO_buffer[]
+   * @param global  max30001_RtoR_data
+   * @param global  max30001_DCLeadOff
+   * @param global  max30001_ACLeadOff
+   * @param global  max30001_LeadON
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   *
+   */
+  int max30001_FIFO_LeadONOff_Read(void);
+
+  /**
+   * @brief This function allows writing to a register.
+   * @param addr:  Address of the register to write to
+   * @param data:  24-bit data read from the register.
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   *
+   */
+  int max30001_reg_write(MAX30001_REG_map_t addr, uint32_t data);
+
+  /**
+   * @brief This function allows reading from a register
+   * @param addr:   Address of the register to read from.
+   * @param *return_data: pointer to the value read from the register.
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   *
+   */
+  int max30001_reg_read(MAX30001_REG_map_t addr, uint32_t *return_data);
+
+  /**
+   * @brief This function enables the DC Lead Off detection. Either ECG or BIOZ can be detected, one at a time.
+   * @brief Registers Used:  CNFG_GEN-0x10
+   * @param En_dcloff: BIOZ Digital Lead Off Detection Enable
+   * @param Ipol: DC Lead Off Current Polarity (if current sources are enabled/connected)
+   * @param Imag: DC Lead off current Magnitude Selection
+   * @param Vth: DC Lead Off Voltage Threshold Selection
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   *
+   */
+  int max30001_Enable_DcLeadOFF_Init(int8_t En_dcloff, int8_t Ipol, int8_t Imag,
+                                     int8_t Vth);
+
+  /**
+   * @brief This function disables the DC Lead OFF feature, whichever is active.
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   *
+   */
+  int max30001_Disable_DcLeadOFF(void);
+
+  /**
+   * @brief This function sets up the BIOZ for AC Lead Off test.
+   * @brief Registers Used:  CNFG_GEN-0x10, MNGR_DYN-0x05
+   * @param En_bloff: BIOZ Digital Lead Off Detection Enable <CNFG_GEN register>
+   * @param Bloff_hi_it:      DC Lead Off Current Polarity (if current sources are enabled/connected) <MNGR_DYN register>
+   * @param Bloff_lo_it:      DC Lead off current Magnitude Selection <MNGR_DYN register>
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   *
+   */
+  int max30001_BIOZ_Enable_ACLeadOFF_Init(uint8_t En_bloff, uint8_t Bloff_hi_it,
+                                          uint8_t Bloff_lo_it);
+
+  /**
+   * @brief This function Turns of the BIOZ AC Lead OFF feature
+   * @brief Registers Used:  CNFG_GEN-0x10
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   *
+   */
+  int max30001_BIOZ_Disable_ACleadOFF(void);
+
+  /**
+   * @brief This function enables the Current Gnerator Monitor
+   * @brief Registers Used:  CNFG_BIOZ-0x18
+   * @returns 0-if no error.  A non-zero value indicates an error.
+   *
+   */
+  int max30001_BIOZ_Enable_BCGMON(void);
+
+  /**
+   *
+   * @brief This function enables the Lead ON detection. Either ECG or BIOZ can be detected, one at a time.
+   * @brief Also, the en_bioz, en_ecg, en_pace setting is saved so that when this feature is disabled through the
+   * @brief max30001_Disable_LeadON() function (or otherwise) the enable/disable state of those features can be retrieved.
+   * @param Channel: ECG or BIOZ detection
+   * @returns 0-if everything is good.  A non-zero value indicates an error.
+   *
+   */
+  int max30001_Enable_LeadON(int8_t Channel);
+
+  /**
+   * @brief This function turns off the Lead ON feature, whichever one is active.  Also, retrieves the en_bioz,
+   * @brief en_ecg, en_pace and sets it back to as it was.
+   * @param 0-if everything is good.  A non-zero value indicates an error.
+   *
+   */
+  int max30001_Disable_LeadON(void);
+
+  /**
+   *
+   * @brief This function is toggled every 2 seconds to switch between ECG Lead ON and BIOZ Lead ON detect
+   * @brief Adjust LEADOFF_SERVICE_TIME to determine the duration between the toggles.
+   * @param CurrentTime - This gets fed the time by RTC_GetValue function
+   *
+   */
+  void max30001_ServiceLeadON(uint32_t currentTime);
+
+  /**
+   *
+   * @brief This function is toggled every 2 seconds to switch between ECG DC Lead Off and BIOZ DC Lead Off
+   * @brief Adjust LEADOFF_SERVICE_TIME to determine the duration between the toggles.
+   * @param CurrentTime - This gets fed the time by RTC_GetValue function
+   *
+   */
+  void max30001_ServiceLeadoff(uint32_t currentTime);
+
+  /**
+   *
+   * @brief This function sets current RtoR values and fmstr values in a pointer structure
+   * @param hspValMax30001 - Pointer to a structure where to store the values
+   *
+   */
+  void max30001_ReadHeartrateData(max30001_t *_hspValMax30001);
+
+  /**
+   * @brief type definition for data interrupt
+   */
+  typedef void (*PtrFunction)(uint32_t id, uint32_t *buffer, uint32_t length);
+
+  /**
+   * @brief Used to connect a callback for when interrupt data is available
+   */
+  void onDataAvailable(PtrFunction _onDataAvailable);
+
+  static MAX30001 *instance;
+
+private:
+  void dataAvailable(uint32_t id, uint32_t *buffer, uint32_t length);
+  /// interrupt handler for async spi events
+  static void spiHandler(int events);
+  /// wrapper method to transmit and recieve SPI data
+  int SPI_Transmit(const uint8_t *tx_buf, uint32_t tx_size, uint8_t *rx_buf,
+                   uint32_t rx_size);
+
+  /// pointer to mbed SPI object
+  SPI *spi;
+  /// is this object the owner of the spi object
+  bool spi_owner;
+  /// buffer to use for async transfers
+  uint8_t buffer[ASYNC_SPI_BUFFER_SIZE];
+  /// function pointer to the async callback
+  event_callback_t functionpointer;
+  /// callback function when interrupt data is available
+  PtrFunction onDataAvailableCallback;
+
+}; // End of MAX30001 Class
+
+/**
+ * @brief Preventive measure used to dismiss interrupts that fire too early during
+ * @brief initialization on INTB line
+ *
+ */
+void MAX30001Mid_IntB_Handler(void);
+
+/**
+ * @brief Preventive measure used to dismiss interrupts that fire too early during
+ * @brief initialization on INT2B line
+ *
+ */
+void MAX30001Mid_Int2B_Handler(void);
+
+/**
+ * @brief Allows Interrupts to be accepted as valid.
+ * @param state: 1-Allow interrupts, Any-Don't allow interrupts.
+ *
+ */
+void MAX30001_AllowInterrupts(int state);
+
+#endif /* MAX30001_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MAX30101/MAX30101/MAX30101.cpp	Thu Mar 28 08:10:23 2019 +0000
@@ -0,0 +1,703 @@
+
+/*******************************************************************************
+ * Copyright (C) 2016 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 "MAX30101.h"
+
+MAX30101 *MAX30101::instance = NULL;
+
+//******************************************************************************
+MAX30101::MAX30101(PinName sda, PinName scl, int slaveAddress): 
+          slaveAddress(slaveAddress) {
+  i2c = new I2C(sda, scl);
+  i2c_owner = true;
+  i2c->frequency(400000);
+  onInterruptCallback = NULL;
+  onDataAvailableCallback = NULL;
+  instance = this;
+}
+
+//******************************************************************************
+MAX30101::MAX30101(I2C *_i2c, int slaveAddress) : 
+          slaveAddress(slaveAddress) {
+  i2c = _i2c;
+  i2c_owner = false;
+  i2c->frequency(400000);
+  onInterruptCallback = NULL;
+  onDataAvailableCallback = NULL;
+  instance = this;
+}
+
+//******************************************************************************
+MAX30101::~MAX30101(void) {
+  if (i2c_owner) {
+    delete i2c;
+  }
+}
+
+//******************************************************************************
+int MAX30101::int_handler(void) {
+  uint16_t index, i;
+  uint16_t rx_bytes, second_rx_bytes;
+  char temp_int;
+  char temp_frac;
+  uint16_t num_active_led;
+  uint32_t sample;
+  int loop = 1;
+  static uint8_t cntr_int = 0;
+
+
+  cntr_int++;
+
+  while (loop) {
+    if (i2c_reg_read(REG_INT_STAT_1, &max30101_Interrupt_Status_1.all) != 0) // Read Interrupt flag bits
+    {
+      return -1;
+    }
+
+    if (i2c_reg_read(REG_INT_STAT_2, &max30101_Interrupt_Status_2.all) != 0) // Read Interrupt flag bits
+    {
+      return -1;
+    }
+
+    if (max30101_Interrupt_Status_1.bit.a_full) {
+      /* Read the sample(s) */
+      char reg = REG_FIFO_DATA;
+
+      num_active_led = 0;
+
+      if (max30101_mode_configuration.bit.mode == 0x02) // Heart Rate mode, i.e. 1 led
+      {
+        num_active_led = 1;
+      } else if (max30101_mode_configuration.bit.mode == 0x03) // SpO2 mode, i.e. 2 led
+      {
+        num_active_led = 2;
+      } else if (max30101_mode_configuration.bit.mode == 0x07) // Multi-LED mode, i.e. 1-4 led
+      {
+        if (max30101_multiLED_mode_ctrl_1.bit.slot1 != 0) {
+          num_active_led++;
+        }
+
+        if (max30101_multiLED_mode_ctrl_1.bit.slot2 != 0) {
+          num_active_led++;
+        }
+
+        if (max30101_multiLED_mode_ctrl_2.bit.slot3 != 0) {
+          num_active_led++;
+        }
+
+        if (max30101_multiLED_mode_ctrl_2.bit.slot4 != 0) {
+          num_active_led++;
+        }
+      }
+               // 3bytes/LED x Number of Active LED x FIFO level selected
+        rx_bytes =  3 * num_active_led * (32-max30101_fifo_configuration.bit.fifo_a_full);   
+
+      second_rx_bytes = rx_bytes;
+
+      /*  The FIFO Size is determined by the Sample size.  The number of bytes
+       * in a Sample is dictated by number of LED's
+       *
+       *   #LED Selected     Bytes in "1" sample
+       *        1                  3
+       *        2                  6
+       *        3                  9
+       *        4                  12
+       *
+       *  The I2C API function limits the number of bytes to read to 256 (i.e.
+       * char).  Therefore, when set for
+       *  Multiple LED's and the FIFO size is set to 32.  It would mean there is
+       * more than 256 bytes.
+       *  In that case two I2C reads have to be made.  However It is important
+       * to not that each "Sample"
+       *  must be read completely and reading only partial number of bytes from
+       * a sample will result in erroneous data.
+       *
+       *  For example:
+       *  Num of LED selected = 3 and FIFO size is set to 32 (i.e. 0 value in
+       * register), then the number of bytes
+       *  will be 3bytes/Led * 3led's * 32 = 288 bytes in all.  Since there are
+       * 3 LED's each sample will contain (3 * 3)
+       *  9bytes.  Therefore Sample 1 = 9bytes, Sample 2 = 18,... Sample 28 =
+       * 252.  Therefore the first
+       *  I2C read should be 252 bytes and the second read should be 288-252 =
+       * 36.
+       *
+       *  It turns out that this size issue comes up only when number of LED
+       * selected is 3 or 4 and choosing 252bytes
+       *  for the first I2C read would work for both Number of LED selection.
+       */
+
+      if (rx_bytes <= CHUNK_SIZE) {
+        I2CM_Read(slaveAddress, &reg, 1, &max30101_rawData[0],
+                  (char)rx_bytes /*total_databytes_1*/);
+      } else {
+        I2CM_Read(slaveAddress, &reg, 1, &max30101_rawData[0], CHUNK_SIZE);
+
+        second_rx_bytes = second_rx_bytes - CHUNK_SIZE;
+        I2CM_Read(slaveAddress, &reg, 1, &max30101_rawData[CHUNK_SIZE],
+                  (char)second_rx_bytes);
+      }
+
+      index = 0;
+
+      for (i = 0; i < rx_bytes; i += 3) {
+        sample = ((uint32_t)(max30101_rawData[i] & 0x03) << 16) | (max30101_rawData[i + 1] << 8) | max30101_rawData[i + 2];
+
+        // Right shift the data based on the LED_PW setting
+        sample = sample >>
+                 (3 -
+                  max30101_spo2_configuration.bit.led_pw); // 0=shift 3, 1=shift 2, 2=shift 1, 3=no shift
+
+        max30101_buffer[index++] = sample;
+      }
+
+      onDataAvailableCallback(MAX30101_OXIMETER_DATA + num_active_led, max30101_buffer, index);
+    }
+
+// This interrupt handles the proximity interrupt, for future enhancements
+#if 0
+   if(max30101_Interrupt_Status_1.bit.prox_int)
+     {
+     max30101_mode_configuration.full=0;
+     max30101_mode_configuration.bit.mode=0x03;     // SpO2 mode
+     i2c_reg_write(REG_MODE_CFG, max30101_mode_configuration.full);
+
+     }
+#endif
+
+    // This interrupt handles the temperature interrupt
+    if (max30101_Interrupt_Status_2.bit.die_temp_rdy) {
+      char reg;
+
+      reg = REG_TINT;
+      if (I2CM_Read(slaveAddress, &reg, 1, &temp_int, 1) != 0) {
+        return -1;
+      }
+
+      reg = REG_TFRAC;
+      if (I2CM_Read(slaveAddress, &reg, 1, &temp_frac, 1) != 0) {
+        return -1;
+      }
+
+      max30101_final_temp = (int8_t)temp_int + 0.0625 * temp_frac;
+
+      if (i2c_reg_write(REG_TEMP_EN, 0x00) != 0) // Die Temperature Config, Temp disable... after one read...
+      {
+        return -1;
+      }
+    }
+
+    if (i2c_reg_read(REG_INT_STAT_1, &max30101_Interrupt_Status_1.all) != 0) // Read Interrupt flag bits
+    {
+      return -1;
+    }
+    if (max30101_Interrupt_Status_1.bit.a_full != 1) {
+      loop = 0;
+    }
+  }
+
+  interruptPostCallback();
+
+
+  return 0;
+}
+
+//******************************************************************************
+int MAX30101::SpO2mode_init(uint8_t fifo_waterlevel_mark, uint8_t sample_avg,
+                            uint8_t sample_rate, uint8_t pulse_width,
+                            uint8_t red_led_current, uint8_t ir_led_current) {
+
+  char status;
+
+  max30101_mode_configuration.all = 0;
+  max30101_mode_configuration.bit.reset = 1;
+  if (i2c_reg_write(REG_MODE_CFG, max30101_mode_configuration.all) != 0) // Reset the device, Mode = don't use...
+  {
+    return -1;
+  }
+
+  /* Give it some settle time (100ms) */
+  wait(1.0 / 10.0); // Let things settle down a bit
+
+  max30101_fifo_configuration.all = 0;
+  max30101_fifo_configuration.bit.smp_ave = sample_avg; // Sample averaging;
+  max30101_fifo_configuration.bit.fifo_roll_over_en = 1; // FIFO Roll over enabled
+  max30101_fifo_configuration.bit.fifo_a_full = fifo_waterlevel_mark; // Interrupt when certain level is filled
+  if (i2c_reg_write(REG_FIFO_CFG, max30101_fifo_configuration.all) != 0) {
+    return -1;
+  }
+
+  max30101_spo2_configuration.bit.spo2_adc_rge = 0x2; // ADC Range 8192 fullscale
+  max30101_spo2_configuration.bit.spo2_sr = sample_rate; // 100 Samp/sec.
+  max30101_spo2_configuration.bit.led_pw = pulse_width; // Pulse Width=411us and ADC Resolution=18
+  if (i2c_reg_write(REG_SPO2_CFG, max30101_spo2_configuration.all) != 0) {
+    return -1;
+  }
+
+  max30101_led1_pa = red_led_current; // RED LED current
+  if (i2c_reg_write(REG_LED1_PA, max30101_led1_pa) != 0) {
+    return -1;
+  }
+
+  max30101_led2_pa = ir_led_current; // IR LED current
+  if (i2c_reg_write(REG_LED2_PA, max30101_led2_pa) != 0) {
+    return -1;
+  }
+
+  /************/
+
+  if (i2c_reg_read(REG_INT_STAT_1, &status) != 0) //  Clear INT1 by reading the status
+  {
+    return -1;
+  }
+
+  if (i2c_reg_read(REG_INT_STAT_2, &status) != 0) //  Clear INT2 by reading the status
+  {
+    return -1;
+  }
+
+  if (i2c_reg_write(REG_FIFO_W_PTR, 0x00) != 0) //  Clear FIFO ptr
+  {
+    return -1;
+  }
+
+  if (i2c_reg_write(REG_FIFO_OVF_CNT, 0x00) != 0) //  Clear FIFO ptr
+  {
+    return -1;
+  }
+
+  if (i2c_reg_write(REG_FIFO_R_PTR, 0x00) != 0) //  Clear FIFO ptr
+  {
+    return -1;
+  }
+
+  max30101_Interrupt_Enable_1.all = 0;
+  max30101_Interrupt_Enable_1.bit.a_full_en = 1; //  Enable FIFO almost full interrupt
+  if (i2c_reg_write(REG_INT_EN_1, max30101_Interrupt_Enable_1.all) != 0) {
+    return -1;
+  }
+
+  max30101_mode_configuration.all = 0;
+  max30101_mode_configuration.bit.mode = 0x03; // SpO2 mode
+  if (i2c_reg_write(REG_MODE_CFG, max30101_mode_configuration.all) != 0) {
+    return -1;
+  }
+
+  return 0;
+}
+
+//******************************************************************************
+int MAX30101::SpO2mode_stop(void) {
+
+  max30101_Interrupt_Enable_1.all = 0;
+  max30101_Interrupt_Enable_1.bit.a_full_en = 0; //  Disable FIFO almost full interrupt
+  if (i2c_reg_write(REG_INT_EN_1, max30101_Interrupt_Enable_1.all) != 0) {
+    return -1;
+  }
+
+  max30101_mode_configuration.all = 0;
+  max30101_mode_configuration.bit.mode = 0x00; // SpO2 mode off
+  if (i2c_reg_write(REG_MODE_CFG, max30101_mode_configuration.all) != 0) {
+    return -1;
+  }
+
+  max30101_led1_pa = 0; // RED LED current, 0.0
+  if (i2c_reg_write(REG_LED1_PA, max30101_led1_pa) != 0) {
+    return -1;
+  }
+
+  max30101_led2_pa = 0; // IR LED current, 0.0
+  if (i2c_reg_write(REG_LED2_PA, max30101_led2_pa) != 0) {
+    return -1;
+  }
+
+  return 0;
+}
+
+//******************************************************************************
+int MAX30101::HRmode_init(uint8_t fifo_waterlevel_mark, uint8_t sample_avg,
+                          uint8_t sample_rate, uint8_t pulse_width,
+                          uint8_t red_led_current) {
+
+  /*uint8_t*/ char status;
+
+  max30101_mode_configuration.all = 0;
+  max30101_mode_configuration.bit.reset = 1;
+  if (i2c_reg_write(REG_MODE_CFG, max30101_mode_configuration.all) != 0) // Reset the device, Mode = don't use...
+  {
+    return -1;
+  }
+
+  /* Give it some settle time (100ms) */
+  wait(1.0 / 10.0); // Let things settle down a bit
+
+  max30101_fifo_configuration.all = 0;
+  max30101_fifo_configuration.bit.smp_ave = sample_avg; // Sample averaging;
+  max30101_fifo_configuration.bit.fifo_roll_over_en = 1; // FIFO Roll over enabled
+  max30101_fifo_configuration.bit.fifo_a_full = fifo_waterlevel_mark; // Interrupt when certain level is filled
+  if (i2c_reg_write(REG_FIFO_CFG, max30101_fifo_configuration.all) != 0) {
+    return -1;
+  }
+
+  max30101_spo2_configuration.bit.spo2_adc_rge = 0x2; // ADC Range 8192 fullscale
+  max30101_spo2_configuration.bit.spo2_sr = sample_rate; // 100 Samp/sec.
+  max30101_spo2_configuration.bit.led_pw = pulse_width; // Pulse Width=411us and ADC Resolution=18
+  if (i2c_reg_write(REG_SPO2_CFG, max30101_spo2_configuration.all) != 0) {
+    return -1;
+  }
+
+  max30101_led1_pa = red_led_current; // RED LED current, 0.0
+  if (i2c_reg_write(REG_LED1_PA, max30101_led1_pa) != 0) {
+    return -1;
+  }
+
+  /************/
+
+  if (i2c_reg_read(REG_INT_STAT_1, &status) != 0) //  Clear INT1 by reading the status
+  {
+    return -1;
+  }
+
+  if (i2c_reg_read(REG_INT_STAT_2, &status) != 0) //  Clear INT2 by reading the status
+  {
+    return -1;
+  }
+
+  if (i2c_reg_write(REG_FIFO_W_PTR, 0x00) != 0) //  Clear FIFO ptr
+  {
+    return -1;
+  }
+
+  if (i2c_reg_write(REG_FIFO_OVF_CNT, 0x00) != 0) //  Clear FIFO ptr
+  {
+    return -1;
+  }
+
+  if (i2c_reg_write(REG_FIFO_R_PTR, 0x00) != 0) //  Clear FIFO ptr
+  {
+    return -1;
+  }
+
+  max30101_Interrupt_Enable_1.all = 0;
+  max30101_Interrupt_Enable_1.bit.a_full_en = 1;
+  // max30101_Interrupt_Enable_1.bit.prox_int_en=0;   //  Enable Proximity
+  // Interrupt
+  if (i2c_reg_write(REG_INT_EN_1, max30101_Interrupt_Enable_1.all) != 0) {
+    return -1;
+  }
+
+  max30101_mode_configuration.all = 0;
+  max30101_mode_configuration.bit.mode = 0x02; // HR mode
+  if (i2c_reg_write(REG_MODE_CFG, max30101_mode_configuration.all) != 0) {
+    return -1;
+  }
+
+  return 0;
+}
+
+//******************************************************************************
+int MAX30101::HRmode_stop(void) {
+
+  max30101_Interrupt_Enable_1.all = 0;
+  max30101_Interrupt_Enable_1.bit.a_full_en = 0; //  Disable FIFO almost full interrupt
+  if (i2c_reg_write(REG_INT_EN_1, max30101_Interrupt_Enable_1.all) != 0) {
+    return -1;
+  }
+
+  max30101_mode_configuration.all = 0;
+  max30101_mode_configuration.bit.mode = 0x00; // HR mode off
+  if (i2c_reg_write(REG_MODE_CFG, max30101_mode_configuration.all) != 0) {
+    return -1;
+  }
+
+  max30101_led1_pa = 0; // RED LED current, 0.0
+  if (i2c_reg_write(REG_LED1_PA, max30101_led1_pa) != 0) {
+    return -1;
+  }
+
+  return 0;
+}
+
+//******************************************************************************
+int MAX30101::Multimode_init(uint8_t fifo_waterlevel_mark, uint8_t sample_avg,
+                             uint8_t sample_rate, uint8_t pulse_width,
+                             uint8_t red_led_current, uint8_t ir_led_current,
+                             uint8_t green_led_current, uint8_t slot_1,
+                             uint8_t slot_2, uint8_t slot_3, uint8_t slot_4) {
+  char status;
+  max30101_mode_configuration.all = 0;
+  max30101_mode_configuration.bit.reset = 1;
+  if (i2c_reg_write(REG_MODE_CFG, max30101_mode_configuration.all) != 0) // Reset the device, Mode = don't use...
+  {
+    return -1;
+  }
+
+  /* Give it some settle time (100ms) */ // Let things settle down a bit
+  wait(1.0 / 10.0);
+
+  max30101_fifo_configuration.all = 0;
+  max30101_fifo_configuration.bit.smp_ave = sample_avg; // Sample averaging;
+  max30101_fifo_configuration.bit.fifo_roll_over_en = 1; // FIFO Roll over enabled
+  max30101_fifo_configuration.bit.fifo_a_full =
+      fifo_waterlevel_mark; // Interrupt when certain level is filled
+  if (i2c_reg_write(REG_FIFO_CFG, max30101_fifo_configuration.all) != 0) {
+    return -1;
+  }
+
+  max30101_spo2_configuration.bit.spo2_adc_rge = 0x2; // ADC Range 8192 fullscale
+  max30101_spo2_configuration.bit.spo2_sr = sample_rate; // 100 Samp/sec.
+  max30101_spo2_configuration.bit.led_pw = pulse_width; // Pulse Width=411us and ADC Resolution=18
+  if (i2c_reg_write(REG_SPO2_CFG, max30101_spo2_configuration.all) != 0) {
+    return -1;
+  }
+
+  max30101_led1_pa = red_led_current; // RED LED current
+  if (i2c_reg_write(REG_LED1_PA, max30101_led1_pa) != 0) {
+    return -1;
+  }
+
+  max30101_led2_pa = ir_led_current; // IR LED current
+  if (i2c_reg_write(REG_LED2_PA, max30101_led2_pa) != 0) {
+    return -1;
+  }
+
+  max30101_led3_pa = green_led_current; // Green LED current
+  if (i2c_reg_write(REG_LED3_PA, max30101_led3_pa) != 0) {
+    return -1;
+  }
+
+  // 0x01=Red(LED1), 0x02=IR(LED2), 0x03=Green(LED3) : Use LEDn_PA to adjust the intensity
+  // 0x05=Red      , 0x06=IR      , 0x07=Green       : Use PILOT_PA to adjust the intensity DO NOT USE THIS ROW...
+
+  max30101_multiLED_mode_ctrl_1.bit.slot1 = slot_1;
+  max30101_multiLED_mode_ctrl_1.bit.slot2 = slot_2;
+  if (i2c_reg_write(REG_SLT2_SLT1, max30101_multiLED_mode_ctrl_1.all)) {
+    return -1;
+  }
+
+  max30101_multiLED_mode_ctrl_2.all = 0;
+  max30101_multiLED_mode_ctrl_2.bit.slot3 = slot_3;
+  max30101_multiLED_mode_ctrl_2.bit.slot4 = slot_4;
+  if (i2c_reg_write(REG_SLT4_SLT3, max30101_multiLED_mode_ctrl_2.all)) {
+    return -1;
+  }
+
+  /************/
+
+  if (i2c_reg_read(REG_INT_STAT_1, &status) != 0) //  Clear INT1 by reading the status
+  {
+    return -1;
+  }
+
+  if (i2c_reg_read(REG_INT_STAT_2, &status) != 0) //  Clear INT2 by reading the status
+  {
+    return -1;
+  }
+
+  if (i2c_reg_write(REG_FIFO_W_PTR, 0x00) != 0) //  Clear FIFO ptr
+  {
+    return -1;
+  }
+
+  if (i2c_reg_write(REG_FIFO_OVF_CNT, 0x00) != 0) //  Clear FIFO ptr
+  {
+    return -1;
+  }
+
+  if (i2c_reg_write(REG_FIFO_R_PTR, 0x00) != 0) //  Clear FIFO ptr
+  {
+    return -1;
+  }
+
+  max30101_Interrupt_Enable_1.all = 0;
+  max30101_Interrupt_Enable_1.bit.a_full_en = 1; //  Enable FIFO almost full interrupt
+  if (i2c_reg_write(REG_INT_EN_1, max30101_Interrupt_Enable_1.all) != 0) {
+    return -1;
+  }
+
+  max30101_mode_configuration.all = 0;
+  max30101_mode_configuration.bit.mode = 0x07; // Multi-LED mode
+  if (i2c_reg_write(REG_MODE_CFG, max30101_mode_configuration.all) != 0) {
+    return -1;
+  }
+
+  return 0;
+}
+
+//******************************************************************************
+int MAX30101::Multimode_stop(void) {
+
+  max30101_Interrupt_Enable_1.all = 0;
+  max30101_Interrupt_Enable_1.bit.a_full_en = 0; //  Disable FIFO almost full interrupt
+  if (i2c_reg_write(REG_INT_EN_1, max30101_Interrupt_Enable_1.all) != 0) {
+    return -1;
+  }
+
+  max30101_mode_configuration.all = 0;
+  max30101_mode_configuration.bit.mode = 0x00; // Multi-LED mode off
+  if (i2c_reg_write(REG_MODE_CFG, max30101_mode_configuration.all) != 0) {
+    return -1;
+  }
+
+  max30101_led1_pa = 0; // RED LED current, 0.0
+  if (i2c_reg_write(REG_LED1_PA, max30101_led1_pa) != 0) {
+    return -1;
+  }
+
+  max30101_led2_pa = 0; // IR LED current, 0.0
+  if (i2c_reg_write(REG_LED2_PA, max30101_led2_pa) != 0) {
+    return -1;
+  }
+
+  max30101_led3_pa = 0; // Green LED current, 0.0
+  if (i2c_reg_write(REG_LED3_PA, max30101_led3_pa) != 0) {
+    return -1;
+  }
+  return 0;
+}
+
+//******************************************************************************
+int MAX30101::tempread(void) {
+  max30101_Interrupt_Enable_2.all = 0;
+  max30101_Interrupt_Enable_2.bit.die_temp_rdy_en = 1; // Enable the Temp Rdy;
+  if (i2c_reg_write(REG_INT_EN_2, 0x02) != 0) // Interrupt Enable 2, Temperature Interrupt
+  {
+    return -1;
+  }
+
+  if (i2c_reg_write(REG_TEMP_EN, 0x01) != 0) // Die Temperature Config, Temp enable...
+  {
+    return -1;
+  }
+  return 0;
+}
+
+//******************************************************************************
+int MAX30101::i2c_reg_write(MAX30101_REG_map_t reg, char value) {
+  char cmdData[2] = {reg, value};
+
+  if (I2CM_Write(slaveAddress, NULL, 0, cmdData, 2) != 0 /*2*/) {
+    return -1;
+  }
+
+  return 0;
+}
+
+//******************************************************************************
+int MAX30101::i2c_reg_read(MAX30101_REG_map_t reg, char *value) {
+  if (I2CM_Read(slaveAddress, (char *)&reg, 1, value, 1) != 0 /*1*/) {
+    return -1;
+  }
+
+  return 0;
+}
+
+/**
+* @brief Read from an I2C device
+* @param slaveAddress slave address to use with transaction
+* @param writeData pointer of data to write
+* @param writeCount number of data to write
+* @param readData pointer to buffer to read to
+* @param readCount number of bytes to read
+*/
+int MAX30101::I2CM_Read(int slaveAddress, char *writeData, char writeCount,
+                        char *readData, char readCount) {
+  if (writeData != NULL && writeCount != 0) {
+    i2c->write(slaveAddress, writeData, writeCount, true);
+  }
+  if (readData != NULL && readCount != 0) {
+    i2c->read(slaveAddress, readData, readCount);
+  }
+  return 0;
+}
+
+/**
+* @brief Write to an I2C device
+* @param slaveAddress slave address to use with transaction
+* @param writeData pointer of data to write
+* @param writeCount1 number of data to write
+* @param writeData2 pointer to buffer to read to
+* @param writeCount2 number of bytes to read
+*/
+int MAX30101::I2CM_Write(int slaveAddress, char *writeData1, char writeCount1,
+                         char *writeData2, char writeCount2) {
+  if (writeData1 != NULL && writeCount1 != 0) {
+    i2c->write(slaveAddress, writeData1, writeCount1);
+  }
+  if (writeData2 != NULL && writeCount2 != 0) {
+    i2c->write(slaveAddress, writeData2, writeCount2);
+  }
+  return 0;
+}
+
+//******************************************************************************
+void MAX30101::onDataAvailable(DataCallbackFunction _onDataAvailable) {
+  onDataAvailableCallback = _onDataAvailable;
+}
+
+/**
+* @brief Used to notify an external function that interrupt data is available
+* @param id type of data available
+* @param buffer 32-bit buffer that points to the data
+* @param length length of 32-bit elements available
+*/
+void MAX30101::dataAvailable(uint32_t id, uint32_t *buffer, uint32_t length) {
+  if (onDataAvailableCallback != NULL) {
+    (*onDataAvailableCallback)(id, buffer, length);
+  }
+}
+
+//******************************************************************************
+void MAX30101::onInterrupt(InterruptFunction _onInterrupt) {
+  onInterruptCallback = _onInterrupt;
+}
+
+/**
+* @brief Executed on interrupt
+* @param id type of data available
+* @param buffer 32-bit buffer that points to the data
+* @param length length of 32-bit elements available
+*/
+void MAX30101::interruptPostCallback(void) {
+  if (onInterruptCallback != NULL) {
+    (*onInterruptCallback)();
+  }
+}
+
+int max30101_enableInterrupts = 0;
+/**************************************************************************************************************/
+void MAX30101MidIntHandler(void) { 
+  MAX30101::instance->int_handler(); 
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MAX30101/MAX30101/MAX30101.h	Thu Mar 28 08:10:23 2019 +0000
@@ -0,0 +1,459 @@
+/*******************************************************************************
+/ * Copyright (C) 2015 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.
+ *******************************************************************************/
+/*
+ * max30101.h
+ *
+ *  Created on: Aug 26, 2015
+ *      Author: faisal.tariq
+ */
+
+#ifndef _MAX30101_H_
+#define _MAX30101_H_
+
+#include "mbed.h"
+
+#define MAX30101_RAW_DATA_SIZE 3 * 4 * 32
+#define MAX30101_PROC_DATA_SIZE 4 * 32
+
+#define MAX30101_OXIMETER_DATA 0x10
+
+#define CHUNK_SIZE 252
+
+// MAX30101 Register addresses
+
+#define MAX30101_INT_PORT 4
+#define MAX30101_INT_PIN 0
+#define MAX30101_MASTER_NUM 2
+
+/**
+* Maxim Integrated MAX30101 Oximeter chip
+*/
+class MAX30101 {
+public:
+  float max30101_final_temp;                         // Global declaration
+  uint32_t max30101_buffer[MAX30101_PROC_DATA_SIZE]; // final Processed data
+  char max30101_rawData[MAX30101_RAW_DATA_SIZE];     //  raw data from the chip
+
+  typedef enum { // MAX30101 Register addresses
+
+    /*Status */
+    REG_INT_STAT_1 = 0x00,
+    REG_INT_STAT_2 = 0x01,
+    REG_INT_EN_1   = 0x02,
+    REG_INT_EN_2   = 0x03,
+
+    REG_FIFO_W_PTR   = 0x04,
+    REG_FIFO_OVF_CNT = 0x05,
+    REG_FIFO_R_PTR   = 0x06,
+    REG_FIFO_DATA    = 0x07,
+    /* Configuration */
+    REG_FIFO_CFG  = 0x08,
+    REG_MODE_CFG  = 0x09,
+    REG_SPO2_CFG  = 0x0A,
+    REG_LED1_PA   = 0x0C,
+    REG_LED2_PA   = 0x0D,
+    REG_LED3_PA   = 0x0E,
+    REG_PILOT_PA  = 0x10,
+    REG_SLT2_SLT1 = 0x11,
+    REG_SLT4_SLT3 = 0x12,
+    /* Die Temp    */
+    REG_TINT    = 0x1F,
+    REG_TFRAC   = 0x20,
+    REG_TEMP_EN = 0x21,
+    /* Proximity Func */
+    REG_PROX_INT_THR = 0x30,
+    /* Part ID        */
+    REG_REV_ID = 0xFE,
+    REG_ID     = 0xFF,
+  } MAX30101_REG_map_t;
+
+  /**********/
+  /* STATUS */
+  /**********/
+  /// @brief STATUS1 (0x00)
+  union max30101_Interrupt_Status_1_reg {
+    char all;
+    struct {
+      char pwr_rdy  : 1;
+      char reserved : 3;
+      char prox_int : 1;
+      char alc_ovf  : 1;
+      char ppg_rdy  : 1;
+      char a_full   : 1;
+    } bit;
+  } max30101_Interrupt_Status_1;
+
+  /// @brief STATUS2 (0x01)
+  union max30101_Interrupt_Status_2_reg {
+    char all;
+    struct {
+      char reserved1    : 1;
+      char die_temp_rdy : 1;
+      char reserved2    : 6;
+    } bit;
+  } max30101_Interrupt_Status_2;
+
+  /// @brief INTERRUPT_ENABLE1 (0x02)
+  volatile union max30101_Interrupt_Enable_1_reg {
+    uint8_t all;
+    struct {
+      uint8_t reserved1   : 4;
+      uint8_t prox_int_en : 1;
+      uint8_t alc_ovf_en  : 1;
+      uint8_t ppg_rdy_en  : 1;
+      uint8_t a_full_en   : 1;
+    } bit;
+  } max30101_Interrupt_Enable_1;
+
+  /// @brief INTERRUPT_ENABLE2 (0x03)
+  volatile union max30101_Interrupt_Enable_2_reg {
+    uint8_t all;
+    struct {
+      uint8_t reserved1       : 1;
+      uint8_t die_temp_rdy_en : 1;
+      uint8_t reserved2       : 6;
+    } bit;
+  } max30101_Interrupt_Enable_2;
+
+  /*********/
+  /* FIFO  */
+  /*********/
+  // 0x04
+  /// @brief FIFO_WR_PTR (0x04)
+  volatile union max30101_fifo_wr_ptr_reg {
+    uint8_t all;
+    struct {
+      uint8_t fifo_wr_ptr : 5;
+      uint8_t reserved1   : 3;
+    } bit;
+  } max30101_fifo_wr_ptr;
+
+  /// @brief OVF_COUNTER (0x05)
+  volatile union max30101_ovf_counter_reg {
+    uint8_t all;
+    struct {
+      uint8_t fifo_ovf_counter : 5;
+      uint8_t reserved1        : 3;
+    } bit;
+  } max30101_ovf_counter_reg;
+
+  /// @brief FIFO_READ_PTR (0x06)
+  volatile union max30101_fifo_rd_ptr_reg {
+    uint8_t all;
+    struct {
+      uint8_t fifo_rd_ptr : 5;
+      uint8_t reserved1   : 3;
+    } bit;
+  } max30101_fifo_rd_ptr;
+
+  // 0x07
+  uint8_t max30101_fifo_data;
+
+  /********************/
+  /* Configuration    */
+  /********************/
+  // 0x08
+  /// @brief FIFO_CONFIGURATION (0x08)
+  volatile union max30101_fifo_configuration_reg {
+    uint8_t all;
+    struct {
+      uint8_t fifo_a_full       : 4;
+      uint8_t fifo_roll_over_en : 1;
+      uint8_t smp_ave           : 3;
+    } bit;
+  } max30101_fifo_configuration;
+
+  /// @brief MODE_CONFIGURATION (0x09)
+  volatile union max30101_mode_configuration_reg {
+    uint8_t all;
+    struct {
+      uint8_t mode      : 3;
+      uint8_t reserved1 : 3;
+      uint8_t reset     : 1;
+      uint8_t shdn      : 1;
+    } bit;
+  } max30101_mode_configuration;
+
+  /// @brief SPO2_CONGIGURATION (0x0A)
+  volatile union max30101_spo2_configuration_reg {
+    uint8_t all;
+    struct {
+      uint8_t led_pw       : 2;
+      uint8_t spo2_sr      : 3;
+      uint8_t spo2_adc_rge : 2;
+      uint8_t reserved1    : 1;
+    } bit;
+  } max30101_spo2_configuration;
+
+  /// @brief LED1_PA (0x0C)
+  uint8_t max30101_led1_pa;
+
+  /// @brief LED2_PA (0x0D)
+  uint8_t max30101_led2_pa;
+
+  /// @brief LED3_PA (0x0E)
+  uint8_t max30101_led3_pa;
+
+  /// @brief PILOT_PA (0x10)
+  uint8_t max30101_pilot_pa;
+
+  volatile union max30101_multiLED_mode_ctrl_1_reg {
+    uint8_t all;
+    struct {
+      uint8_t slot1     : 3;
+      uint8_t reserved  : 1;
+      uint8_t slot2     : 3;
+      uint8_t reserved1 : 1;
+    } bit;
+  } max30101_multiLED_mode_ctrl_1;
+
+  volatile union max30101_multiLED_mode_ctrl_2_reg {
+    uint8_t all;
+    struct {
+      uint8_t slot3     : 3;
+      uint8_t reserved  : 1;
+      uint8_t slot4     : 3;
+      uint8_t reserved1 : 1;
+    } bit;
+  } max30101_multiLED_mode_ctrl_2;
+
+  /********************/
+  /* Die Temperature  */
+  /********************/
+
+  uint8_t max30101_tinit;
+
+  uint8_t max30101_tfrac;
+
+  volatile union max30101_die_temp_config {
+    uint8_t all;
+    struct {
+      uint8_t temp_en  : 1;
+      uint8_t reserved : 7;
+    } bit;
+  } max30101_die_temp_config;
+  /*******************************/
+  /***** Function Prototypes *****/
+  /*******************************/
+
+  uint8_t max30101_prox_int_thresh;
+
+  /**
+  * MAX30101 constructor.
+  *
+  * @param sda mbed pin to use for SDA line of I2C interface.
+  * @param scl mbed pin to use for SCL line of I2C interface.
+  */
+  MAX30101(PinName sda, PinName scl, int slaveAddress);
+
+  /**
+  *  MAX30101 constructor.
+  *
+  * @param i2c I2C object to use.
+  */
+  MAX30101(I2C *i2c, int slaveAddress);
+
+  /**
+  * MAX30101 destructor.
+  */
+  ~MAX30101(void);
+
+  /**
+       * @brief Allows reading from MAX30101 register
+   * @param reg: is the register address, to read from (look at max30101.h and the
+   *             data sheet for details)
+   * @param value: is the pointer to the value read from the register
+   * @returns  0-if no error.  A non-zero value indicates an error.
+   */
+  int i2c_reg_read(MAX30101_REG_map_t reg, char *value);
+
+  /**
+   * @brief Allows writing to MAX30101 register
+   * @param reg: is the register address, to read from (look at max30101.h and
+   * the
+   *        data sheet for details)
+   * @param value: is the value to write to the register
+   * @returns  0-if if no error.  A non-zero value indicates an error.
+   */
+  int i2c_reg_write(MAX30101_REG_map_t reg, char value);
+
+  /**
+   * @brief This function sets up for the SpO2 mode.  The data is returned in
+   * the callback function
+   * @brief max30101_int_handler in global array: buffer[].  SP mode handles two LED (Red,IR) data.  Hence it
+   * @brief can fill up the FIFO up to a maximum of 3bytes/sample x 32 x 2 = 192bytes.
+   * @param fifo_waterlevel_mark: corresponds to FIFO_A_FULL, In FIFO Configuration Register (0x08)
+   * @param sample_avg: corresponds to SMP_AVE, in FIFO Configuration Register (0x08)
+   * @param sample_rate: corresponds to SPO2_SR, IN SpO2 Configuration Register (0x0A)
+   * @param pulse_width: corresponds to LED_PW in SpO2 Configuration register(0x0A)
+   * @param red_led_current: corresponds to LED1_PA register (0x0C).  Please see data sheet for values
+   * @param ir_led_current: corresponds to LED2_PA register (0x0D).  Please see data sheet for values
+   * @returns 0-if everything is good.  A non-zero value indicates an error.
+   */
+  int SpO2mode_init(uint8_t fifo_waterlevel_mark, uint8_t sample_avg,
+                    uint8_t sample_rate, uint8_t pulse_width,
+                    uint8_t red_led_current, uint8_t ir_led_current);
+
+  /**
+   * @brief This function will stop the SpO2 mode and turn off all operating LED�s.
+   * @return  0-if if no error.  A non-zero value indicates an error.
+   */
+  int SpO2mode_stop(void);
+
+  /**
+   * @brief This function sets up for the HR mode.  The data is returned in thecallback function
+   * @brief max30101_int_handler in global array: buffer[].HR mode handles one LED (Red) data.  Hence it can fill
+   * @brief up the FIFO up to a maximum of 3bytes/sample x 32 = 96bytes.
+   * @brief fifo_waterlevel_mark: corresponds to FIFO_A_FULL, In FIFO Configuration Register (0x08)
+   * @param sample_avg: corresponds to SMP_AVE, in FIFO Configuration Register (0x08)
+   * @param sample_rate:corresponds to SPO2_SR, IN SpO2 Configuration Register (0x0A)
+   * @param pulse_width: corresponds to LED_PW in SpO2 Configuration Register(0x0A)
+   * @param red_led_current: corresponds to LED1_PA register (0x0C).  Please see data sheet for values
+   * @returns  0-if if no error.  A non-zero value indicates an error.
+   */
+  int HRmode_init(uint8_t fifo_waterlevel_mark, uint8_t sample_avg,
+                  uint8_t sample_rate, uint8_t pulse_width,
+                  uint8_t red_led_current);
+
+  /**
+   * @brief This function will stop the HR mode and turn off all operating
+   * LED’s.
+   * @return  0-if if no error.  A non-zero value indicates an error.
+   */
+  int HRmode_stop(void);
+
+  /**
+   *@brief This function sets up for the Multi-mode.  The data is returned in the callback function max30101_int_handler in global array:
+   *@brief buffer[].  Multi-LED mode can handle 1 to 4 LED combinations.  Hence it can fill up the FIFO up to a maximum of
+   *@brief 3bytes/sample x 32 x 4 = 384bytes.
+   *@param fifo_waterlevel_mark: corresponds to FIFO_A_FULL, In FIFO Configuration Register (0x08)
+   *@param sample_avg: corresponds to SMP_AVE, in FIFO Configuration Register (0x08)
+   *@param sample_rate:corresponds to SPO2_SR, IN SpO2 Configuration Register (0x0A)
+   *@param pulse_width: corresponds to LED_PW in SpO2 Configuration register(0x0A)
+   *@param red_led_current: corresponds to LED1_PA register (0x0C).  Please see data sheet for values
+   *@param ir_led_current: corresponds to LED2_PA register (0x0D).  Please see data sheet for values
+   *@param green_led_current: corresponds to LED3_PA register (0x0E).  Please see data sheet for values
+   *@param slot_1,…,slot_4: corresponds to Multi-LED Mode control Registers (0x11-0x12).
+   *@returns  0-if if no error.  A non-zero value indicates an error.
+   */
+  int Multimode_init(uint8_t fifo_waterlevel_mark, uint8_t sample_avg,
+                     uint8_t sample_rate, uint8_t pulse_width,
+                     uint8_t red_led_current, uint8_t ir_led_current,
+                     uint8_t green_led_current, uint8_t slot_1, uint8_t slot_2,
+                     uint8_t slot_3, uint8_t slot_4);
+
+  /**
+   * @brief This function will stop the Multi-mode and turn off all operating LED’s.
+   * @returns  0-if if no error.  A non-zero value indicates an error.
+   */
+  int Multimode_stop(void);
+
+  /**
+   * @brief This is a function that sets up for temperature read and should be called after one of the mode
+   * @brief has been setup.  The data is returned in the callback function max30101_int_handler.  This
+   * @brief function needs to be called every time temperature reading is required.
+   * @brief Call the temp function after one of the MODES have been started
+   * @brief Note that the temp is disabled after one read... also, it is not necessary
+   * @brief to read the temp frequently...
+   * @returns  0-if if no error.  A non-zero value indicates an error.
+   */
+  int tempread(void);
+
+  /**
+   *@brief This is a callback function which collects the data from the FIFO of the MAX30101 in a 32-bit
+   *@brief unsigned global array called max30101_buffer[].  Upon every interrupt from the MAX30101, this
+   *@brief function is called to service the FIFO of the MAX30101.  This callback function also services the
+   *@brief interrupt for the temp data.  The temp data is collected in a floating point global variable
+   *@brief final_temp.
+   *@param max30101_buffer[], global uint32_t
+   *@returns  0-if everything is good.  A non-zero value indicates an error.
+   */
+  int int_handler(void);
+  /**
+  * @brief type definition for data interrupt
+  */
+  typedef void (*DataCallbackFunction)(uint32_t id, uint32_t *buffer,
+                                       uint32_t length);
+  /**
+  * @brief type definition for general interrupt
+  */
+  typedef void (*InterruptFunction)();
+
+  /**
+  * @brief Used to connect a callback for when interrupt data is available
+  */
+  void onInterrupt(InterruptFunction _onInterrupt);
+
+  /**
+  * @brief Used to connect a callback for when interrupt data is available
+  */
+  void onDataAvailable(DataCallbackFunction _onDataAvailable);
+
+  /**
+  * @brief Interrupt callback
+  */
+  void MAX30101_OnInterrupt(void);
+  
+  static MAX30101 *instance;
+
+private:
+  /// called when interrupt data is available
+  void dataAvailable(uint32_t id, uint32_t *buffer, uint32_t length);
+  /// callback function at the end of the interrupt
+  void interruptPostCallback(void);
+  /// callback function when interrupt data is available
+  DataCallbackFunction onDataAvailableCallback;
+  /// callback function when interrupt data is available
+  InterruptFunction onInterruptCallback;
+  /// Read I2c wrapper method
+  int I2CM_Read(int slaveAddress, char *writeData, char writeCount, char *readData, char readCount);
+  /// Write I2c wrapper method
+  int I2CM_Write(int slaveAddress, char *writeData1, char writeCount1, char *writeData2, char writeCount2);
+  /// pointer to I2C object
+  I2C *i2c;
+  /// flag to track if this object is the owner (created) the I2C object
+  bool i2c_owner;
+  /// Device slave address
+  int slaveAddress;
+};
+
+/**
+*  @brief Resets the I2C block, when needed
+*/
+extern void I2CM_Init_Reset(uint8_t index, int speed);
+
+ /**
+  * @brief Used for debugging, if needed
+  */
+void MAX30101MidIntHandler(void);
+
+#endif /* _MAX30101_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/System/System.cpp	Thu Mar 28 08:10:23 2019 +0000
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (C) 2016 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"
+
+//******************************************************************************
+void I2CM_Init_Reset(uint8_t index, int speed) {
+  mxc_i2cm_regs_t *regs = MXC_I2CM_GET_I2CM(index);
+  /* reset module */
+  regs->ctrl = MXC_F_I2CM_CTRL_MSTR_RESET_EN;
+  regs->ctrl = 0;
+  /* enable tx_fifo and rx_fifo */
+  regs->ctrl |= (MXC_F_I2CM_CTRL_TX_FIFO_EN | MXC_F_I2CM_CTRL_RX_FIFO_EN);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/System/System.h	Thu Mar 28 08:10:23 2019 +0000
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (C) 2016 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.
+ *******************************************************************************
+ */
+#ifndef _SYSTEM_H_
+#define _SYSTEM_H_
+
+/**
+* This issues a reset to the I2C Peripheral 
+*/
+void I2CM_Init_Reset(uint8_t index, int speed);
+
+#endif // _SYSTEM_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBDevice.lib	Thu Mar 28 08:10:23 2019 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/teams/MaximIntegrated/code/USBDevice/#dad310740b28
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Thu Mar 28 08:10:23 2019 +0000
@@ -0,0 +1,215 @@
+ #include "mbed.h"
+ #include "MAX14720.h"
+ #include "MAX30001.h"
+ #include "MAX30101.h"
+ #include "System.h"
+ #include "USBSerial.h"
+ 
+ /************************************************************************************************************************************/
+ /// define the HVOUT Boost Voltage default for the MAX14720 PMIC
+ #define HVOUT_VOLTAGE 4500 // set to 4500 mV
+ 
+ /// define all I2C addresses
+ #define MAX14720_I2C_SLAVE_ADDR (0x54)
+ #define MAX30101_I2C_SLAVE_ADDR (0xAE)
+ 
+ // Settings for ECG Initialization
+ #define En_ecg     0x01
+ #define Openp      0x00
+ #define Openn      0x00
+ #define Pol        0x00
+ #define Calp_sel   0x00
+ #define Caln_sel   0x00
+ #define E_fit      0x0F
+ #define Rate       0x02
+ #define Gain       0x00
+ #define Dhpf       0x01
+ #define Dlpf       0x01
+ 
+ // Settings for ECG RtoR
+ #define En_rtor    0x01
+ #define Wndw       0x03
+ #define Gain1      0x0f
+ #define Pavg       0x02
+ #define Ptsf       0x03
+ #define Hoff       0x20
+ #define Ravg       0x02
+ #define Rhsf       0x04
+ #define Clr_rrint  0x01
+ 
+ // Settings for Lead Detection
+ #define En_dcloff  0x01
+ #define Ipol       0x00
+ #define Imag       0x00
+ #define Vth        0x00
+ 
+ // Settings for the HR initialization
+ #define FIFO_WATERLEVEL_MARK 15
+ #define SAMPLE_AVG           2
+ #define SAMPLE_RATE          1
+ #define PULSE_WIDTH          2
+ #define RED_LED_CURRENT      0x1F
+ #define IR_LED_CURRENT       0X1F
+ 
+ /// Define with Maxim VID and a Maxim assigned PID, set to version 0x0001 and non-blocking
+ USBSerial usbSerial(0x0b6a, 0x0100, 0x0001, false);
+ 
+ // I2C Master 2
+ I2C i2c2(I2C2_SDA, I2C2_SCL); // used by MAX14720, MAX30101, LIS2DH
+ 
+ // SPI Master 0 with SPI0_SS for use with MAX30001
+ SPI spi(SPI0_MOSI, SPI0_MISO, SPI0_SCK, SPI0_SS); // used by MAX30001
+ 
+ // PMIC
+ MAX14720 max14720(&i2c2, MAX14720_I2C_SLAVE_ADDR);
+ 
+ // Optical Oximeter
+ //MAX30101 max30101(&i2c2, MAX30101_I2C_SLAVE_ADDR);
+ //InterruptIn max30101_Interrupt(P4_0);
+
+ // ECG device
+ MAX30001 max30001(&spi);
+ InterruptIn max30001_InterruptB(P3_6);
+ InterruptIn max30001_Interrupt2B(P4_5);
+ 
+ /// PWM used as fclk for the MAX30001
+ PwmOut pwmout(P1_7);
+  
+ // Data of sensors
+ int32_t ECG_Raw;
+ //int32_t SpO_Raw;
+ uint32_t index = 0;
+ DigitalOut led(LED1); 
+ 
+ //@brief Creates a packet that will be streamed via USB Serial
+ //@brief the packet created will be inserted into a fifo to be streamed at a later time
+ //@param id Streaming ID
+ //@param buffer Pointer to a uint32 array that contains the data to include in the packet
+ //@param number Number of elements in the buffer
+ //
+ void StreamPacketUint32_ex(uint32_t id, uint32_t *buffer, uint32_t number) {
+    int k;
+    if(id == MAX30001_DATA_ECG)
+    {
+        for (k = 0; k < number; k++) 
+        {
+            ECG_Raw = (int32_t)(buffer[k] << 8);
+            ECG_Raw = ECG_Raw >> 14;
+            usbSerial.printf("%d|" , index);
+            usbSerial.printf("%d\r\n", ECG_Raw);
+            index++;
+        }
+    } 
+ }
+ /*void StreamPacketUint32_ex(uint32_t id, uint32_t *buffer, uint32_t number) {
+    int i;
+    if(id == MAX30101_OXIMETER_DATA + 2)
+    {
+        for (i = 0; i < number; i++) 
+        {
+            SpO_Raw = (int32_t)(buffer[i]);
+        }
+        usbSerial.printf("%d\r\n", SpO_Raw);
+    } 
+ }*/
+ //******************************************************************************
+ /*void MAX30101_OnInterrupt(void){
+    I2CM_Init_Reset(2, 1);
+ }*/
+ //*******************************************************************************
+ int main() {
+    // hold results for returning functions
+    int result;
+    
+    // initialize HVOUT on the MAX14720 PMIC
+    result = max14720.init();
+    if (result == MAX14720_ERROR){
+        printf("Error initializing MAX14720");
+    }
+    max14720.boostEn = MAX14720::BOOST_ENABLED;
+    max14720.boostSetVoltage(HVOUT_VOLTAGE);
+    
+    
+    // This is the SpO2 mode (IR&Red LED)
+    /*max30101.SpO2mode_init(FIFO_WATERLEVEL_MARK, SAMPLE_AVG, SAMPLE_RATE,PULSE_WIDTH, RED_LED_CURRENT,IR_LED_CURRENT);
+        
+    // MAX30101 initialize interrupt  
+    max30101.onInterrupt(&MAX30101_OnInterrupt);
+    max30101.onDataAvailable(&StreamPacketUint32_ex);
+    max30101_Interrupt.fall(&MAX30101MidIntHandler);*/
+    
+    // Interrupt priority    
+    NVIC_SetPriority(GPIO_P0_IRQn, 5);
+    NVIC_SetPriority(GPIO_P1_IRQn, 5);
+    NVIC_SetPriority(GPIO_P2_IRQn, 5);
+    NVIC_SetPriority(GPIO_P3_IRQn, 5);
+    NVIC_SetPriority(GPIO_P4_IRQn, 5);
+    NVIC_SetPriority(GPIO_P5_IRQn, 5);
+    NVIC_SetPriority(GPIO_P6_IRQn, 5);
+    // used by the MAX30001
+    NVIC_SetPriority(SPI1_IRQn, 0);
+    
+    /* ECG Initialize */
+    max30001_InterruptB.disable_irq();
+    max30001_Interrupt2B.disable_irq();
+    max30001_InterruptB.mode(PullUp);
+    max30001_InterruptB.fall(&MAX30001Mid_IntB_Handler);
+    max30001_Interrupt2B.mode(PullUp);
+    max30001_Interrupt2B.fall(&MAX30001Mid_Int2B_Handler);
+    max30001_InterruptB.enable_irq();
+    max30001_Interrupt2B.enable_irq();
+    MAX30001_AllowInterrupts(1);    
+    // Configuring the FCLK for the ECG, set to 32.768KHZ
+    pwmout.period_us(31);
+    pwmout.write(0.5);          // 0-1 is 0-100%, 0.5 = 50% duty cycle.
+    //max30001.max30001_RtoR_InitStart(En_rtor, Wndw, Gain1, Pavg, Ptsf, Hoff, Ravg, Rhsf, Clr_rrint);
+    max30001.max30001_sw_rst(); // Do a software reset of the MAX30001
+    max30001.max30001_INT_assignment(
+        MAX30001::MAX30001_INT_B,  // en_enint_loc
+        MAX30001::MAX30001_NO_INT, // en_eovf_loc
+        MAX30001::MAX30001_NO_INT, // en_fstint_loc
+
+        MAX30001::MAX30001_INT_2B, // en_dcloffint_loc
+        MAX30001::MAX30001_INT_B, // en_bint_loc
+        MAX30001::MAX30001_NO_INT, // en_bovf_loc
+
+        MAX30001::MAX30001_INT_2B, // en_bover_loc
+        MAX30001::MAX30001_INT_2B, // en_bundr_loc
+        MAX30001::MAX30001_NO_INT, // en_bcgmon_loc
+
+        MAX30001::MAX30001_INT_B,  // en_pint_loc
+        MAX30001::MAX30001_NO_INT, // en_povf_loc,
+        MAX30001::MAX30001_NO_INT, // en_pedge_loc
+
+        MAX30001::MAX30001_INT_2B, // en_lonint_loc
+        MAX30001::MAX30001_INT_B,  // en_rrint_loc
+        MAX30001::MAX30001_NO_INT, //  en_samp_loc
+
+        MAX30001::MAX30001_INT_ODNR,  // intb_Type
+        MAX30001::MAX30001_INT_ODNR); // int2b_Type
+        
+    // MAX30001 initialize interrupt
+    max30001.max30001_ECG_InitStart(En_ecg, Openp, Openn, Pol, Calp_sel, Caln_sel, E_fit, Rate, Gain, Dhpf, Dlpf);
+    //max30001.max30001_Enable_DcLeadOFF_Init(En_dcloff, Ipol, Imag, Vth);
+    //max30001.max30001_FIFO_LeadONOff_Read();
+    max30001.max30001_synch();
+    max30001.onDataAvailable(&StreamPacketUint32_ex);
+    int a;
+    while (1) 
+    {
+        a = usbSerial._getc();
+        if (a == 65)
+        {
+            max30001.max30001_Stop_ECG();
+            index = 0;
+        }
+        if (a == 97)
+        {
+            //max30001.max30001_sw_rst(); 
+            max30001.max30001_ECG_InitStart(En_ecg, Openp, Openn, Pol, Calp_sel, Caln_sel, E_fit, Rate, Gain, Dhpf, Dlpf);
+            //max30001.max30001_synch();
+            //max30001.onDataAvailable(&StreamPacketUint32_ex);            
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Thu Mar 28 08:10:23 2019 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/users/mbed_official/code/mbed/builds/84c0a372a020
\ No newline at end of file