mirror of
https://github.com/espruino/Espruino.git
synced 2025-12-08 19:06:15 +00:00
96 lines
3.5 KiB
C
96 lines
3.5 KiB
C
/*
|
|
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
|
|
*
|
|
* Copyright (C) 2021 Gordon Williams <gw@pur3.co.uk>
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* ----------------------------------------------------------------------------
|
|
* heart rate monitoring using VC31 proprietary binary blob
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
#include "heartrate.h"
|
|
#include "hrm_vc31.h"
|
|
#include "hrm.h"
|
|
#include "jshardware.h"
|
|
#include "jsinteractive.h"
|
|
#include "vc31_binary/algo.h"
|
|
|
|
HrmInfo hrmInfo;
|
|
|
|
/// Initialise heart rate monitoring
|
|
void hrm_init() {
|
|
memset(&hrmInfo, 0, sizeof(hrmInfo));
|
|
hrmInfo.isWorn = false;
|
|
hrmInfo.lastPPGTime = jshGetSystemTime();
|
|
hrmInfo.sportMode = SPORT_TYPE_NORMAL;
|
|
}
|
|
|
|
/// Add new heart rate value
|
|
bool hrm_new(int ppgValue, Vector3 *acc) {
|
|
// work out time passed since last sample (it might not be exactly hrmUpdateInterval)
|
|
JsSysTime time = jshGetSystemTime();
|
|
int timeDiff = (int)(jshGetMillisecondsFromTime(time-hrmInfo.lastPPGTime)+0.5);
|
|
hrmInfo.lastPPGTime = time;
|
|
// if we've just started wearing again, reset the algorithm
|
|
if (vcInfo.isWearing && !hrmInfo.isWorn) {
|
|
hrmInfo.isWorn = true;
|
|
// initialise VC31 algorithm (should do when going from wearing to not wearing)
|
|
Algo_Init();
|
|
hrmInfo.lastHRM = 0;
|
|
hrmInfo.lastConfidence = 0;
|
|
hrmInfo.msSinceLastHRM = 0;
|
|
hrmInfo.avg = ppgValue;
|
|
} else {
|
|
hrmInfo.isWorn = vcInfo.isWearing;
|
|
if (!hrmInfo.isWorn) return false;
|
|
}
|
|
int f = (ppgValue-hrmInfo.avg)*256;
|
|
if (f < HRMVALUE_MIN) f = HRMVALUE_MIN;
|
|
if (f > HRMVALUE_MAX) f = HRMVALUE_MAX;
|
|
hrmInfo.filtered = f;
|
|
hrmInfo.avg = ((int)hrmInfo.avg*7 + ppgValue) >> 3;
|
|
if (ppgValue<HRMVALUE_MIN) ppgValue=HRMVALUE_MIN;
|
|
if (ppgValue>HRMVALUE_MAX) ppgValue=HRMVALUE_MAX;
|
|
hrmInfo.raw = ppgValue;
|
|
// Feed data into algorithm
|
|
AlgoInputData_t inputData;
|
|
inputData.axes.x = acc->y >> 5; // perpendicular to the direction of the arm
|
|
inputData.axes.y = acc->x >> 5; // along the direction of the arm
|
|
inputData.axes.z = acc->z >> 5;
|
|
inputData.ppgSample = vcInfo.ppgValue | (vcInfo.wasAdjusted ? 0x1000 : 0);
|
|
inputData.envSample = vcInfo.envValue;
|
|
hrmInfo.msSinceLastHRM += timeDiff;
|
|
Algo_Input(&inputData, timeDiff, hrmInfo.sportMode, 0/*surfaceRecogMode*/,0/*opticalAidMode*/);
|
|
AlgoOutputData_t outputData;
|
|
Algo_Output(&outputData);
|
|
//jsiConsolePrintf("HRM %d %d %d\n", outputData.hrData, outputData.reliability, hrmInfo.msSinceLastHRM);
|
|
if (outputData.hrData!=hrmInfo.lastHRM ||
|
|
outputData.reliability!=hrmInfo.lastConfidence ||
|
|
((hrmInfo.msSinceLastHRM > 2000) && outputData.hrData && outputData.reliability)) {
|
|
// update when figures change OR when 2 secs have passed (readings are usually every 1 sec)
|
|
hrmInfo.lastConfidence = outputData.reliability;
|
|
hrmInfo.lastHRM = outputData.hrData;
|
|
hrmInfo.bpm10 = 10 * outputData.hrData;
|
|
hrmInfo.confidence = outputData.reliability;
|
|
hrmInfo.msSinceLastHRM = 0;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// Append extra information to an existing HRM event object
|
|
void hrm_get_hrm_info(JsVar *o) {
|
|
NOT_USED(o);
|
|
}
|
|
|
|
// Append extra information to an existing HRM-raw event object
|
|
void hrm_get_hrm_raw_info(JsVar *o) {
|
|
} |