Darien Figueroa / Mbed OS Final_Program

Dependencies:   USBDevice

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers OpticalView.cs Source File

OpticalView.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 #define USE_MEDICALCHARTHELPER
00037 //#define CES_DEMO
00038 
00039 using System;
00040 using System.Collections.Generic;
00041 using System.Collections;
00042 using System.ComponentModel;
00043 using System.Drawing;
00044 using System.Data;
00045 using System.Linq;
00046 using System.Text;
00047 using System.Windows.Forms;
00048 using RPCSupport.Streaming;
00049 using Maxim.Charting;
00050 using System.Threading;
00051 using HealthSensorPlatform.View;
00052 
00053 using System.Windows.Forms.DataVisualization.Charting;
00054 
00055 // DEBUG
00056 using System.IO;
00057 
00058 namespace HealthSensorPlatform.CustomControls
00059 {
00060     public partial class OpticalView : UserControl, IDeviceView, IOpticalAlgorithmView
00061     {
00062         /* Constant Fields */
00063         static string StartString = "Start Monitor";
00064         static string StopString = "Stop Monitor";
00065 
00066         const int ChartTime = 4; // 4 seconds
00067 
00068         /* Fields */
00069         private bool connected = false;
00070         private bool streaming = false;
00071 
00072         private RPCSupport.RPCClient rpcClient;
00073         //private MedicalChartHelper medicalChartLED;
00074         //private MedicalChartHelper medicalChartAccel;
00075         private AutoScaleCalculator fifo1Calc;
00076         private AutoScaleCalculator fifo2Calc;
00077         private AutoScaleCalculator fifo3Calc;
00078 
00079         eStreamMode streamMode;
00080         byte fifo_waterlevel_mark = 0x0f;
00081         byte sample_avg;
00082         byte sample_rate;
00083         byte pulse_width;
00084         byte red_led_current;
00085         byte ir_led_current;
00086         byte green_led_current;
00087         byte slot_1;
00088         byte slot_2;
00089         byte slot_3;
00090         byte slot_4;
00091 
00092         // Heart Rate Sensor
00093         int points; // Number of x-axis points for a plot
00094         int sampleRate; // Human readable sample rate
00095         int sampleAverage; // Human readable number of average points
00096         // LIS2HD
00097         int sampleRateAccel; 
00098         int pointsAccel;
00099 
00100         EventHandler<PartialArrayIntAvailableEventArgs> appendChart; // Allows event to be unregistered
00101 
00102         Dictionary<string, MedianFilter> intervalDict = new Dictionary<string, MedianFilter>();
00103         Dictionary<string, AutoScaleCalculator> chartScaleDict = new Dictionary<string, AutoScaleCalculator>();
00104 
00105         List<Control> streamingControls = new List<Control>();
00106 
00107 #if CES_DEMO
00108         // Algorithm Data
00109         Queue red;
00110         Queue ir;
00111         Queue led;
00112         // struct to run algorithms
00113         AlgorithmMobileBU.AlgorithmConfiguration config;
00114         AlgorithmMobileBU.AlgorithmOutput output;
00115         int algoCounter = 0;
00116 #endif
00117 
00118         // DEBUG
00119         //StreamWriter file = new StreamWriter("hsp_output_data.csv");
00120 
00121         /* Constructors */
00122         public OpticalView()
00123         {
00124             InitializeComponent();
00125 
00126             OpticalSensorInitControls();
00127 
00128             cboSampleRate.SelectedIndexChanged += new EventHandler(cboSRPWLed_SelectedIndexChanged);
00129             cboPulseWidth.SelectedIndexChanged += new EventHandler(cboSRPWLed_SelectedIndexChanged);
00130             cboRedLED.SelectedIndexChanged += new EventHandler(cboSRPWLed_SelectedIndexChanged);
00131             cboIRLED.SelectedIndexChanged += new EventHandler(cboSRPWLed_SelectedIndexChanged);
00132             cboGreenLED.SelectedIndexChanged += new EventHandler(cboSRPWLed_SelectedIndexChanged);
00133 
00134             cboSampleRate.SelectedIndexChanged += new EventHandler(cboSampleRate_SelectedIndexChanged);
00135             cboSampleAvg.SelectedIndexChanged += new EventHandler(cboSampleRate_SelectedIndexChanged);
00136 
00137             streamingControls.AddRange(new Control[] { panel1, maximGroupBoxSettings, maximGroupBoxLEDcurrents, maximGroupBoxLEDTimingSlots, btnDefaults });
00138 #if CES_DEMO
00139             // Algorithm 
00140             red = new Queue();
00141             ir = new Queue();
00142             led = new Queue();
00143 
00144             config = new AlgorithmMobileBU.AlgorithmConfiguration();
00145             output = new AlgorithmMobileBU.AlgorithmOutput();
00146 
00147             config.snrNoFingerThreshold = -9;
00148             config.acLowPerfusionThreshold = 950;
00149             config.isAGC = 0;
00150 
00151             //updateAlgorithm();           
00152             lblHeartRate.Visible = true;
00153             lblHeartRateText.Visible = true;
00154 #endif
00155         }
00156 
00157         /* Delegates */
00158         //public delegate void StreamingStartStopEventHandler(StreamingStartStopEventArgs e);
00159 
00160         /* Events */
00161         //public event StreamingStartStopEventHandler StreamingStartStop;
00162         public event EventHandler<StreamingStartStopEventArgs> StreamingStartStop;
00163 
00164         /* Enums */
00165         public enum eStreamMode
00166         {
00167             eHR,
00168             eSPO2,
00169             eMulti
00170         }
00171 
00172         /* Properties */
00173         public RPCSupport.RPCClient RPCClient
00174         {
00175             set
00176             {
00177                 rpcClient = value;
00178                 appendChart = new EventHandler<PartialArrayIntAvailableEventArgs>(On_AppendChart);
00179                 rpcClient.streaming.PartialArrayIntAvailable += appendChart;
00180             }
00181         }
00182 
00183         public bool Connected
00184         {
00185             get
00186             {
00187                 return connected;
00188             }
00189             set
00190             {
00191                 connected = value;
00192                 if (connected == false)
00193                     if (btnMonitoring.Text == StopString)
00194                         streamingStartStop();
00195             }
00196         }
00197 
00198         public int AccelSampleRate
00199         {
00200             get
00201             {
00202                 return sampleRateAccel;
00203             }
00204         }
00205 
00206         public int OpticalSampleRate
00207         {
00208             get
00209             {
00210                 return sampleRate / sampleAverage;
00211             }
00212         }
00213         
00214         public eStreamMode ModeConfiguration
00215         {
00216             get
00217             {
00218                 return streamMode;
00219             }
00220         }
00221 
00222         /* Methods */
00223 
00224         // Clean up streaming 
00225         public void Close()
00226         {
00227             rpcClient.streaming.PartialArrayIntAvailable -= appendChart; // Stop event from firing
00228             // Disable streaming if enabled
00229             if (btnMonitoring.Text == StopString)
00230                 streamingStartStop();
00231         }
00232 
00233         public void DisplayAlgorithmResult(double heartRateBPM, bool heartRateBPMValid, double heartRateBPMSignalStrength, 
00234             double spO2Percent, bool spO2PercentValid, double spO2PercentSignalStrength)
00235         {
00236             // 100Hz only - TODO
00237             if (OpticalSampleRate != 100)
00238                 return;
00239 
00240             if (heartRateBPMValid)
00241             {
00242                 lblHeartRate.ForeColor = SystemColors.ControlText;
00243                 lblHeartRate.Text = string.Format("{0}", heartRateBPM * (sampleRate / 100.0)); // 100.0 for default sample rate
00244             }
00245             else
00246             {
00247                 lblHeartRate.ForeColor = Color.Gray;
00248             }
00249 
00250             if (spO2PercentValid)
00251             {
00252                 lblSpO2.ForeColor = SystemColors.ControlText;
00253                 lblSpO2.Text = string.Format("{0:0.0}", spO2Percent);
00254             }
00255             else
00256             {
00257                 lblSpO2.ForeColor = Color.Gray;
00258             }
00259         }
00260 
00261         public void DisplayAlgorithmReset()
00262         {
00263             lblHeartRate.Text = "----";
00264             lblHeartRate.ForeColor = Color.Gray;
00265 
00266             lblSpO2.Text = "----";
00267             lblSpO2.ForeColor = Color.Gray;
00268         }
00269 
00270         System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
00271         void InitGraphs()
00272         {
00273             /*
00274             medicalChartLED = new MedicalChartHelper(chartLED,
00275                 "ChartArea1Red", "SeriesRed", "Red ADC Code",
00276                 "ChartArea2IR", "SeriesIR", "IR ADC Code",
00277                 "ChartArea3Green", "SeriesGreen", "Green ADC Code",
00278                 MedicalChartHelper.DataFormats.FormatUnsigned);
00279             medicalChartLED._plotPoints = 200;
00280             medicalChartAccel = new MedicalChartHelper(chartAccel,
00281                 "ChartArea4AccelX", "SeriesAccelX", "Accelerometer X",
00282                 "ChartArea5AccelY", "SeriesAccelY", "Accelerometer Y",
00283                 "ChartArea6AccelZ", "SeriesAccelZ", "Accelerometer Z",
00284                 MedicalChartHelper.DataFormats.Format16bit2sComplement);
00285             */
00286 
00287             MedianFilter fifo1 = new MedianFilter(10);
00288             MedianFilter fifo2 = new MedianFilter(10);
00289             MedianFilter fifo3 = new MedianFilter(10);
00290             MedianFilter accelx = new MedianFilter(10);
00291             MedianFilter accely = new MedianFilter(10);
00292             MedianFilter accelz = new MedianFilter(10);
00293 
00294             intervalDict.Add("ChartArea1Red", fifo1);
00295             intervalDict.Add("ChartArea2IR", fifo2);
00296             intervalDict.Add("ChartArea3Green", fifo3);
00297 
00298             intervalDict.Add("ChartArea4AccelX", accelx);
00299             intervalDict.Add("ChartArea5AccelY", accely);
00300             intervalDict.Add("ChartArea6AccelZ", accelz);
00301 
00302             fifo1Calc = new AutoScaleCalculator(0, 90000);
00303             fifo1Calc.Minimum = 0;
00304             fifo1Calc.Maximum = Math.Pow(2, 18);
00305             fifo1Calc.Intervals = 5;
00306             fifo1Calc.MinimumRange = 200;
00307             fifo1Calc.ScaleTrigger = 0.8;
00308             fifo1Calc.RescaleTargetRange = 0.25;
00309             chartScaleDict.Add("ChartArea1Red", fifo1Calc);
00310 
00311             fifo2Calc = new AutoScaleCalculator(0, 90000);
00312             fifo2Calc.Minimum = 0;
00313             fifo2Calc.Maximum = Math.Pow(2, 18);
00314             fifo2Calc.Intervals = 5;
00315             fifo2Calc.MinimumRange = 200;
00316             fifo2Calc.ScaleTrigger = 0.8;
00317             fifo2Calc.RescaleTargetRange = 0.25;
00318             chartScaleDict.Add("ChartArea2IR", fifo2Calc);
00319 
00320             fifo3Calc = new AutoScaleCalculator(0, 90000);
00321             fifo3Calc.Minimum = 0;
00322             fifo3Calc.Maximum = Math.Pow(2, 18);
00323             fifo3Calc.Intervals = 5;
00324             fifo3Calc.MinimumRange = 200;
00325             fifo3Calc.ScaleTrigger = 0.8;
00326             fifo3Calc.RescaleTargetRange = 0.25;
00327             chartScaleDict.Add("ChartArea3Green", fifo2Calc);
00328 
00329             AutoScaleCalculator accelXCalc = new AutoScaleCalculator(-10000, 10000);
00330             accelXCalc.Minimum = -32768;
00331             accelXCalc.Maximum = 32767;
00332             accelXCalc.Intervals = 5;
00333             accelXCalc.MinimumRange = 500;
00334             accelXCalc.ScaleTrigger = 0.8;
00335             accelXCalc.RescaleTargetRange = 0.25;
00336             chartScaleDict.Add("ChartArea4AccelX", accelXCalc);
00337 
00338             AutoScaleCalculator accelYCalc = new AutoScaleCalculator(-10000, 10000);
00339             accelYCalc.Minimum = -32768;
00340             accelYCalc.Maximum = 32767;
00341             accelYCalc.Intervals = 5;
00342             accelYCalc.MinimumRange = 500;
00343             accelYCalc.ScaleTrigger = 0.8;
00344             accelYCalc.RescaleTargetRange = 0.25;
00345             chartScaleDict.Add("ChartArea5AccelY", accelYCalc);
00346 
00347             AutoScaleCalculator accelZCalc = new AutoScaleCalculator(-10000, 10000);
00348             accelZCalc.Minimum = -32768;
00349             accelZCalc.Maximum = 32767;
00350             accelZCalc.Intervals = 5;
00351             accelZCalc.MinimumRange = 500;
00352             accelZCalc.ScaleTrigger = 0.8;
00353             accelZCalc.RescaleTargetRange = 0.25;
00354             chartScaleDict.Add("ChartArea6AccelZ", accelZCalc);
00355 
00356             /*
00357             Random rand = new Random();
00358             int[] data1 = new int[10];
00359             int[] data2 = new int[10];
00360             int[] data3 = new int[10];
00361             double[] data1_ = new double[10];
00362             double[] data2_ = new double[10];
00363             double[] data3_ = new double[10];
00364             for (int i = 0; i < data1.Length; i++)
00365             {
00366                 data1[i] = rand.Next(10);
00367                 data2[i] = rand.Next(10);
00368                 data3[i] = rand.Next(10);
00369                 data1_[i] = rand.NextDouble() * 10;
00370                 data2_[i] = rand.NextDouble() * 10;
00371                 data3_[i] = rand.NextDouble() * 10;
00372             }
00373             */
00374 
00375             /*
00376             int[] dummyData = new int[] { 0 };
00377             medicalChartLED.AppendDataChartArea1(dummyData, 0, 0);
00378             medicalChartLED.AppendDataChartArea2(dummyData, 0, 0);
00379             medicalChartLED.AppendDataChartArea3(dummyData, 0, 0);
00380             //medicalChartAccel._xCount1++;
00381             //medicalChartAccel._xCount2++;
00382             //medicalChartAccel._xCount3++;
00383             medicalChartAccel.AppendDataChartArea1(dummyData, 0, 0);
00384             medicalChartAccel.AppendDataChartArea2(dummyData, 0, 0);
00385             medicalChartAccel.AppendDataChartArea3(dummyData, 0, 0);
00386             */
00387 
00388             setupGraphs();
00389 
00390             chartLED.ChartAreas["ChartArea3Green"].Visible = false;
00391             timer.Interval = 50;    
00392             //timer.Tick += new EventHandler(timer_Tick);
00393         }
00394 
00395         void setupGraphs()
00396         {
00397             chartLED.SuspendLayout();
00398             chartAccel.SuspendLayout();
00399 
00400             /* Initialize Empty Chart Grid */
00401             chartLED.Series["SeriesRed"].Points.Clear();
00402             chartLED.Series["SeriesIR"].Points.Clear();
00403             chartLED.Series["SeriesGreen"].Points.Clear();
00404 
00405             chartAccel.Series["SeriesAccelX"].Points.Clear();
00406             chartAccel.Series["SeriesAccelY"].Points.Clear();
00407             chartAccel.Series["SeriesAccelZ"].Points.Clear();
00408 
00409             // Clear labels
00410             chartLED.ChartAreas["ChartArea1Red"].AxisX.CustomLabels.Clear();
00411             chartLED.ChartAreas["ChartArea2IR"].AxisX.CustomLabels.Clear();
00412             chartLED.ChartAreas["ChartArea3Green"].AxisX.CustomLabels.Clear();
00413             chartAccel.ChartAreas["ChartArea4AccelX"].AxisX.CustomLabels.Clear();
00414             chartAccel.ChartAreas["ChartArea5AccelY"].AxisX.CustomLabels.Clear();
00415             chartAccel.ChartAreas["ChartArea6AccelZ"].AxisX.CustomLabels.Clear();
00416 
00417             chartLED.Series["SeriesRed"].Points.Add(0);
00418             chartLED.Series["SeriesIR"].Points.Add(0);
00419             chartLED.Series["SeriesGreen"].Points.Add(0);
00420 
00421             chartAccel.Series["SeriesAccelX"].Points.Add(0);
00422             chartAccel.Series["SeriesAccelY"].Points.Add(0);
00423             chartAccel.Series["SeriesAccelZ"].Points.Add(0);
00424 
00425             // Initialize Plots for OS24
00426             chartLED.ChartAreas["ChartArea1Red"].AxisX.Interval = points / ChartTime;
00427             chartLED.ChartAreas["ChartArea2IR"].AxisX.Interval = points / ChartTime;
00428             chartLED.ChartAreas["ChartArea3Green"].AxisX.Interval = points / ChartTime;
00429             chartLED.ChartAreas["ChartArea1Red"].AxisX.Maximum = points;
00430             chartLED.ChartAreas["ChartArea2IR"].AxisX.Maximum = points;
00431             chartLED.ChartAreas["ChartArea3Green"].AxisX.Maximum = points;
00432             chartLED.ChartAreas["ChartArea1Red"].AxisY.Maximum = 90000;
00433             chartLED.ChartAreas["ChartArea1Red"].AxisY.Minimum = 0;
00434             chartLED.ChartAreas["ChartArea2IR"].AxisY.Maximum = 90000;
00435             chartLED.ChartAreas["ChartArea2IR"].AxisY.Minimum = 0;
00436             chartLED.ChartAreas["ChartArea3Green"].AxisY.Maximum = 90000;
00437             chartLED.ChartAreas["ChartArea3Green"].AxisY.Minimum = 0;
00438 
00439             // Initialize Plots for LIS2HD
00440             sampleRateAccel = sampleRate;
00441             //pointsAccel = (sampleRateAccel / sampleAverage) * ChartTime;
00442             pointsAccel = (sampleRateAccel) * ChartTime;
00443             chartAccel.ChartAreas["ChartArea4AccelX"].AxisX.Interval = pointsAccel / ChartTime;
00444             chartAccel.ChartAreas["ChartArea5AccelY"].AxisX.Interval = pointsAccel / ChartTime;
00445             chartAccel.ChartAreas["ChartArea6AccelZ"].AxisX.Interval = pointsAccel / ChartTime;
00446             chartAccel.ChartAreas["ChartArea4AccelX"].AxisX.Maximum = pointsAccel;
00447             chartAccel.ChartAreas["ChartArea5AccelY"].AxisX.Maximum = pointsAccel;
00448             chartAccel.ChartAreas["ChartArea6AccelZ"].AxisX.Maximum = pointsAccel;
00449             chartAccel.ChartAreas["ChartArea4AccelX"].AxisY.Minimum = -10000;
00450             chartAccel.ChartAreas["ChartArea5AccelY"].AxisY.Minimum = -10000;
00451             chartAccel.ChartAreas["ChartArea6AccelZ"].AxisY.Minimum = -10000;
00452             chartAccel.ChartAreas["ChartArea4AccelX"].AxisY.Maximum = 10000;
00453             chartAccel.ChartAreas["ChartArea5AccelY"].AxisY.Maximum = 10000;
00454             chartAccel.ChartAreas["ChartArea6AccelZ"].AxisY.Maximum = 10000;
00455 
00456             // Set X-axis labels in seconds
00457             for (int i = 0; i < ChartTime + 1; i++)
00458             {
00459                 chartLED.ChartAreas["ChartArea1Red"].AxisX.CustomLabels.Add( (sampleRate / sampleAverage) * (2 * i - 1) / 2, (sampleRate / sampleAverage) * (2 * i + 1) / 2, i.ToString());
00460                 chartLED.ChartAreas["ChartArea2IR"].AxisX.CustomLabels.Add( (sampleRate / sampleAverage) * (2 * i - 1) / 2, (sampleRate / sampleAverage) * (2 * i + 1) / 2, i.ToString());
00461                 chartLED.ChartAreas["ChartArea3Green"].AxisX.CustomLabels.Add( (sampleRate / sampleAverage) * (2 * i - 1) / 2, (sampleRate / sampleAverage) * (2 * i + 1) / 2, i.ToString());
00462 
00463                 chartAccel.ChartAreas["ChartArea4AccelX"].AxisX.CustomLabels.Add(sampleRateAccel * (2 * i - 1) / 2, sampleRateAccel * (2 * i + 1) / 2, i.ToString());
00464                 chartAccel.ChartAreas["ChartArea5AccelY"].AxisX.CustomLabels.Add(sampleRateAccel * (2 * i - 1) / 2, sampleRateAccel * (2 * i + 1) / 2, i.ToString());
00465                 chartAccel.ChartAreas["ChartArea6AccelZ"].AxisX.CustomLabels.Add(sampleRateAccel * (2 * i - 1) / 2, sampleRateAccel * (2 * i + 1) / 2, i.ToString());
00466             }
00467 
00468             chartLED.ResumeLayout();
00469             chartLED.Invalidate();
00470             chartAccel.ResumeLayout();
00471             chartAccel.Invalidate();
00472         }
00473 
00474         void timer_Tick(object sender, EventArgs e)
00475         {
00476             /*Single tmpData = dynamicData[0].Y;
00477             for (int i = 0; i < dynamicData.Length - 1; i++)
00478             {
00479                 dynamicData[i].Y = dynamicData[i + 1].Y;
00480             }
00481             dynamicData[dynamicData.Length - 1].Y = tmpData;*/
00482 
00483             //PointF[] newData = GenerateDynamicData(100, 5);
00484             //UpdateLedChart("SeriesRed", newData);
00485             //UpdateLedChart("SeriesIR", newData);
00486             //UpdateLedChart("SeriesGreen", newData);
00487         }
00488 
00489         /*private void UpdateLedChart(string seriesName, PointF[] data)
00490         {
00491             int count; 
00492 
00493             chartLED.SuspendLayout();
00494             //chartLED.Series[seriesName].Points.Clear();
00495             foreach (PointF pt in data)
00496             {
00497                 //chartLED.Series[seriesName].Points.AddXY(pt.X, pt.Y);
00498                 chartLED.Series[seriesName].Points.Add(pt.Y);
00499             }
00500 
00501             for (count = chartLED.Series[seriesName].Points.Count; 
00502                 count > points; 
00503                 count = chartLED.Series[seriesName].Points.Count)
00504             {
00505                 chartLED.Series[seriesName].Points.RemoveAt(0);
00506             } 
00507             chartLED.ResumeLayout();
00508             chartLED.Invalidate();
00509         }*/
00510 
00511         private void UpdateXYZChart(string seriesName, int[] data)
00512         {
00513             int datapoint;
00514             int count;
00515 
00516             chartAccel.SuspendLayout();
00517             //chartLED.Series[seriesName].Points.Clear();
00518             foreach (int val in data)
00519             {
00520                 //chartLED.Series[seriesName].Points.AddXY(pt.X, pt.Y);
00521                 datapoint = val;
00522                 // Two's complement conversion
00523                 if (val > 0x8000)
00524                 {
00525                     datapoint = datapoint - 0x10000;
00526                 }
00527                     chartAccel.Series[seriesName].Points.Add(datapoint);
00528             }
00529 
00530             for (count = chartAccel.Series[seriesName].Points.Count;
00531                 count > pointsAccel;
00532                 count = chartAccel.Series[seriesName].Points.Count)
00533             {
00534                 chartAccel.Series[seriesName].Points.RemoveAt(0);
00535             }
00536             //chartAccel.ResetAutoValues();
00537             chartAccel.ResumeLayout();
00538             chartAccel.Invalidate();
00539         }
00540 
00541         private void UpdateLedChart(string seriesName, int[] data)
00542         {
00543             int[] dataPoints = new int[points];
00544             int j = 0;
00545             int count;
00546 
00547             chartLED.SuspendLayout();
00548             //chartLED.Series[seriesName].Points.Clear();
00549 
00550             // Update Chart with new data
00551             if (data.Length > points)
00552                 j = data.Length - points;
00553 
00554             for (; j < data.Length; j++ )
00555             {
00556                 chartLED.Series[seriesName].Points.Add(data[j]);
00557 #if CES_DEMO
00558                 if (seriesName.CompareTo("SeriesRed") == 0)
00559                     red.Enqueue(data[j]);
00560                 else if (seriesName.CompareTo("SeriesIR") == 0)
00561                     ir.Enqueue(data[j]);
00562                 else if (seriesName.CompareTo("SeriesGreen") == 0)
00563                     led.Enqueue(data[j]);
00564 #endif
00565             }
00566 
00567             for (count = chartLED.Series[seriesName].Points.Count; 
00568                 count > points; 
00569                 count = chartLED.Series[seriesName].Points.Count)
00570             {
00571                 chartLED.Series[seriesName].Points.RemoveAt(0);
00572             }
00573         }
00574 
00575         private void UpdateLedChartScale(string chartName, string seriesName)
00576         {
00577             int min = Int32.MaxValue, max = 0;
00578             int i, j;
00579             int[] data = new int[points];
00580             int graphCount;
00581             //int maxRound, minRound;
00582 
00583             graphCount = chartLED.Series[seriesName].Points.Count;
00584 
00585             for (j = 0; j < graphCount; j++ )
00586             {
00587                 data[j] = (int)chartLED.Series[seriesName].Points[j].YValues[0];
00588             }
00589 
00590             //if (data.Length < sampleRate)
00591             //    return; // not enough data to draw graph
00592             /*else*/
00593             if (graphCount < (sampleRate / sampleAverage) * 2) // look back 2 seconds
00594             {
00595                 i = 0;
00596             }
00597             else // look back 2 seconds
00598             {
00599                 i = graphCount - (sampleRate / sampleAverage) * 2;
00600             }
00601 
00602             min = data[i];
00603             max = data[i];
00604             for (; i < graphCount; i++ )
00605             {
00606                 if (data[i] < min && data[i] != 0)
00607                     min = data[i];
00608                 else if (data[i] > max)
00609                     max = data[i];
00610             }
00611 
00612             /*
00613             MedianFilter filter;
00614             intervalDict.TryGetValue(chartName, out filter);
00615 
00616             var minMax = chartInterval(min, max, chartLED.ChartAreas[chartName].AxisY.Minimum, chartLED.ChartAreas[chartName].AxisY.Maximum, filter);
00617             minRound = minMax.Item1;
00618             maxRound = minMax.Item2;
00619 
00620 
00621 
00622             // For no finger on sensor
00623             if (max < 500)
00624                 max = 500;
00625             */
00626 
00627             AutoScaleCalculator chartScale;
00628             chartScaleDict.TryGetValue(chartName, out chartScale);
00629 
00630             var minMax = chartScale.Interval(min, max);
00631 
00632             // Round to nearest 100 with averaging
00633             //chartLED.ChartAreas[chartName].AxisY.Maximum = (chartLED.ChartAreas[chartName].AxisY.Maximum + (max / 100 + 1) * 100)/2;
00634             //chartLED.ChartAreas[chartName].AxisY.Maximum = (((int)chartLED.ChartAreas[chartName].AxisY.Maximum + max)/200 + 1) * 100;
00635             //chartLED.ChartAreas[chartName].AxisY.Minimum = (chartLED.ChartAreas[chartName].AxisY.Minimum + (min / 100 - 1) * 100)/2;
00636             //chartLED.ChartAreas[chartName].AxisY.Minimum = (((int)chartLED.ChartAreas[chartName].AxisY.Minimum + min)/200 - 1) * 100;
00637             chartLED.ChartAreas[chartName].AxisY.Minimum = minMax.Item1;
00638             chartLED.ChartAreas[chartName].AxisY.Maximum = minMax.Item2;
00639 
00640             chartLED.ResumeLayout();
00641             chartLED.Invalidate();
00642         }
00643 
00644         private void UpdateXYZChartScale(string chartName, string seriesName)
00645         {
00646             int min = Int32.MaxValue, max = Int32.MinValue;
00647             int i, j;
00648             int maxRound, minRound;
00649             int graphCount;
00650 
00651             int[] data = new int[pointsAccel];
00652 
00653             graphCount = chartAccel.Series[seriesName].Points.Count;
00654 
00655             // Save all points from plot to data[]
00656             for (j = 0; j < graphCount; j++)
00657             {
00658                 data[j] = (int)chartAccel.Series[seriesName].Points[j].YValues[0];
00659             }
00660 
00661             if (graphCount < (sampleRateAccel / sampleAverage) * 2) // look back 3 seconds
00662                 i = 0;
00663             else
00664                 i = graphCount - (sampleRateAccel / sampleAverage) * 2;
00665 
00666             // Find min/max
00667             min = data[i];
00668             max = data[i];
00669             for (; i < graphCount; i++)
00670             {
00671                 if (data[i] < min)
00672                     min = data[i];
00673                 else if (data[i] > max)
00674                     max = data[i];
00675             }
00676 
00677             /*
00678             // Sane defaults
00679             if (min == max)
00680             {
00681                 min = 0;
00682                 max = 100;
00683             }
00684 
00685             MedianFilter filter;
00686             intervalDict.TryGetValue(chartName, out filter);
00687 
00688             var minMax = chartInterval(min, max, chartAccel.ChartAreas[chartName].AxisY.Minimum, chartAccel.ChartAreas[chartName].AxisY.Maximum, filter);
00689             minRound = minMax.Item1;
00690             maxRound = minMax.Item2;
00691 
00692             if (maxRound > 32768)
00693                 maxRound = 33000;
00694 
00695             if (minRound < -32768)
00696                 minRound = -33000;
00697             */
00698 
00699             AutoScaleCalculator chartScale;
00700             chartScaleDict.TryGetValue(chartName, out chartScale);
00701 
00702             var minMax = chartScale.Interval(min, max);
00703             minRound = (int)minMax.Item1;
00704             maxRound = (int)minMax.Item2;
00705 
00706             // Set the Min and Max for Y Axis
00707             //chartAccel.ChartAreas[chartName].AxisY.Maximum = (((int)chartAccel.ChartAreas[chartName].AxisY.Maximum + max) / 200 + 1) * 100;
00708             //chartAccel.ChartAreas[chartName].AxisY.Minimum = (((int)chartAccel.ChartAreas[chartName].AxisY.Minimum + min) / 200 - 1) * 100;
00709             chartAccel.ChartAreas[chartName].AxisY.Maximum = maxRound;
00710             chartAccel.ChartAreas[chartName].AxisY.Minimum = minRound;
00711             //System.Diagnostics.Debug.Print(chartName + " count: " + graphCount + " minRound: " + minRound + " maxRound: " + maxRound + " min: " + min + " max: " + max);
00712 
00713             chartAccel.ResumeLayout();
00714             chartAccel.Invalidate();
00715         }
00716 
00717         /*private PointF[] dynamicData;
00718         private static PointF[] GenerateDynamicData(double amplitude, int sampleCount)
00719         {
00720             Random rnd = new Random();
00721             PointF[] points = new PointF[sampleCount];
00722             points[0] = new PointF(0, (Single)(amplitude * rnd.NextDouble()));
00723             for (int i = 1; i < sampleCount; i++)
00724             {
00725                 points[i] = new PointF(i, (Single)(points[i - 1].Y + (amplitude / 10 * (0.5 - rnd.NextDouble()))));
00726                 if (points[i].Y > amplitude) points[i].Y = (Single)amplitude;
00727             }
00728             return (points);
00729         }*/
00730 
00731         /// <summary>
00732         /// Calculate rounded minimum and maximum for chart data
00733         /// </summary>
00734         /// <param name="minimum"></param>
00735         /// <param name="maximum"></param>
00736         /// <param name="chartInterval"></param>
00737         /// <returns></returns>
00738         private static Tuple<int, int> chartInterval(int minimum, int maximum, double chartMinimum, double chartMaximum, MedianFilter chartInterval)
00739         {
00740             int delta, interval, roundInterval, roundCenter;
00741             double mag, magPower, magMostSigDigit;
00742             int center;
00743 
00744             // 10% and 90% range
00745             int chartRange = (int)(chartMaximum - chartMinimum);
00746             int dataRange = maximum - minimum;
00747             if (minimum < chartMinimum + chartRange * 0.10 || maximum > chartMaximum - chartRange * 0.10
00748                 || dataRange > 0.9 * chartRange || dataRange < 0.1 * chartRange)
00749             {
00750 
00751                 delta = (int)((maximum - minimum));
00752 
00753                 interval = delta * (100 / 35) / 5; // delta * 4 = 25% * 4 = 100 (full chart scale)
00754                 center = minimum + (maximum - minimum) / 2;
00755 
00756                 mag = Math.Floor(Math.Log10(interval));
00757                 magPower = Math.Pow(10, mag);
00758 
00759                 magMostSigDigit = (int)(interval / (double)magPower + 0.5);
00760 
00761                 if (magMostSigDigit >= 5.0)
00762                     magMostSigDigit = 10;
00763                 else if (magMostSigDigit >= 2.0)
00764                     magMostSigDigit = 5;
00765                 else if (magMostSigDigit >= 1.0)
00766                     magMostSigDigit = 2;
00767 
00768                 roundInterval = (int)(magMostSigDigit * magPower);
00769                 if (roundInterval < 100)
00770                 {
00771                     roundInterval = 100;
00772                 }
00773                 roundInterval = chartInterval.Filter(roundInterval);
00774 
00775                 roundCenter = ((center + 100) / 200) * 200;
00776 
00777                 int roundMin = (int)(roundCenter - roundInterval * 2.5);
00778                 int roundMax = (int)(roundCenter + roundInterval * 2.5);
00779                 if (roundInterval > 104858)
00780                 {
00781                     roundMin = 0;
00782                     roundMax = 550000;
00783                 }
00784                 /*else
00785                 {
00786                     if (roundMin < 0) // || roundMax > 524288)
00787                     {
00788                         roundMin = 0;
00789                         roundMax = roundInterval * 5;
00790                     }
00791                 }*/
00792 
00793                 return new Tuple<int, int>(roundMin, roundMax);
00794             }
00795 
00796             return new Tuple<int, int>((int)chartMinimum, (int)chartMaximum);
00797         }
00798 
00799         void OpticalSensorInitControls()
00800         {
00801             cboMode.Items.AddRange(new string[] { "HR","SPO2","LED" });
00802             cboSampleRate.Items.AddRange(new string[] { "50", "100", "200", "400" });
00803             cboSampleAvg.Items.AddRange(new string[] { "1", "2", "4", "8", "16", "32" });
00804             cboPulseWidth.Items.AddRange(new string[] { "69", "118", "215", "411" });
00805             cboADCFSrangenA.Items.AddRange(new string[] { "2048", "4096", "8192", "16384" });
00806             double slopeInt = 25.0 / 128.0;
00807             for (int index = 0; index < 256; index++)
00808             {
00809                 string str = index < 0x0F ? (0.2 * index).ToString() : (slopeInt * index + slopeInt).ToString();
00810                 cboIRLED.Items.Add(str);
00811                 cboRedLED.Items.Add(str);
00812                 cboGreenLED.Items.Add(str);
00813                 cboPilotPA.Items.Add(str);
00814             }
00815 
00816             OpticalSensorDefaults();
00817             calculateAvgCurrent();
00818 
00819             InitGraphs();            
00820         }
00821 
00822         public void OpticalSensorDefaults()
00823         {
00824             cboMode.SelectedItem = "SPO2";
00825             cboRedLED.SelectedItem = "10.15625";
00826             cboIRLED.SelectedItem = "10.15625";
00827             cboGreenLED.SelectedItem = "10.15625";
00828             cboSampleRate.SelectedItem = "100";
00829             cboPulseWidth.SelectedItem = "411";
00830             cboSampleAvg.SelectedItem = "1";
00831             cboADCFSrangenA.SelectedItem = "8192";
00832 
00833             cboLEDslot1.SelectedIndex = 1;
00834             cboLEDslot2.SelectedIndex = 2;
00835             cboLEDslot3.SelectedIndex = 3;
00836             cboLEDslot4.SelectedIndex = 0;
00837 
00838             // Used to generate the initial chart grid
00839             sample_rate = (byte)cboSampleRate.SelectedIndex;
00840             sample_avg = (byte)cboSampleAvg.SelectedIndex;
00841 
00842             sampleRate = (1 << sample_rate) * 50; // (1 << sample_rate) = 2^sample_rate
00843             sampleAverage = (1 << sample_avg); // 2^sample_avg
00844             points = (sampleRate / sampleAverage) * ChartTime; // 4 seconds, 2^sample_av
00845 
00846             sampleRateAccel = sampleRate; 
00847             pointsAccel = (sampleRateAccel / sampleAverage) * ChartTime;
00848         }
00849 
00850         private void cbo_IndexChanged(object sender, EventArgs e)
00851         {
00852             if ((MaximStyle.MaximComboBox)sender == cboMode)
00853             {
00854                 bool HRmode = (cboMode.Text == "HR");
00855                 bool SPO2mode = (cboMode.Text == "SPO2");
00856                 bool multiLEDmode = (cboMode.Text == "LED");
00857                 //labelcboRedLED.Enabled = myMAX30101.valid_Red;
00858                 //cboRedLED.Enabled = myMAX30101.valid_Red;
00859                 bool valid_IR = (multiLEDmode || SPO2mode);
00860                 bool valid_Green = multiLEDmode;
00861                 bool valid_Red = multiLEDmode;
00862                 labelcboIRLED.Enabled = valid_IR;
00863                 cboIRLED.Enabled = valid_IR;
00864                 labelcboGreenLED.Enabled = valid_Green;
00865                 cboGreenLED.Enabled = valid_Green;
00866                 cboLEDslot1.Enabled = multiLEDmode;
00867                 cboLEDslot2.Enabled = multiLEDmode;
00868                 cboLEDslot3.Enabled = multiLEDmode;
00869                 cboLEDslot4.Enabled = multiLEDmode;
00870                 {
00871                     // Hide unused LED channel graphs
00872                     // | mode | ChartArea1Red | ChartArea2IR | ChartArea3Green |
00873                     // | LED  |   visible     |   visible    |   visible       | MAX30101 only
00874                     // | SPO2 |   visible     |   visible    |   hidden        |
00875                     // | HR   |   visible     |   hidden     |   hidden        | MAX30101: Red only. MAX30100: IR only.
00876                     valid_Red = true;
00877                     valid_IR = multiLEDmode || SPO2mode;
00878                     valid_Green = multiLEDmode;
00879                     
00880                     chartLED.ChartAreas["ChartArea1Red"].Visible = valid_Red;
00881                     chartLED.ChartAreas["ChartArea2IR"].Visible = valid_IR;
00882                     chartLED.ChartAreas["ChartArea3Green"].Visible = valid_Green;                   
00883                 }
00884             }
00885         }
00886 
00887         public void On_AppendChart(object sender, PartialArrayIntAvailableEventArgs e)
00888         {
00889             if (streaming)
00890             {
00891                 if ((e.reportID & 0xF0) == PartialArrayIntAvailableEventArgs.PACKET_MAX30101)
00892                 {
00893                     if (e.array1.Length != 0)
00894                     {
00895                         UpdateLedChart("SeriesRed", e.array1);
00896                         UpdateLedChartScale("ChartArea1Red", "SeriesRed");
00897                     }
00898                     if (e.array2.Length != 0)
00899                     {
00900                         UpdateLedChart("SeriesIR", e.array2);
00901                         UpdateLedChartScale("ChartArea2IR", "SeriesIR");
00902                     }
00903                     if (e.array3.Length != 0)
00904                     {
00905                         UpdateLedChart("SeriesGreen", e.array3);
00906                         UpdateLedChartScale("ChartArea3Green", "SeriesGreen");
00907                     }
00908                 }
00909                 if (e.reportID == PartialArrayIntAvailableEventArgs.PACKET_LIS2DH)
00910                 {
00911                     if (e.array1.Length != 0)
00912                     {
00913                         UpdateXYZChart("SeriesAccelX", e.array1);
00914                         UpdateXYZChartScale("ChartArea4AccelX", "SeriesAccelX");
00915                     }
00916                     if (e.array2.Length != 0)
00917                     {
00918                         UpdateXYZChart("SeriesAccelY", e.array2);
00919                         UpdateXYZChartScale("ChartArea5AccelY", "SeriesAccelY");
00920                     }
00921                     if (e.array3.Length != 0)
00922                     {
00923                         UpdateXYZChart("SeriesAccelZ", e.array3);
00924                         UpdateXYZChartScale("ChartArea6AccelZ", "SeriesAccelZ");
00925                     }
00926 
00927 #if CES_DEMO
00928                 if (sampleRate == 100)
00929                     updateAlgorithm();
00930 #endif
00931                 }
00932             }
00933         }
00934 
00935 #if CES_DEMO
00936         private void updateAlgorithm()
00937         {
00938             int rtn = 0;
00939 
00940             while (red.Count != 0 ) //&& ir.Couunt != 0 && led.Count != 0)
00941             {
00942                 StringBuilder outputData = new StringBuilder();
00943                 int redVal = (Int32)red.Dequeue(); // Always dequeue red, checked in while loop
00944                 int irVal = ir.Count > 0 ? (Int32)ir.Dequeue() : 1;
00945                 int ledVal = led.Count > 0 ? (Int32)led.Dequeue() : 1;
00946 
00947                 switch (streamMode)
00948                 {
00949                     case eStreamMode.eSPO2:
00950                         rtn = AlgorithmMobileBU.runAlgorithm_win(irVal, redVal, 1, // ir, r, led
00951                                     25, sampleRate, ++algoCounter, 
00952                                     0, 0, 0, ref config, ref output);
00953                         break;
00954                     case eStreamMode.eHR: // TODO: Not functioning
00955                         rtn = AlgorithmMobileBU.runAlgorithm_win(1, redVal, 1, // ir, r, led
00956                                     25, sampleRate, ++algoCounter, 
00957                                     0, 0, 0, ref config, ref output);
00958                         break;
00959                     case eStreamMode.eMulti:
00960                         rtn = AlgorithmMobileBU.runAlgorithm_win(irVal, redVal, ledVal, // ir, r, led
00961                                     25, sampleRate, ++algoCounter, 
00962                                     0, 0, 0, ref config, ref output);
00963                         break;
00964                 }
00965 
00966                 //outputData.Append(DateTime.Now.ToString("HH:mm:ss.ffff"));
00967                 //outputData.Append(",");
00968                 //outputData.Append(irVal);
00969                 //outputData.Append(",");
00970                 //outputData.Append(redVal);
00971                 //outputData.Append(",");
00972                 //outputData.Append(0); // Can be green
00973                 //outputData.Append(",");
00974                 //outputData.Append(0); // Ax
00975                 //outputData.Append(",");
00976                 //outputData.Append(0); // Ay
00977                 //outputData.Append(",");
00978                 //outputData.Append(0); // Az
00979                 //outputData.Append(",");
00980 
00981                 //file.WriteLine(outputData.ToString()); // Raw data output
00982             }
00983 
00984             lblHeartRate.Text = Math.Round(output.hr).ToString(); //redIn.ToString();
00985             lblRespRate.Text = output.resp_rate.ToString("N");
00986             lblSpO2.Text = output.R == 0 ? "0" : (-45.060 * output.R * output.R + 30.354 * output.R + 94.845).ToString("N");//output.spo2.ToString("N");
00987             lblHeartRateVariation.Text = output.hrv.ToString("N");
00988             lblPulseInterval.Text = output.pulse_interval.ToString("N");
00989         }
00990 
00991 #endif
00992 
00993         private void OpticalView_Load(object sender, EventArgs e)
00994         {
00995             //OpticalSensorInitControls();
00996             //OpticalSensorDefaults();
00997         }
00998 
00999         private void streamingStartStop()
01000         {
01001             if (cboMode.Text == "HR") streamMode = eStreamMode.eHR;
01002             if (cboMode.Text == "SPO2") streamMode = eStreamMode.eSPO2;
01003             if (cboMode.Text == "LED") streamMode = eStreamMode.eMulti;
01004 
01005             if (Connected && btnMonitoring.Text == StartString)
01006             {
01007                 streaming = true;
01008                 sample_rate = (byte)cboSampleRate.SelectedIndex;
01009                 sample_avg = (byte)cboSampleAvg.SelectedIndex;
01010                 pulse_width = (byte)cboPulseWidth.SelectedIndex;
01011                 red_led_current = (byte)cboRedLED.SelectedIndex;
01012                 ir_led_current = (byte)cboIRLED.SelectedIndex;
01013                 green_led_current = (byte)cboGreenLED.SelectedIndex;
01014                 slot_1 = (byte)cboLEDslot1.SelectedIndex;
01015                 slot_2 = (byte)cboLEDslot2.SelectedIndex;
01016                 slot_3 = (byte)cboLEDslot3.SelectedIndex;
01017                 slot_4 = (byte)cboLEDslot4.SelectedIndex;
01018 
01019                 sampleRate = Int32.Parse((string)cboSampleRate.SelectedItem);
01020                 sampleAverage = Int32.Parse((string)cboSampleAvg.SelectedItem);
01021                 points = (sampleRate / sampleAverage ) * ChartTime;
01022 
01023                 foreach (Control c in streamingControls)
01024                     c.Enabled = false;
01025 
01026 #if CES_DEMO
01027                 // For Algorithm
01028                 sampleRate = (1 << sample_rate) * 50; // (1 << sample_rate) = 2^sample_rate
01029                 sampleAverage = (1 << sample_avg); // 2^sample_avg
01030                 points = (sampleRate / sampleAverage) * ChartTime; // 4 seconds, 2^sample_av
01031 
01032                 sampleRateAccel = 10; // TODO, update with real value from Jerry
01033                 pointsAccel = (sampleRateAccel / sampleAverage) * ChartTime;
01034 
01035                 // Reset algorithm counter
01036                 algoCounter = 0;
01037 
01038                 if (sampleRate == 100)
01039                 {
01040                     lblHeartRateText.Enabled = true;
01041                     lblHeartRate.Enabled = true;
01042                     lblSpO2.Enabled = true;
01043                     lblSpO2Text.Enabled = true;
01044                 }
01045                 else
01046                 {
01047                     lblHeartRateText.Enabled = false;
01048                     lblHeartRate.Enabled = false;
01049                     lblSpO2.Enabled = false;
01050                     lblSpO2Text.Enabled = false;
01051                 }
01052 #endif
01053 
01054                 // Setup grid
01055                 setupGraphs();
01056 
01057                 switch (streamMode)
01058                 {
01059                     case eStreamMode.eHR:
01060                         rpcClient.MAX30101.HRmode_init(fifo_waterlevel_mark, sample_avg, sample_rate, pulse_width,
01061                                                                          red_led_current, (byte)(sample_rate + 4));
01062                         break;
01063                     case eStreamMode.eMulti:
01064                         rpcClient.MAX30101.Multimode_init(fifo_waterlevel_mark, sample_avg, sample_rate, pulse_width,
01065                                              red_led_current, ir_led_current, green_led_current,
01066                                              slot_1, slot_2, slot_3, slot_4, (byte)(sample_rate + 4));
01067                         break;
01068                     case eStreamMode.eSPO2:
01069                         rpcClient.MAX30101.SpO2mode_init(fifo_waterlevel_mark, sample_avg, sample_rate, pulse_width,
01070                                                                          red_led_current, ir_led_current, (byte)(sample_rate + 4));
01071                         break;
01072                 }
01073 
01074                 btnMonitoring.Text = StopString;
01075 
01076                 if (StreamingStartStop != null) 
01077                     StreamingStartStop(this, new StreamingStartStopEventArgs() { state = true });
01078 
01079             }
01080             else if (btnMonitoring.Text == StopString)
01081             {
01082                 streaming = false;
01083                 switch (streamMode)
01084                 {
01085                     case eStreamMode.eHR:
01086                         rpcClient.MAX30101.HRmode_stop(connected);
01087                         break;
01088                     case eStreamMode.eMulti:
01089                         rpcClient.MAX30101.Multimode_stop(connected);
01090                         break;
01091                     case eStreamMode.eSPO2:
01092                         rpcClient.MAX30101.SpO2mode_stop(connected);
01093                         break;
01094                 }
01095                 //rpcClient.MAX30101.StopStreaming();
01096                 btnMonitoring.Text = StartString;
01097 
01098                 foreach (Control c in streamingControls)
01099                     c.Enabled = true;
01100                 
01101                 if (StreamingStartStop != null)
01102                     StreamingStartStop(this, new StreamingStartStopEventArgs() { state = false });
01103             }
01104         }
01105 
01106         private void btnMonitoring_Click(object sender, EventArgs e)
01107         {
01108             //if (Connected)
01109             streamingStartStop();
01110         }
01111 
01112         private void button1_Click(object sender, EventArgs e)
01113         {
01114             timer.Start();
01115         }
01116 
01117         private void button1_Click_1(object sender, EventArgs e)
01118         {
01119             /* Debug*/
01120             //int count = chartLED.Series["SeriesRed"].Points.Count;
01121             //int count2 = chartAccel.Series["SeriesAccelX"].Points.Count;
01122             UpdateXYZChartScale("ChartArea6AccelZ", "SeriesAccelZ");
01123         }
01124 
01125         private void btnDefaults_Click(object sender, EventArgs e)
01126         {
01127             OpticalSensorDefaults();
01128         }
01129 
01130         private void cboSRPWLed_SelectedIndexChanged(object sender, EventArgs e)
01131         {
01132             calculateAvgCurrent();
01133         }
01134 
01135         private void calculateAvgCurrent()
01136         {
01137             double ratio = double.Parse(cboPulseWidth.Text) * 1e-6 * double.Parse(cboSampleRate.Text);
01138             string _noDataString = "---";
01139             if (ratio <= 1)
01140             {
01141                 lblAvgIRLEDcurrent.Text = String.Format("{0:0.00}", double.Parse(cboIRLED.Text) * ratio);
01142                 lblAvgRedLEDcurrent.Text = String.Format("{0:0.00}", double.Parse(cboRedLED.Text) * ratio);
01143                 // https://jira.maxim-ic.com/browse/OS24EVK-17 Green LED: Multi-LED Mode timeslice; FIFO Read Red, IR, Green
01144                 lblAvgGreenLEDcurrent.Text = String.Format("{0:0.00}", double.Parse(cboGreenLED.Text) * ratio);
01145                 // https://jira.maxim-ic.com/browse/OS24EVK-32 update lblAvgPilotPALEDcurrent from cboPilotPA similar to lblAvgGreenLEDcurrent
01146                 //lblAvgPilotPALEDcurrent.Text = String.Format("{0:0.00}", double.Parse(cboPilotPA.Text) * ratio);
01147             }
01148             else
01149             {
01150                 lblAvgIRLEDcurrent.Text = _noDataString;
01151                 lblAvgRedLEDcurrent.Text = _noDataString;
01152                 // https://jira.maxim-ic.com/browse/OS24EVK-17 Green LED: Multi-LED Mode timeslice; FIFO Read Red, IR, Green
01153                 lblAvgGreenLEDcurrent.Text = _noDataString;
01154                 // https://jira.maxim-ic.com/browse/OS24EVK-32 update lblAvgPilotPALEDcurrent from cboPilotPA similar to lblAvgGreenLEDcurrent
01155                 lblAvgPilotPALEDcurrent.Text = _noDataString;
01156             }
01157         }
01158 
01159         void cboSampleRate_SelectedIndexChanged(object sender, EventArgs e)
01160         {
01161             if ((string)cboSampleRate.SelectedItem == "100" && (string)cboSampleAvg.SelectedItem == "1")
01162                 grpAlgorithm.Enabled = true;
01163             else
01164                 grpAlgorithm.Enabled = false;
01165 
01166             sampleRate = Int32.Parse((string)cboSampleRate.SelectedItem);
01167             sampleAverage = Int32.Parse((string)cboSampleAvg.SelectedItem);
01168         }
01169 
01170         public string SettingsString()
01171         {
01172             StringBuilder strBuilder = new StringBuilder();
01173 
01174             strBuilder.Append("% ");
01175             strBuilder.Append("Mode = ");
01176             strBuilder.Append(cboMode.SelectedItem);
01177             strBuilder.Append(Environment.NewLine);
01178 
01179             strBuilder.Append("% ");
01180             strBuilder.Append("Sample Rate (Hz) = ");
01181             strBuilder.Append(cboSampleRate.SelectedItem);
01182             strBuilder.Append(" Sample Average = ");
01183             strBuilder.Append(cboSampleAvg.SelectedItem);
01184             strBuilder.Append(" Pulse Width (us) = ");
01185             strBuilder.Append(cboPulseWidth.SelectedItem);
01186             strBuilder.Append(" ADC Full Scale Range (nA) = ");
01187             strBuilder.Append(cboADCFSrangenA.SelectedItem);
01188             strBuilder.Append(Environment.NewLine);
01189 
01190             strBuilder.Append("% ");
01191             strBuilder.Append(" LED Red (mA) = ");
01192             strBuilder.Append(cboRedLED.SelectedItem);
01193             strBuilder.Append(" LED IR (mA) = ");
01194             strBuilder.Append(cboIRLED.SelectedItem);
01195             strBuilder.Append(" LED Green (mA) = ");
01196             strBuilder.Append(cboGreenLED.SelectedItem);
01197             strBuilder.Append(Environment.NewLine);
01198 
01199             strBuilder.Append("% ");
01200             strBuilder.Append("LED Slot 1 = ");
01201             strBuilder.Append(cboLEDslot1.SelectedIndex);
01202             strBuilder.Append(" LED Slot 2 = ");
01203             strBuilder.Append(cboLEDslot2.SelectedIndex);
01204             strBuilder.Append(" LED Slot 3 = ");
01205             strBuilder.Append(cboLEDslot3.SelectedIndex);
01206             strBuilder.Append(" LED Slot 4 = ");
01207             strBuilder.Append(cboLEDslot4.SelectedIndex);
01208 
01209             return strBuilder.ToString();
01210         }
01211 
01212         public string AccelSettingString()
01213         {
01214             return "% Sample Rate (Hz) = " + AccelSampleRate;
01215         }
01216 
01217         public InitArgs.HRModeInitStart GetHRModeArgs()
01218         {
01219             InitArgs.HRModeInitStart args = new InitArgs.HRModeInitStart();
01220 
01221             args.FifoWaterlevelMark = fifo_waterlevel_mark;
01222             args.SampleRate = (byte)cboSampleRate.SelectedIndex;
01223             args.SampleAverage = (byte)cboSampleAvg.SelectedIndex;
01224             args.PulseWidth = (byte)cboPulseWidth.SelectedIndex;
01225             args.RedLedCurrent = (byte)cboRedLED.SelectedIndex;
01226 
01227             return args;
01228         }
01229 
01230         public InitArgs.SpO2HRModeInitStart GetSpO2HRModeArgs()
01231         {
01232             InitArgs.SpO2HRModeInitStart args = new InitArgs.SpO2HRModeInitStart();
01233 
01234             args.FifoWaterlevelMark = fifo_waterlevel_mark;
01235             args.SampleRate = (byte)cboSampleRate.SelectedIndex;
01236             args.SampleAverage = (byte)cboSampleAvg.SelectedIndex;
01237             args.PulseWidth = (byte)cboPulseWidth.SelectedIndex;
01238             args.RedLedCurrent = (byte)cboRedLED.SelectedIndex;
01239             args.IRLedCurrent = (byte)cboIRLED.SelectedIndex;
01240 
01241             return args;
01242         }
01243 
01244         public InitArgs.MultiModeInitStart GetMultiModeArgs()
01245         {
01246             InitArgs.MultiModeInitStart args = new InitArgs.MultiModeInitStart();
01247 
01248             args.FifoWaterlevelMark = fifo_waterlevel_mark;
01249             args.SampleRate = (byte)cboSampleRate.SelectedIndex;
01250             args.SampleAverage = (byte)cboSampleAvg.SelectedIndex;
01251             args.PulseWidth = (byte)cboPulseWidth.SelectedIndex;
01252             args.RedLedCurrent = (byte)cboRedLED.SelectedIndex;
01253             args.IRLedCurrent = (byte)cboIRLED.SelectedIndex;
01254             args.GreenLedCurrent = (byte)cboGreenLED.SelectedIndex;
01255             args.Slot1 = (byte)cboLEDslot1.SelectedIndex;
01256             args.Slot2 = (byte)cboLEDslot2.SelectedIndex;
01257             args.Slot3 = (byte)cboLEDslot3.SelectedIndex;
01258             args.Slot4 = (byte)cboLEDslot4.SelectedIndex;
01259 
01260             return args;
01261         }
01262 
01263         public void SetHRModeArgs(InitArgs.HRModeInitStart args)
01264         {
01265             cboSampleRate.SelectedIndex = args.SampleRate; 
01266             cboSampleAvg.SelectedIndex = args.SampleAverage;
01267             cboPulseWidth.SelectedIndex = args.PulseWidth;
01268             cboRedLED.SelectedIndex = args.RedLedCurrent;
01269         }
01270         
01271         public void SetSpO2HRModeArgs(InitArgs.SpO2HRModeInitStart args)
01272         {
01273             cboSampleRate.SelectedIndex = args.SampleRate; 
01274             cboSampleAvg.SelectedIndex = args.SampleAverage;
01275             cboPulseWidth.SelectedIndex = args.PulseWidth;
01276             cboRedLED.SelectedIndex = args.RedLedCurrent;
01277             cboIRLED.SelectedIndex = args.IRLedCurrent;
01278         }
01279 
01280         public void SetMultiModeArgs(InitArgs.MultiModeInitStart args)
01281         {
01282             cboSampleRate.SelectedIndex = args.SampleRate;
01283             cboSampleAvg.SelectedIndex = args.SampleAverage;
01284             cboPulseWidth.SelectedIndex = args.PulseWidth;
01285             cboRedLED.SelectedIndex = args.RedLedCurrent;
01286             cboIRLED.SelectedIndex = args.IRLedCurrent;
01287             cboGreenLED.SelectedIndex = args.GreenLedCurrent;
01288             cboLEDslot1.SelectedIndex = args.Slot1;
01289             cboLEDslot2.SelectedIndex = args.Slot2;
01290             cboLEDslot3.SelectedIndex = args.Slot3;
01291             cboLEDslot4.SelectedIndex = args.Slot4;
01292         }
01293 
01294         class MedianFilter
01295         {
01296             Queue<int> items;
01297             int depth;
01298 
01299             public MedianFilter(int depth)
01300             {
01301                 items = new Queue<int>(depth + 1);
01302                 this.depth = depth;
01303             }
01304 
01305             public int Filter(int current)
01306             {
01307                 int last;
01308 
01309                 items.Enqueue(current);
01310                 if (items.Count > depth)
01311                 {
01312                     items.Dequeue();
01313                 }
01314 
01315                 last = items.Peek();
01316 
01317                 if (items.Count < depth)
01318                 {
01319                     return current;
01320                 }
01321                 else
01322                 {
01323                     int count;
01324                     int[] arrayItems = items.ToArray();
01325                     int maxCount = 0;
01326                     int maxKey = 0;
01327 
01328                     Dictionary<int, int> valueOccurance = new Dictionary<int, int>();
01329 
01330                     for (int i = 0; i < arrayItems.Length; i++)
01331                     {
01332                         bool exists = valueOccurance.TryGetValue(arrayItems[i], out count);
01333                         if (exists)
01334                         {
01335                             count++;
01336                             valueOccurance.Remove(arrayItems[i]);
01337                             valueOccurance.Add(arrayItems[i], count);
01338                         }
01339                         else
01340                         {
01341                             valueOccurance.Add(arrayItems[i], 1);
01342                         }
01343                     }
01344 
01345                     foreach (KeyValuePair<int, int> item in valueOccurance)
01346                     {
01347                         if (item.Key > maxCount)
01348                         {
01349                             maxKey = item.Key;
01350                         }
01351                     }
01352 
01353                     return maxKey;
01354                 }
01355 
01356             }
01357         }
01358 
01359         /*
01360         public class StreamingStartStopEventArgs : EventArgs
01361         {
01362             public bool state { get; set; }
01363         }*/
01364 
01365     }
01366 }