![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
repo time
Dependencies: mbed MAX14720 MAX30205 USBDevice
Diff: HspGuiSourceV301/HSPGui/Presenter/StreamPresenter.cs
- Revision:
- 20:6d2af70c92ab
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/HspGuiSourceV301/HSPGui/Presenter/StreamPresenter.cs Tue Apr 06 06:41:40 2021 +0000 @@ -0,0 +1,265 @@ +/******************************************************************************* +* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved. +* +* This software is protected by copyright laws of the United States and +* of foreign countries. This material may also be protected by patent laws +* and technology transfer regulations of the United States and of foreign +* countries. This software is furnished under a license agreement and/or a +* nondisclosure agreement and may only be used or reproduced in accordance +* with the terms of those agreements. Dissemination of this information to +* any party or parties not specified in the license agreement and/or +* nondisclosure agreement is expressly prohibited. +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES +* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +* +* Except as contained in this notice, the name of Maxim Integrated +* Products, Inc. shall not be used except as stated in the Maxim Integrated +* Products, Inc. Branding Policy. +* +* The mere transfer of this software does not imply any licenses +* of trade secrets, proprietary technology, copyrights, patents, +* trademarks, maskwork rights, or any other form of intellectual +* property whatsoever. Maxim Integrated Products, Inc. retains all +* ownership rights. +******************************************************************************* +*/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using RPCSupport; +using RPCSupport.Streaming; +using HealthSensorPlatform.CustomControls; +using HealthSensorPlatform.Model; +using HealthSensorPlatform.View; + +namespace HealthSensorPlatform.Presenter +{ + public class StreamPresenter + { + const double NoData = -5000; + const int NoRToR = -1; + + private RPCClient rpcClient; + private EcgView ecgView; + private IFormView formView; + private int rToRRaw = NoRToR; + private PaceData paceData; + private bool start = false; + + public StreamPresenter() + { + + } + + public StreamPresenter(EcgView ecgView) + { + this.ecgView = ecgView; + } + + public StreamPresenter(RPCClient rpcClient, EcgView ecgView, IFormView formView) + { + this.rpcClient = rpcClient; + this.ecgView = ecgView; + this.formView = formView; + + ecgView.StreamingStartStop += new EventHandler<StreamingStartStopEventArgs>(OnStreamingStartStop); + rpcClient.streaming.PartialArrayIntAvailable += new EventHandler<PartialArrayIntAvailableEventArgs>(OnStreamData); + } + + private void OnStreamingStartStop(object sender, StreamingStartStopEventArgs e) + { + start = e.state; + + if (ecgView.Connected && !start) // Clear Interrupts on stream start and stop, start to prevent RPC Int Assignment freeze + { + rpcClient.MAX30001.WriteReg(0x02, 0x03); // Stop Interrupts + rpcClient.MAX30001.WriteReg(0x03, 0x03); // Stop Interrupts + } + + formView.EcgLogFileItem(false); + formView.BioZLogFileItem(false); + formView.RtoRLogFileItem(false); + formView.PaceLogFileItem(false); + } + + private void OnStreamData(object sender, PartialArrayIntAvailableEventArgs e) + { + int leadOffState; + if (start && e.array1.Length > 0) // Ignore events unless started (from flash logging) + { + leadOffState = e.array1[0]; + + switch(e.reportID) + { + case PartialArrayIntAvailableEventArgs.PACKET_MAX30001_LEADOFF_DC: + ecgView.SetDCLeadOff(leadOffState); + break; + case PartialArrayIntAvailableEventArgs.PACKET_MAX30001_LEADOFF_AC: + ecgView.SetACLeadOff(leadOffState); + break; + } + + switch (e.reportID) + { + case PartialArrayIntAvailableEventArgs.PACKET_MAX30001_ECG: + ProcessEcg(e.array1); + break; + case PartialArrayIntAvailableEventArgs.PACKET_MAX30001_BIOZ: + ProcessBioZ(e.array1); + break; + case PartialArrayIntAvailableEventArgs.PACKET_MAX30001_PACE: + ProcessPace(e.array1); + break; + case PartialArrayIntAvailableEventArgs.PACKET_MAX30001_RTOR: + rToRRaw = e.array1[0]; + ecgView.DisplayRToR(e.array1[0]); + break; + } + } + } + + void ProcessBioZ(int[] rawData) + { + BioZFifo[] bioZFifo; + double[] bioZImpedance; + + bioZFifo = ConvertBioZ(rawData); + + bioZImpedance = new double[bioZFifo.Length]; + for (int i = 0; i < bioZFifo.Length; i++) + { + bioZImpedance[i] = bioZFifo[i].Data; + } + ecgView.DisplayBioZ(bioZImpedance); + } + + public BioZFifo[] ConvertBioZ(int[] data) + { + BioZFifo[] impedence = new BioZFifo[data.Length]; + EcgView.ChartInfo chartInfo = ecgView.BioZInfo; + int dataShift; + + for (int i = 0; i < data.Length; i++) + { + dataShift = data[i] >> chartInfo.Shift; + + // Two's Complement Conversions + if (dataShift > chartInfo.Threshold) + { + dataShift -= chartInfo.Offset; + } + + // 1.9734 = 1/2^19 * 1e-6 + impedence[i].Data = dataShift * 1.9073486328125 / + (chartInfo.Gain * ((chartInfo.CurrentGenerator == 0) ? 1 : chartInfo.CurrentGenerator)); + impedence[i].BTag = data[i] & 0x07; + } + + return impedence; + } + + public double[] ProcessEcg(int[] rawData) + { + EcgFifo[] ecgFifo; + double[] ecgVoltage = new double[rawData.Length]; + double[] rToRInterval = null; + + // Pace File Log + string[] paceRegisterLog = new string[rawData.Length]; + + List<EcgView.PacePoint> pacePoints = new List<EcgView.PacePoint>(); + + ecgFifo = ConvertEcg(rawData); + + // ECG + for (int i = 0; i < ecgFifo.Length; i++) + { + ecgVoltage[i] = ecgFifo[i].Data; + + if (ecgFifo[i].PTag != 0x07 && paceData != null) // Pace Event + { + PaceData.PaceRegister paceRegister = paceData.PaceGroup(ecgFifo[i].PTag); // Register Group + PaceData.PaceEdge[] paceEdges = paceRegister.Edge; // Pace Edge + + // Pace Charting Data + int k = 0; + PaceData.PaceEdge edge; + do + { + edge = paceEdges[k]; + // Convert Pace into ECG samples + // (Pace Raw / (2 * FMSTR )) / (1 / ECG Sample Rate) = Pace Raw * ECG Sample Rate / (2 * FMSTR) + pacePoints.Add(new EcgView.PacePoint(i + (edge.Data * ecgView.SampleRateEcg / (2 * ecgView.MasterClockFrequency)), edge.Polarity)); + + k++; + } + while (!(edge.Last == true || k >= 6)); + } + } + + // R to R + if (ecgView.EnableRToR) + { + rToRInterval = new double[rawData.Length]; + for (int i = 0; i < rToRInterval.Length; i++) + { + rToRInterval[i] = NoData; + } + + if (rToRRaw > 0) + { + rToRInterval[0] = ecgVoltage[0]; // Plot at height of ECG signal + rToRRaw = NoRToR; + } + } + + ecgView.DisplayEcg(ecgVoltage, pacePoints.ToArray(), rToRInterval); + + return ecgVoltage; + } + + public EcgFifo[] ConvertEcg(int[] data) + { + EcgFifo[] voltage = new EcgFifo[data.Length]; + EcgView.ChartInfo chartInfo = ecgView.EcgInfo; + int dataShift; + + for (int i = 0; i < data.Length; i++) + { + dataShift = data[i] >> chartInfo.Shift; + + // Two's Complement Conversions + if (dataShift > chartInfo.Threshold) + { + dataShift -= chartInfo.Offset; + } + + voltage[i].Data = 1000 * 7.62939453125e-6 * dataShift / chartInfo.Gain; + voltage[i].PTag = data[i] & 0x07; + voltage[i].ETag = (data[i] >> 3) & 0x07; + } + + return voltage; + } + + public PaceData ProcessPace(int[] data) + { + paceData = new PaceData(data); + + return paceData; + } + + } +}