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.
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 }
Generated on Tue Jul 12 2022 21:52:39 by
1.7.2