Darien Figueroa / Mbed 2 deprecated repo3

Dependencies:   mbed MAX14720 MAX30205 USBDevice

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers RawFileLogPresenter.cs Source File

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 }