From a907a06e437b0fc01f55c1229750b0931a0660d1 Mon Sep 17 00:00:00 2001
From: koalo <koalo@koalo.de>
Date: Wed, 21 Aug 2019 17:57:47 +0200
Subject: [PATCH] feat(bhi160): Provide accelerometer samples for MicroPython

---
 pycardium/modules/bhi160-sys.c | 59 +++++++++++++++++++++++++++++++++-
 pycardium/modules/py/bhi160.py | 18 +++++++++++
 pycardium/modules/qstrdefs.h   |  4 +++
 3 files changed, 80 insertions(+), 1 deletion(-)

diff --git a/pycardium/modules/bhi160-sys.c b/pycardium/modules/bhi160-sys.c
index 35d81b25..49c70b51 100644
--- a/pycardium/modules/bhi160-sys.c
+++ b/pycardium/modules/bhi160-sys.c
@@ -5,6 +5,15 @@
 #include "api/common.h"
 #include "mphalport.h"
 
+extern const mp_obj_type_t mp_type_bhi160_sample;
+
+typedef struct _bhi160_sample_obj_t {
+	mp_obj_base_t base;
+	int x;
+	int y;
+	int z;
+} bhi160_sample_obj_t;
+
 STATIC mp_obj_t mp_bhi160_enable_sensor(size_t n_args, const mp_obj_t *args)
 {
 	int sensor_type = mp_obj_get_int(args[0]);
@@ -30,8 +39,56 @@ STATIC mp_obj_t mp_bhi160_read_sensor(mp_obj_t stream_id_in)
 
 	int n = epic_stream_read(sd, buf, sizeof(buf));
 
-	return MP_OBJ_NEW_SMALL_INT(n);
+	mp_obj_list_t *list = mp_obj_new_list(0, NULL);
+	for (int i = 0; i < n; i++) {
+		bhi160_sample_obj_t *o = m_new_obj(bhi160_sample_obj_t);
+		o->base.type           = &mp_type_bhi160_sample;
+		o->x                   = buf[i].x;
+		o->y                   = buf[i].y;
+		o->z                   = buf[i].z;
+
+		mp_obj_list_append(list, MP_OBJ_FROM_PTR(o));
+	}
+
+	return MP_OBJ_FROM_PTR(list);
+}
+
+STATIC mp_obj_t mp_bhi160_x(mp_obj_t type)
+{
+	bhi160_sample_obj_t *self = MP_OBJ_TO_PTR(type);
+	return MP_OBJ_NEW_SMALL_INT(self->x);
+}
+static MP_DEFINE_CONST_FUN_OBJ_1(mp_bhi160_x_obj, mp_bhi160_x);
+
+STATIC mp_obj_t mp_bhi160_y(mp_obj_t type)
+{
+	bhi160_sample_obj_t *self = MP_OBJ_TO_PTR(type);
+	return MP_OBJ_NEW_SMALL_INT(self->y);
 }
+static MP_DEFINE_CONST_FUN_OBJ_1(mp_bhi160_y_obj, mp_bhi160_y);
+
+STATIC mp_obj_t mp_bhi160_z(mp_obj_t type)
+{
+	bhi160_sample_obj_t *self = MP_OBJ_TO_PTR(type);
+	return MP_OBJ_NEW_SMALL_INT(self->z);
+}
+static MP_DEFINE_CONST_FUN_OBJ_1(mp_bhi160_z_obj, mp_bhi160_z);
+
+STATIC const mp_rom_map_elem_t bhi160_sample_locals_dict_table[] = {
+	{ MP_ROM_QSTR(MP_QSTR_x), MP_ROM_PTR(&mp_bhi160_x_obj) },
+	{ MP_ROM_QSTR(MP_QSTR_y), MP_ROM_PTR(&mp_bhi160_y_obj) },
+	{ MP_ROM_QSTR(MP_QSTR_z), MP_ROM_PTR(&mp_bhi160_z_obj) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(
+	bhi160_sample_locals_dict, bhi160_sample_locals_dict_table
+);
+
+const mp_obj_type_t mp_type_bhi160_sample = {
+	{ &mp_type_type },
+	.name        = MP_QSTR_BHI160Sample,
+	.locals_dict = (mp_obj_dict_t *)&bhi160_sample_locals_dict,
+};
 
 STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(
 	mp_bhi160_enable_sensor_obj, 4, 4, mp_bhi160_enable_sensor
diff --git a/pycardium/modules/py/bhi160.py b/pycardium/modules/py/bhi160.py
index 4d13895f..a4eb371e 100644
--- a/pycardium/modules/py/bhi160.py
+++ b/pycardium/modules/py/bhi160.py
@@ -30,6 +30,24 @@ class BHI160Accelerometer:
             interrupt.disable_callback(interrupt.BHI160_ACCELEROMETER)
             interrupt.set_callback(interrupt.BHI160_ACCELEROMETER, None)
 
+    def convert(self, value):
+        return 2 * value / 32768.0
+
+    def read(self):
+        result = []
+        if self.acc_sd is not None:
+            for sample in sys_bhi160.read_sensor(self.acc_sd):
+                result.append(
+                    dict(
+                        {
+                            "x": self.convert(sample.x()),
+                            "y": self.convert(sample.y()),
+                            "z": self.convert(sample.z()),
+                        }
+                    )
+                )
+        return result
+
     def _accelerometer_interrupt(self, _):
         if self.acc_sd is not None:
             data = sys_bhi160.read_sensor(self.acc_sd)
diff --git a/pycardium/modules/qstrdefs.h b/pycardium/modules/qstrdefs.h
index 4d9ff17a..84bd55b9 100644
--- a/pycardium/modules/qstrdefs.h
+++ b/pycardium/modules/qstrdefs.h
@@ -64,6 +64,10 @@ Q(RTC_ALARM)
 Q(sys_bhi160)
 Q(enable_sensor)
 Q(read_sensor)
+Q(BHI160Sample)
+Q(x)
+Q(y)
+Q(z)
 
 /* display */
 Q(sys_display)
-- 
GitLab