From 43e05fc9d549a1aeba191b6e74d1d694d1a6d992 Mon Sep 17 00:00:00 2001 From: schneider <schneider@blinkenlichts.net> Date: Sun, 26 Apr 2020 01:09:22 +0200 Subject: [PATCH] feat(spo2): Add Maxim RD117 pycardium interface --- pycardium/meson.build | 1 + pycardium/modules/qstrdefs.h | 3 ++ pycardium/modules/spo2_algo.c | 83 +++++++++++++++++++++++++++++++++++ pycardium/mpconfigport.h | 1 + 4 files changed, 88 insertions(+) create mode 100644 pycardium/modules/spo2_algo.c diff --git a/pycardium/meson.build b/pycardium/meson.build index d983ab7bb..2bfb09d31 100644 --- a/pycardium/meson.build +++ b/pycardium/meson.build @@ -15,6 +15,7 @@ modsrc = files( 'modules/os.c', 'modules/personal_state.c', 'modules/power.c', + 'modules/spo2_algo.c', 'modules/sys_ble.c', 'modules/sys_bme680.c', 'modules/sys_display.c', diff --git a/pycardium/modules/qstrdefs.h b/pycardium/modules/qstrdefs.h index b145dc118..f842f5344 100644 --- a/pycardium/modules/qstrdefs.h +++ b/pycardium/modules/qstrdefs.h @@ -212,3 +212,6 @@ Q(EVENT_PAIRING_COMPLETE) Q(EVENT_PAIRING_FAILED) Q(EVENT_SCAN_REPORT) +/* SpO2 */ +Q(spo2_algo) +Q(maxim_rd117) diff --git a/pycardium/modules/spo2_algo.c b/pycardium/modules/spo2_algo.c new file mode 100644 index 000000000..c10ae6386 --- /dev/null +++ b/pycardium/modules/spo2_algo.c @@ -0,0 +1,83 @@ +#include "epicardium.h" + +#include "RD117_MBED/algorithm/algorithm.h" +#include "py/builtin.h" +#include "py/obj.h" +#include "py/runtime.h" + +static mp_obj_t +mp_maxim_rd177(mp_obj_t ir, mp_obj_t red) +{ + uint32_t pun_ir_buffer[500]; + uint32_t pun_red_buffer[500]; + int32_t n_ir_buffer_length; + + int32_t pn_spo2 = 0; + int8_t pch_spo2_valid = 0; + int32_t pn_heart_rate = 0; + int8_t pch_hr_valid = 0; + + size_t ir_len; + mp_obj_t *ir_elem; + mp_obj_get_array(ir, &ir_len, &ir_elem); + + if (ir_len < 100 || ir_len > 500) { + nlr_raise(mp_obj_new_exception_msg_varg( + &mp_type_TypeError, + "rd177 needs a tuple of length 100 to 500 (%d given)", + ir_len) + ); + } + + size_t red_len; + mp_obj_t *red_elem; + mp_obj_get_array(red, &red_len, &red_elem); + + if (red_len != ir_len) { + nlr_raise(mp_obj_new_exception_msg_varg( + &mp_type_TypeError, + "Length of ir and red data needs to be equal") + ); + } + + n_ir_buffer_length = ir_len; + for(size_t i=0; i<ir_len; i++) { + pun_ir_buffer[i] = mp_obj_get_int(ir_elem[i]); + pun_red_buffer[i] = mp_obj_get_int(red_elem[i]); + } + + maxim_heart_rate_and_oxygen_saturation(pun_ir_buffer, n_ir_buffer_length, pun_red_buffer, &pn_spo2, &pch_spo2_valid, &pn_heart_rate, &pch_hr_valid); + + mp_obj_t spo2 = mp_obj_new_int(pn_spo2); + mp_obj_t hr = mp_obj_new_int(pn_heart_rate); + mp_obj_t spo2_valid = mp_obj_new_int(pch_spo2_valid); + mp_obj_t hr_valid = mp_obj_new_int(pch_hr_valid); + + mp_obj_t tup[] = { + spo2, + spo2_valid, + hr, + hr_valid + }; + + return mp_obj_new_tuple(4, tup); +} +static MP_DEFINE_CONST_FUN_OBJ_2(maxim_rd117, mp_maxim_rd177); + +static const mp_rom_map_elem_t spo2_algo_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_spo2_algo) }, + { MP_ROM_QSTR(MP_QSTR_maxim_rd117), MP_ROM_PTR(&maxim_rd117) }, +}; +static MP_DEFINE_CONST_DICT( + spo2_algo_module_globals, spo2_algo_module_globals_table +); + +// Define module object. +const mp_obj_module_t spo2_algo_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&spo2_algo_module_globals, +}; + +/* Register the module to make it available in Python */ +/* clang-format off */ +MP_REGISTER_MODULE(MP_QSTR_spo2_algo, spo2_algo_module, MODULE_SPO2_ALGO_ENABLED); diff --git a/pycardium/mpconfigport.h b/pycardium/mpconfigport.h index 4dd6aa129..c9f687ac4 100644 --- a/pycardium/mpconfigport.h +++ b/pycardium/mpconfigport.h @@ -68,6 +68,7 @@ int mp_hal_csprng_read_int(void); #define MODULE_OS_ENABLED (1) #define MODULE_PERSONAL_STATE_ENABLED (1) #define MODULE_POWER_ENABLED (1) +#define MODULE_SPO2_ALGO_ENABLED (1) #define MODULE_UTIME_ENABLED (1) #define MODULE_VIBRA_ENABLED (1) #define MODULE_WS2812_ENABLED (1) -- GitLab