Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed MAX14720 MAX30205 USBDevice
RawFileLogPresenter.cs
00001 /******************************************************************************* 00002 * Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved. 00003 * 00004 * This software is protected by copyright laws of the United States and 00005 * of foreign countries. This material may also be protected by patent laws 00006 * and technology transfer regulations of the United States and of foreign 00007 * countries. This software is furnished under a license agreement and/or a 00008 * nondisclosure agreement and may only be used or reproduced in accordance 00009 * with the terms of those agreements. Dissemination of this information to 00010 * any party or parties not specified in the license agreement and/or 00011 * nondisclosure agreement is expressly prohibited. 00012 * 00013 * The above copyright notice and this permission notice shall be included 00014 * in all copies or substantial portions of the Software. 00015 * 00016 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 00017 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 00018 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 00019 * IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES 00020 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 00021 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 00022 * OTHER DEALINGS IN THE SOFTWARE. 00023 * 00024 * Except as contained in this notice, the name of Maxim Integrated 00025 * Products, Inc. shall not be used except as stated in the Maxim Integrated 00026 * Products, Inc. Branding Policy. 00027 * 00028 * The mere transfer of this software does not imply any licenses 00029 * of trade secrets, proprietary technology, copyrights, patents, 00030 * trademarks, maskwork rights, or any other form of intellectual 00031 * property whatsoever. Maxim Integrated Products, Inc. retains all 00032 * ownership rights. 00033 ******************************************************************************* 00034 */ 00035 00036 using System; 00037 using System.Collections.Generic; 00038 using System.Linq; 00039 using System.Text; 00040 00041 using HealthSensorPlatform.View; 00042 using HealthSensorPlatform.Model; 00043 using HealthSensorPlatform.CustomControls; 00044 00045 using RPCSupport; 00046 using RPCSupport.Streaming; 00047 00048 namespace HealthSensorPlatform.Presenter 00049 { 00050 public class RawFileLogPresenter 00051 { 00052 IRawFileLogView ecgLog; 00053 IRawFileLogView bioZLog; 00054 IRawFileLogView rToRLog; 00055 IRawFileLogView paceLog; 00056 IFormView formView; 00057 IEcgView ecgView; 00058 00059 bool fileLog = false; // user enabled file logging 00060 bool streaming = false; // streaming data or flash log data, only save data from streaming 00061 //bool flashLog = false; 00062 00063 IDataLoggingView dataLogView; 00064 00065 PaceData paceData; 00066 00067 RToRCalculator rToRCalculator; 00068 bool rToRFirst = true; // received first RR value for offset correction 00069 00070 //bool ecgLeadOff; // DC Lead off data for ECG or BioZ Channel 00071 DCLeadOff leadOff; // lead off status bits 00072 ACLeadOff acLeadOff; // bioz lead off status bits 00073 00074 int count = 0; 00075 int bioZCount = 0; 00076 //int ppgCount = 0; 00077 //int accelCount = 0; 00078 00079 string logFileDirectory = null; 00080 00081 View.FileLogView.FileLogHeader fileLogHeader = new View.FileLogView.FileLogHeader(); 00082 00083 public RawFileLogPresenter(IRawFileLogView ecg, IRawFileLogView bioZ, IRawFileLogView rToR, IRawFileLogView pace, IFormView formView, RPCClient rpcClient, IEcgView ecgView, IDataLoggingView dataLogView) 00084 { 00085 this.ecgLog = ecg; 00086 this.bioZLog = bioZ; 00087 this.rToRLog = rToR; 00088 this.paceLog = pace; 00089 this.formView = formView; 00090 this.ecgView = ecgView; 00091 00092 this.dataLogView = dataLogView; 00093 00094 formView.FileLogEnable += new EventHandler<EnableEventArgs>(OnLogFileEnable); 00095 ecgView.StreamingStartStop += new EventHandler<StreamingStartStopEventArgs>(OnStreamStart); 00096 //dataLogView.LogDownloadStart += new EventHandler<EventArgs>(OnLogDownloadStart); 00097 rpcClient.streaming.PartialArrayIntAvailable += new EventHandler<PartialArrayIntAvailableEventArgs>(OnStreamData); 00098 } 00099 00100 public void OnLogFileEnable(object sender, EnableEventArgs e) 00101 { 00102 fileLog = e.Enable; 00103 00104 if (e.Enable) 00105 { 00106 bool result = false; 00107 IRawFileLogView log = ecgLog; 00108 string filePrefixName = String.Empty; 00109 00110 switch(e.Stream) 00111 { 00112 case StreamType.Ecg: 00113 log = ecgLog; 00114 filePrefixName = "hsp-ecg"; 00115 break; 00116 case StreamType.RToR: 00117 log = rToRLog; 00118 filePrefixName = "hsp-rtor"; 00119 break; 00120 case StreamType.Pace: 00121 log = paceLog; 00122 filePrefixName = "hsp-pace"; 00123 break; 00124 case StreamType.BioZ: 00125 log = bioZLog; 00126 filePrefixName = "hsp-bioz"; 00127 break; 00128 } 00129 00130 if (logFileDirectory != null) // Set starting directory to be the same as the last 00131 log.FileDirectory = logFileDirectory; 00132 00133 result = log.SelectCSVFile(filePrefixName); 00134 log.Enable = result; 00135 00136 if (result) // Save directory if success 00137 logFileDirectory = log.FileDirectory; 00138 00139 formView.LogFileItem(e.Stream, result); 00140 } 00141 else 00142 { 00143 switch (e.Stream) 00144 { 00145 case StreamType.Ecg: 00146 ecgLog.Enable = false; 00147 break; 00148 case StreamType.RToR: 00149 rToRLog.Enable = false; 00150 break; 00151 case StreamType.Pace: 00152 paceLog.Enable = false; 00153 break; 00154 case StreamType.BioZ: 00155 bioZLog.Enable = false; 00156 break; 00157 } 00158 00159 formView.LogFileItem(e.Stream, false); 00160 } 00161 } 00162 00163 public void OnStreamStart(object sender, StreamingStartStopEventArgs e) 00164 { 00165 streaming = e.state; 00166 count = 0; 00167 bioZCount = 0; 00168 00169 if (e.state) 00170 { 00171 leadOff = new DCLeadOff { NegativeHigh = false, NegativeLow = false, PostiveHigh = false, PostiveLow = false }; 00172 acLeadOff = new ACLeadOff { BioZOverRange = false, BioZUnderRange = false }; 00173 00174 if (ecgLog != null && ecgLog.Enable && ecgView.EnableECG) 00175 { 00176 //ecgLog.WriteLine("% " + ecgView.HspSetting.EcgSettingString()); // TODO: What is the requirement for headers 00177 ecgLog.WriteLine(fileLogHeader.Ecg); 00178 } 00179 00180 if (bioZLog != null && bioZLog.Enable && ecgView.EnableBioZ) 00181 { 00182 //ecgLog.WriteLine("% " + ecgView.HspSetting.BioZSettingString()); 00183 bioZLog.WriteLine(fileLogHeader.BioZ); 00184 } 00185 00186 if (rToRLog != null && rToRLog.Enable && ecgView.EnableRToR) 00187 { 00188 rToRLog.WriteLine(fileLogHeader.RToR); 00189 rToRCalculator = new RToRCalculator(ecgView.MasterClockField, ecgView.EcgArgs.Rate, ecgView.EcgArgs.Dlpf, ecgView.RToRArgs.Wndw); 00190 } 00191 00192 if (paceLog != null && paceLog.Enable && ecgView.EnablePace) 00193 { 00194 paceLog.WriteLine(fileLogHeader.Pace); 00195 } 00196 } 00197 else 00198 { 00199 if (ecgLog != null) 00200 ecgLog.Enable = false; 00201 00202 if (bioZLog != null) 00203 bioZLog.Enable = false; 00204 00205 if (rToRLog != null) 00206 rToRLog.Enable = false; 00207 00208 if (paceLog != null) 00209 paceLog.Enable = false; 00210 } 00211 } 00212 00213 void fileLogStop() 00214 { 00215 fileLog = false; 00216 stop(); 00217 00218 } 00219 00220 void stop() 00221 { 00222 if (ecgLog != null && ecgLog.Enable) 00223 ecgLog.Enable = false; 00224 00225 if (rToRLog != null && rToRLog.Enable) 00226 rToRLog.Enable = false; 00227 00228 if (paceLog != null && paceLog.Enable) 00229 paceLog.Enable = false; 00230 00231 if (bioZLog != null && bioZLog.Enable) 00232 bioZLog.Enable = false; 00233 00234 formView.LogFileItem(StreamType.Ecg, false); 00235 formView.LogFileItem(StreamType.RToR, false); 00236 formView.LogFileItem(StreamType.Pace, false); 00237 formView.LogFileItem(StreamType.BioZ, false); 00238 } 00239 00240 private void OnStreamData(object sender, PartialArrayIntAvailableEventArgs e) 00241 { 00242 if (streaming) 00243 { 00244 switch (e.reportID) 00245 { 00246 case PartialArrayIntAvailableEventArgs.PACKET_MAX30001_ECG: 00247 if (ecgLog.Enable) 00248 ProcessEcg(e.array1); 00249 break; 00250 case PartialArrayIntAvailableEventArgs.PACKET_MAX30001_BIOZ: 00251 if (bioZLog.Enable) 00252 ProcessBioZ(e.array1); 00253 break; 00254 case PartialArrayIntAvailableEventArgs.PACKET_MAX30001_PACE: 00255 if (paceLog.Enable) 00256 paceData = new PaceData(e.array1); 00257 break; 00258 case PartialArrayIntAvailableEventArgs.PACKET_MAX30001_RTOR: 00259 if (rToRLog.Enable) 00260 ProcessRToR(e.array1[0]); 00261 break; 00262 case PartialArrayIntAvailableEventArgs.PACKET_END_OF_STREAM: 00263 fileLogStop(); 00264 break; 00265 case PartialArrayIntAvailableEventArgs.PACKET_MAX30001_LEADOFF_DC: 00266 ProcessLeadOff(e.array1[0]); 00267 break; 00268 case PartialArrayIntAvailableEventArgs.PACKET_MAX30001_LEADOFF_AC: 00269 ProcessACLeadOff(e.array1[0]); 00270 break; 00271 } 00272 } 00273 } 00274 00275 void ProcessBioZ(int[] rawData) 00276 { 00277 BioZFifo[] bioZFifo; 00278 double sampleRate = ecgView.SampleRateBioZ; 00279 double[] time = new double[rawData.Length]; 00280 00281 bioZFifo = ConvertBioZ(rawData); 00282 00283 for (int i = 0; i < time.Length; i++) 00284 { 00285 time[i] = bioZCount / sampleRate; 00286 bioZCount++; 00287 } 00288 00289 if (ecgView.EnableDCLeadOff == false && ecgView.EnableBioZOverUnderRange == true) 00290 bioZLog.DisplayBioZ(time, bioZFifo, acLeadOff); 00291 else if (ecgView.EnableDCLeadOff == true && ecgView.EnableEcgDCLeadOff == false && ecgView.EnableBioZOverUnderRange == false) // && ecgLeadOff == false) 00292 bioZLog.DisplayBioZ(time, bioZFifo, leadOff); 00293 else if (ecgView.EnableDCLeadOff == true && ecgView.EnableEcgDCLeadOff == false && ecgView.EnableBioZOverUnderRange == true) 00294 bioZLog.DisplayBioZ(time, bioZFifo, leadOff, acLeadOff); 00295 else if ((ecgView.EnableDCLeadOff == false && ecgView.EnableBioZOverUnderRange == false) || 00296 ecgView.EnableEcgDCLeadOff == true && ecgView.EnableEcgDCLeadOff == true && ecgView.EnableBioZOverUnderRange == false) 00297 bioZLog.DisplayBioZ(time, bioZFifo); 00298 } 00299 00300 public BioZFifo[] ConvertBioZ(int[] data) 00301 { 00302 BioZFifo[] impedance = new BioZFifo[data.Length]; 00303 EcgView.ChartInfo chartInfo = ecgView.BioZInfo; 00304 int dataShift; 00305 00306 for (int i = 0; i < data.Length; i++) 00307 { 00308 dataShift = data[i] >> chartInfo.Shift; 00309 00310 // Two's Complement Conversions 00311 if (dataShift > chartInfo.Threshold) 00312 { 00313 dataShift -= chartInfo.Offset; 00314 } 00315 00316 // 1.9734 = 1/2^19 * 1e-6 00317 impedance[i].Data = dataShift * 1.9073486328125 / 00318 (chartInfo.Gain * ((chartInfo.CurrentGenerator == 0) ? 1 : chartInfo.CurrentGenerator)); 00319 impedance[i].Code = data[i]; 00320 impedance[i].BioZData = dataShift; 00321 impedance[i].BTag = data[i] & 0x07; 00322 } 00323 00324 return impedance; 00325 } 00326 00327 void ProcessEcg(int[] rawData) 00328 { 00329 EcgFifo[] ecgFifo; 00330 double ecgRate = ecgView.SampleRateEcg; 00331 double[] ecgVoltage = new double[rawData.Length]; 00332 double[] timeSecond = new double[rawData.Length]; 00333 00334 ecgFifo = ConvertEcg(rawData); 00335 00336 for (int i = 0; i < ecgFifo.Length; i++ ) 00337 { 00338 timeSecond[i] = count / ecgRate; 00339 00340 // Look for Pace Events 00341 if (paceLog.Enable) 00342 { 00343 //for (int j = 0; j < ecgFifo.Length; j++) 00344 //{ 00345 if (ecgFifo[i].PTag != 7) 00346 { 00347 PaceData.PaceRegister paceRegister = paceData.PaceGroup(ecgFifo[i].PTag); 00348 List<double> timeMillsecondPace = new List<double>(); 00349 List<PaceData.PaceEdge> paceEdges = new List<PaceData.PaceEdge>(); 00350 00351 for (int k = 0; k < 6; k++) 00352 { 00353 PaceData.PaceEdge edge = paceRegister.Edge[k]; 00354 00355 timeMillsecondPace.Add(count / ecgRate + ConvertPace(edge.Data)); 00356 paceEdges.Add(edge); 00357 00358 if (edge.Last == true) 00359 break; 00360 } 00361 00362 paceLog.DisplayPace(timeMillsecondPace.ToArray(), paceEdges.ToArray()); 00363 System.Diagnostics.Debug.Print("ECG PTag = " + ecgFifo[i].PTag); 00364 } 00365 //} 00366 } 00367 00368 count++; 00369 } 00370 00371 if (ecgView.EnableDCLeadOff && ecgView.EnableEcgDCLeadOff) 00372 ecgLog.DisplayEcg(timeSecond, ecgFifo, leadOff); 00373 else 00374 ecgLog.DisplayEcg(timeSecond, ecgFifo); 00375 00376 } 00377 00378 public EcgFifo[] ConvertEcg(int[] data) 00379 { 00380 EcgFifo[] voltage = new EcgFifo[data.Length]; 00381 EcgView.ChartInfo chartInfo = ecgView.EcgInfo; 00382 int dataShift; 00383 00384 for (int i = 0; i < data.Length; i++) 00385 { 00386 dataShift = data[i] >> chartInfo.Shift; 00387 00388 // Two's Complement Conversions 00389 if (dataShift > chartInfo.Threshold) 00390 { 00391 dataShift -= chartInfo.Offset; 00392 } 00393 00394 voltage[i].Data = 1000 * 7.62939453125e-6 * dataShift / chartInfo.Gain; 00395 voltage[i].EcgData = dataShift; 00396 voltage[i].Code = data[i]; 00397 voltage[i].PTag = data[i] & 0x07; 00398 voltage[i].ETag = (data[i] >> 3) & 0x07; 00399 } 00400 00401 return voltage; 00402 } 00403 00404 public double ConvertRToR(int data) 00405 { 00406 return ecgView.TimeResolution * 1000 * data * 512; 00407 } 00408 00409 public double ConvertPace(int data) 00410 { 00411 return data * ecgView.TimeResolution; 00412 } 00413 00414 public string PaceRegisterGroupToString(PaceData.PaceRegister paceRegister) 00415 { 00416 StringBuilder paceRegisterLogBuilder = new StringBuilder(); 00417 for (int j = 0; j < 6; j++) 00418 { 00419 paceRegisterLogBuilder.Append(paceRegister.Edge[j].Data / (2 * ecgView.MasterClockFrequency)); 00420 paceRegisterLogBuilder.Append(", "); 00421 paceRegisterLogBuilder.Append(paceRegister.Edge[j].Polarity ? 'R' : 'F'); 00422 paceRegisterLogBuilder.Append(", "); 00423 paceRegisterLogBuilder.Append(paceRegister.Edge[j].Last ? 'Y' : 'N'); 00424 paceRegisterLogBuilder.Append(", "); 00425 } 00426 00427 return paceRegisterLogBuilder.ToString(); 00428 } 00429 00430 void ProcessLeadOff(int data) 00431 { 00432 /* 00433 if (bitShiftMask(data, 8)) // ECG lead off 00434 ecgLeadOff = true; 00435 else if (bitShiftMask(data, 9)) // BioZ lead off 00436 ecgLeadOff = false; 00437 */ 00438 00439 leadOff = new DCLeadOff() 00440 { 00441 PostiveHigh = bitShiftMask(data, 3), 00442 PostiveLow = bitShiftMask(data, 2), 00443 NegativeHigh = bitShiftMask(data, 1), 00444 NegativeLow = bitShiftMask(data, 0) 00445 }; 00446 00447 } 00448 00449 void ProcessACLeadOff(int data) 00450 { 00451 acLeadOff = new ACLeadOff() 00452 { 00453 BioZUnderRange = bitShiftMask(data, 1), 00454 BioZOverRange = bitShiftMask(data, 0), 00455 }; 00456 } 00457 00458 private static bool bitShiftMask(int data, int index) 00459 { 00460 int state; 00461 int mask = 1 << index; 00462 state = ((data & mask) == mask) ? 1 : 0; 00463 return state == 1; 00464 } 00465 00466 void ProcessRToR(int data) 00467 { 00468 if (rToRFirst) 00469 { 00470 rToRLog.DisplayRToR(data, rToRCalculator.Corrected(data, true) / 1000); 00471 rToRFirst = false; 00472 } 00473 else 00474 rToRLog.DisplayRToR(data, rToRCalculator.Corrected(data, false) / 1000); 00475 } 00476 } 00477 }
Generated on Thu Jul 28 2022 18:07:15 by
 1.7.2