From f7b5abefbd43b096f7717871325c781d82b98ba3 Mon Sep 17 00:00:00 2001
From: Arist <aristkojevnikov@gmail.com>
Date: Sun, 2 Feb 2020 20:39:07 +0100
Subject: [PATCH] test(max86150): MAX86150 Epicardium API

---
 l0dables/meson.build      |   1 +
 l0dables/spo2/README.md   |   5 ++
 l0dables/spo2/main.c      | 147 ++++++++++++++++++++++++++++++++++++++
 l0dables/spo2/meson.build |  13 ++++
 4 files changed, 166 insertions(+)
 create mode 100644 l0dables/spo2/README.md
 create mode 100644 l0dables/spo2/main.c
 create mode 100644 l0dables/spo2/meson.build

diff --git a/l0dables/meson.build b/l0dables/meson.build
index f4be10b5..bf73b2b2 100644
--- a/l0dables/meson.build
+++ b/l0dables/meson.build
@@ -1,3 +1,4 @@
 subdir('lib/')
 
 subdir('blinky/')
+subdir('spo2/')
diff --git a/l0dables/spo2/README.md b/l0dables/spo2/README.md
new file mode 100644
index 00000000..65375d18
--- /dev/null
+++ b/l0dables/spo2/README.md
@@ -0,0 +1,5 @@
+SpO2
+======
+
+This l0adable displays a histogram of the MAX86150 red LED level (with DC offset removed)
+later versions should be able to calculate the blood oxigen saturation
diff --git a/l0dables/spo2/main.c b/l0dables/spo2/main.c
new file mode 100644
index 00000000..0773ed21
--- /dev/null
+++ b/l0dables/spo2/main.c
@@ -0,0 +1,147 @@
+#include "epicardium.h"
+
+#include "max32665.h"
+#include <mxc_delay.h>
+#include <math.h>
+#include <stdio.h>
+// #include <stdint.h>
+#include <stdlib.h>
+
+#define WIDTH 160
+#define HEIGHT 80
+
+#define Y_OFFSET 36
+#define Y_SCALE 35
+
+void delay_us(unsigned long delay)
+{
+	mxc_delay_start(delay);
+	while (mxc_delay_check()) {
+		__WFI();
+	}
+	mxc_delay_stop();
+}
+/*
+ * main() is called when l0dable is loaded and executed.
+ */
+int main(void)
+{
+	struct max86150_sensor_config cfg = { 0 };
+	cfg.sample_buffer_len             = 128;
+	cfg.ppg_sample_rate               = 200;
+
+	int sensor_stream = epic_max86150_enable_sensor(&cfg, sizeof(cfg));
+	struct max86150_sensor_data data_buf[cfg.sample_buffer_len], data;
+
+	epic_disp_open();
+	double history[WIDTH];
+	uint8_t history_pos = 0;
+	double history_max  = 0;
+
+	double history_max_avg[10];
+	uint8_t history_max_pos = 0;
+
+	int32_t last_sample   = 0;
+	double filtered_value = 0;
+
+	int32_t avg[10];
+	uint8_t avg_pos = 0;
+
+	// union disp_framebuffer fb;
+
+	// char *str = "             ";
+
+	for (;;) {
+		int ret = epic_stream_read(
+			sensor_stream, &data_buf, sizeof(data_buf)
+		);
+
+		if (ret > 0) {
+			for (int i = 0; i < ret; i++) {
+				data = data_buf[i];
+
+				avg[avg_pos] = data.red;
+				if (avg_pos < 9) {
+					avg_pos++;
+				} else {
+					avg_pos = 0;
+				}
+
+				int32_t avg_data = 0;
+				for (int a = 0; a < 10; a++) {
+					avg_data += avg[a];
+				}
+				avg_data = avg_data / 10;
+
+				// DC offset removal
+				filtered_value = 0.9 * (filtered_value +
+							(double)avg_data -
+							(double)last_sample);
+				last_sample    = avg_data;
+
+				history[history_pos] = filtered_value;
+				//history[history_pos] = data.red;
+				if (history_pos < WIDTH - 1) {
+					history_pos++;
+				} else {
+					history_pos = 0;
+				}
+
+				//delay_us(10000);
+			}
+
+			epic_disp_clear(0);
+
+			//sprintf(str, "%10ld", data.red);
+			//epic_disp_print(10,10,str,0xFFFF,0);
+
+			history_max = 0;
+			for (int i = 0; i < WIDTH; i++) {
+				if (fabs(history[i]) > history_max) {
+					history_max = fabs(history[i]);
+				}
+			}
+			if (history_max <= 0) {
+				history_max = 1;
+			}
+
+			history_max_avg[history_max_pos] = history_max;
+			if (history_max_pos < 9) {
+				history_max_pos++;
+			} else {
+				history_max_pos = 0;
+			}
+
+			history_max = 0;
+			for (int a = 0; a < 9; a++) {
+				history_max += history_max_avg[a];
+			}
+			history_max = history_max / 10;
+
+			int32_t scale = history_max / Y_SCALE + 1;
+
+			for (int i = history_pos; i < WIDTH + history_pos;
+			     i++) {
+				//epic_disp_pixel(history_pos, HEIGHT-10, 0xFFFF);
+				if (i <= WIDTH) {
+					epic_disp_pixel(
+						i - history_pos,
+						(history[i] / scale) + Y_OFFSET,
+						0xFFFF
+					);
+				} else {
+					epic_disp_pixel(
+						i - history_pos,
+						(history[i - WIDTH] / scale) +
+							Y_OFFSET,
+						0xFFFF);
+				}
+			}
+
+			epic_disp_update();
+		}
+		//mxc_delay(1000);
+	}
+
+	//epic_disp_close();
+}
diff --git a/l0dables/spo2/meson.build b/l0dables/spo2/meson.build
new file mode 100644
index 00000000..0ff4d21f
--- /dev/null
+++ b/l0dables/spo2/meson.build
@@ -0,0 +1,13 @@
+name = 'spo2'
+
+elf = executable(
+  name + '.elf',
+  'main.c',
+  build_by_default: true,
+  dependencies: [l0dable_startup, api_caller],
+  link_whole: [l0dable_startup_lib],
+  link_args: [
+    '-Wl,-Map=' + meson.current_build_dir() + '/' + name + '.map,-lgcc',
+  ],
+  pie: true,
+)
-- 
GitLab