repo time

Dependencies:   mbed MAX14720 MAX30205 USBDevice

Committer:
darienf
Date:
Tue Apr 06 06:41:40 2021 +0000
Revision:
20:6d2af70c92ab
another repo

Who changed what in which revision?

UserRevisionLine numberNew contents of line
darienf 20:6d2af70c92ab 1 /*******************************************************************************
darienf 20:6d2af70c92ab 2 * Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
darienf 20:6d2af70c92ab 3 *
darienf 20:6d2af70c92ab 4 * This software is protected by copyright laws of the United States and
darienf 20:6d2af70c92ab 5 * of foreign countries. This material may also be protected by patent laws
darienf 20:6d2af70c92ab 6 * and technology transfer regulations of the United States and of foreign
darienf 20:6d2af70c92ab 7 * countries. This software is furnished under a license agreement and/or a
darienf 20:6d2af70c92ab 8 * nondisclosure agreement and may only be used or reproduced in accordance
darienf 20:6d2af70c92ab 9 * with the terms of those agreements. Dissemination of this information to
darienf 20:6d2af70c92ab 10 * any party or parties not specified in the license agreement and/or
darienf 20:6d2af70c92ab 11 * nondisclosure agreement is expressly prohibited.
darienf 20:6d2af70c92ab 12 *
darienf 20:6d2af70c92ab 13 * The above copyright notice and this permission notice shall be included
darienf 20:6d2af70c92ab 14 * in all copies or substantial portions of the Software.
darienf 20:6d2af70c92ab 15 *
darienf 20:6d2af70c92ab 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
darienf 20:6d2af70c92ab 17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
darienf 20:6d2af70c92ab 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
darienf 20:6d2af70c92ab 19 * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
darienf 20:6d2af70c92ab 20 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
darienf 20:6d2af70c92ab 21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
darienf 20:6d2af70c92ab 22 * OTHER DEALINGS IN THE SOFTWARE.
darienf 20:6d2af70c92ab 23 *
darienf 20:6d2af70c92ab 24 * Except as contained in this notice, the name of Maxim Integrated
darienf 20:6d2af70c92ab 25 * Products, Inc. shall not be used except as stated in the Maxim Integrated
darienf 20:6d2af70c92ab 26 * Products, Inc. Branding Policy.
darienf 20:6d2af70c92ab 27 *
darienf 20:6d2af70c92ab 28 * The mere transfer of this software does not imply any licenses
darienf 20:6d2af70c92ab 29 * of trade secrets, proprietary technology, copyrights, patents,
darienf 20:6d2af70c92ab 30 * trademarks, maskwork rights, or any other form of intellectual
darienf 20:6d2af70c92ab 31 * property whatsoever. Maxim Integrated Products, Inc. retains all
darienf 20:6d2af70c92ab 32 * ownership rights.
darienf 20:6d2af70c92ab 33 *******************************************************************************
darienf 20:6d2af70c92ab 34 */
darienf 20:6d2af70c92ab 35
darienf 20:6d2af70c92ab 36 using System;
darienf 20:6d2af70c92ab 37 using System.Collections;
darienf 20:6d2af70c92ab 38 using System.Collections.Generic;
darienf 20:6d2af70c92ab 39 using System.Linq;
darienf 20:6d2af70c92ab 40 using System.Text;
darienf 20:6d2af70c92ab 41
darienf 20:6d2af70c92ab 42 //------------------------------------------------------------------------------------------
darienf 20:6d2af70c92ab 43 // OS24EVK-59 split into HeartRateApp EXE and MAX30101 DLL.
darienf 20:6d2af70c92ab 44 // Moved all MAX30101 DLL classes into namespace Maxim.MAX30101GUI
darienf 20:6d2af70c92ab 45 // Moved all HeartRateApp GUI classes into namespace Maxim.MAX30101
darienf 20:6d2af70c92ab 46 // OS24EVK-59 Create separate project that builds Maxim.MAX30101GUI DLL library
darienf 20:6d2af70c92ab 47
darienf 20:6d2af70c92ab 48 namespace Maxim.MAX30101GUI
darienf 20:6d2af70c92ab 49 {
darienf 20:6d2af70c92ab 50 /// <summary>
darienf 20:6d2af70c92ab 51 /// Encapsulate the Maxim SKA Algorithm
darienf 20:6d2af70c92ab 52 /// </summary>
darienf 20:6d2af70c92ab 53 public class MaximSKAlgorithmClass : MaximAlgorithmClass
darienf 20:6d2af70c92ab 54 {
darienf 20:6d2af70c92ab 55 public MaximSKAlgorithmClass()
darienf 20:6d2af70c92ab 56 {
darienf 20:6d2af70c92ab 57 // https://jira.maxim-ic.com/browse/OS24EVK-40 remove "algorithm" from algorithm names
darienf 20:6d2af70c92ab 58 // https://jira.maxim-ic.com/browse/OS24EVK-45 Rename PBA / SKA algorithms
darienf 20:6d2af70c92ab 59 Name = "Maxim Example Algorithm 2 [SKA.dll]";
darienf 20:6d2af70c92ab 60 }
darienf 20:6d2af70c92ab 61
darienf 20:6d2af70c92ab 62 // https://jira.maxim-ic.com/browse/OS24EVK-15 any SKA dependencies? e.g. init MaximSKAlgorithmClass._cboPulseWidthIndex from (byte)(cboPulseWidth.SelectedIndex)
darienf 20:6d2af70c92ab 63 // public byte _cboPulseWidthIndex = 0;
darienf 20:6d2af70c92ab 64
darienf 20:6d2af70c92ab 65 // Steve Koh's variables
darienf 20:6d2af70c92ab 66 int _heartRateBPMint; // alias HR
darienf 20:6d2af70c92ab 67 float _spO2Percentfloat; // alias fSPO2
darienf 20:6d2af70c92ab 68
darienf 20:6d2af70c92ab 69 const int _SKA_windowSize = 100;
darienf 20:6d2af70c92ab 70 const int _SKA_bufferSize = 500;
darienf 20:6d2af70c92ab 71 // https://jira.maxim-ic.com/browse/OS24EVK-15 MaximSKAlgorithmClass accumulate irBuf[0..] _SKA_bufferSize for SKA.SKA_work
darienf 20:6d2af70c92ab 72 int[] irBuf = new int[_SKA_bufferSize];
darienf 20:6d2af70c92ab 73 int[] redBuf = new int[_SKA_bufferSize];
darienf 20:6d2af70c92ab 74 int[] greenBuf = new int[_SKA_bufferSize];
darienf 20:6d2af70c92ab 75 // https://jira.maxim-ic.com/browse/OS24EVK-35 Support HR from Green LED (SKA)
darienf 20:6d2af70c92ab 76 ArrayList _SKA_IRList = new ArrayList();
darienf 20:6d2af70c92ab 77 ArrayList _SKA_tempIRList = new ArrayList();
darienf 20:6d2af70c92ab 78 ArrayList _SKA_redList = new ArrayList();
darienf 20:6d2af70c92ab 79 ArrayList _SKA_tempRedList = new ArrayList();
darienf 20:6d2af70c92ab 80 ArrayList _SKA_greenList = new ArrayList();
darienf 20:6d2af70c92ab 81 ArrayList _SKA_tempGreenList = new ArrayList();
darienf 20:6d2af70c92ab 82 int _SKA_numSamplesSinceLastCalc;
darienf 20:6d2af70c92ab 83 int _SKA_elapsedSecond;
darienf 20:6d2af70c92ab 84 //int _SKA_validHRcount;
darienf 20:6d2af70c92ab 85 //int _SKA_invalidHRcount;
darienf 20:6d2af70c92ab 86 //int _SKA_validSPO2count;
darienf 20:6d2af70c92ab 87 //int _SKA_invalidSPO2count;
darienf 20:6d2af70c92ab 88 //int _SKA_lastValidHRtimestamp;
darienf 20:6d2af70c92ab 89 //int _SKA_lastValidSPO2timestamp;
darienf 20:6d2af70c92ab 90 // diagnostic: output from SKA algorithm filtering
darienf 20:6d2af70c92ab 91 float[] irAcBuf = new float[100];
darienf 20:6d2af70c92ab 92 float[] redAcBuf = new float[100];
darienf 20:6d2af70c92ab 93 // end of Steve Koh's variables
darienf 20:6d2af70c92ab 94
darienf 20:6d2af70c92ab 95 /// <summary>
darienf 20:6d2af70c92ab 96 /// Clear any internal class members,
darienf 20:6d2af70c92ab 97 /// in response to startMonitorToolStripMenuItem
darienf 20:6d2af70c92ab 98 /// </summary>
darienf 20:6d2af70c92ab 99 override public void Clear()
darienf 20:6d2af70c92ab 100 {
darienf 20:6d2af70c92ab 101 _SKA_elapsedSecond = 1;
darienf 20:6d2af70c92ab 102 //_SKA_lastValidHRtimestamp = 1;
darienf 20:6d2af70c92ab 103 //_SKA_lastValidSPO2timestamp = 1;
darienf 20:6d2af70c92ab 104 //_SKA_validHRcount = 0;
darienf 20:6d2af70c92ab 105 //_SKA_invalidHRcount = 0;
darienf 20:6d2af70c92ab 106 //_SKA_validSPO2count = 0;
darienf 20:6d2af70c92ab 107 //_SKA_invalidSPO2count = 0;
darienf 20:6d2af70c92ab 108
darienf 20:6d2af70c92ab 109 _SKA_IRList = new ArrayList();
darienf 20:6d2af70c92ab 110 _SKA_tempIRList = new ArrayList();
darienf 20:6d2af70c92ab 111 _SKA_redList = new ArrayList();
darienf 20:6d2af70c92ab 112 _SKA_tempRedList = new ArrayList();
darienf 20:6d2af70c92ab 113 _SKA_greenList = new ArrayList();
darienf 20:6d2af70c92ab 114 _SKA_tempGreenList = new ArrayList();
darienf 20:6d2af70c92ab 115 _SKA_numSamplesSinceLastCalc = 0;
darienf 20:6d2af70c92ab 116 // https://jira.maxim-ic.com/browse/OS24EVK-15 SKA need preload _SKA_IRList _SKA_bufferSize in startMonitorToolStripMenuItem_Click
darienf 20:6d2af70c92ab 117 for (int index = 0; index < _SKA_bufferSize; index++)
darienf 20:6d2af70c92ab 118 {
darienf 20:6d2af70c92ab 119 _SKA_IRList.Add(0);
darienf 20:6d2af70c92ab 120 _SKA_redList.Add(0);
darienf 20:6d2af70c92ab 121 _SKA_greenList.Add(0);
darienf 20:6d2af70c92ab 122 }
darienf 20:6d2af70c92ab 123 }
darienf 20:6d2af70c92ab 124
darienf 20:6d2af70c92ab 125 /// <summary>
darienf 20:6d2af70c92ab 126 /// <para>InterfaceRedIRGreenLEDdataConsumer</para>
darienf 20:6d2af70c92ab 127 /// <para>Producer-Consumer data sink for
darienf 20:6d2af70c92ab 128 /// raw Red/IR/Green LED data.
darienf 20:6d2af70c92ab 129 /// Produced by MAX30101, consumed by algorithm.
darienf 20:6d2af70c92ab 130 /// </para>
darienf 20:6d2af70c92ab 131 /// </summary>
darienf 20:6d2af70c92ab 132 /// <param name="sampleNumber"></param>
darienf 20:6d2af70c92ab 133 /// <param name="rawIR"></param>
darienf 20:6d2af70c92ab 134 /// <param name="rawRed"></param>
darienf 20:6d2af70c92ab 135 /// <param name="rawGreen"></param>
darienf 20:6d2af70c92ab 136 /// <param name="rawIRvalid"></param>
darienf 20:6d2af70c92ab 137 /// <param name="rawRedvalid"></param>
darienf 20:6d2af70c92ab 138 /// <param name="rawGreenvalid"></param>
darienf 20:6d2af70c92ab 139 override public void ConsumeRedIRGreenLEDdata(
darienf 20:6d2af70c92ab 140 int sampleNumber,
darienf 20:6d2af70c92ab 141 int rawIR,
darienf 20:6d2af70c92ab 142 int rawRed,
darienf 20:6d2af70c92ab 143 int rawGreen,
darienf 20:6d2af70c92ab 144 bool rawIRvalid,
darienf 20:6d2af70c92ab 145 bool rawRedvalid,
darienf 20:6d2af70c92ab 146 bool rawGreenvalid
darienf 20:6d2af70c92ab 147 )
darienf 20:6d2af70c92ab 148 {
darienf 20:6d2af70c92ab 149 base.ConsumeRedIRGreenLEDdata(sampleNumber, rawIR, rawRed, rawGreen, rawIRvalid, rawRedvalid, rawGreenvalid);
darienf 20:6d2af70c92ab 150
darienf 20:6d2af70c92ab 151 bool valid_IR = rawIRvalid;
darienf 20:6d2af70c92ab 152 bool valid_Red = rawRedvalid;
darienf 20:6d2af70c92ab 153 bool valid_Green = rawGreenvalid;
darienf 20:6d2af70c92ab 154 // https://jira.maxim-ic.com/browse/OS24EVK-25 SpO2 mode if LED mode and Red and IR data
darienf 20:6d2af70c92ab 155 bool HRvalid = (valid_Red || valid_Green);
darienf 20:6d2af70c92ab 156 bool SPO2valid = (valid_Red && valid_IR);
darienf 20:6d2af70c92ab 157 //
darienf 20:6d2af70c92ab 158 // example: https://jira.maxim-ic.com/browse/OS24EVK-37 SpO2 Temperature Compensation
darienf 20:6d2af70c92ab 159 #region SpO2_Temperature_Compensation
darienf 20:6d2af70c92ab 160 // SpO2 Temperature Compensation (See MAX30101 data sheet, Applications Information)
darienf 20:6d2af70c92ab 161 // Estimate red LED temperature rise from peak current and pulse width configuration settings,
darienf 20:6d2af70c92ab 162 // then use estimated red LED temperature to estimate actual red LED wavelength.
darienf 20:6d2af70c92ab 163 //
darienf 20:6d2af70c92ab 164 // double red_LED_temperature_delta = lookup table from peak current and duty cycle
darienf 20:6d2af70c92ab 165 // See MAX30101 data sheet Table 13. RED LED Current Settings vs LED Temperature Rise
darienf 20:6d2af70c92ab 166 //
darienf 20:6d2af70c92ab 167 // double red_LED_temperatureDegreesC = base._temperatureDegreesC + red_LED_temperature_delta;
darienf 20:6d2af70c92ab 168 //
darienf 20:6d2af70c92ab 169 // double red_LED_wavelength = lookup table from red_LED_temperatureDegreesC
darienf 20:6d2af70c92ab 170 // See MAX30101 data sheet toc10 RED LED PEAK WAVELENGTH vs TEMPERATURE
darienf 20:6d2af70c92ab 171 //
darienf 20:6d2af70c92ab 172 #endregion SpO2_Temperature_Compensation
darienf 20:6d2af70c92ab 173
darienf 20:6d2af70c92ab 174 double heartRateBPM; // = (double)heartRateBPMint
darienf 20:6d2af70c92ab 175 bool heartRateBPMValid = false;
darienf 20:6d2af70c92ab 176 double heartRateBPMSignalStrength = 0;
darienf 20:6d2af70c92ab 177 double spO2Percent; // = (double)spO2Percentfloat
darienf 20:6d2af70c92ab 178 bool spO2PercentValid = false;
darienf 20:6d2af70c92ab 179 double spO2PercentSignalStrength = 0; // = (double)SPO2error
darienf 20:6d2af70c92ab 180 float SPO2error = 0;
darienf 20:6d2af70c92ab 181 // https://jira.maxim-ic.com/browse/OS24EVK-15 move SKA algorithm into MaximSKAlgorithmClass
darienf 20:6d2af70c92ab 182
darienf 20:6d2af70c92ab 183 // https://jira.maxim-ic.com/browse/OS24EVK-15 MaximSKAlgorithmClass accumulate irBuf[0..] _SKA_bufferSize for SKA.SKA_work
darienf 20:6d2af70c92ab 184 // int[] irBuf = new int[_SKA_bufferSize];
darienf 20:6d2af70c92ab 185 // int[] redBuf = new int[_SKA_bufferSize];
darienf 20:6d2af70c92ab 186 for (int index = 0; index < _SKA_tempRedList.Count; index++)
darienf 20:6d2af70c92ab 187 {
darienf 20:6d2af70c92ab 188 _SKA_IRList.Add((int)_SKA_tempIRList[index]);
darienf 20:6d2af70c92ab 189 _SKA_IRList.RemoveAt(0);
darienf 20:6d2af70c92ab 190 _SKA_redList.Add((int)_SKA_tempRedList[index]);
darienf 20:6d2af70c92ab 191 _SKA_redList.RemoveAt(0);
darienf 20:6d2af70c92ab 192 _SKA_greenList.Add((int)_SKA_tempGreenList[index]);
darienf 20:6d2af70c92ab 193 _SKA_greenList.RemoveAt(0);
darienf 20:6d2af70c92ab 194 _SKA_numSamplesSinceLastCalc++;
darienf 20:6d2af70c92ab 195 }
darienf 20:6d2af70c92ab 196 _SKA_tempIRList.Clear();
darienf 20:6d2af70c92ab 197 _SKA_tempRedList.Clear();
darienf 20:6d2af70c92ab 198 _SKA_tempGreenList.Clear();
darienf 20:6d2af70c92ab 199 //
darienf 20:6d2af70c92ab 200 if (_SKA_numSamplesSinceLastCalc < _SKA_windowSize)
darienf 20:6d2af70c92ab 201 {
darienf 20:6d2af70c92ab 202 _SKA_IRList.Add(rawIR);
darienf 20:6d2af70c92ab 203 _SKA_IRList.RemoveAt(0);
darienf 20:6d2af70c92ab 204 _SKA_redList.Add(rawRed);
darienf 20:6d2af70c92ab 205 _SKA_redList.RemoveAt(0);
darienf 20:6d2af70c92ab 206 _SKA_greenList.Add(rawGreen);
darienf 20:6d2af70c92ab 207 _SKA_greenList.RemoveAt(0);
darienf 20:6d2af70c92ab 208 }
darienf 20:6d2af70c92ab 209 else
darienf 20:6d2af70c92ab 210 {
darienf 20:6d2af70c92ab 211 _SKA_tempIRList.Add(rawIR);
darienf 20:6d2af70c92ab 212 _SKA_tempRedList.Add(rawRed);
darienf 20:6d2af70c92ab 213 _SKA_tempGreenList.Add(rawGreen);
darienf 20:6d2af70c92ab 214 }
darienf 20:6d2af70c92ab 215 _SKA_numSamplesSinceLastCalc++;
darienf 20:6d2af70c92ab 216 //
darienf 20:6d2af70c92ab 217 if (_SKA_numSamplesSinceLastCalc >= _SKA_windowSize)
darienf 20:6d2af70c92ab 218 {
darienf 20:6d2af70c92ab 219 _SKA_numSamplesSinceLastCalc = 0;
darienf 20:6d2af70c92ab 220 for (int index = 0; index < _SKA_IRList.Count; index++)
darienf 20:6d2af70c92ab 221 {
darienf 20:6d2af70c92ab 222 irBuf[index] = (int)_SKA_IRList[index];
darienf 20:6d2af70c92ab 223 redBuf[index] = (int)_SKA_redList[index];
darienf 20:6d2af70c92ab 224 greenBuf[index] = (int)_SKA_greenList[index];
darienf 20:6d2af70c92ab 225 }
darienf 20:6d2af70c92ab 226
darienf 20:6d2af70c92ab 227 // Steve Koh's algorithm uses Fs=100Sps. It processes 500 samples at a time. Shift in 100 new samples before the function is called.
darienf 20:6d2af70c92ab 228 // Since we're running at 100Sps, this routine is called every 100 samples.
darienf 20:6d2af70c92ab 229 // Although _SKA_elapsedSecond = num samples / Fs, Steve used an integer type and so only Fs=100Sps or 50Sps would work. Regardless, we are using fixed 100Sps.
darienf 20:6d2af70c92ab 230 //
darienf 20:6d2af70c92ab 231 // Heart Rate/SpO2 Monitor function takes 18bit input irBuffer[500] and redBuffer[500].
darienf 20:6d2af70c92ab 232 // Inputs:
darienf 20:6d2af70c92ab 233 // int lapsedSecond -> _SKA_elapsedSecond must be >3 before anything happens
darienf 20:6d2af70c92ab 234 // const int irBuffer[500] -> irBuf
darienf 20:6d2af70c92ab 235 // const int redBuffer[500] -> redBuf
darienf 20:6d2af70c92ab 236 // Outputs:
darienf 20:6d2af70c92ab 237 // unsigned int *heartRate -> HR Heart Rate in beats per minute.
darienf 20:6d2af70c92ab 238 // float *SPO2 -> fSPO2 SpO2 value as %saturation.
darienf 20:6d2af70c92ab 239 // boolean_T *SPO2valid -> SPO2valid
darienf 20:6d2af70c92ab 240 // boolean_T *HRvalid -> HRvalid
darienf 20:6d2af70c92ab 241 // float *SPO2errorStatus -> SPO2error looks like a signal strength?
darienf 20:6d2af70c92ab 242 // float last100Ir[100] -> irAcBuf
darienf 20:6d2af70c92ab 243 // float last100Red[100] -> redAcBuf
darienf 20:6d2af70c92ab 244 //
darienf 20:6d2af70c92ab 245 if (valid_Green && !valid_IR) // Green mode - green into IR channel
darienf 20:6d2af70c92ab 246 {
darienf 20:6d2af70c92ab 247 // https://jira.maxim-ic.com/browse/OS24EVK-15 move SKA algorithm into MaximSKAlgorithmClass
darienf 20:6d2af70c92ab 248 // https://jira.maxim-ic.com/browse/OS24EVK-35 Support HR from Green LED (SKA Algorithm)
darienf 20:6d2af70c92ab 249 // for SKA green LED support, looks like we have to preload redBuf with Green LED data...
darienf 20:6d2af70c92ab 250 // no IR, but we can use Green instead for HR. (No SpO2 measurement so both channels Green.)
darienf 20:6d2af70c92ab 251 SKA.SKA_work(
darienf 20:6d2af70c92ab 252 _SKA_elapsedSecond,
darienf 20:6d2af70c92ab 253 greenBuf,
darienf 20:6d2af70c92ab 254 greenBuf,
darienf 20:6d2af70c92ab 255 ref _heartRateBPMint,
darienf 20:6d2af70c92ab 256 ref _spO2Percentfloat,
darienf 20:6d2af70c92ab 257 ref spO2PercentValid,
darienf 20:6d2af70c92ab 258 ref heartRateBPMValid,
darienf 20:6d2af70c92ab 259 ref SPO2error,
darienf 20:6d2af70c92ab 260 irAcBuf,
darienf 20:6d2af70c92ab 261 redAcBuf);
darienf 20:6d2af70c92ab 262 }
darienf 20:6d2af70c92ab 263 else if (valid_Red && !valid_IR && !valid_Green) // HR mode - red into IR channel
darienf 20:6d2af70c92ab 264 {
darienf 20:6d2af70c92ab 265 SKA.SKA_work(
darienf 20:6d2af70c92ab 266 _SKA_elapsedSecond,
darienf 20:6d2af70c92ab 267 redBuf,
darienf 20:6d2af70c92ab 268 redBuf,
darienf 20:6d2af70c92ab 269 ref _heartRateBPMint,
darienf 20:6d2af70c92ab 270 ref _spO2Percentfloat,
darienf 20:6d2af70c92ab 271 ref spO2PercentValid,
darienf 20:6d2af70c92ab 272 ref heartRateBPMValid,
darienf 20:6d2af70c92ab 273 ref SPO2error,
darienf 20:6d2af70c92ab 274 irAcBuf,
darienf 20:6d2af70c92ab 275 redAcBuf);
darienf 20:6d2af70c92ab 276 }
darienf 20:6d2af70c92ab 277 else // SpO2 mode
darienf 20:6d2af70c92ab 278 {
darienf 20:6d2af70c92ab 279 // https://jira.maxim-ic.com/browse/OS24EVK-15 move SKA algorithm into MaximSKAlgorithmClass
darienf 20:6d2af70c92ab 280 // normal HR from Red, SpO2 if IR is available
darienf 20:6d2af70c92ab 281 // SKA.SKA_work(_SKA_elapsedSecond, irBuf, redBuf, ref HR, ref fSPO2, ref SPO2valid, ref HRvalid, ref SPO2error, irAcBuf, redAcBuf);
darienf 20:6d2af70c92ab 282 SKA.SKA_work(
darienf 20:6d2af70c92ab 283 _SKA_elapsedSecond,
darienf 20:6d2af70c92ab 284 irBuf,
darienf 20:6d2af70c92ab 285 redBuf,
darienf 20:6d2af70c92ab 286 ref _heartRateBPMint,
darienf 20:6d2af70c92ab 287 ref _spO2Percentfloat,
darienf 20:6d2af70c92ab 288 ref spO2PercentValid,
darienf 20:6d2af70c92ab 289 ref heartRateBPMValid,
darienf 20:6d2af70c92ab 290 ref SPO2error,
darienf 20:6d2af70c92ab 291 irAcBuf,
darienf 20:6d2af70c92ab 292 redAcBuf);
darienf 20:6d2af70c92ab 293 }
darienf 20:6d2af70c92ab 294 _SKA_elapsedSecond++;
darienf 20:6d2af70c92ab 295
darienf 20:6d2af70c92ab 296
darienf 20:6d2af70c92ab 297 // https://jira.maxim-ic.com/browse/OS24EVK-15 SKA algorithm report results by InterfaceHeartRateSpO2dataConsumer.ConsumeHeartRateSpO2data(heartRateBPM, ...)
darienf 20:6d2af70c92ab 298 heartRateBPM = (double)_heartRateBPMint;
darienf 20:6d2af70c92ab 299 spO2Percent = (double)_spO2Percentfloat;
darienf 20:6d2af70c92ab 300 // OS24EVK-35 don't report SpO2 if there was not valid red and IR data (i.e. green only)
darienf 20:6d2af70c92ab 301 if (!(valid_Red && valid_IR)) { spO2PercentValid = false; }
darienf 20:6d2af70c92ab 302 spO2PercentSignalStrength = (double)SPO2error;
darienf 20:6d2af70c92ab 303 // https://jira.maxim-ic.com/browse/OS24EVK-15 SKAAlgorithm reporting SpO2 999 as if that was valid.
darienf 20:6d2af70c92ab 304 // SKA Algorithm reports SpO2 bogus value 999% as valid; need to determine why reported as a valid result.
darienf 20:6d2af70c92ab 305 // spO2PercentValid = (spO2PercentSignalStrength > 0);
darienf 20:6d2af70c92ab 306 // don't modify spO2PercentValid; already passed by ref from SKA.SKA_work()
darienf 20:6d2af70c92ab 307 ReportResultsHeartRateSpO2dataAvailable(heartRateBPM, heartRateBPMValid, heartRateBPMSignalStrength, spO2Percent, spO2PercentValid, spO2PercentSignalStrength);
darienf 20:6d2af70c92ab 308 System.Diagnostics.Debug.Print("heartRateBPM: " + heartRateBPM + " heartRateBPMValid: " + heartRateBPMValid + " spO2Percent: " + spO2Percent + " spO2PercentValid: " + spO2PercentValid);
darienf 20:6d2af70c92ab 309 } // if (_SKA_numSamplesSinceLastCalc >= _SKA_windowSize)
darienf 20:6d2af70c92ab 310 }
darienf 20:6d2af70c92ab 311
darienf 20:6d2af70c92ab 312 }
darienf 20:6d2af70c92ab 313 }