diff --git a/epicardium/epicardium.h b/epicardium/epicardium.h
index 01709785540c27f72ca8a85bf08412978470029b..84071d042c85643dfc181549f038e46c9c4b354a 100644
--- a/epicardium/epicardium.h
+++ b/epicardium/epicardium.h
@@ -133,9 +133,8 @@ typedef _Bool bool;
 #define API_MAX30001_ENABLE        0xf0
 #define API_MAX30001_DISABLE       0xf1
 
-#define API_MAX86150_INIT		0x0100
-#define API_MAX86150_GET_DATA		0x0101
-#define API_MAX86150_SET_LED_AMPLITUDE	0x0102
+#define API_MAX86150_ENABLE        0x0100
+#define API_MAX86150_DISABLE       0x0101
 
 #define API_USB_SHUTDOWN           0x110
 #define API_USB_STORAGE            0x111
@@ -194,18 +193,20 @@ API(API_INTERRUPT_DISABLE, int epic_interrupt_disable(api_int_id_t int_id));
 /** RTC Alarm interrupt.  See :c:func:`epic_isr_rtc_alarm`. */
 #define EPIC_INT_RTC_ALARM              3
 /** BHI160 Accelerometer.  See :c:func:`epic_isr_bhi160_accelerometer`. */
-#define EPIC_INT_BHI160_ACCELEROMETER   4
+#define EPIC_INT_BHI160_ACCELEROMETER	4
 /** BHI160 Orientation Sensor.  See :c:func:`epic_isr_bhi160_orientation`. */
-#define EPIC_INT_BHI160_ORIENTATION     5
+#define EPIC_INT_BHI160_ORIENTATION	5
 /** BHI160 Gyroscope.  See :c:func:`epic_isr_bhi160_gyroscope`. */
-#define EPIC_INT_BHI160_GYROSCOPE       6
+#define EPIC_INT_BHI160_GYROSCOPE	6
 /** MAX30001 ECG.  See :c:func:`epic_isr_max30001_ecg`. */
-#define EPIC_INT_MAX30001_ECG           7
+#define EPIC_INT_MAX30001_ECG		7
 /** BHI160 Magnetometer.  See :c:func:`epic_isr_bhi160_magnetometer`. */
 #define EPIC_INT_BHI160_MAGNETOMETER    8
+/** MAX86150 ECG and PPG sensor.  See :c:func:`epic_isr_max86150`. */
+#define EPIC_INT_MAX86150		9
 
 /* Number of defined interrupts. */
-#define EPIC_INT_NUM                    9
+#define EPIC_INT_NUM                    10
 /* clang-format on */
 
 /*
@@ -871,6 +872,84 @@ API(API_BME680_GET_DATA, int epic_bme680_read_sensors(
 	struct bme680_sensor_data *data
 ));
 
+/**
+ * MAX86150
+ * ======
+ */
+
+/**
+ * Configuration for a MAX86150 sensor.
+ *
+ * This struct is used when enabling a sensor using
+ * :c:func:`epic_max86150_enable_sensor`.
+ */
+struct max86150_sensor_config {
+    /**
+     * Number of samples Epicardium should keep for this sensor.  Do not set
+     * this number too high as the sample buffer will eat RAM.
+     */
+    size_t sample_buffer_len;
+    /**
+     * Sample rate for PPG from the sensor in Hz.  Maximum data rate is limited
+     * to 200 Hz for all sensors though some might be limited at a lower
+     * rate.
+     *
+     * Possible values are 10, 20, 50, 84, 100, 200.
+     */
+    uint16_t ppg_sample_rate;
+};
+
+/**
+ * MAX86150 Sensor Data
+ */
+struct max86150_sensor_data {
+	/** Red LED data */
+	uint32_t red;
+	/** IR LED data */
+	uint32_t ir;
+	/** ECG data */
+	int32_t ecg;
+};
+
+/**
+ * Enable a MAX86150 PPG and ECG sensor.
+ * 
+ * Calling this function will instruct the MAX86150 to collect a 
+ * data from the sensor.  You can then retrieve the samples using 
+ * :c:func:`epic_stream_read`.
+ *
+ * :param max86150_sensor_config* config: Configuration for this sensor.
+ * :param size_t config_size: Size of ``config``.
+ * :returns: A sensor descriptor which can be used with
+ *    :c:func:`epic_stream_read` or a negative error value:
+ *
+ *    - ``-ENOMEM``:  The MAX86150 driver failed to create a stream queue.
+ *    - ``-ENODEV``:  The MAX86150 driver failed due to physical connectivity problem
+ *      (broken wire, unpowered, etc).
+ *    - ``-EINVAL``:  config->ppg_sample_rate is not one of 10, 20, 50, 84, 100, 200
+ *      or config_size is not size of config.
+ *
+ * .. versionadded:: 1.13
+ */
+API(API_MAX86150_ENABLE, int epic_max86150_enable_sensor(struct max86150_sensor_config *config, size_t config_size));
+
+/**
+ * Disable the MAX86150 sensor.
+ *
+ * :returns: 0 in case of success or forward negative error value from stream_deregister.
+ *
+ * .. versionadded:: 1.13
+ */
+API(API_MAX86150_DISABLE, int epic_max86150_disable_sensor());
+
+/**
+ * **Interrupt Service Routine** for :c:data:`EPIC_INT_MAX86150`
+ *
+ * :c:func:`epic_isr_max86150` is called whenever the MAX86150
+ * PPG sensor has new data available.
+ */
+API_ISR(EPIC_INT_MAX86150, epic_isr_max86150);
+
 /**
  * Personal State
  * ==============
@@ -1139,7 +1218,7 @@ struct bhi160_sensor_config {
 };
 
 /**
- * Enable a BHI160 virtual sensor.  Calling this funciton will instruct the
+ * Enable a BHI160 virtual sensor.  Calling this function will instruct the
  * BHI160 to collect data for this specific virtual sensor.  You can then
  * retrieve the samples using :c:func:`epic_stream_read`.
  *
@@ -1854,9 +1933,9 @@ struct max30001_sensor_config {
 };
 
 /**
- * Enable a MAX30001 ecg sensor.
+ * Enable a MAX30001 ECG sensor.
  *
- * Calling this funciton will instruct the MAX30001 to collect data for this
+ * Calling this function will instruct the MAX30001 to collect data for this
  * sensor.  You can then retrieve the samples using :c:func:`epic_stream_read`.
  *
  * :param max30001_sensor_config* config: Configuration for this sensor.
diff --git a/epicardium/main.c b/epicardium/main.c
index 831a3e12f9fe3c3dbf391663612e6368487bbfb5..c5e2768c37177f97f6a2388bdfdd8b71f10cd591 100644
--- a/epicardium/main.c
+++ b/epicardium/main.c
@@ -113,6 +113,16 @@ int main(void)
 		    NULL) != pdPASS) {
 		panic("Failed to create %s task!", "MAX30001");
 	}
+	/* MAX86150 */
+	if (xTaskCreate(
+		    vMAX86150Task,
+		    (const char *)"MAX86150 Driver",
+		    configMINIMAL_STACK_SIZE * 2,
+		    NULL,
+		    tskIDLE_PRIORITY + 1,
+		    NULL) != pdPASS) {
+		panic("Failed to create %s task!", "MAX86150");
+	}
 	/* API */
 	if (xTaskCreate(
 		    vApiDispatcher,
diff --git a/epicardium/modules/hardware.c b/epicardium/modules/hardware.c
index afc44f64b7e241b0603b8239fd0aa5b8cdd0c2ff..358154334f1b7f3a2d508e7348e70999aa67257c 100644
--- a/epicardium/modules/hardware.c
+++ b/epicardium/modules/hardware.c
@@ -194,6 +194,11 @@ int hardware_early_init(void)
 	 */
 	max30001_mutex_init();
 
+	/*
+	 * max86150 mutex init
+	 */
+	max86150_mutex_init();
+
 	/* Allow user space to trigger interrupts.
 	 * Used for BLE, not sure if needed. */
 	SCB->CCR |= SCB_CCR_USERSETMPEND_Msk;
@@ -283,5 +288,7 @@ int hardware_reset(void)
 
 	epic_max30001_disable_sensor();
 
+	epic_max86150_disable_sensor();
+
 	return 0;
 }
diff --git a/epicardium/modules/max86150.c b/epicardium/modules/max86150.c
new file mode 100644
index 0000000000000000000000000000000000000000..428d0caf22f8f78511e1e7a0792602af092605e1
--- /dev/null
+++ b/epicardium/modules/max86150.c
@@ -0,0 +1,236 @@
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdio.h>
+#include "max86150.h"
+#include "epicardium.h"
+#include "modules.h"
+#include "modules/log.h"
+#include "modules/stream.h"
+#include "gpio.h"
+#include "pmic.h"
+
+#include "FreeRTOS.h"
+#include "task.h"
+#include "queue.h"
+
+#include "api/interrupt-sender.h"
+#include "modules/modules.h"
+
+static const gpio_cfg_t max86150_interrupt_pin = {
+	PORT_1, PIN_13, GPIO_FUNC_IN, GPIO_PAD_PULL_UP
+};
+
+/* MAX86150 Task ID */
+static TaskHandle_t max86150_task_id = NULL;
+
+/* MAX86150 Mutex */
+static struct mutex max86150_mutex = { 0 };
+
+/* Stream */
+static struct stream_info max86150_stream;
+
+/* Active */
+static bool max86150_sensor_active = false;
+
+int epic_max86150_enable_sensor(
+	struct max86150_sensor_config *config, size_t config_size
+) {
+	int result = 0;
+
+	if (sizeof(struct max86150_sensor_config) != config_size) {
+		return -EINVAL;
+	}
+
+	mutex_lock(&max86150_mutex);
+	hwlock_acquire(HWLOCK_I2C);
+
+	struct stream_info *stream = &max86150_stream;
+	stream->item_size          = sizeof(struct max86150_sensor_data);
+	stream->queue =
+		xQueueCreate(config->sample_buffer_len, stream->item_size);
+	if (stream->queue == NULL) {
+		result = -ENOMEM;
+		goto out_free;
+	}
+
+	uint8_t ppg_sample_rate;
+
+	if (config->ppg_sample_rate == 10) {
+		ppg_sample_rate = MAX86150_PPG_SAMPLERATE_10;
+	} else if (config->ppg_sample_rate == 20) {
+		ppg_sample_rate = MAX86150_PPG_SAMPLERATE_20;
+	} else if (config->ppg_sample_rate == 50) {
+		ppg_sample_rate = MAX86150_PPG_SAMPLERATE_50;
+	} else if (config->ppg_sample_rate == 84) {
+		ppg_sample_rate = MAX86150_PPG_SAMPLERATE_84;
+	} else if (config->ppg_sample_rate == 100) {
+		ppg_sample_rate = MAX86150_PPG_SAMPLERATE_100;
+	} else if (config->ppg_sample_rate == 200) {
+		ppg_sample_rate = MAX86150_PPG_SAMPLERATE_200;
+	} else {
+		result = -EINVAL;
+		goto out_free;
+	}
+
+	result = stream_register(SD_MAX86150, stream);
+	if (result < 0) {
+		vQueueDelete(stream->queue);
+		goto out_free;
+	}
+
+	bool begin_result = max86150_begin();
+	if (!begin_result) {
+		result = -ENODEV;
+		vQueueDelete(stream->queue);
+		goto out_free;
+	}
+
+	max86150_setup(ppg_sample_rate);
+	max86150_get_int1();
+	max86150_get_int2();
+
+	max86150_sensor_active = true;
+	result                 = SD_MAX86150;
+
+out_free:
+	hwlock_release(HWLOCK_I2C);
+	mutex_unlock(&max86150_mutex);
+	return result;
+}
+
+int epic_max86150_disable_sensor(void)
+{
+	int result = 0;
+
+	mutex_lock(&max86150_mutex);
+	hwlock_acquire(HWLOCK_I2C);
+
+	struct stream_info *stream = &max86150_stream;
+	result                     = stream_deregister(SD_MAX86150, stream);
+	if (result < 0) {
+		goto out_free;
+	}
+
+	vQueueDelete(stream->queue);
+	stream->queue = NULL;
+
+	// disable max86150 leds
+	max86150_set_led_red_amplitude(0);
+	max86150_set_led_ir_amplitude(0);
+
+	max86150_sensor_active = false;
+
+	result = 0;
+out_free:
+	hwlock_release(HWLOCK_I2C);
+	mutex_unlock(&max86150_mutex);
+	return result;
+}
+
+static int max86150_handle_sample(struct max86150_sensor_data *data)
+{
+	//LOG_INFO("max86150", "Sample! %ld, %ld, %ld", data->red, data->ir, data->ecg);
+
+	if (max86150_stream.queue == NULL) {
+		return -ESRCH;
+	}
+
+	/* Discard overflow.  See discussion in !316. */
+	if (xQueueSend(max86150_stream.queue, data, 0) != pdTRUE) {
+		LOG_WARN("max86150", "queue full");
+		return -EIO;
+	}
+	return api_interrupt_trigger(EPIC_INT_MAX86150);
+}
+
+static int max86150_fetch_fifo(void)
+{
+	int result = 0;
+
+	mutex_lock(&max86150_mutex);
+	hwlock_acquire(HWLOCK_I2C);
+
+	struct max86150_sensor_data sample;
+
+	// There is a recommendation from Maxim not to read the entire FIFO, but rather a fixed number of samples.
+	// See https://os.mbed.com/users/laserdad/code/MAX86150_ECG_PPG//file/3c728f3d1f10/main.cpp/
+	// So we should not use max86150_check() but max86150_get_sample().
+	while (max86150_get_sample(&sample.red, &sample.ir, &sample.ecg) > 0) {
+		result = max86150_handle_sample(&sample);
+		// stop in case of errors
+		if (result < 0) {
+			break;
+		}
+	}
+	hwlock_release(HWLOCK_I2C);
+	mutex_unlock(&max86150_mutex);
+	return result;
+}
+
+/*
+ * Callback for the MAX86150 interrupt pin.  This callback is called from the
+ * SDK's GPIO interrupt driver, in interrupt context.
+ */
+static void max86150_interrupt_callback(void *_)
+{
+	BaseType_t xHigherPriorityTaskWoken = pdFALSE;
+
+	if (max86150_task_id != NULL) {
+		vTaskNotifyGiveFromISR(
+			max86150_task_id, &xHigherPriorityTaskWoken
+		);
+		portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
+	}
+}
+/* }}} */
+
+void max86150_mutex_init(void)
+{
+	mutex_create(&max86150_mutex);
+}
+
+void vMAX86150Task(void *pvParameters)
+{
+	max86150_task_id = xTaskGetCurrentTaskHandle();
+
+	mutex_lock(&max86150_mutex);
+	hwlock_acquire(HWLOCK_I2C);
+
+	/* Install interrupt callback */
+	GPIO_Config(&max86150_interrupt_pin);
+	GPIO_RegisterCallback(
+		&max86150_interrupt_pin, max86150_interrupt_callback, NULL
+	);
+	GPIO_IntConfig(
+		&max86150_interrupt_pin, GPIO_INT_EDGE, GPIO_INT_FALLING
+	);
+	GPIO_IntEnable(&max86150_interrupt_pin);
+	NVIC_SetPriority(
+		(IRQn_Type)MXC_GPIO_GET_IRQ(max86150_interrupt_pin.port), 2
+	);
+	NVIC_EnableIRQ(
+		(IRQn_Type)MXC_GPIO_GET_IRQ(max86150_interrupt_pin.port)
+	);
+
+	hwlock_release(HWLOCK_I2C);
+	mutex_unlock(&max86150_mutex);
+
+	/* ----------------------------------------- */
+
+	while (1) {
+		if (max86150_sensor_active) {
+			//LOG_INFO("max86150", "Interrupt!");
+			int ret = max86150_fetch_fifo();
+			if (ret < 0) {
+				LOG_ERR("max86150", "Unknown error: %d", -ret);
+			}
+		}
+		/*
+		 * Wait for interrupt.  After two seconds, fetch FIFO anyway
+		 *
+		 * In the future, reads using epic_stream_read() might also
+		 * trigger a FIFO fetch, from outside this task.
+		 */
+		ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(2000));
+	}
+}
diff --git a/epicardium/modules/meson.build b/epicardium/modules/meson.build
index 8ead5e72c4cc80e3fe0601d713784028cc16645f..474b32930f9b4970fdde4cf65c6891f5eead8a1f 100644
--- a/epicardium/modules/meson.build
+++ b/epicardium/modules/meson.build
@@ -13,6 +13,7 @@ module_sources = files(
   'lifecycle.c',
   'light_sensor.c',
   'log.c',
+  'max86150.c',
   'max30001.c',
   'mutex.c',
   'panic.c',
diff --git a/epicardium/modules/modules.h b/epicardium/modules/modules.h
index 567a2a82bb98341451c5ea3c5b847a05e63b1951..0444b688f33cb879e3cca9f59cb1eb365999eb17 100644
--- a/epicardium/modules/modules.h
+++ b/epicardium/modules/modules.h
@@ -111,6 +111,12 @@ void disp_forcelock();
 #define BHI160_MUTEX_WAIT_MS          50
 void vBhi160Task(void *pvParameters);
 
+/* ---------- MAX86150 ----------------------------------------------------- */
+#define MAX86150_MUTEX_WAIT_MS		50
+void vMAX86150Task(void *pvParameters);
+void max86150_mutex_init(void);
+
+
 /* ---------- MAX30001 ----------------------------------------------------- */
 void vMAX30001Task(void *pvParameters);
 void max30001_mutex_init(void);
diff --git a/epicardium/modules/sleep.c b/epicardium/modules/sleep.c
index 4b94fa7977ac5533247cd1b5ce60009f8ded42af..c7c060e14a2094d68945710a97c3b2a4983a7c31 100644
--- a/epicardium/modules/sleep.c
+++ b/epicardium/modules/sleep.c
@@ -176,9 +176,9 @@ void sleep_deepsleep(void)
 	/* This will fail if there is no
      * harmonic board attached */
 	max86150_begin();
-	max86150_getINT1();
-	max86150_getINT2();
-	max86150_shutDown();
+	max86150_get_int1();
+	max86150_get_int2();
+	max86150_shut_down();
 #endif
 	epic_bhi160_disable_all_sensors();
 	epic_bme680_deinit();
diff --git a/epicardium/modules/stream.h b/epicardium/modules/stream.h
index f6f939708d4aaa91d3ca9fc02f03e21bf4e69339..a953537aea4d1bb6a3aed755d0ec236098366781 100644
--- a/epicardium/modules/stream.h
+++ b/epicardium/modules/stream.h
@@ -36,6 +36,7 @@ enum stream_descriptor {
 	SD_BHI160_GYROSCOPE,
 	/** MAX30001 ECG */
 	SD_MAX30001_ECG,
+	SD_MAX86150,
 	/** Highest descriptor must always be ``SD_MAX``. */
 	SD_MAX,
 };
diff --git a/lib/vendor/Maxim/MAX86150/max86150.c b/lib/vendor/Maxim/MAX86150/max86150.c
index ab14bb1086a56f4af34ae046dbcc07f602f20f18..203df693a4f8cbbbc06d992afee7803ec0693197 100644
--- a/lib/vendor/Maxim/MAX86150/max86150.c
+++ b/lib/vendor/Maxim/MAX86150/max86150.c
@@ -18,151 +18,132 @@
 
 typedef uint8_t byte;
 
-static const uint8_t MAX86150_INTSTAT1 =		0x00;
-static const uint8_t MAX86150_INTSTAT2 =		0x01;
-static const uint8_t MAX86150_INTENABLE1 =		0x02;
-static const uint8_t MAX86150_INTENABLE2 =		0x03;
+static const uint8_t MAX86150_INTSTAT1   = 0x00;
+static const uint8_t MAX86150_INTSTAT2   = 0x01;
+static const uint8_t MAX86150_INTENABLE1 = 0x02;
+static const uint8_t MAX86150_INTENABLE2 = 0x03;
 
-static const uint8_t MAX86150_FIFOWRITEPTR = 	0x04;
-static const uint8_t MAX86150_FIFOOVERFLOW = 	0x05;
-static const uint8_t MAX86150_FIFOREADPTR = 	0x06;
-static const uint8_t MAX86150_FIFODATA 		=		0x07;
+static const uint8_t MAX86150_FIFOWRITEPTR = 0x04;
+static const uint8_t MAX86150_FIFOOVERFLOW = 0x05;
+static const uint8_t MAX86150_FIFOREADPTR  = 0x06;
+static const uint8_t MAX86150_FIFODATA     = 0x07;
 
-static const uint8_t MAX86150_FIFOCONFIG = 		0x08;
-static const uint8_t MAX86150_FIFOCONTROL1= 	0x09;
-static const uint8_t MAX86150_FIFOCONTROL2 = 	0x0A;
+static const uint8_t MAX86150_FIFOCONFIG   = 0x08;
+static const uint8_t MAX86150_FIFOCONTROL1 = 0x09;
+static const uint8_t MAX86150_FIFOCONTROL2 = 0x0A;
 
-static const uint8_t MAX86150_SYSCONTROL = 	0x0D;
-static const uint8_t MAX86150_PPGCONFIG1 = 		0x0E;
-static const uint8_t MAX86150_PPGCONFIG2 = 		0x0F;
-static const uint8_t MAX86150_LED_PROX_AMP = 	0x10;
+static const uint8_t MAX86150_SYSCONTROL   = 0x0D;
+static const uint8_t MAX86150_PPGCONFIG1   = 0x0E;
+static const uint8_t MAX86150_PPGCONFIG2   = 0x0F;
+static const uint8_t MAX86150_LED_PROX_AMP = 0x10;
 
-static const uint8_t MAX86150_LED1_PULSEAMP = 	0x11;
-static const uint8_t MAX86150_LED2_PULSEAMP = 	0x12;
-static const uint8_t MAX86150_LED_RANGE 		= 	0x14;
-static const uint8_t MAX86150_LED_PILOT_PA 	= 	0x15;
+static const uint8_t MAX86150_LED1_PULSEAMP = 0x11;
+static const uint8_t MAX86150_LED2_PULSEAMP = 0x12;
+static const uint8_t MAX86150_LED_RANGE     = 0x14;
+static const uint8_t MAX86150_LED_PILOT_PA  = 0x15;
 
-static const uint8_t MAX86150_ECG_CONFIG1 	= 	0x3C;
-static const uint8_t MAX86150_ECG_CONFIG3 	= 	0x3E;
-static const uint8_t MAX86150_PROXINTTHRESH = 	0x10;
+static const uint8_t MAX86150_ECG_CONFIG1   = 0x3C;
+static const uint8_t MAX86150_ECG_CONFIG3   = 0x3E;
+static const uint8_t MAX86150_PROXINTTHRESH = 0x10;
 
-static const uint8_t MAX86150_PARTID = 			0xFF;
+static const uint8_t MAX86150_PARTID = 0xFF;
 
 // MAX86150 Commands
-static const uint8_t MAX86150_INT_A_FULL_MASK =		(byte)~0b10000000;
-static const uint8_t MAX86150_INT_A_FULL_ENABLE = 	0x80;
-static const uint8_t MAX86150_INT_A_FULL_DISABLE = 	0x00;
+static const uint8_t MAX86150_INT_A_FULL_MASK    = (byte)~0b10000000;
+static const uint8_t MAX86150_INT_A_FULL_ENABLE  = 0x80;
+static const uint8_t MAX86150_INT_A_FULL_DISABLE = 0x00;
 
-static const uint8_t MAX86150_INT_DATA_RDY_MASK = (byte)~0b01000000;
-static const uint8_t MAX86150_INT_DATA_RDY_ENABLE =	0x40;
+static const uint8_t MAX86150_INT_DATA_RDY_MASK    = (byte)~0b01000000;
+static const uint8_t MAX86150_INT_DATA_RDY_ENABLE  = 0x40;
 static const uint8_t MAX86150_INT_DATA_RDY_DISABLE = 0x00;
 
-static const uint8_t MAX86150_INT_ALC_OVF_MASK = (byte)~0b00100000;
-static const uint8_t MAX86150_INT_ALC_OVF_ENABLE = 	0x20;
+static const uint8_t MAX86150_INT_ALC_OVF_MASK    = (byte)~0b00100000;
+static const uint8_t MAX86150_INT_ALC_OVF_ENABLE  = 0x20;
 static const uint8_t MAX86150_INT_ALC_OVF_DISABLE = 0x00;
 
-static const uint8_t MAX86150_INT_PROX_INT_MASK = (byte)~0b00010000;
-static const uint8_t MAX86150_INT_PROX_INT_ENABLE = 0x10;
+static const uint8_t MAX86150_INT_PROX_INT_MASK    = (byte)~0b00010000;
+static const uint8_t MAX86150_INT_PROX_INT_ENABLE  = 0x10;
 static const uint8_t MAX86150_INT_PROX_INT_DISABLE = 0x00;
 
-static const uint8_t MAX86150_SAMPLEAVG_MASK =	(byte)~0b11100000;
-static const uint8_t MAX86150_SAMPLEAVG_1 = 	0x00;
-static const uint8_t MAX86150_SAMPLEAVG_2 = 	0x20;
-static const uint8_t MAX86150_SAMPLEAVG_4 = 	0x40;
-static const uint8_t MAX86150_SAMPLEAVG_8 = 	0x60;
-static const uint8_t MAX86150_SAMPLEAVG_16 = 	0x80;
-static const uint8_t MAX86150_SAMPLEAVG_32 = 	0xA0;
-
-static const uint8_t MAX86150_ROLLOVER_MASK = 	0xEF;
-static const uint8_t MAX86150_ROLLOVER_ENABLE = 0x10;
-static const uint8_t MAX86150_ROLLOVER_DISABLE = 0x00;
-
-static const uint8_t MAX86150_A_FULL_MASK = 	0xF0;
-
-static const uint8_t MAX86150_SHUTDOWN_MASK = 	0x7F;
-static const uint8_t MAX86150_SHUTDOWN = 		0x80;
-static const uint8_t MAX86150_WAKEUP = 			0x00;
-
-static const uint8_t MAX86150_RESET_MASK = 		0xFE;
-static const uint8_t MAX86150_RESET = 			0x01;
-
-static const uint8_t MAX86150_MODE_MASK = 		0xF8;
-static const uint8_t MAX86150_MODE_REDONLY = 	0x02;
-static const uint8_t MAX86150_MODE_REDIRONLY = 	0x03;
-static const uint8_t MAX86150_MODE_MULTILED = 	0x07;
-
-static const uint8_t MAX86150_ADCRANGE_MASK = 	0x9F;
-static const uint8_t MAX86150_ADCRANGE_2048 = 	0x00;
-static const uint8_t MAX86150_ADCRANGE_4096 = 	0x20;
-static const uint8_t MAX86150_ADCRANGE_8192 = 	0x40;
-static const uint8_t MAX86150_ADCRANGE_16384 = 	0x60;
-
-static const uint8_t MAX86150_SAMPLERATE_MASK = 0xE3;
-static const uint8_t MAX86150_SAMPLERATE_50 = 	0x00;
-static const uint8_t MAX86150_SAMPLERATE_100 = 	0x04;
-static const uint8_t MAX86150_SAMPLERATE_200 = 	0x08;
-static const uint8_t MAX86150_SAMPLERATE_400 = 	0x0C;
-static const uint8_t MAX86150_SAMPLERATE_800 = 	0x10;
-static const uint8_t MAX86150_SAMPLERATE_1000 = 0x14;
-static const uint8_t MAX86150_SAMPLERATE_1600 = 0x18;
-static const uint8_t MAX86150_SAMPLERATE_3200 = 0x1C;
-
-static const uint8_t MAX86150_PULSEWIDTH_MASK = 0xFC;
-static const uint8_t MAX86150_PULSEWIDTH_69 = 	0x00;
-static const uint8_t MAX86150_PULSEWIDTH_118 = 	0x01;
-static const uint8_t MAX86150_PULSEWIDTH_215 = 	0x02;
-static const uint8_t MAX86150_PULSEWIDTH_411 = 	0x03;
-
-static const uint8_t MAX86150_SLOT1_MASK = 		0xF0;
-static const uint8_t MAX86150_SLOT2_MASK = 		0x0F;
-static const uint8_t MAX86150_SLOT3_MASK = 		0xF0;
-static const uint8_t MAX86150_SLOT4_MASK = 		0x0F;
-
-static const uint8_t SLOT_NONE 				= 			0x00;
-static const uint8_t SLOT_RED_LED 		= 			0x01;
-static const uint8_t SLOT_IR_LED 			= 			0x02;
-static const uint8_t SLOT_RED_PILOT 	=				0x09;
-static const uint8_t SLOT_IR_PILOT 		= 			0x0A;
-static const uint8_t SLOT_ECG					= 			0x0D;
-
-static const uint8_t MAX_30105_EXPECTEDPARTID = 0x1E;
-
-static uint8_t _i2caddr;
-
-//activeLEDs is the number of channels turned on, and can be 1 to 3. 2 is common for Red+IR.
-static byte activeDevices; //Gets set during max86150_setup. Allows max86150_check() to calculate how many bytes to read from FIFO
-
-static void max86150_bitMask(uint8_t reg, uint8_t mask, uint8_t thing);
-
-#define STORAGE_SIZE 128 //Each long is 4 bytes so limit this to fit on your micro
-typedef struct Record
-{
-    uint32_t red[STORAGE_SIZE];
-    uint32_t IR[STORAGE_SIZE];
-    int32_t ecg[STORAGE_SIZE];
-    byte head;
-    byte tail;
+static const uint8_t MAX86150_SAMPLEAVG_MASK = (byte)~0b00000111;
+
+static const uint8_t MAX86150_ROLLOVER_MASK    = (byte)~0b00010000;
+static const uint8_t MAX86150_ROLLOVER_ENABLE  = 0b00010000;
+static const uint8_t MAX86150_ROLLOVER_DISABLE = 0b00000000;
+
+static const uint8_t MAX86150_ALMOST_FULL_CLEAR_MASK    = (byte)~0b01000000;
+static const uint8_t MAX86150_ALMOST_FULL_CLEAR_ENABLE  = 0b01000000;
+static const uint8_t MAX86150_ALMOST_FULL_CLEAR_DISABLE = 0b00000000;
+
+static const uint8_t MAX86150_ALMOST_FULL_REPEAT_MASK    = (byte)~0b00100000;
+static const uint8_t MAX86150_ALMOST_FULL_REPEAT_ENABLE  = 0b00100000;
+static const uint8_t MAX86150_ALMOST_FULL_REPEAT_DISABLE = 0b00000000;
+
+static const uint8_t MAX86150_A_FULL_MASK = (byte)~0b00001111;
+
+static const uint8_t MAX86150_SHUTDOWN_MASK = (byte)~0b00000010;
+static const uint8_t MAX86150_SHUTDOWN      = 0b10;
+static const uint8_t MAX86150_WAKEUP        = 0b00;
+
+static const uint8_t MAX86150_FIFO_ENABLE_MASK = (byte)~0b00000100;
+static const uint8_t MAX86150_FIFO_ENABLE      = 0b100;
+static const uint8_t MAX86150_FIFO_DISABLE     = 0b000;
+
+static const uint8_t MAX86150_RESET_MASK = (byte)~0b00000001;
+static const uint8_t MAX86150_RESET      = 0b1;
+
+static const uint8_t MAX86150_ADCRANGE_MASK = (byte)~0b11000000;
+
+static const uint8_t MAX86150_PPG_SAMPLERATE_MASK = (byte)~0b00111100;
+
+static const uint8_t MAX86150_PPG_PULSEWIDTH_MASK = (byte)~0b00000011;
+
+static const uint8_t MAX86150_SLOT1_MASK = 0xF0;
+static const uint8_t MAX86150_SLOT2_MASK = 0x0F;
+static const uint8_t MAX86150_SLOT3_MASK = 0xF0;
+static const uint8_t MAX86150_SLOT4_MASK = 0x0F;
+
+static const uint8_t MAX86150_LED1_RANGE_MASK = (byte)~0b00000011;
+static const uint8_t MAX86150_LED2_RANGE_MASK = (byte)~0b00001100;
+
+static const uint8_t MAX86150_ECG_SAMPLERATE_MASK = (byte)~0b00000111;
+
+static const uint8_t MAX86150_ECG_PGA_GAIN_MASK = (byte)~0b00001100;
+
+static const uint8_t MAX86150_ECG_IA_GAIN_MASK = (byte)~0b00000011;
+
+static const uint8_t MAX86150_EXPECTEDPARTID = 0x1E;
+
+static byte activeDevices =
+	3; //Gets set during max86150_setup. Allows max86150_check() to calculate how many bytes to read from FIFO
+
+#define STORAGE_SIZE                                                           \
+	128 //Each long is 4 bytes so limit this to fit on your micro
+typedef struct Record {
+	uint32_t red[STORAGE_SIZE];
+	uint32_t IR[STORAGE_SIZE];
+	int32_t ecg[STORAGE_SIZE];
+	byte head;
+	byte tail;
 } sense_struct; //This is our circular buffer of readings from the sensor
 
 static sense_struct sense;
 
 static void delay(int ms)
 {
-    TMR_Delay(MXC_TMR0, MSEC(ms), 0);
+	TMR_Delay(MXC_TMR0, MSEC(ms), 0);
 }
 
 bool max86150_begin(void)
 {
-  _i2caddr = MAX86150_ADDRESS;
-
-  // Step 1: Initial Communication and Verification
-  // Check that a MAX86150 is connected
-  if (max86150_readPartID() != MAX_30105_EXPECTEDPARTID) {
-    // Error -- Part ID read from MAX86150 does not match expected part ID.
-    // This may mean there is a physical connectivity problem (broken wire, unpowered, etc).
-    return false;
-  }
-  return true;
+	// Step 1: Initial Communication and Verification
+	// Check that a MAX86150 is connected
+	if (max86150_read_part_id() != MAX86150_EXPECTEDPARTID) {
+		// Error -- Part ID read from MAX86150 does not match expected part ID.
+		// This may mean there is a physical connectivity problem (broken wire, unpowered, etc).
+		return false;
+	}
+	return true;
 }
 
 //
@@ -170,498 +151,704 @@ bool max86150_begin(void)
 //
 
 //Begin Interrupt configuration
-uint8_t max86150_getINT1(void)
+uint8_t max86150_get_int1(void)
 {
-  return (max86150_readRegister8(_i2caddr, MAX86150_INTSTAT1));
-}
-uint8_t max86150_getINT2(void) {
-  return (max86150_readRegister8(_i2caddr, MAX86150_INTSTAT2));
-}
-
-void max86150_enableAFULL(void) {
-  max86150_bitMask(MAX86150_INTENABLE1, MAX86150_INT_A_FULL_MASK, MAX86150_INT_A_FULL_ENABLE);
+	return (max86150_read_register(MAX86150_ADDRESS, MAX86150_INTSTAT1));
 }
-void max86150_disableAFULL(void) {
-  max86150_bitMask(MAX86150_INTENABLE1, MAX86150_INT_A_FULL_MASK, MAX86150_INT_A_FULL_DISABLE);
-}
-
-void max86150_enableDATARDY(void) {
-  max86150_bitMask(MAX86150_INTENABLE1, MAX86150_INT_DATA_RDY_MASK, MAX86150_INT_DATA_RDY_ENABLE);
-}
-void max86150_disableDATARDY(void) {
-  max86150_bitMask(MAX86150_INTENABLE1, MAX86150_INT_DATA_RDY_MASK, MAX86150_INT_DATA_RDY_DISABLE);
-}
-
-void max86150_enableALCOVF(void) {
-  max86150_bitMask(MAX86150_INTENABLE1, MAX86150_INT_ALC_OVF_MASK, MAX86150_INT_ALC_OVF_ENABLE);
-}
-void max86150_disableALCOVF(void) {
-  max86150_bitMask(MAX86150_INTENABLE1, MAX86150_INT_ALC_OVF_MASK, MAX86150_INT_ALC_OVF_DISABLE);
+uint8_t max86150_get_int2(void)
+{
+	return (max86150_read_register(MAX86150_ADDRESS, MAX86150_INTSTAT2));
 }
 
-void max86150_enablePROXINT(void) {
-  max86150_bitMask(MAX86150_INTENABLE1, MAX86150_INT_PROX_INT_MASK, MAX86150_INT_PROX_INT_ENABLE);
-}
-void max86150_disablePROXINT(void) {
-  max86150_bitMask(MAX86150_INTENABLE1, MAX86150_INT_PROX_INT_MASK, MAX86150_INT_PROX_INT_DISABLE);
+void max86150_set_int_full(bool enabled)
+{
+	if (enabled) {
+		max86150_bit_mask(
+			MAX86150_INTENABLE1,
+			MAX86150_INT_A_FULL_MASK,
+			MAX86150_INT_A_FULL_ENABLE
+		);
+	} else {
+		max86150_bit_mask(
+			MAX86150_INTENABLE1,
+			MAX86150_INT_A_FULL_MASK,
+			MAX86150_INT_A_FULL_DISABLE
+		);
+	}
+}
+
+void max86150_set_int_datardy(bool enabled)
+{
+	if (enabled) {
+		max86150_bit_mask(
+			MAX86150_INTENABLE1,
+			MAX86150_INT_DATA_RDY_MASK,
+			MAX86150_INT_DATA_RDY_ENABLE
+		);
+	} else {
+		max86150_bit_mask(
+			MAX86150_INTENABLE1,
+			MAX86150_INT_DATA_RDY_MASK,
+			MAX86150_INT_DATA_RDY_DISABLE
+		);
+	}
+}
+
+void max86150_set_int_ambient_light_overflow(bool enabled)
+{
+	if (enabled) {
+		max86150_bit_mask(
+			MAX86150_INTENABLE1,
+			MAX86150_INT_ALC_OVF_MASK,
+			MAX86150_INT_ALC_OVF_ENABLE
+		);
+	} else {
+		max86150_bit_mask(
+			MAX86150_INTENABLE1,
+			MAX86150_INT_ALC_OVF_MASK,
+			MAX86150_INT_ALC_OVF_DISABLE
+		);
+	}
+}
+
+void max86150_set_int_proximity(bool enabled)
+{
+	if (enabled) {
+		max86150_bit_mask(
+			MAX86150_INTENABLE1,
+			MAX86150_INT_PROX_INT_MASK,
+			MAX86150_INT_PROX_INT_ENABLE
+		);
+	} else {
+		max86150_bit_mask(
+			MAX86150_INTENABLE1,
+			MAX86150_INT_PROX_INT_MASK,
+			MAX86150_INT_PROX_INT_DISABLE
+		);
+	}
 }
 //End Interrupt configuration
 
-void max86150_softReset(void) {
-  max86150_bitMask(MAX86150_SYSCONTROL, MAX86150_RESET_MASK, MAX86150_RESET);
-
-  // Poll for bit to clear, reset is then complete
-  // Timeout after 100ms
-  //TODO
-  //unsigned long startTime = millis();
-  //while (millis() - startTime < 100)
-  {
-    //uint8_t response = max86150_readRegister8(_i2caddr, MAX86150_SYSCONTROL);
-    //if ((response & MAX86150_RESET) == 0) break; //We're done!
-    delay(1); //Let's not over burden the I2C bus
-  }
-}
-
-void max86150_shutDown(void) {
-  // Put IC into low power mode (datasheet pg. 19)
-  // During shutdown the IC will continue to respond to I2C commands but will
-  // not update with or take new readings (such as temperature)
-  max86150_bitMask(MAX86150_SYSCONTROL, MAX86150_SHUTDOWN_MASK, MAX86150_SHUTDOWN);
-}
-
-void max86150_wakeUp(void) {
-  // Pull IC out of low power mode (datasheet pg. 19)
-  max86150_bitMask(MAX86150_SYSCONTROL, MAX86150_SHUTDOWN_MASK, MAX86150_WAKEUP);
+void max86150_soft_reset(void)
+{
+	max86150_bit_mask(
+		MAX86150_SYSCONTROL, MAX86150_RESET_MASK, MAX86150_RESET
+	);
+
+	// Poll for bit to clear, reset is then complete
+	// Timeout after 100 tries
+	uint8_t tries = 0;
+	while (tries < 100) {
+		uint8_t response = max86150_read_register(
+			MAX86150_ADDRESS, MAX86150_SYSCONTROL
+		);
+		if ((response & MAX86150_RESET) == 0)
+			break; //We're done!
+		tries++;
+		delay(1); //Let's not over burden the I2C bus
+	}
+}
+
+void max86150_shut_down(void)
+{
+	// Put IC into low power mode (datasheet pg. 19)
+	// During shutdown the IC will continue to respond to I2C commands but will
+	// not update with or take new readings (such as temperature)
+	max86150_bit_mask(
+		MAX86150_SYSCONTROL, MAX86150_SHUTDOWN_MASK, MAX86150_SHUTDOWN
+	);
 }
 
-void max86150_setLEDMode(uint8_t mode) {
-  // Set which LEDs are used for sampling -- Red only, RED+IR only, or custom.
-  // See datasheet, page 19
-  //max86150_bitMask(MAX86150_PPGCONFIG1, MAX86150_MODE_MASK, mode);
+void max86150_wake_up(void)
+{
+	// Pull IC out of low power mode (datasheet pg. 19)
+	max86150_bit_mask(
+		MAX86150_SYSCONTROL, MAX86150_SHUTDOWN_MASK, MAX86150_WAKEUP
+	);
 }
 
-void max86150_setADCRange(uint8_t adcRange) {
-  // adcRange: one of MAX86150_ADCRANGE_2048, _4096, _8192, _16384
-  //max86150_bitMask(MAX86150_PARTICLECONFIG, MAX86150_ADCRANGE_MASK, adcRange);
+void max86150_set_fifo_enable(bool enabled)
+{
+	if (enabled) {
+		max86150_bit_mask(
+			MAX86150_SYSCONTROL,
+			MAX86150_FIFO_ENABLE_MASK,
+			MAX86150_FIFO_ENABLE
+		);
+	} else {
+		max86150_bit_mask(
+			MAX86150_SYSCONTROL,
+			MAX86150_FIFO_ENABLE_MASK,
+			MAX86150_FIFO_DISABLE
+		);
+	}
+}
+
+void max86150_set_ppg_adc_range(uint8_t adcRange)
+{
+	// adcRange: one of MAX86150_ADCRANGE_*
+	max86150_bit_mask(
+		MAX86150_PPGCONFIG1, MAX86150_ADCRANGE_MASK, adcRange
+	);
 }
 
-void max86150_setSampleRate(uint8_t sampleRate) {
-  // sampleRate: one of MAX86150_SAMPLERATE_50, _100, _200, _400, _800, _1000, _1600, _3200
-  //max86150_bitMask(MAX86150_PARTICLECONFIG, MAX86150_SAMPLERATE_MASK, sampleRate);
+void max86150_set_ppg_sample_rate(uint8_t sampleRate)
+{
+	// sampleRate: one of MAX86150_PPG_SAMPLERATE_*
+	max86150_bit_mask(
+		MAX86150_PPGCONFIG1, MAX86150_PPG_SAMPLERATE_MASK, sampleRate
+	);
 }
 
-void max86150_setPulseWidth(uint8_t pulseWidth) {
-  // pulseWidth: one of MAX86150_PULSEWIDTH_69, _188, _215, _411
-  //max86150_bitMask(MAX86150_PPGCONFIG1, MAX86150_PULSEWIDTH_MASK, pulseWidth);
+void max86150_set_ppg_pulse_width(uint8_t pulseWidth)
+{
+	// pulseWidth: one of MAX86150_PPG_PULSEWIDTH_*
+	max86150_bit_mask(
+		MAX86150_PPGCONFIG1, MAX86150_PPG_PULSEWIDTH_MASK, pulseWidth
+	);
 }
 
 // NOTE: Amplitude values: 0x00 = 0mA, 0x7F = 25.4mA, 0xFF = 50mA (typical)
 // See datasheet, page 21
-void max86150_setPulseAmplitudeRed(uint8_t amplitude)
+void max86150_set_led_red_amplitude(uint8_t amplitude)
 {
-  max86150_writeRegister8(_i2caddr, MAX86150_LED2_PULSEAMP, amplitude);
+	max86150_write_register(
+		MAX86150_ADDRESS, MAX86150_LED2_PULSEAMP, amplitude
+	);
+	max86150_bit_mask(
+		MAX86150_LED_RANGE,
+		MAX86150_LED2_RANGE_MASK,
+		MAX86150_LED2_RANGE_50
+	);
 }
 
-void max86150_setPulseAmplitudeIR(uint8_t amplitude)
+void max86150_set_led_ir_amplitude(uint8_t amplitude)
 {
-  max86150_writeRegister8(_i2caddr, MAX86150_LED1_PULSEAMP, amplitude);
+	max86150_write_register(
+		MAX86150_ADDRESS, MAX86150_LED1_PULSEAMP, amplitude
+	);
+	max86150_bit_mask(
+		MAX86150_LED_RANGE,
+		MAX86150_LED1_RANGE_MASK,
+		MAX86150_LED1_RANGE_50
+	);
 }
 
-void max86150_setPulseAmplitudeProximity(uint8_t amplitude) {
-  max86150_writeRegister8(_i2caddr, MAX86150_LED_PROX_AMP, amplitude);
+void max86150_set_led_proximity_amplitude(uint8_t amplitude)
+{
+	max86150_write_register(
+		MAX86150_ADDRESS, MAX86150_LED_PROX_AMP, amplitude
+	);
 }
 
-void max86150_setProximityThreshold(uint8_t threshMSB)
+void max86150_set_proximity_threshold(uint8_t threshMSB)
 {
-  // The threshMSB signifies only the 8 most significant-bits of the ADC count.
-  max86150_writeRegister8(_i2caddr, MAX86150_PROXINTTHRESH, threshMSB);
+	// The threshMSB signifies only the 8 most significant-bits of the ADC count.
+	max86150_write_register(
+		MAX86150_ADDRESS, MAX86150_PROXINTTHRESH, threshMSB
+	);
 }
 
 //Given a slot number assign a thing to it
 //Devices are SLOT_RED_LED or SLOT_RED_PILOT (proximity)
 //Assigning a SLOT_RED_LED will pulse LED
 //Assigning a SLOT_RED_PILOT will ??
-void max86150_enableSlot(uint8_t slotNumber, uint8_t device)
-{
-	  //uint8_t originalContents;
-
-	  switch (slotNumber) {
-	    case (1):
-	      max86150_bitMask(MAX86150_FIFOCONTROL1, MAX86150_SLOT1_MASK, device);
-	      break;
-	    case (2):
-	      max86150_bitMask(MAX86150_FIFOCONTROL1, MAX86150_SLOT2_MASK, device << 4);
-	      break;
-	    case (3):
-	      max86150_bitMask(MAX86150_FIFOCONTROL2, MAX86150_SLOT3_MASK, device);
-	      break;
-	    case (4):
-	      max86150_bitMask(MAX86150_FIFOCONTROL2, MAX86150_SLOT4_MASK, device << 4);
-	      break;
-	    default:
-	      //Shouldn't be here!
-	      break;
-	  }
+void max86150_fifo_enable_slot(uint8_t slotNumber, uint8_t device)
+{
+	switch (slotNumber) {
+	case (1):
+		max86150_bit_mask(
+			MAX86150_FIFOCONTROL1, MAX86150_SLOT1_MASK, device
+		);
+		break;
+	case (2):
+		max86150_bit_mask(
+			MAX86150_FIFOCONTROL1,
+			MAX86150_SLOT2_MASK,
+			device << 4
+		);
+		break;
+	case (3):
+		max86150_bit_mask(
+			MAX86150_FIFOCONTROL2, MAX86150_SLOT3_MASK, device
+		);
+		break;
+	case (4):
+		max86150_bit_mask(
+			MAX86150_FIFOCONTROL2,
+			MAX86150_SLOT4_MASK,
+			device << 4
+		);
+		break;
+	default:
+		//Shouldn't be here!
+		break;
+	}
 }
 
 //Clears all slot assignments
 void max86150_disableSlots(void)
 {
-  max86150_writeRegister8(_i2caddr, MAX86150_FIFOCONTROL1, 0);
-  max86150_writeRegister8(_i2caddr, MAX86150_FIFOCONTROL2, 0);
+	max86150_write_register(MAX86150_ADDRESS, MAX86150_FIFOCONTROL1, 0);
+	max86150_write_register(MAX86150_ADDRESS, MAX86150_FIFOCONTROL2, 0);
 }
 
 //
 // FIFO Configuration
 //
 
-void max86150_setFIFOAverage(uint8_t numberOfSamples)
+void max86150_set_ppg_averaging(uint8_t numberOfSamples)
 {
-  max86150_bitMask(MAX86150_FIFOCONFIG, MAX86150_SAMPLEAVG_MASK, numberOfSamples);
+	max86150_bit_mask(
+		MAX86150_FIFOCONFIG, MAX86150_SAMPLEAVG_MASK, numberOfSamples
+	);
 }
 
 //Resets all points to start in a known state
-void max86150_clearFIFO(void) {
-  max86150_writeRegister8(_i2caddr, MAX86150_FIFOWRITEPTR, 0);
-  max86150_writeRegister8(_i2caddr, MAX86150_FIFOOVERFLOW, 0);
-  max86150_writeRegister8(_i2caddr, MAX86150_FIFOREADPTR, 0);
+void max86150_clear_fifo(void)
+{
+	max86150_write_register(MAX86150_ADDRESS, MAX86150_FIFOWRITEPTR, 0);
+	max86150_write_register(MAX86150_ADDRESS, MAX86150_FIFOOVERFLOW, 0);
+	max86150_write_register(MAX86150_ADDRESS, MAX86150_FIFOREADPTR, 0);
 }
 
 //Enable roll over if FIFO over flows
-void max86150_enableFIFORollover(void) {
-  max86150_bitMask(MAX86150_FIFOCONFIG, MAX86150_ROLLOVER_MASK, MAX86150_ROLLOVER_ENABLE);
-}
-
-//Disable roll over if FIFO over flows
-void max86150_disableFIFORollover(void) {
-  max86150_bitMask(MAX86150_FIFOCONFIG, MAX86150_ROLLOVER_MASK, MAX86150_ROLLOVER_DISABLE);
+void max86150_set_fifo_rollover(bool enabled)
+{
+	if (enabled) {
+		max86150_bit_mask(
+			MAX86150_FIFOCONFIG,
+			MAX86150_ROLLOVER_MASK,
+			MAX86150_ROLLOVER_ENABLE
+		);
+	} else {
+		max86150_bit_mask(
+			MAX86150_FIFOCONFIG,
+			MAX86150_ROLLOVER_MASK,
+			MAX86150_ROLLOVER_DISABLE
+		);
+	}
+}
+
+//Enable fifo almost full flag clear on data read
+void max86150_set_fifo_almost_full_clear(bool enabled)
+{
+	if (enabled) {
+		max86150_bit_mask(
+			MAX86150_FIFOCONFIG,
+			MAX86150_ALMOST_FULL_CLEAR_MASK,
+			MAX86150_ALMOST_FULL_CLEAR_ENABLE
+		);
+	} else {
+		max86150_bit_mask(
+			MAX86150_FIFOCONFIG,
+			MAX86150_ALMOST_FULL_CLEAR_MASK,
+			MAX86150_ALMOST_FULL_CLEAR_DISABLE
+		);
+	}
+}
+
+//Enable fifo almost full flag repeated assertion
+void max86150_set_fifo_almost_full_repeat(bool enabled)
+{
+	if (enabled) {
+		max86150_bit_mask(
+			MAX86150_FIFOCONFIG,
+			MAX86150_ALMOST_FULL_REPEAT_MASK,
+			MAX86150_ALMOST_FULL_REPEAT_ENABLE
+		);
+	} else {
+		max86150_bit_mask(
+			MAX86150_FIFOCONFIG,
+			MAX86150_ALMOST_FULL_REPEAT_MASK,
+			MAX86150_ALMOST_FULL_REPEAT_DISABLE
+		);
+	}
 }
 
 //Power on default is 32 samples
 //Note it is reverse: 0x00 is 32 samples, 0x0F is 17 samples
-void max86150_setFIFOAlmostFull(uint8_t numberOfSamples) {
-  max86150_bitMask(MAX86150_FIFOCONFIG, MAX86150_A_FULL_MASK, numberOfSamples);
+void max86150_set_fifo_almost_full(uint8_t numberOfSamples)
+{
+	max86150_bit_mask(
+		MAX86150_FIFOCONFIG, MAX86150_A_FULL_MASK, numberOfSamples
+	);
 }
 
 //Read the FIFO Write Pointer
-uint8_t max86150_getWritePointer(void) {
-  return (max86150_readRegister8(_i2caddr, MAX86150_FIFOWRITEPTR));
+uint8_t max86150_get_fifo_write_pointer(void)
+{
+	return (max86150_read_register(MAX86150_ADDRESS, MAX86150_FIFOWRITEPTR));
 }
 
 //Read the FIFO Read Pointer
-uint8_t max86150_getReadPointer(void) {
-  return (max86150_readRegister8(_i2caddr, MAX86150_FIFOREADPTR));
-}
-
-// Set the PROX_INT_THRESHold
-void max86150_setPROXINTTHRESH(uint8_t val) {
-  max86150_writeRegister8(_i2caddr, MAX86150_PROXINTTHRESH, val);
+uint8_t max86150_get_fifo_read_pointer(void)
+{
+	return (max86150_read_register(MAX86150_ADDRESS, MAX86150_FIFOREADPTR));
 }
 
 //
 // Device ID and Revision
 //
-uint8_t max86150_readPartID() {
-  return max86150_readRegister8(_i2caddr, MAX86150_PARTID);
+uint8_t max86150_read_part_id()
+{
+	return max86150_read_register(MAX86150_ADDRESS, MAX86150_PARTID);
 }
 
-//Setup the sensor
-//The MAX86150 has many settings. By default we select:
-// Sample Average = 4
-// Mode = MultiLED
-// ADC Range = 16384 (62.5pA per LSB)
-// Sample rate = 50
-//Use the default max86150_setup if you are just getting started with the MAX86150 sensor
-void max86150_setup(byte powerLevel, byte sampleAverage, byte ledMode, int sampleRate, int pulseWidth, int adcRange)
+//Set ecg sample rate
+void max86150_set_ecg_sample_rate(uint8_t sampleRate)
 {
-		activeDevices=3;
-		max86150_writeRegister8(_i2caddr,MAX86150_SYSCONTROL,0x01);
-		delay(100);
-		max86150_writeRegister8(_i2caddr,MAX86150_FIFOCONFIG,0x7F);
-
-		//FIFO Configuration
-		//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-		//The chip will average multiple samples of same type together if you wish
-		if (sampleAverage == 1) max86150_setFIFOAverage(MAX86150_SAMPLEAVG_1); //No averaging per FIFO record
-		else if (sampleAverage == 2) max86150_setFIFOAverage(MAX86150_SAMPLEAVG_2);
-		else if (sampleAverage == 4) max86150_setFIFOAverage(MAX86150_SAMPLEAVG_4);
-		else if (sampleAverage == 8) max86150_setFIFOAverage(MAX86150_SAMPLEAVG_8);
-		else if (sampleAverage == 16) max86150_setFIFOAverage(MAX86150_SAMPLEAVG_16);
-		else if (sampleAverage == 32) max86150_setFIFOAverage(MAX86150_SAMPLEAVG_32);
-		else max86150_setFIFOAverage(MAX86150_SAMPLEAVG_4);
-
-		uint16_t FIFOCode = 0x00;
-
-	  FIFOCode = FIFOCode<<4 | 0x0009;// : FIFOCode;  //insert ECG front of ETI in FIFO
-	  FIFOCode = FIFOCode<<8 | 0x0021;//) : FIFOCode; //insert Red(2) and IR (1) in front of ECG in FIFO
+	// sampleRate: one of MAX86150_ECG_SAMPLERATE_*
+	max86150_bit_mask(
+		MAX86150_ECG_CONFIG1, MAX86150_ECG_SAMPLERATE_MASK, sampleRate
+	);
+}
 
+//Set ecg pga gain
+void max86150_set_ecg_pga_gain(uint8_t gain)
+{
+	// sampleRate: one of MAX86150_ECG_PGA_GAIN_*
+	max86150_bit_mask(
+		MAX86150_ECG_CONFIG3, MAX86150_ECG_PGA_GAIN_MASK, gain
+	);
+}
 
-		//FIFO Control 1 = FD2|FD1, FIFO Control 2 = FD4|FD3
+//Set ecg pga gain
+void max86150_set_ecg_instrumentation_amplifier_gain(uint8_t gain)
+{
+	// sampleRate: one of MAX86150_ECG_IA_GAIN_*
+	max86150_bit_mask(
+		MAX86150_ECG_CONFIG3, MAX86150_ECG_IA_GAIN_MASK, gain
+	);
+}
 
-		max86150_writeRegister8(_i2caddr,MAX86150_FIFOCONTROL1,(0b00100001));
-		//max86150_writeRegister8(_i2caddr,MAX86150_FIFOCONTROL1,(0b00001001));
-		//max86150_writeRegister8(_i2caddr,MAX86150_FIFOCONTROL1,(0b00000010));
-		max86150_writeRegister8(_i2caddr,MAX86150_FIFOCONTROL2,(0b00001001));
-		//max86150_writeRegister8(_i2caddr,MAX86150_FIFOCONTROL2,(0b00000000));
-		//max86150_writeRegister8(_i2caddr,MAX86150_FIFOCONTROL1, (char)(FIFOCode & 0x00FF) );
-		//max86150_writeRegister8(_i2caddr,MAX86150_FIFOCONTROL2, (char)(FIFOCode >>8) );
+//Setup the sensor
+//The MAX86150 has many settings.
+//Use the default max86150_setup if you are just getting started with the MAX86150 sensor
+void max86150_setup(const uint8_t ppg_sample_rate)
+{
+	max86150_soft_reset();
+	max86150_set_ppg_averaging(MAX86150_SAMPLEAVG_4);
+	max86150_set_fifo_rollover(true);
+	max86150_set_fifo_almost_full(8);
+	max86150_set_fifo_almost_full_clear(true);
+	max86150_set_fifo_almost_full_repeat(true);
 
-		max86150_writeRegister8(_i2caddr,MAX86150_PPGCONFIG1,0b11010001);
-		//max86150_writeRegister8(_i2caddr,MAX86150_PPGCONFIG1,0b11100111);
+	max86150_fifo_enable_slot(1, MAX86150_SLOT_RED_LED);
+	max86150_fifo_enable_slot(2, MAX86150_SLOT_IR_LED);
+	max86150_fifo_enable_slot(3, MAX86150_SLOT_ECG);
+	//max86150_fifo_enable_slot(4, MAX86150_SLOT_NONE);
 
-		max86150_writeRegister8(_i2caddr,MAX86150_PPGCONFIG2, 0x06);
-		max86150_writeRegister8(_i2caddr,MAX86150_LED_RANGE, 0x00 ); // PPG_ADC_RGE: 32768nA
+	max86150_set_ppg_adc_range(MAX86150_ADCRANGE_16384);
+	max86150_set_ppg_sample_rate(ppg_sample_rate);
+	max86150_set_ppg_pulse_width(MAX86150_PPG_PULSEWIDTH_100);
 
-		max86150_writeRegister8(_i2caddr,MAX86150_SYSCONTROL,0x04);//start FIFO
+	max86150_set_led_ir_amplitude(0x66);
+	max86150_set_led_red_amplitude(0x66);
 
-		max86150_writeRegister8(_i2caddr,MAX86150_ECG_CONFIG1,0b00000011);
-		//max86150_writeRegister8(_i2caddr,MAX86150_ECG_CONFIG1,0b00000001);
-		max86150_writeRegister8(_i2caddr,MAX86150_ECG_CONFIG3,0b00001101);
+	max86150_set_ecg_sample_rate(MAX86150_ECG_SAMPLERATE_200);
+	max86150_set_ecg_pga_gain(MAX86150_ECG_PGA_GAIN_8);
+	max86150_set_ecg_instrumentation_amplifier_gain(
+		MAX86150_ECG_IA_GAIN_9_5
+	);
 
-		max86150_setPulseAmplitudeRed(0xFF);
-		max86150_setPulseAmplitudeIR(0xFF);
+	max86150_set_int_datardy(false);
+	max86150_set_int_full(true);
 
-  //Multi-LED Mode Configuration, Enable the reading of the three LEDs
-  //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-  //max86150_enableSlot(1, SLOT_RED_LED);
-  //if (ledMode > 1)
-	//max86150_enableSlot(2, SLOT_IR_LED);
-  //if (ledMode > 2)
-	//max86150_enableSlot(3, SLOT_ECG);
-  //max86150_enableSlot(1, SLOT_RED_PILOT);
-  //max86150_enableSlot(2, SLOT_IR_PILOT);
-  //max86150_enableSlot(3, SLOT_GREEN_PILOT);
-  //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+	max86150_clear_fifo(); //Reset the FIFO before we begin checking the sensor
 
-  	max86150_clearFIFO(); //Reset the FIFO before we begin checking the sensor
+	max86150_set_fifo_enable(true);
 }
 
 //Tell caller how many samples are max86150_available
 uint8_t max86150_available(void)
 {
-  int8_t numberOfSamples = sense.head - sense.tail;
-  if (numberOfSamples < 0) numberOfSamples += STORAGE_SIZE;
+	int8_t numberOfSamples = sense.head - sense.tail;
+	if (numberOfSamples < 0)
+		numberOfSamples += STORAGE_SIZE;
 
-  return (numberOfSamples);
+	return (numberOfSamples);
 }
 
 //Report the most recent red value
-uint32_t max86150_getRed(void)
+uint32_t max86150_get_red(void)
 {
-  //Check the sensor for new data for 250ms
-  if(max86150_safeCheck(250))
-    return (sense.red[sense.head]);
-  else
-    return(0); //Sensor failed to find new data
+	//Check the sensor for new data for 250ms
+	if (max86150_safeCheck(250))
+		return (sense.red[sense.head]);
+	else
+		return (0); //Sensor failed to find new data
 }
 
 //Report the most recent IR value
-uint32_t max86150_getIR(void)
+uint32_t max86150_get_ir(void)
 {
-  //Check the sensor for new data for 250ms
-  if(max86150_safeCheck(250))
-    return (sense.IR[sense.head]);
-  else
-    return(0); //Sensor failed to find new data
+	//Check the sensor for new data for 250ms
+	if (max86150_safeCheck(250))
+		return (sense.IR[sense.head]);
+	else
+		return (0); //Sensor failed to find new data
 }
 
 //Report the most recent Green value
-int32_t max86150_getECG(void)
+int32_t max86150_get_ecg(void)
 {
-  //Check the sensor for new data for 250ms
-  if(max86150_safeCheck(250))
-    return (sense.ecg[sense.head]);
-  else
-    return(0); //Sensor failed to find new data
+	//Check the sensor for new data for 250ms
+	if (max86150_safeCheck(250))
+		return (sense.ecg[sense.head]);
+	else
+		return (0); //Sensor failed to find new data
 }
 
 //Report the next Red value in the FIFO
-uint32_t max86150_getFIFORed(void)
+uint32_t max86150_get_fifo_red(void)
 {
-  return (sense.red[sense.tail]);
+	return (sense.red[sense.tail]);
 }
 
 //Report the next IR value in the FIFO
-uint32_t max86150_getFIFOIR(void)
+uint32_t max86150_get_fifo_ir(void)
 {
-  return (sense.IR[sense.tail]);
+	return (sense.IR[sense.tail]);
 }
 
 //Report the next Green value in the FIFO
-int32_t max86150_getFIFOECG(void)
+int32_t max86150_get_fifo_ecg(void)
 {
-  return (sense.ecg[sense.tail]);
+	return (sense.ecg[sense.tail]);
 }
 
 //Advance the tail
-void max86150_nextSample(void)
+void max86150_next_sample(void)
 {
-  if(max86150_available()) //Only advance the tail if new data is max86150_available
-  {
-    sense.tail++;
-    sense.tail %= STORAGE_SIZE; //Wrap condition
-  }
+	if (max86150_available()) { //Only advance the tail if new data is max86150_available
+		sense.tail++;
+		sense.tail %= STORAGE_SIZE; //Wrap condition
+	}
 }
 
+//Polls the sensor for new data
+//Call regularly
+//If new data is max86150_available, it updates the head and tail in the main struct
+//Returns number of new samples obtained
+uint8_t max86150_get_sample(uint32_t *red, uint32_t *ir, int32_t *ecg)
+{
+	//Read register FIDO_DATA in (3-byte * number of active LED) chunks
+	//Until FIFO_RD_PTR = FIFO_WR_PTR
+
+	byte readPointer  = max86150_get_fifo_read_pointer();
+	byte writePointer = max86150_get_fifo_write_pointer();
+
+	int numberOfSamples = 0;
+
+	//Do we have new data?
+	if (readPointer != writePointer) {
+		//Calculate the number of readings we need to get from sensor
+		numberOfSamples = writePointer - readPointer;
+		if (numberOfSamples < 0)
+			numberOfSamples += 32; //Wrap condition
+
+		//Get ready to read a burst of data from the FIFO register
+		uint8_t command[] = { MAX86150_FIFODATA };
+
+		// Important! true is for repeated start (since we are not reading complete fifo)
+		// See https://os.mbed.com/users/laserdad/code/MAX86150_ECG_PPG//file/3c728f3d1f10/main.cpp/
+		I2C_MasterWrite(
+			MXC_I2C1_BUS0, MAX86150_ADDRESS << 1, command, 1, true
+		);
+
+		if (numberOfSamples > 0) {
+			uint8_t data[3 * 3];
+			I2C_MasterRead(
+				MXC_I2C1_BUS0,
+				MAX86150_ADDRESS << 1,
+				data,
+				3 * 3,
+				0
+			);
+
+			*red = (data[0] << 16) | (data[1] << 8) | (data[2]);
+			*ir  = (data[3] << 16) | (data[4] << 8) | (data[5]);
+			*ecg = (data[6] << 16) | (data[7] << 8) | (data[8]);
+		}
+
+	}                         //End readPtr != writePtr
+	return (numberOfSamples); //Let the world know how much new data we found
+}
 //Polls the sensor for new data
 //Call regularly
 //If new data is max86150_available, it updates the head and tail in the main struct
 //Returns number of new samples obtained
 uint16_t max86150_check(void)
 {
-  //Read register FIDO_DATA in (3-byte * number of active LED) chunks
-  //Until FIFO_RD_PTR = FIFO_WR_PTR
-
-  byte readPointer = max86150_getReadPointer();
-  byte writePointer = max86150_getWritePointer();
-
-  int numberOfSamples = 0;
-
-  //Do we have new data?
-  if (readPointer != writePointer)
-  {
-    //Calculate the number of readings we need to get from sensor
-    numberOfSamples = writePointer - readPointer;
-    if (numberOfSamples < 0) numberOfSamples += 32; //Wrap condition
-
-    //We now have the number of readings, now calc bytes to read
-    //For this example we are just doing Red and IR (3 bytes each)
-    int bytesLeftToRead = numberOfSamples * activeDevices * 3;
-
-    //Get ready to read a burst of data from the FIFO register
-    uint8_t command[] = {MAX86150_FIFODATA};
-    I2C_MasterWrite(MXC_I2C1_BUS0, _i2caddr << 1, command, 1, 0);
-
-    //We may need to read as many as 288 bytes so we read in blocks no larger than I2C_BUFFER_LENGTH
-    //I2C_BUFFER_LENGTH changes based on the platform. 64 bytes for SAMD21, 32 bytes for Uno.
-    //Wire.requestFrom() is limited to BUFFER_LENGTH which is 32 on the Uno
-    while (bytesLeftToRead > 0)
-    {
-      int toGet = bytesLeftToRead;
-      if (toGet > I2C_BUFFER_LENGTH)
-      {
-        //If toGet is 32 this is bad because we read 6 bytes (Red+IR * 3 = 6) at a time
-        //32 % 6 = 2 left over. We don't want to request 32 bytes, we want to request 30.
-        //32 % 9 (Red+IR+GREEN) = 5 left over. We want to request 27.
-
-        toGet = I2C_BUFFER_LENGTH - (I2C_BUFFER_LENGTH % (activeDevices * 3)); //Trim toGet to be a multiple of the samples we need to read
-      }
-
-      bytesLeftToRead -= toGet;
-
-      //Request toGet number of bytes from sensor
-      //_i2cPort->requestFrom(_i2caddr, toGet);
-      uint8_t data[toGet];
-      uint8_t *p = data;
-      I2C_MasterRead(MXC_I2C1_BUS0, _i2caddr << 1, data, toGet, 0);
-
-      while (toGet > 0)
-      {
-        sense.head++; //Advance the head of the storage struct
-        sense.head %= STORAGE_SIZE; //Wrap condition
-
-        byte temp[sizeof(uint32_t)]; //Array of 4 bytes that we will convert into long
-        uint32_t tempLong;
-
-        //Burst read three bytes - RED
-        temp[3] = 0;
-        temp[2] = *p++;
-        temp[1] = *p++;
-        temp[0] = *p++;
-
-        //Convert array to long
-        memcpy(&tempLong, temp, sizeof(tempLong));
+	//Read register FIDO_DATA in (3-byte * number of active LED) chunks
+	//Until FIFO_RD_PTR = FIFO_WR_PTR
+
+	byte readPointer  = max86150_get_fifo_read_pointer();
+	byte writePointer = max86150_get_fifo_write_pointer();
+
+	int numberOfSamples = 0;
+
+	//Do we have new data?
+	if (readPointer != writePointer) {
+		//Calculate the number of readings we need to get from sensor
+		numberOfSamples = writePointer - readPointer;
+		if (numberOfSamples < 0)
+			numberOfSamples += 32; //Wrap condition
+
+		//We now have the number of readings, now calc bytes to read
+		//For this example we are just doing Red and IR (3 bytes each)
+		int bytesLeftToRead = numberOfSamples * activeDevices * 3;
+
+		//Get ready to read a burst of data from the FIFO register
+		uint8_t command[] = { MAX86150_FIFODATA };
+		I2C_MasterWrite(
+			MXC_I2C1_BUS0, MAX86150_ADDRESS << 1, command, 1, 0
+		);
+
+		//We may need to read as many as 288 bytes so we read in blocks no larger than I2C_BUFFER_LENGTH
+		//I2C_BUFFER_LENGTH changes based on the platform. 64 bytes for SAMD21, 32 bytes for Uno.
+		//Wire.requestFrom() is limited to BUFFER_LENGTH which is 32 on the Uno
+		while (bytesLeftToRead > 0) {
+			int toGet = bytesLeftToRead;
+			if (toGet > I2C_BUFFER_LENGTH) {
+				//If toGet is 32 this is bad because we read 9 bytes (Red+IR+ECG * 3 = 9) at a time
+				//32 % 9 = 5 left over. We don't want to request 32 bytes, we want to request 27.
+				//32 % 9 (Red+IR+GREEN) = 5 left over. We want to request 27.
+
+				toGet = I2C_BUFFER_LENGTH -
+					(I2C_BUFFER_LENGTH %
+					 (activeDevices *
+					  3)); //Trim toGet to be a multiple of the samples we need to read
+			}
+
+			bytesLeftToRead -= toGet;
+
+			//Request toGet number of bytes from sensor
+			//_i2cPort->requestFrom(MAX86150_ADDRESS, toGet);
+			uint8_t data[bytesLeftToRead];
+			uint8_t *p = data;
+			I2C_MasterRead(
+				MXC_I2C1_BUS0,
+				MAX86150_ADDRESS << 1,
+				data,
+				bytesLeftToRead,
+				0
+			);
+
+			while (bytesLeftToRead > 0) {
+				sense.head++; //Advance the head of the storage struct
+				sense.head %= STORAGE_SIZE; //Wrap condition
+
+				byte temp[sizeof(
+					uint32_t)]; //Array of 4 bytes that we will convert into long
+				uint32_t tempLong;
+
+				//Burst read three bytes - RED
+				temp[3] = 0;
+				temp[2] = *p++;
+				temp[1] = *p++;
+				temp[0] = *p++;
+
+				//Convert array to long
+				memcpy(&tempLong, temp, sizeof(tempLong));
 
 				tempLong &= 0x7FFFF; //Zero out all but 18 bits
 
-        sense.red[sense.head] = tempLong; //Store this reading into the sense array
+				sense.red[sense.head] =
+					tempLong; //Store this reading into the sense array
 
-        if (activeDevices > 1)
-        {
-          //Burst read three more bytes - IR
-          temp[3] = 0;
-          temp[2] = *p++;
-          temp[1] = *p++;
-          temp[0] = *p++;
+				if (activeDevices > 1) {
+					//Burst read three more bytes - IR
+					temp[3] = 0;
+					temp[2] = *p++;
+					temp[1] = *p++;
+					temp[0] = *p++;
 
-          //Convert array to long
-          memcpy(&tempLong, temp, sizeof(tempLong));
+					//Convert array to long
+					memcpy(&tempLong,
+					       temp,
+					       sizeof(tempLong));
 					//Serial.println(tempLong);
-				  tempLong &= 0x7FFFF; //Zero out all but 18 bits
+					tempLong &=
+						0x7FFFF; //Zero out all but 18 bits
 
-				  sense.IR[sense.head] = tempLong;
-        }
+					sense.IR[sense.head] = tempLong;
+				}
 
-        if (activeDevices > 2)
-        {
-          //Burst read three more bytes - ECG
+				if (activeDevices > 2) {
+					//Burst read three more bytes - ECG
 					int32_t tempLongSigned;
-
-          temp[3] = 0;
-          temp[2] = *p++;
-          temp[1] = *p++;
-          temp[0] = *p++;
+					temp[3] = 0;
+					temp[2] = *p++;
+					temp[1] = *p++;
+					temp[0] = *p++;
 
 					//Serial.println(tempLong);
-          //Convert array to long
-          memcpy(&tempLongSigned, temp, sizeof(tempLongSigned));
-
-		  		//tempLong &= 0x3FFFF; //Zero out all but 18 bits
+					//Convert array to long
+					memcpy(&tempLongSigned,
+					       temp,
+					       sizeof(tempLongSigned));
+					//tempLong &= 0x3FFFF; //Zero out all but 18 bits
+					sense.ecg[sense.head] = tempLongSigned;
+				}
 
-          sense.ecg[sense.head] = tempLongSigned;
-        }
-
-        toGet -= activeDevices * 3;
-      }
-    } //End while (bytesLeftToRead > 0)
-  } //End readPtr != writePtr
-  return (numberOfSamples); //Let the world know how much new data we found
+				bytesLeftToRead -= activeDevices * 3;
+			}
+		}                 //End while (bytesLeftToRead > 0)
+	}                         //End readPtr != writePtr
+	return (numberOfSamples); //Let the world know how much new data we found
 }
 
 //Check for new data but give up after a certain amount of time
 //Returns true if new data was found
 //Returns false if new data was not found
-bool max86150_safeCheck(uint8_t maxTimeToCheck)
+bool max86150_safe_check(uint8_t max_tries)
 {
-  // TODO
-  //uint32_t markTime = millis();
-
-  while(1)
-  {
-	//if(millis() - markTime > maxTimeToCheck) return(false);
+	uint8_t tries = 0;
 
-	if(max86150_check() == true) //We found new data!
-	  return(true);
+	while (tries < max_tries) {
+		if (max86150_check() == true) { //We found new data!
+			return (true);
+		}
 
-	delay(1);
-  }
+		tries++;
+		delay(1);
+	}
+	return false;
 }
 
 //Given a register, read it, mask it, and then set the thing
-void max86150_bitMask(uint8_t reg, uint8_t mask, uint8_t thing)
+void max86150_bit_mask(uint8_t reg, uint8_t mask, uint8_t thing)
 {
-  // Grab current register context
-  uint8_t originalContents = max86150_readRegister8(_i2caddr, reg);
+	// Grab current register context
+	uint8_t originalContents =
+		max86150_read_register(MAX86150_ADDRESS, reg);
 
-  // Zero-out the portions of the register we're interested in
-  originalContents = originalContents & mask;
+	// Zero-out the portions of the register we're interested in
+	originalContents = originalContents & mask;
 
-  // Change contents
-  max86150_writeRegister8(_i2caddr, reg, originalContents | thing);
+	// Change contents
+	max86150_write_register(
+		MAX86150_ADDRESS, reg, originalContents | thing
+	);
 }
 
-uint8_t max86150_readRegister8(uint8_t address, uint8_t reg) {
-
-  uint8_t tempData = 0;
-  uint8_t command[] = {reg};
-  I2C_MasterWrite(MXC_I2C1_BUS0, address << 1, command, 1, 0);
+uint8_t max86150_read_register(uint8_t address, uint8_t reg)
+{
+	uint8_t tempData  = 0;
+	uint8_t command[] = { reg };
+	// Important! true is for repeated start (since we are not reading complete fifo)
+	// See https://os.mbed.com/users/laserdad/code/MAX86150_ECG_PPG//file/3c728f3d1f10/main.cpp/
+	I2C_MasterWrite(MXC_I2C1_BUS0, address << 1, command, 1, true);
 
-  I2C_MasterRead(MXC_I2C1_BUS0, address << 1, &tempData, 1, 0);
+	I2C_MasterRead(MXC_I2C1_BUS0, address << 1, &tempData, 1, 0);
 
-  return tempData;
+	return tempData;
 }
 
-void max86150_writeRegister8(uint8_t address, uint8_t reg, uint8_t value) {
-  uint8_t command[] = {reg, value};
-  I2C_MasterWrite(MXC_I2C1_BUS0, address << 1, command, 2, 0);
+void max86150_write_register(uint8_t address, uint8_t reg, uint8_t value)
+{
+	uint8_t command[] = { reg, value };
+	I2C_MasterWrite(MXC_I2C1_BUS0, address << 1, command, 2, 0);
 }
diff --git a/lib/vendor/Maxim/MAX86150/max86150.h b/lib/vendor/Maxim/MAX86150/max86150.h
index c9454ea51b32d591824e14ea2db2b7735b28735b..66b102183186fe2626aa17b7f62ad33589aa936a 100644
--- a/lib/vendor/Maxim/MAX86150/max86150.h
+++ b/lib/vendor/Maxim/MAX86150/max86150.h
@@ -18,86 +18,115 @@
 #include <stdint.h>
 #include <stdbool.h>
 
-typedef uint8_t byte;
 
-bool max86150_begin(void);
-
-uint32_t max86150_getRed(void); //Returns immediate red value
-uint32_t max86150_getIR(void); //Returns immediate IR value
-int32_t max86150_getECG(void); //Returns immediate ECG value
-bool max86150_safeCheck(uint8_t maxTimeToCheck); //Given a max amount of time, check for new data
-
-// Configuration
-void max86150_softReset();
-void max86150_shutDown();
-void max86150_wakeUp();
+static const uint8_t MAX86150_SAMPLEAVG_1 = 	0b000;
+static const uint8_t MAX86150_SAMPLEAVG_2 = 	0b001;
+static const uint8_t MAX86150_SAMPLEAVG_4 = 	0b010;
+static const uint8_t MAX86150_SAMPLEAVG_8 = 	0b011;
+static const uint8_t MAX86150_SAMPLEAVG_16 = 	0b100;
+static const uint8_t MAX86150_SAMPLEAVG_32 = 	0b101;
+
+static const uint8_t MAX86150_ADCRANGE_4096 = 	0b00000000;
+static const uint8_t MAX86150_ADCRANGE_8192 = 	0b01000000;
+static const uint8_t MAX86150_ADCRANGE_16384 = 	0b10000000;
+static const uint8_t MAX86150_ADCRANGE_32768 = 	0b11000000;
+
+static const uint8_t MAX86150_PPG_SAMPLERATE_10 =	0b00000000;
+static const uint8_t MAX86150_PPG_SAMPLERATE_20 =	0b00000100;
+static const uint8_t MAX86150_PPG_SAMPLERATE_50 =	0b00001000;
+static const uint8_t MAX86150_PPG_SAMPLERATE_84 =	0b00001100;
+static const uint8_t MAX86150_PPG_SAMPLERATE_100 =	0b00010000;
+static const uint8_t MAX86150_PPG_SAMPLERATE_200 =	0b00010100;
+static const uint8_t MAX86150_PPG_SAMPLERATE_400 =	0b00011000;
+static const uint8_t MAX86150_PPG_SAMPLERATE_800 =	0b00011100;
+static const uint8_t MAX86150_PPG_SAMPLERATE_1000 =	0b00100000;
+static const uint8_t MAX86150_PPG_SAMPLERATE_1600 =	0b00100100;
+static const uint8_t MAX86150_PPG_SAMPLERATE_3200 =	0b00101000;
+
+static const uint8_t MAX86150_PPG_PULSEWIDTH_50 =	0b00;
+static const uint8_t MAX86150_PPG_PULSEWIDTH_100 =	0b01;
+static const uint8_t MAX86150_PPG_PULSEWIDTH_200 =	0b10;
+static const uint8_t MAX86150_PPG_PULSEWIDTH_400 =	0b11;
+
+static const uint8_t MAX86150_SLOT_NONE =	0b0000;
+static const uint8_t MAX86150_SLOT_RED_LED =	0b0010;
+static const uint8_t MAX86150_SLOT_IR_LED =	0b0001;
+static const uint8_t MAX86150_SLOT_RED_PILOT =	0b0110;
+static const uint8_t MAX86150_SLOT_IR_PILOT =	0b0101;
+static const uint8_t MAX86150_SLOT_ECG =	0b1001;
+
+static const uint8_t MAX86150_LED1_RANGE_50 =	0b00;
+static const uint8_t MAX86150_LED1_RANGE_100 =	0b01;
+static const uint8_t MAX86150_LED2_RANGE_50 =	0b0000;
+static const uint8_t MAX86150_LED2_RANGE_100 =	0b0100;
+
+static const uint8_t MAX86150_ECG_SAMPLERATE_200 =	0b011;
+static const uint8_t MAX86150_ECG_SAMPLERATE_400 =	0b010;
+static const uint8_t MAX86150_ECG_SAMPLERATE_800 =	0b001;
+static const uint8_t MAX86150_ECG_SAMPLERATE_1600 =	0b000;
+static const uint8_t MAX86150_ECG_SAMPLERATE_3200 =	0b100;
+
+static const uint8_t MAX86150_ECG_PGA_GAIN_1 =		0b0000;
+static const uint8_t MAX86150_ECG_PGA_GAIN_2 =		0b0100;
+static const uint8_t MAX86150_ECG_PGA_GAIN_4 =		0b1000;
+static const uint8_t MAX86150_ECG_PGA_GAIN_8 =		0b1100;
+
+static const uint8_t MAX86150_ECG_IA_GAIN_5 =		0b00;
+static const uint8_t MAX86150_ECG_IA_GAIN_9_5 =		0b01;
+static const uint8_t MAX86150_ECG_IA_GAIN_20 =		0b10;
+static const uint8_t MAX86150_ECG_IA_GAIN_50 =		0b11;
 
-void max86150_setLEDMode(uint8_t mode);
 
-void max86150_setADCRange(uint8_t adcRange);
-void max86150_setSampleRate(uint8_t sampleRate);
-void max86150_setPulseWidth(uint8_t pulseWidth);
 
-void max86150_setPulseAmplitudeRed(uint8_t value);
-void max86150_setPulseAmplitudeIR(uint8_t value);
-void max86150_setPulseAmplitudeProximity(uint8_t value);
-
-void max86150_setProximityThreshold(uint8_t threshMSB);
+bool max86150_begin(void);
 
-//Multi-led configuration mode (page 22)
-void max86150_enableSlot(uint8_t slotNumber, uint8_t device); //Given slot number, assign a device to slot
+uint8_t max86150_get_int1(void);
+uint8_t max86150_get_int2(void);
+
+void max86150_set_int_full(bool enabled);
+void max86150_set_int_datardy(bool enabled);
+void max86150_set_int_ambient_light_overflow(bool enabled);
+void max86150_set_int_proximity(bool enabled);
+
+void max86150_soft_reset(void);
+void max86150_shut_down(void);
+void max86150_wake_up(void);
+void max86150_set_ppg_adc_range(uint8_t adcRange);
+void max86150_set_ppg_sample_rate(uint8_t sampleRate);
+void max86150_set_ppg_pulse_width(uint8_t pulseWidth);
+void max86150_set_led_red_amplitude(uint8_t amplitude);
+void max86150_set_led_ir_amplitude(uint8_t amplitude);
+void max86150_set_led_proximity_amplitude(uint8_t amplitude);
+void max86150_set_proximity_threshold(uint8_t threshMSB);
+void max86150_fifo_enable_slot(uint8_t slotNumber, uint8_t device);
 void max86150_disableSlots(void);
-
-// Data Collection
-
-//Interrupts (page 13, 14)
-uint8_t max86150_getINT1(void); //Returns the main interrupt group
-uint8_t max86150_getINT2(void); //Returns the temp ready interrupt
-void max86150_enableAFULL(void); //Enable/disable individual interrupts
-void max86150_disableAFULL(void);
-void max86150_enableDATARDY(void);
-void max86150_disableDATARDY(void);
-void max86150_enableALCOVF(void);
-void max86150_disableALCOVF(void);
-void max86150_enablePROXINT(void);
-void max86150_disablePROXINT(void);
-void max86150_enableDIETEMPRDY(void);
-void max86150_disableDIETEMPRDY(void);
-
-//FIFO Configuration (page 18)
-void max86150_setFIFOAverage(uint8_t samples);
-void max86150_enableFIFORollover();
-void max86150_disableFIFORollover();
-void max86150_setFIFOAlmostFull(uint8_t samples);
-
-//FIFO Reading
-uint16_t max86150_check(void); //Checks for new data and fills FIFO
-uint8_t max86150_available(void); //Tells caller how many new samples are available (head - tail)
-void max86150_nextSample(void); //Advances the tail of the sense array
-uint32_t max86150_getFIFORed(void); //Returns the FIFO sample pointed to by tail
-uint32_t max86150_getFIFOIR(void); //Returns the FIFO sample pointed to by tail
-int32_t max86150_getFIFOECG(void); //Returns the FIFO sample pointed to by tail
-
-uint8_t max86150_getWritePointer(void);
-uint8_t max86150_getReadPointer(void);
-void max86150_clearFIFO(void); //Sets the read/write pointers to zero
-
-//Proximity Mode Interrupt Threshold
-void max86150_setPROXINTTHRESH(uint8_t val);
-
-// Die Temperature
-float max86150_readTemperature();
-float max86150_readTemperatureF();
-
-// Detecting ID/Revision
-uint8_t max86150_getRevisionID();
-uint8_t max86150_readPartID();
-uint8_t max86150_readRegLED();
-
-// Setup the IC with user selectable settings
-//void max86150_setup(byte powerLevel = 0x1F, byte sampleAverage = 4, byte ledMode = 3, int sampleRate = 400, int pulseWidth = 411, int adcRange = 4096);
-void max86150_setup(byte powerLevel, byte sampleAverage, byte ledMode, int sampleRate, int pulseWidth, int adcRange);
-
-// Low-level I2C communication
-uint8_t max86150_readRegister8(uint8_t address, uint8_t reg);
-void max86150_writeRegister8(uint8_t address, uint8_t reg, uint8_t value);
+void max86150_set_ppg_averaging(uint8_t numberOfSamples);
+void max86150_clear_fifo(void);
+void max86150_set_fifo_rollover(bool enabled);
+void max86150_set_fifo_almost_full_clear(bool enabled);
+void max86150_set_fifo_almost_full_repeat(bool enabled);
+void max86150_set_fifo_almost_full(uint8_t numberOfSamples);
+uint8_t max86150_get_fifo_write_pointer(void);
+uint8_t max86150_get_fifo_read_pointer(void);
+uint8_t max86150_read_part_id();
+void max86150_set_ecg_sample_rate(uint8_t sampleRate);
+void max86150_set_ecg_pga_gain(uint8_t gain);
+void max86150_set_ecg_instrumentation_amplifier_gain(uint8_t gain);
+
+void max86150_setup(const uint8_t ppg_sample_rate);
+
+uint8_t max86150_available(void);
+uint32_t max86150_get_red(void);
+uint32_t max86150_get_ir(void);
+int32_t max86150_get_ecg(void);
+uint32_t max86150_get_fifo_red(void);
+uint32_t max86150_get_fifo_ir(void);
+int32_t max86150_get_fifo_ecg(void);
+void max86150_next_sample(void);
+uint8_t max86150_get_sample(uint32_t *red, uint32_t *ir, int32_t *ecg);
+uint16_t max86150_check(void);
+bool max86150_safe_check(uint8_t max_tries);
+
+void max86150_bit_mask(uint8_t reg, uint8_t mask, uint8_t thing);
+uint8_t max86150_read_register(uint8_t address, uint8_t reg);
+void max86150_write_register(uint8_t address, uint8_t reg, uint8_t value);